import { decodeSchema, EncodedSchema, findAllDefs, JSONSchema, jsonSchema, } from "@noya-app/noya-schemas"; import { expect, it } from "bun:test"; import { checkTypeSafe } from "../checkType"; const defs = findAllDefs(jsonSchema); const stringSchema: JSONSchema = { type: "string", default: "hello world", _kind: "String", }; it("validates a string schema", () => { expect(checkTypeSafe(stringSchema, jsonSchema, defs)).toBe(true); const invalidStringSchema = { type: "string", default: "hello world", }; expect(checkTypeSafe(invalidStringSchema, jsonSchema, defs)).toBe(false); }); it("decodes a string schema", () => { const decoded = decodeSchema(stringSchema as unknown as EncodedSchema); const value = "hello world"; expect(checkTypeSafe(value, decoded, [])).toBe(true); const invalidValue = 42; expect(checkTypeSafe(invalidValue, decoded, [])).toBe(false); }); const arraySchema: JSONSchema = { type: "array", _kind: "Array", items: { type: "string", _kind: "String", }, }; it("validates an array schema", () => { expect(checkTypeSafe(arraySchema, jsonSchema, defs)).toBe(true); }); it("decodes an array schema", () => { const decoded = decodeSchema(arraySchema as unknown as EncodedSchema); const value = ["hello world"]; expect(checkTypeSafe(value, decoded, [])).toBe(true); const invalidValue = [42]; expect(checkTypeSafe(invalidValue, decoded, [])).toBe(false); }); const objectSchema: JSONSchema = { type: "object", _kind: "Object", properties: { name: { type: "string", _kind: "String", }, age: { type: "number", minimum: 0, _kind: "Number", }, tags: { type: "array", _kind: "Array", items: { type: "string", _kind: "String", }, }, }, required: ["name"], }; it("validates a nested object schema", () => { expect(checkTypeSafe(objectSchema, jsonSchema, defs)).toBe(true); }); it("decodes a nested object schema", () => { const decoded = decodeSchema(objectSchema as unknown as EncodedSchema); const value = { name: "hello world", age: 42, tags: ["hello", "world"] }; expect(checkTypeSafe(value, decoded, [])).toBe(true); const invalidValue = { // missing name age: 42, tags: ["hello", "world"], }; expect(checkTypeSafe(invalidValue, decoded, [])).toBe(false); const invalidValue2 = { name: "hello world", age: 42, // bad type tags: ["hello", "world", 42], }; expect(checkTypeSafe(invalidValue2, decoded, [])).toBe(false); }); const enumSchema: JSONSchema = { anyOf: [ { const: "compact", type: "string", _kind: "Literal" }, { const: "detailed", type: "string", _kind: "Literal" }, ], default: "compact", _kind: "Union", }; it("validates and decodes an enum schema", () => { expect(checkTypeSafe(enumSchema, jsonSchema, defs)).toBe(true); const decoded = decodeSchema(enumSchema as unknown as EncodedSchema); expect(checkTypeSafe("detailed", decoded, [])).toBe(true); expect(checkTypeSafe("unknown", decoded, [])).toBe(false); }); const discriminatedUnionSchema: JSONSchema = { anyOf: [ { type: "object", properties: { kind: { const: "solid", type: "string", _kind: "Literal" }, color: { type: "string", _kind: "String" }, }, required: ["kind", "color"], _kind: "Object", }, { type: "object", properties: { kind: { const: "gradient", type: "string", _kind: "Literal" }, from: { type: "string", _kind: "String" }, to: { type: "string", _kind: "String" }, }, required: ["kind", "from", "to"], _kind: "Object", }, ], discriminator: "kind", default: { kind: "solid", color: "#000000" }, _kind: "Union", }; it("validates and decodes a discriminated union schema", () => { expect(checkTypeSafe(discriminatedUnionSchema, jsonSchema, defs)).toBe(true); const decoded = decodeSchema( discriminatedUnionSchema as unknown as EncodedSchema ); expect( checkTypeSafe( { kind: "gradient", from: "#000000", to: "#ffffff" }, decoded, [] ) ).toBe(true); expect( checkTypeSafe({ kind: "gradient", color: "#000000" }, decoded, []) ).toBe(false); });