Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions desktop/test-loader-hooks.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import fs from "node:fs";
import path from "node:path";
import ts from "typescript";
Expand All @@ -13,6 +13,17 @@ const repoRoot = path.resolve(
"..",
);

// `nextResolve` requires specifiers to be URLs or relative paths. Passing an
// absolute filesystem path happens to work on POSIX (node coerces it), but on
// Windows an absolute path like `C:\...` parses as a URL with protocol `c:`
// and every test run dies with ERR_UNSUPPORTED_ESM_URL_SCHEME. Hand absolute
// paths to node as proper file:// URLs on all platforms.
function toFileSpecifier(candidatePath) {
return path.isAbsolute(candidatePath)
? pathToFileURL(candidatePath).href
: candidatePath;
}

function resolveSourcePath(basePath) {
// Existence decides, not path.extname — a dotted basename like
// `ProfileAvatarEditor.utils` (→ .utils.ts on disk) looks like an
Expand Down Expand Up @@ -63,7 +74,7 @@ export function resolve(specifier, context, nextResolve) {
}
if (specifier === "@features-manifest") {
const resolved = path.join(repoRoot, "preview-features.json");
return nextResolve(resolved, context);
return nextResolve(toFileSpecifier(resolved), context);
}
if (specifier.startsWith("@/")) {
const stripped = specifier.slice(2);
Expand All @@ -73,7 +84,7 @@ export function resolve(specifier, context, nextResolve) {
// Otherwise paths like `@/.../foo.mjs` would be coerced into `foo.mjs.ts`
// and fail to resolve.
const resolved = resolveSourcePath(`${srcRoot}/${stripped}`);
return nextResolve(resolved ?? `${srcRoot}/${stripped}`, context);
return nextResolve(toFileSpecifier(resolved ?? `${srcRoot}/${stripped}`), context);
}
// Resolve extensionless relative TS imports (e.g. `./parseImeta`) — the app's
// bundler adds the extension, but node's ESM resolver does not. Without this,
Expand All @@ -90,7 +101,7 @@ export function resolve(specifier, context, nextResolve) {
path.resolve(path.dirname(parentPath), specifier),
);
if (resolved) {
return nextResolve(resolved, context);
return nextResolve(toFileSpecifier(resolved), context);
}
return nextResolve(specifier, context);
}
Expand Down