UNPKG

typescript-runtime-schemas

Version:

A TypeScript schema generation tool that extracts Zod schemas from TypeScript source files with runtime validation support. Generate validation schemas directly from your existing TypeScript types with support for computed types and constraint-based valid

303 lines (280 loc) 15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ts_morph_1 = require("ts-morph"); const supports_runtime_validation_checker_1 = require("./supports-runtime-validation-checker"); describe("SupportsRuntimeValidation Checker", () => { let project; beforeEach(() => { project = new ts_morph_1.Project({ compilerOptions: { target: ts_morph_1.ScriptTarget.ES2020, module: ts_morph_1.ModuleKind.CommonJS, strict: true, }, useInMemoryFileSystem: true, }); }); describe("Basic Examples from Requirements", () => { it("should return false for type A = { id: number, title: string }", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type A = { id: number, title: string }; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const typeA = sourceFile.getTypeAlias("A"); expect(typeA).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(typeA)).toBe(false); }); it("should return true for type B = A & SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type A = { id: number, title: string }; type B = A & SupportsRuntimeValidation; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const typeB = sourceFile.getTypeAlias("B"); expect(typeB).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(typeB)).toBe(true); }); it("should return false for type C = Pick<B, 'id'>", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type A = { id: number, title: string }; type B = A & SupportsRuntimeValidation; type C = Pick<B, 'id'>; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const typeC = sourceFile.getTypeAlias("C"); expect(typeC).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(typeC)).toBe(false); }); it("should return true for type D = Pick<B, 'id'> & SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type A = { id: number, title: string }; type B = A & SupportsRuntimeValidation; type D = Pick<B, 'id'> & SupportsRuntimeValidation; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const typeD = sourceFile.getTypeAlias("D"); expect(typeD).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(typeD)).toBe(true); }); }); describe("Complex Intersection Types", () => { it("should return true for multiple intersections with SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type OtherType = { other: string }; type ComplexType = { id: number } & OtherType & SupportsRuntimeValidation; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const complexType = sourceFile.getTypeAlias("ComplexType"); expect(complexType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(complexType)).toBe(true); }); it("should return true when SupportsRuntimeValidation is first in intersection", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type BaseType = { id: number }; type FirstType = SupportsRuntimeValidation & BaseType; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const firstType = sourceFile.getTypeAlias("FirstType"); expect(firstType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(firstType)).toBe(true); }); it("should return false for intersections without SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type TypeA = { id: number }; type TypeB = { name: string }; type IntersectionType = TypeA & TypeB; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const intersectionType = sourceFile.getTypeAlias("IntersectionType"); expect(intersectionType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(intersectionType)).toBe(false); }); }); describe("Interface Support", () => { it("should return true for interface extending SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; interface TestInterface extends SupportsRuntimeValidation { id: number; name: string; } `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const testInterface = sourceFile.getInterface("TestInterface"); expect(testInterface).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(testInterface)).toBe(true); }); it("should return false for interface not extending SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; interface TestInterface { id: number; name: string; } `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const testInterface = sourceFile.getInterface("TestInterface"); expect(testInterface).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(testInterface)).toBe(false); }); it("should return true for interface extending multiple types including SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; interface BaseInterface { id: number; } interface TestInterface extends BaseInterface, SupportsRuntimeValidation { name: string; } `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const testInterface = sourceFile.getInterface("TestInterface"); expect(testInterface).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(testInterface)).toBe(true); }); }); describe("Edge Cases", () => { it("should return true for direct SupportsRuntimeValidation type alias", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type DirectType = SupportsRuntimeValidation; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const directType = sourceFile.getTypeAlias("DirectType"); expect(directType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(directType)).toBe(true); }); it("should return false for union types containing SupportsRuntimeValidation", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type BaseType = { id: number }; type UnionType = BaseType | SupportsRuntimeValidation; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const unionType = sourceFile.getTypeAlias("UnionType"); expect(unionType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(unionType)).toBe(false); }); it("should return false for utility types like Pick, Omit, Partial", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type BaseType = { id: number; name: string } & SupportsRuntimeValidation; type PickType = Pick<BaseType, 'id'>; type OmitType = Omit<BaseType, 'name'>; type PartialType = Partial<BaseType>; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const pickType = sourceFile.getTypeAlias("PickType"); const omitType = sourceFile.getTypeAlias("OmitType"); const partialType = sourceFile.getTypeAlias("PartialType"); expect(pickType).toBeDefined(); expect(omitType).toBeDefined(); expect(partialType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(pickType)).toBe(false); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(omitType)).toBe(false); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(partialType)).toBe(false); }); it("should handle empty type alias", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type EmptyType = {}; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const emptyType = sourceFile.getTypeAlias("EmptyType"); expect(emptyType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(emptyType)).toBe(false); }); }); describe("Convenience Function checkTypeInSourceCode", () => { it("should work with the convenience function for type aliases", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type A = { id: number, title: string }; type B = A & SupportsRuntimeValidation; type C = Pick<B, 'id'>; type D = Pick<B, 'id'> & SupportsRuntimeValidation; `; expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "A")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "B")).toBe(true); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "C")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "D")).toBe(true); }); it("should work with the convenience function for interfaces", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; interface InterfaceA { id: number; title: string; } interface InterfaceB extends SupportsRuntimeValidation { id: number; title: string; } `; expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "InterfaceA")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "InterfaceB")).toBe(true); }); it("should throw error for non-existent type", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; type A = { id: number }; `; expect(() => { (0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "NonExistentType"); }).toThrow("Type NonExistentType not found in source code"); }); }); describe("Real-world Examples", () => { it("should handle complex real-world type definitions", () => { const sourceCode = ` export type SupportsRuntimeValidation = {}; // Base types type User = { id: string; name: string; email: string; }; type UserPermissions = { canRead: boolean; canWrite: boolean; canDelete: boolean; }; // Types with runtime validation type ValidatedUser = User & SupportsRuntimeValidation; type ValidatedUserWithPermissions = User & UserPermissions & SupportsRuntimeValidation; // Types without runtime validation type UserProfile = Pick<User, 'name' | 'email'>; type UserSummary = Omit<User, 'email'>; // Mixed types type ValidatedUserProfile = Pick<ValidatedUser, 'name' | 'email'> & SupportsRuntimeValidation; `; expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "User")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "UserPermissions")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "ValidatedUser")).toBe(true); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "ValidatedUserWithPermissions")).toBe(true); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "UserProfile")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "UserSummary")).toBe(false); expect((0, supports_runtime_validation_checker_1.checkTypeInSourceCode)(sourceCode, "ValidatedUserProfile")).toBe(true); }); }); describe("Import Scenarios", () => { it("should handle qualified name references", () => { const sourceCode = ` namespace ValidationTypes { export type SupportsRuntimeValidation = {}; } type TestType = { id: number } & ValidationTypes.SupportsRuntimeValidation; `; const sourceFile = project.createSourceFile("test.ts", sourceCode); const testType = sourceFile.getTypeAlias("TestType"); expect(testType).toBeDefined(); expect((0, supports_runtime_validation_checker_1.isTopLevelIntersectionWithSupportsRuntimeValidation)(testType)).toBe(true); }); }); }); //# sourceMappingURL=supports-runtime-validation-checker.test.js.map