diff --git a/.gitignore b/.gitignore index 3afd07b..d9bd26c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.modded.ts +*.modded \ No newline at end of file diff --git a/src/enum/enum.test.ts b/src/enum/enum.test.ts index e1119ff..5b37b83 100644 --- a/src/enum/enum.test.ts +++ b/src/enum/enum.test.ts @@ -1,4 +1,4 @@ -import { executeTest } from "../utils/test.ts"; +import { executeProjectTest, executeTest } from "../utils/test.ts"; import { enumCodemod } from "./enum.ts"; const testFn = executeTest({ @@ -6,6 +6,11 @@ const testFn = executeTest({ codemod: enumCodemod, }); +const projectTestFn = executeProjectTest({ + testDir: "src/enum/spec/", + codemod: enumCodemod, +}); + Deno.test("converts string enum to object", async () => { await testFn("string-enum"); }); @@ -53,3 +58,10 @@ Deno.test("enum usage in template literals and conditionals", async () => { Deno.test("enum usage with arrays, maps and complex data structures", async () => { await testFn("data-structures"); }); + +Deno.test.only( + "converts enums across multiple files with imports", + async () => { + await projectTestFn("proj"); + }, +); diff --git a/src/enum/enum.ts b/src/enum/enum.ts index 40bca72..398f94a 100644 --- a/src/enum/enum.ts +++ b/src/enum/enum.ts @@ -83,6 +83,7 @@ function updateEnumReferences(sourceFile: Node, enumNames: string[]): void { } export function enumCodemod(filePath: string): void { + // breaking on glob const sourceFile = project.addSourceFileAtPath(filePath); const enums = sourceFile.getEnums(); diff --git a/src/utils/test.ts b/src/utils/test.ts index 3746589..cc573d0 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -120,3 +120,71 @@ export const executeTest = (config: { } }; }; + +export const executeProjectTest = (config: { + testDir: `${string}/`; + codemod: (globPath: string) => void; + checkTsOptions?: string[]; +}) => { + const { testDir, codemod, checkTsOptions } = config; + + return async ( + projectSlug: string, + ) => { + const projectDir = testDir + projectSlug + "/"; + const tmpDir = testDir + projectSlug + ".modded/"; + + try { + // Find all .in.ts files in the project directory + const entries = []; + for await (const entry of Deno.readDir(projectDir)) { + if (entry.isFile && entry.name.endsWith(".in.ts")) { + entries.push(entry.name); + } + } + + // Create temp directory and copy files + await Deno.mkdir(tmpDir, { recursive: true }); + + for (const fileName of entries) { + const originalContent = await Deno.readTextFile(projectDir + fileName); + const tmpFileName = fileName.replace(".in.ts", ".ts"); + const tmpFilePath = tmpDir + tmpFileName; + + await Deno.writeTextFile(tmpFilePath, originalContent); + } + + // Run codemod on the temp directory (pass glob pattern) + codemod(tmpDir + "*.ts"); + + // Format all files + for (const fileName of entries) { + const tmpFileName = fileName.replace(".in.ts", ".ts"); + const tmpFilePath = tmpDir + tmpFileName; + await denoFmt(tmpFilePath); + } + + // Verify against expected outputs + for (const fileName of entries) { + const outFileName = fileName.replace(".in.ts", ".out.ts"); + const tmpFileName = fileName.replace(".in.ts", ".ts"); + + const expectedOutput = await Deno.readTextFile(projectDir + outFileName); + const actualOutput = await Deno.readTextFile(tmpDir + tmpFileName); + + await checkTsFile(tmpDir + tmpFileName, checkTsOptions); + assertEquals(actualOutput, expectedOutput, `File ${fileName} transformation mismatch`); + } + + } finally { + // Clean up temp directory + if (!Deno.env.get("DEBUG")) { + try { + await Deno.remove(tmpDir, { recursive: true }); + } catch { + // Ignore cleanup errors + } + } + } + }; +};