import { describe, it } from "@std/testing/bdd"; import { expect } from "@std/expect"; import { SchemaGenerator } from "../../src/schema-generator.ts"; import { createTestProgram } from "../utils.ts"; import ts from "typescript"; describe("Circular alias error handling", () => { it("should throw descriptive error for circular Default aliases", async () => { const code = ` type Default = T; type A = B; type B = A; interface SchemaRoot { circularAlias: A; } `; const { checker, sourceFile } = await createTestProgram(code); const rootInterface = sourceFile.statements.find((stmt) => ts.isInterfaceDeclaration(stmt) && stmt.name.text === "SchemaRoot" ); if (!rootInterface || !ts.isInterfaceDeclaration(rootInterface)) { throw new Error("SchemaRoot interface not found"); } const circularProperty = rootInterface.members[0] as ts.PropertySignature; const type = checker.getTypeFromTypeNode(circularProperty.type!); const generator = new SchemaGenerator(); expect(() => { generator.generateSchema(type, checker, circularProperty.type); }).toThrow("Circular type alias detected: A -> B -> A"); }); it("should handle longer circular chains", async () => { const code = ` type Default = T; type A = B; type B = C; type C = A; interface SchemaRoot { circularAlias: A; } `; const { checker, sourceFile } = await createTestProgram(code); const rootInterface = sourceFile.statements.find((stmt) => ts.isInterfaceDeclaration(stmt) && stmt.name.text === "SchemaRoot" ); if (!rootInterface || !ts.isInterfaceDeclaration(rootInterface)) { throw new Error("SchemaRoot interface not found"); } const circularProperty = rootInterface.members[0] as ts.PropertySignature; const type = checker.getTypeFromTypeNode(circularProperty.type!); const generator = new SchemaGenerator(); expect(() => { generator.generateSchema(type, checker, circularProperty.type); }).toThrow("Circular type alias detected: A -> B -> C -> A"); }); });