mirror of
https://github.com/dsh-market/dsh-market.git
synced 2026-09-28 05:03:07 +08:00
fix(e2e): resolve the repo root as a path, not a URL pathname
First Windows run of the layer-3 lane failed before a single spec ran:
Error: spawnSync C:\Windows\system32\cmd.exe ENOENT
cmd.exe was not missing. Node reports an invalid CWD as ENOENT against the
executable it never got to launch, and the cwd came from
resolve(new URL('../..', import.meta.url).pathname)
On Windows that pathname keeps a leading slash — `/D:/a/repo` — and
resolving it yields a directory that does not exist. fileURLToPath is the
conversion that handles the drive letter. The same line had been copied into
the fixture registry, so both are fixed.
Why it reached CI at all: tsconfig excludes `tests`, so nothing typechecked
the scaffold, and the first version of this fix — which dropped the
fileURLToPath import while adding its call — was still green locally, since
a missing import is a runtime error and the file only runs when the e2e lane
does. tsconfig.tests.json now covers tests/web and runs as part of
`npm run typecheck`; removing that import again fails the gate immediately.
Process handling had to change too, or the lane could not have run on
Windows at all:
- teardown used `process.kill(-pid)`, a process GROUP call Windows does not
have. It throws, the fallback kills only the shell wrapper, and the real
dsh keeps holding the port — a hung job rather than a failed one. Windows
goes through `taskkill /T` instead.
- `detached: true` maps to DETACHED_PROCESS there: no console at all, the
very thing #40 had to undo, and pointless now that the kill no longer
needs a group. POSIX-only.
Full test typechecking is a bigger job — mixing the server and client test
configs surfaces 300+ errors that are config mismatch, not defects — so this
covers the scaffold only, which is where the failure actually was.
This commit is contained in:
+1
-1
@@ -21,7 +21,7 @@
|
||||
"plugin-manager"
|
||||
],
|
||||
"scripts": {
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
||||
"build": "tsc -p tsconfig.json && npm run build:client",
|
||||
"build:client": "tsdown && node scripts/normalize-client-banner.mjs",
|
||||
"check": "npm run typecheck && npm run build && node scripts/restart-smoke.mjs",
|
||||
|
||||
@@ -18,10 +18,13 @@ import type { Server } from 'node:http'
|
||||
import { createHash } from 'node:crypto'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { readFileSync, readdirSync } from 'node:fs'
|
||||
import { basename, join, resolve } from 'node:path'
|
||||
import { basename, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import type { Registry, RegistryPlugin } from '../../src/registry.ts'
|
||||
|
||||
const FIXTURE_ROOT = resolve(new URL('./fixtures', import.meta.url).pathname)
|
||||
// fileURLToPath, not .pathname — see the note in scaffold.ts: a Windows
|
||||
// pathname keeps its leading slash and resolves to a nonexistent directory.
|
||||
const FIXTURE_ROOT = fileURLToPath(new URL('./fixtures', import.meta.url))
|
||||
const UPSTREAM = 'https://registry.npmjs.org'
|
||||
|
||||
export interface ServedPackage {
|
||||
|
||||
@@ -13,12 +13,18 @@ import { execSync, spawn, spawnSync } from 'node:child_process'
|
||||
import type { ChildProcess } from 'node:child_process'
|
||||
import { mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import type { Page } from 'playwright'
|
||||
import { packFixture, startFixtureRegistry } from './registry.ts'
|
||||
import type { FixtureRegistry } from './registry.ts'
|
||||
|
||||
const REPO_ROOT = resolve(new URL('../..', import.meta.url).pathname)
|
||||
// fileURLToPath, not .pathname: on Windows the pathname carries a leading
|
||||
// slash (`/D:/a/repo`), and resolving that yields a directory that does not
|
||||
// exist. Node then reports the failure as ENOENT on cmd.exe — the shell it
|
||||
// never got to run — which is what made the first Windows e2e run look like
|
||||
// a missing shell rather than a bad cwd.
|
||||
const REPO_ROOT = fileURLToPath(new URL('../..', import.meta.url))
|
||||
|
||||
/** Working directory for dsh invocations — source launches need their repo
|
||||
* root so `--import tsx/esm` resolves; a global dsh doesn't care. */
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
// The layer-3 scaffold is plain Node code that the main config does not
|
||||
// cover (it excludes `tests`), so a missing import there fails only at
|
||||
// runtime — and only on the platform that happens to hit that line. A
|
||||
// dropped `fileURLToPath` import shipped exactly that way: green locally,
|
||||
// ENOENT on Windows CI.
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": { "noEmit": true, "rootDir": "." },
|
||||
"include": ["tests/web", "src"],
|
||||
"exclude": ["lib", "src/client"]
|
||||
}
|
||||
Reference in New Issue
Block a user