Skip to content

TypeScript transpiler breaks relative imports to sibling .ts files #438

Closed

Description

@ngarbezza

Context

We're dogfooding Testy as the test runner for a deterministic core we're building in TypeScript (see 10Pines/10p-internal-apps#162). A previous evaluation against @pmoo/testy@8.0.0 found the timeout-crash bug (#432, fixed in the 8.1.0 line — thanks for the quick turnaround!). Re-running the same evaluation against current main (commit ff0dad2) to confirm the fix, we found a new regression introduced by the TypeScript transpiler added since 8.0.0.

Bug

Any .ts test file that imports another .ts file with a relative path fails to load, even though the same test worked fine on 8.0.0 (which had no built-in transpiler and relied on Node's own type-stripping).

TypescriptTranspiler.generateTemporalJavascriptFromTypescript (lib/typescript/typescript_transpiler.js) transpiles the test file and writes the result to <cwd>/.testy-cache/<basename>.js, then TestFileLoader imports it from there. The transpiled code still contains the original relative import specifier (e.g. import { greet } from "./greet.ts"), but that path is now resolved relative to .testy-cache/, not to the original file's directory — so it doesn't exist there.

Repro

mkdir repro && cd repro
npm init -y && npm pkg set type=module
npm install github:ngarbezza/testy#ff0dad20d1f16851e3dd64d63a9bb9de1ea001a1

cat > greet.ts <<'EOF'
export function greet(name: string): string {
  return `hello, ${name}`;
}
EOF

cat > greet_test.ts <<'EOF'
import { suite, test, assert } from "@pmoo/testy";
import { greet } from "./greet.ts";

suite("greet", () => {
  test("says hello", () => {
    assert.that(greet("world")).isEqualTo("hello, world");
  });
});
EOF

cat > .testyrc.json <<'EOF'
{ "directory": ".", "filter": "greet_test\\.ts$" }
EOF

npx testy greet_test.ts

Observed

Error loading suite .../greet_test.ts!
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../.testy-cache/greet.ts'
imported from '.../.testy-cache/greet_test.ts.js'
Did you mean to import "../greet.ts"?

Expected

The test passes, same as it did on 8.0.0 (no transpiler involved, Node's native type stripping handled it directly and relative imports resolved normally).

Notes

  • Confirmed this isn't specific to our setup: a minimal two-file repro (above) reproduces it, and the same two files pass fine when pinned to @pmoo/testy@8.0.0.
  • Since Node (≥ 22, which is now the minimum per Raise minimum supported Node version to 22 and build on 22, 24 and 26 #435) already strips types from .ts files natively, it's worth asking whether the new transpiler needs to run at all when native support is available — or, if it must run (e.g. for older/other runtimes), whether it should preserve the original file's directory when writing to .testy-cache (or write the temp file next to the original) so relative imports keep resolving correctly.
  • This blocks adopting Testy for any multi-file TypeScript project where a test imports the code under test, which is the common case.

Full write-up with all 4 adoption criteria re-evaluated: 10Pines/10p-internal-apps spike/core-ts/README.md (private repo, happy to share details if useful).

Activity

  1. ngarbezza commented on Oct 28, 2026

    @ngarbezza
    OwnerAuthor

    Esto quedó resuelto en #452 (mergeado en main), que cerró el issue duplicado #450. El JS transpilado ahora se escribe junto al .ts original, así que los imports relativos a archivos .ts hermanos resuelven correctamente. Estará disponible en la próxima versión publicada.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions