diff --git a/.gitignore b/.gitignore index 1586e95..3afd07b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -tmp - +*.modded.ts diff --git a/src/enum/enum.test.ts b/src/enum/enum.test.ts index de558f7..e1119ff 100644 --- a/src/enum/enum.test.ts +++ b/src/enum/enum.test.ts @@ -1,100 +1,55 @@ import { executeTest } from "../utils/test.ts"; import { enumCodemod } from "./enum.ts"; -const testFn = await executeTest(import.meta.dirname!, enumCodemod); +const testFn = executeTest({ + testDir: "src/enum/spec/", + codemod: enumCodemod, +}); Deno.test("converts string enum to object", async () => { - await testFn({ - testFile: "string_enum_test.ts", - inFile: "src/enum/spec/string-enum.in.ts", - outFile: "src/enum/spec/string-enum.out.ts", - }); + await testFn("string-enum"); }); Deno.test("converts numeric enum to object", async () => { - await testFn({ - testFile: "numeric_enum_test.ts", - inFile: "src/enum/spec/numeric-enum.in.ts", - outFile: "src/enum/spec/numeric-enum.out.ts", - }); + await testFn("numeric-enum"); }); Deno.test("converts auto-incrementing enum to object", async () => { - await testFn({ - testFile: "auto_enum_test.ts", - inFile: "src/enum/spec/auto-enum.in.ts", - outFile: "src/enum/spec/auto-enum.out.ts", - }); + await testFn("auto-enum"); }); Deno.test("converts mixed value enum to object", async () => { - await testFn({ - testFile: "mixed_enum_test.ts", - inFile: "src/enum/spec/mixed-enum.in.ts", - outFile: "src/enum/spec/mixed-enum.out.ts", - }); + await testFn("mixed-enum"); }); Deno.test("converts multiple enums in single file", async () => { - await testFn({ - testFile: "multiple_enums_test.ts", - inFile: "src/enum/spec/multiple-enums.in.ts", - outFile: "src/enum/spec/multiple-enums.out.ts", - }); + await testFn("multiple-enums"); }); Deno.test("preserves enum usage in complex scenarios", async () => { - await testFn({ - testFile: "complex_usage_test.ts", - inFile: "src/enum/spec/complex-usage.in.ts", - outFile: "src/enum/spec/complex-usage.out.ts", - }); + await testFn("complex-usage"); }); Deno.test("handles const enum conversion", async () => { - await testFn({ - testFile: "const_enum_test.ts", - inFile: "src/enum/spec/const-enum.in.ts", - outFile: "src/enum/spec/const-enum.out.ts", - }); + await testFn("const-enum"); }); Deno.test("preserves comments", async () => { - await testFn({ - testFile: "comments_test.ts", - inFile: "src/enum/spec/comments.in.ts", - outFile: "src/enum/spec/comments.out.ts", - }); + await testFn("comments"); }); Deno.test("comprehensive enum transformation - full sample", async () => { - await testFn({ - testFile: "comprehensive_sample.ts", - inFile: "src/enum/spec/comprehensive.in.ts", - outFile: "src/enum/spec/comprehensive.out.ts", - }); + await testFn("comprehensive"); }); Deno.test("enum usage in destructuring and object patterns", async () => { - await testFn({ - testFile: "destructuring_test.ts", - inFile: "src/enum/spec/object-patterns.in.ts", - outFile: "src/enum/spec/object-patterns.out.ts", - }); + await testFn("object-patterns"); }); Deno.test("enum usage in template literals and conditionals", async () => { - await testFn({ - testFile: "templates_conditionals_test.ts", - inFile: "src/enum/spec/template-literal.in.ts", - outFile: "src/enum/spec/template-literal.out.ts", - }); + await testFn("template-literal"); }); Deno.test("enum usage with arrays, maps and complex data structures", async () => { - await testFn({ - testFile: "data_structures_test.ts", - inFile: "src/enum/spec/data-structures.in.ts", - outFile: "src/enum/spec/data-structures.out.ts", - }); + await testFn("data-structures"); }); diff --git a/src/parameter-properties/parameter-properties.test.ts b/src/parameter-properties/parameter-properties.test.ts index d1e6a0b..a2b6dfc 100644 --- a/src/parameter-properties/parameter-properties.test.ts +++ b/src/parameter-properties/parameter-properties.test.ts @@ -1,103 +1,57 @@ import { executeTest } from "../utils/test.ts"; import { parameterPropertiesCodemod } from "./parameter-properties.ts"; -const testFn = await executeTest( - import.meta.dirname!, - parameterPropertiesCodemod, +const testFn = executeTest( + { + testDir: "src/parameter-properties/spec/", + codemod: parameterPropertiesCodemod, + }, ); Deno.test("converts public parameter properties", async () => { - await testFn({ - testFile: "public_params_test.ts", - inFile: "src/parameter-properties/spec/public-params.in.ts", - outFile: "src/parameter-properties/spec/public-params.out.ts", - }); + await testFn("public-params"); }); Deno.test("converts private parameter properties", async () => { - await testFn({ - testFile: "private_params_test.ts", - inFile: "src/parameter-properties/spec/private-params.in.ts", - outFile: "src/parameter-properties/spec/private-params.out.ts", - }); + await testFn("private-params"); }); Deno.test("converts readonly parameter properties", async () => { - await testFn({ - testFile: "readonly_params_test.ts", - inFile: "src/parameter-properties/spec/readonly-params.in.ts", - outFile: "src/parameter-properties/spec/readonly-params.out.ts", - }); + await testFn("readonly-params"); }); Deno.test("converts mixed access modifiers", async () => { - await testFn({ - testFile: "mixed_modifiers_test.ts", - inFile: "src/parameter-properties/spec/mixed-modifiers.in.ts", - outFile: "src/parameter-properties/spec/mixed-modifiers.out.ts", - }); + await testFn("mixed-modifiers"); }); Deno.test("handles parameter properties with initializers", async () => { - await testFn({ - testFile: "initializers_test.ts", - inFile: "src/parameter-properties/spec/initializers.in.ts", - outFile: "src/parameter-properties/spec/initializers.out.ts", - }); + await testFn("initializers"); }); Deno.test("handles complex types in parameter properties", async () => { - await testFn({ - testFile: "complex_types_test.ts", - inFile: "src/parameter-properties/spec/complex-types.in.ts", - outFile: "src/parameter-properties/spec/complex-types.out.ts", - }); + await testFn("complex-types"); }); Deno.test("handles multiple classes in single file", async () => { - await testFn({ - testFile: "multiple_classes_test.ts", - inFile: "src/parameter-properties/spec/multiple-classes.in.ts", - outFile: "src/parameter-properties/spec/multiple-classes.out.ts", - }); + await testFn("multiple-classes"); }); Deno.test("preserves existing class properties", async () => { - await testFn({ - testFile: "existing_properties_test.ts", - inFile: "src/parameter-properties/spec/existing-properties.in.ts", - outFile: "src/parameter-properties/spec/existing-properties.out.ts", - }); + await testFn("existing-properties"); }); Deno.test("handles classes without parameter properties", async () => { - await testFn({ - testFile: "no_params_test.ts", - inFile: "src/parameter-properties/spec/no-params.in.ts", - outFile: "src/parameter-properties/spec/no-params.out.ts", - }); + await testFn("no-params"); }); Deno.test("preserves comments", async () => { - await testFn({ - testFile: "comments_test.ts", - inFile: "src/parameter-properties/spec/comments.in.ts", - outFile: "src/parameter-properties/spec/comments.out.ts", - }); + await testFn("comments"); }); Deno.test("handles generic classes", async () => { - await testFn({ - testFile: "generic_classes_test.ts", - inFile: "src/parameter-properties/spec/generic-classes.in.ts", - outFile: "src/parameter-properties/spec/generic-classes.out.ts", - }); + await testFn("generic-classes"); }); Deno.test("handles abstract classes", async () => { - await testFn({ - testFile: "abstract_classes_test.ts", - inFile: "src/parameter-properties/spec/abstract-classes.in.ts", - outFile: "src/parameter-properties/spec/abstract-classes.out.ts", - }); + await testFn("abstract-classes"); }); diff --git a/src/path-alias/path-alias.test.ts b/src/path-alias/path-alias.test.ts index 1400109..06d25ef 100644 --- a/src/path-alias/path-alias.test.ts +++ b/src/path-alias/path-alias.test.ts @@ -1,100 +1,55 @@ import { executeTest } from "../utils/test.ts"; import { pathAliasCodemod } from "./path-alias.ts"; -const testFn = await executeTest(import.meta.dirname!, pathAliasCodemod); +const testFn = executeTest({ + testDir: "src/path-alias/spec/src/tests/", + codemod: pathAliasCodemod, +}); Deno.test.only("converts simple path alias to relative path", async () => { - await testFn({ - testFile: "simple_alias_test.ts", - inFile: "src/path-alias/spec/src/tests/simple-alias.in.ts", - outFile: "src/path-alias/spec/src/tests/simple-alias.out.ts", - }); + await testFn("simple-alias"); }); Deno.test("converts wildcard path alias to relative path", async () => { - await testFn({ - testFile: "wildcard_alias_test.ts", - inFile: "src/path-alias/spec/src/tests/wildcard-alias.in.ts", - outFile: "src/path-alias/spec/src/tests/wildcard-alias.out.ts", - }); + await testFn("wildcard-alias"); }); Deno.test("handles multiple imports with different aliases", async () => { - await testFn({ - testFile: "multiple_imports_test.ts", - inFile: "src/path-alias/spec/src/tests/multiple-imports.in.ts", - outFile: "src/path-alias/spec/src/tests/multiple-imports.out.ts", - }); + await testFn("multiple-imports"); }); Deno.test("preserves relative imports unchanged", async () => { - await testFn({ - testFile: "relative_imports_test.ts", - inFile: "src/path-alias/spec/src/tests/relative-imports.in.ts", - outFile: "src/path-alias/spec/src/tests/relative-imports.out.ts", - }); + await testFn("relative-imports"); }); Deno.test("preserves external package imports unchanged", async () => { - await testFn({ - testFile: "external_packages_test.ts", - inFile: "src/path-alias/spec/src/tests/external-packages.in.ts", - outFile: "src/path-alias/spec/src/tests/external-packages.out.ts", - }); + await testFn("external-packages"); }); Deno.test("handles complex nested path aliases", async () => { - await testFn({ - testFile: "nested_aliases_test.ts", - inFile: "src/path-alias/spec/src/tests/nested-aliases.in.ts", - outFile: "src/path-alias/spec/src/tests/nested-aliases.out.ts", - }); + await testFn("nested-aliases"); }); Deno.test("handles mixed import types", async () => { - await testFn({ - testFile: "mixed_imports_test.ts", - inFile: "src/path-alias/spec/src/tests/mixed-imports.in.ts", - outFile: "src/path-alias/spec/src/tests/mixed-imports.out.ts", - }); + await testFn("mixed-imports"); }); Deno.test("handles type-only imports", async () => { - await testFn({ - testFile: "type_imports_test.ts", - inFile: "src/path-alias/spec/src/tests/type-imports.in.ts", - outFile: "src/path-alias/spec/src/tests/type-imports.out.ts", - }); + await testFn("type-imports"); }); Deno.test("handles default and named imports", async () => { - await testFn({ - testFile: "default_named_imports_test.ts", - inFile: "src/path-alias/spec/src/tests/default-named-imports.in.ts", - outFile: "src/path-alias/spec/src/tests/default-named-imports.out.ts", - }); + await testFn("default-named-imports"); }); Deno.test("handles re-exports", async () => { - await testFn({ - testFile: "re_exports_test.ts", - inFile: "src/path-alias/spec/src/tests/re-exports.in.ts", - outFile: "src/path-alias/spec/src/tests/re-exports.out.ts", - }); + await testFn("re-exports"); }); Deno.test("handles dynamic imports", async () => { - await testFn({ - testFile: "dynamic_imports_test.ts", - inFile: "src/path-alias/spec/src/tests/dynamic-imports.in.ts", - outFile: "src/path-alias/spec/src/tests/dynamic-imports.out.ts", - }); + await testFn("dynamic-imports"); }); Deno.test("comprehensive path alias transformation", async () => { - await testFn({ - testFile: "comprehensive_test.ts", - inFile: "src/path-alias/spec/src/tests/comprehensive.in.ts", - outFile: "src/path-alias/spec/src/tests/comprehensive.out.ts", - }); + await testFn("comprehensive"); }); diff --git a/src/path-alias/path-alias.ts b/src/path-alias/path-alias.ts index a237b48..22095b1 100644 --- a/src/path-alias/path-alias.ts +++ b/src/path-alias/path-alias.ts @@ -63,21 +63,25 @@ function resolvePathAlias( const wildcardPart = match[1]; - // Replace the wildcard in the target const resolvedPath = target.replace("*", wildcardPart); - // Convert to relative path from current file location - const currentDir = dirname(currentFilePath); - - // Find the tsconfig.json file to determine the base directory const tsConfigPath = findTsConfigPath(currentFilePath); const baseDir = tsConfigPath ? dirname(tsConfigPath) : dirname(currentFilePath); - // Calculate relative path from current file to the resolved path - const relativePath = relative(currentDir, join(baseDir, resolvedPath)); - + console.log({ + currentFilePath, + baseDir, + resolvedPath, + joined: join(baseDir, resolvedPath), + }); + // currentDir is not what we want. we need to use the path of the file + const relativePath = relative( + currentFilePath, + join(baseDir, resolvedPath), + ); + console.log({ relativePath }); // Add .ts extension if not present if ( !relativePath.endsWith(".ts") && !relativePath.endsWith(".tsx") && @@ -140,11 +144,7 @@ function convertPathAliases(sourceFile: SourceFile): void { ) { return; } - console.log({ - importPath, - pathMappings, - sourceFilePath: sourceFile.getFilePath(), - }); + const relativePath = resolvePathAlias( importPath, pathMappings, diff --git a/src/path-alias/spec/src/tests/simple-alias.out.ts b/src/path-alias/spec/src/tests/simple-alias.out.ts index ff8fdad..a348335 100644 --- a/src/path-alias/spec/src/tests/simple-alias.out.ts +++ b/src/path-alias/spec/src/tests/simple-alias.out.ts @@ -1,6 +1,6 @@ -import { UserService } from "../../src/services/user.ts"; -import { Logger } from "../../src/utils/logger.ts"; -import { Config } from "../../src/config/app.ts"; +import { UserService } from "../services/user.ts"; +import { Logger } from "../utils/logger.ts"; +import { Config } from "../config/app.ts"; export class UserController { constructor( diff --git a/src/utils/test.ts b/src/utils/test.ts index 9e0438d..b88b5ac 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -86,38 +86,30 @@ class TestUtils { } } -export const executeTest = async ( - dir: string, - codemod: (filePath: string) => void, -) => { - const tmpDir = join(dir, "spec/tmp"); +export const executeTest = (config: { + testDir: `${string}/`; + codemod: (filePath: string) => void; +}) => { + const { testDir, codemod } = config; const utils = new TestUtils(codemod); - const tmpExists = await exists(tmpDir); - if (!tmpExists) { - await Deno.mkdir(tmpDir); - } return async ( - config: { - testFile: string; - inFile: string; - outFile: string; - }, + testSlug: string, ) => { - const { testFile, inFile, outFile } = config; - const tmpPath = `${tmpDir}/${testFile}`; - + const testFile = testDir + testSlug + ".in.ts"; + const outFile = testDir + testSlug + ".out.ts"; + const tmpFile = testDir + testSlug + ".modded.ts"; try { const originalContent = await Deno.readTextFile( - inFile, + testFile, ); const expectedOutput = await Deno.readTextFile( outFile, ); - await utils.createTestFile(tmpPath, originalContent); - const result = await utils.runAndReadCodemod(tmpPath); - await checkTsFile(tmpPath); + await utils.createTestFile(tmpFile, originalContent); + const result = await utils.runAndReadCodemod(tmpFile); + await checkTsFile(tmpFile); assertEquals(result, expectedOutput); } finally { await utils.cleanup();