This commit is contained in:
147
packages/util/__test__/json.spec.ts
Normal file
147
packages/util/__test__/json.spec.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { parseWithSchema } from "../src/json";
|
||||
import { z } from "zod";
|
||||
|
||||
describe("json", () => {
|
||||
describe("parseWithSchema", () => {
|
||||
const schema = z.object({
|
||||
test: z.boolean().optional(),
|
||||
name: z.string(),
|
||||
nested: z.object({ foo: z.string() }).strict().optional(),
|
||||
});
|
||||
it("should throw with invalid json", () => {
|
||||
expect(() => parseWithSchema("blah", schema)).toThrow(
|
||||
new Error(
|
||||
`Invalid JSON: Unexpected token 'b', "blah" is not valid JSON`,
|
||||
),
|
||||
);
|
||||
});
|
||||
it("should parse", () => {
|
||||
const json = `{
|
||||
"test":true,
|
||||
"name":"bob",
|
||||
"unknown":"unknown",
|
||||
"nested":{
|
||||
"foo":"bar"
|
||||
}
|
||||
}`;
|
||||
|
||||
expect(parseWithSchema(json, schema)).toStrictEqual({
|
||||
test: true,
|
||||
name: "bob",
|
||||
nested: { foo: "bar" },
|
||||
});
|
||||
});
|
||||
it("should throw with invalid schema", () => {
|
||||
const json = `{
|
||||
"test":"yes",
|
||||
"nested":{
|
||||
"foo":1
|
||||
}
|
||||
}`;
|
||||
|
||||
expect(() => parseWithSchema(json, schema)).toThrow(
|
||||
new Error(
|
||||
`JSON does not match schema: "test" expected boolean, received string, "name" required, "nested.foo" expected string, received number`,
|
||||
),
|
||||
);
|
||||
});
|
||||
it("should migrate if valid json", () => {
|
||||
const json = `{
|
||||
"name": 1
|
||||
}`;
|
||||
|
||||
const result = parseWithSchema(json, schema, {
|
||||
migrate: () => {
|
||||
return {
|
||||
name: "migrated",
|
||||
test: false,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({
|
||||
name: "migrated",
|
||||
test: false,
|
||||
});
|
||||
});
|
||||
it("should revert to fallback if invalid json", () => {
|
||||
const json = `blah`;
|
||||
|
||||
const result = parseWithSchema(json, schema, {
|
||||
fallback: {
|
||||
name: "migrated",
|
||||
test: false,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({
|
||||
name: "migrated",
|
||||
test: false,
|
||||
});
|
||||
});
|
||||
it("should throw if migration fails", () => {
|
||||
const json = `{
|
||||
"name": 1
|
||||
}`;
|
||||
|
||||
expect(() => {
|
||||
parseWithSchema(json, schema, {
|
||||
//@ts-expect-error need to test migration failure
|
||||
migrate: () => {
|
||||
return {
|
||||
name: null,
|
||||
test: "Hi",
|
||||
};
|
||||
},
|
||||
});
|
||||
}).toThrow(
|
||||
new Error(
|
||||
`Migrated value does not match schema: "test" expected boolean, received string, "name" expected string, received null`,
|
||||
),
|
||||
);
|
||||
});
|
||||
it("should revert to fallback if migration fails", () => {
|
||||
const json = `{
|
||||
"name": 1
|
||||
}`;
|
||||
|
||||
const result = parseWithSchema(json, schema, {
|
||||
fallback: {
|
||||
name: "fallback",
|
||||
test: false,
|
||||
},
|
||||
//@ts-expect-error need to test migration failure
|
||||
migrate: () => {
|
||||
return {
|
||||
name: null,
|
||||
test: "Hi",
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({
|
||||
name: "fallback",
|
||||
test: false,
|
||||
});
|
||||
});
|
||||
it("migrate function should receive value", () => {
|
||||
const json = `{
|
||||
"test":"test"
|
||||
}`;
|
||||
|
||||
const result = parseWithSchema(json, schema, {
|
||||
migrate: (value) => {
|
||||
expect(value).toEqual({ test: "test" });
|
||||
return {
|
||||
name: "valid",
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({
|
||||
name: "valid",
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user