UNPKG

@jakub.knejzlik/ts-query

Version:

TypeScript implementation of SQL builder

215 lines (192 loc) 8.77 kB
import dayjs from "dayjs"; import { Condition, Conditions } from "./Condition"; import { Q } from "./Query"; const flavor = Q.flavors.mysql; describe("Condition Serialization and Deserialization", () => { // EQUAL it("should serialize and deserialize equal condition", () => { const condition = Conditions.equal("foo", 123); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); it("should serialize and deserialize equal condition multiple times", () => { const condition = Conditions.equal("foo", 123); const serialized = Condition.fromJSON(condition.toJSON()).toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // NOT EQUAL it("should serialize and deserialize notEqual condition", () => { const condition = Conditions.notEqual("foo", 123); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // GREATER THAN it("should serialize and deserialize greaterThan condition", () => { const condition = Conditions.greaterThan("foo", 123); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // LESS THAN it("should serialize and deserialize lessThan condition", () => { const condition = Conditions.lessThan("foo", 123); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // BETWEEN it("should serialize and deserialize between condition", () => { const condition = Conditions.between("foo", ["abcd", 2]); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); const json = { type: "BetweenCondition", key: "foo", from: "abcd", to: 2, }; expect(Condition.fromJSON(json).toSQL(flavor)).toEqual( condition.toSQL(flavor) ); }); it("should serialize and deserialize between with expressions", () => { const condition = Conditions.between("foo", ["abcd", Q.raw("now()")]); const json = condition.toJSON(); expect(Condition.fromJSON(json).toSQL(flavor)).toEqual( condition.toSQL(flavor) ); }); it("should serialize and deserialize between with date", () => { const condition = Conditions.between("foo", [ dayjs().startOf("day"), dayjs().endOf("day").toDate(), ]); const json = condition.toJSON(); expect(Condition.fromJSON(json).toSQL(flavor)).toEqual( condition.toSQL(flavor) ); }); // IN it("should serialize and deserialize in condition", () => { const condition = Conditions.in("foo", [1, 2, 3]); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); it("should serialize and deserialize in condition with strings", () => { const condition = Conditions.in("type", ["IncomingInvoice", "ExpenditureCashSlip"]); const serialized = condition!.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition!.toSQL(flavor)); expect(deserialized.toSQL(flavor)).toEqual( '`type` IN ("IncomingInvoice", "ExpenditureCashSlip")' ); }); // NOT IN it("should serialize and deserialize notIn condition", () => { const condition = Conditions.notIn("foo", [1, 2, 3]); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); it("should serialize and deserialize notIn condition with strings", () => { const condition = Conditions.notIn("type", ["IncomingInvoice", "ExpenditureCashSlip"]); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); // Verify the fix: strings should be quoted as values, not treated as columns expect(deserialized.toSQL(flavor)).toEqual( '`type` NOT IN ("IncomingInvoice", "ExpenditureCashSlip")' ); }); it("should handle round-trip serialization of notIn condition", () => { const condition = Conditions.notIn("status", ["deleted", "banned"]); const firstSerialized = condition.toJSON(); const firstDeserialized = Condition.fromJSON(firstSerialized); const secondSerialized = firstDeserialized.toJSON(); const secondDeserialized = Condition.fromJSON(secondSerialized); expect(secondDeserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // AND it("should serialize and deserialize and condition", () => { const condition1 = Conditions.equal("foo", 123); const condition2 = Conditions.greaterThan("bar", Q.raw("a")); const condition = Conditions.and([condition1, condition2]); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // OR it("should serialize and deserialize or condition", () => { const condition1 = Conditions.equal("foo", 123); const condition2 = Conditions.lessThan("bar", 50); const condition = Conditions.or([condition1, condition2]); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // NULL it("should serialize and deserialize null condition", () => { const condition = Conditions.null("foo"); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // NOT NULL it("should serialize and deserialize notNull condition", () => { const condition = Conditions.notNull("foo"); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // LIKE it("should serialize and deserialize like condition", () => { const condition = Conditions.like("foo", "He_lo wor%"); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // NOT LIKE it("should serialize and deserialize notLike condition", () => { const condition = Conditions.notLike("foo", "He_lo wor%"); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); // NOT it("should serialize and deserialize not condition", () => { const condition = Conditions.not(Conditions.equal("foo", 123)); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); it("should serialize and deserialize complex not condition", () => { const andCondition = Conditions.and([ Conditions.equal("foo", 123), Conditions.greaterThan("bar", 50), ]); const condition = Conditions.not(andCondition!); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); it("should serialize and deserialize nested not condition", () => { const innerNot = Conditions.not(Conditions.equal("foo", 123)); const condition = Conditions.not(innerNot); const serialized = condition.toJSON(); const deserialized = Condition.fromJSON(serialized); expect(deserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); it("should handle round-trip serialization of not condition", () => { const condition = Conditions.not(Conditions.in("foo", [1, 2, 3])!); const firstSerialized = condition.toJSON(); const firstDeserialized = Condition.fromJSON(firstSerialized); const secondSerialized = firstDeserialized.toJSON(); const secondDeserialized = Condition.fromJSON(secondSerialized); expect(secondDeserialized.toSQL(flavor)).toEqual(condition.toSQL(flavor)); }); });