mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(desktop): make the test loader work on Windows (#2758)
The resolve hook hands nextResolve absolute filesystem paths. Node's ESM resolver requires URLs or relative specifiers: POSIX absolute paths happen to be coerced, but a Windows path like C:\... parses as a URL with protocol 'c:', so every desktop unit-test run on Windows dies immediately with ERR_UNSUPPORTED_ESM_URL_SCHEME - on a clean tree, before any test executes. CI never sees it (Linux runners). Convert absolute paths to file:// URLs (pathToFileURL) at the three nextResolve call sites. On POSIX the resulting URL is identical to what node coerced before; on Windows the loader now works. With this change the full desktop suite (318 files, 3487 tests) passes on Windows 11 / node 24.14.1. Independently reported by another Windows contributor in #2634's testing notes. Claude-Session: https://claude.ai/code/session_01YFkHsUe1UUBBuvL81Zoe3n --------- Signed-off-by: technicallybrantley <77166260+technicallybrantley@users.noreply.github.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
co-authored by
Claude Fable 5
Will Pfleger
parent
545bb46b82
commit
8bb43d5191
@@ -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";
|
||||
@@ -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
|
||||
@@ -76,7 +87,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);
|
||||
@@ -86,7 +97,10 @@ 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,
|
||||
@@ -103,7 +117,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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user