mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-07-17 16:47:05 +00:00
test(backend): fix Windows ENOENT in backend-tests-glob regression check (#7794)
* test(backend): make the glob regression check Windows-safe
The previous version called execFileSync('npx', ...). On Windows
runners (and any Windows host where npx is installed as npx.cmd),
node's child_process.spawn does not auto-pick the .cmd shim, so
the call fails with spawnSync npx ENOENT. CI on develop went red
for "Windows without plugins" because of this — Linux passed.
Resolve mocha's JS entry directly via require.resolve and run it
under the current node process. No shell, no .cmd resolution,
identical behaviour on every platform.
Also normalise the absolute paths mocha prints to POSIX-relative
form so the toContain() assertions match on both Linux (which
emits forward slashes) and Windows (backslashes).
Verified locally that the test still fails when the package.json
glob is reverted to the broken tests/backend/specs/**.ts pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(backend): use path.relative for cross-platform glob normalization
Qodo flagged the prefix-strip + sep-split approach as brittle. On
Windows runners mocha can emit paths with mixed separators or
different drive-letter casing, in which case startsWith() misses
the prefix and the assertions fail against absolute paths.
path.relative(srcRoot, abs) handles drive-letter casing and mixed
separators consistently, then a final replace([\\/]) -> '/' yields
POSIX-relative paths regardless of how mocha printed them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b195b135e4
commit
662637d1ac
1 changed files with 17 additions and 7 deletions
|
|
@ -13,21 +13,20 @@
|
|||
|
||||
import {execFileSync} from 'child_process';
|
||||
import {readFileSync} from 'fs';
|
||||
import {join} from 'path';
|
||||
import {isAbsolute, join, relative} from 'path';
|
||||
import {describe, it, expect} from 'vitest';
|
||||
|
||||
const srcRoot = join(__dirname, '..', '..', '..');
|
||||
const pkg = JSON.parse(readFileSync(join(srcRoot, 'package.json'), 'utf8'));
|
||||
|
||||
// Strip `cross-env NAME=value` prefixes and the leading binary name so we
|
||||
// can pass the remaining tokens straight to npx mocha --dry-run.
|
||||
// invoke mocha directly with the rest of the script's arguments.
|
||||
const tokens = String(pkg.scripts.test).split(/\s+/);
|
||||
while (tokens[0] && /^[A-Z_][A-Z0-9_]*=/.test(tokens[0])) tokens.shift();
|
||||
if (tokens[0] === 'cross-env') {
|
||||
tokens.shift();
|
||||
while (tokens[0] && /^[A-Z_][A-Z0-9_]*=/.test(tokens[0])) tokens.shift();
|
||||
}
|
||||
// Drop the binary itself (mocha) — npx will re-add it.
|
||||
if (tokens[0] === 'mocha') tokens.shift();
|
||||
|
||||
const REQUIRED = [
|
||||
|
|
@ -38,15 +37,26 @@ const REQUIRED = [
|
|||
|
||||
describe('backend test glob', () => {
|
||||
it('discovers nested specs under tests/backend/specs/{api,admin}/', () => {
|
||||
// Resolve mocha's JS entry directly and run it under the current node.
|
||||
// Going through `npx` (or even via the package.json bin shim) breaks on
|
||||
// Windows runners where the resolver doesn't auto-pick `.cmd`/`.bat`.
|
||||
const mochaBin = require.resolve('mocha/bin/mocha.js');
|
||||
const out = execFileSync(
|
||||
'npx', ['mocha', '--dry-run', '--list-files', ...tokens],
|
||||
process.execPath, [mochaBin, '--dry-run', '--list-files', ...tokens],
|
||||
{cwd: srcRoot, encoding: 'utf8', env: {...process.env, NODE_ENV: 'production'}},
|
||||
);
|
||||
// mocha --list-files prints absolute paths. Normalise to repo-relative.
|
||||
const seen = out.split('\n')
|
||||
// mocha --list-files prints absolute paths with platform separators.
|
||||
// Normalise to repo-relative POSIX paths so the assertions match on
|
||||
// both Linux and Windows runners. path.relative handles drive-letter
|
||||
// casing and mixed separators consistently; absolute lines that fall
|
||||
// outside srcRoot (shouldn't happen with --recursive on srcRoot, but
|
||||
// be defensive) are passed through untouched and would fail the
|
||||
// toContain() check loudly rather than silently.
|
||||
const seen = out.split(/\r?\n/)
|
||||
.map((l) => l.trim())
|
||||
.filter(Boolean)
|
||||
.map((l) => l.replace(`${srcRoot}/`, ''));
|
||||
.map((l) => (isAbsolute(l) ? relative(srcRoot, l) : l))
|
||||
.map((l) => l.split(/[\\/]/).join('/'));
|
||||
for (const required of REQUIRED) {
|
||||
expect(seen, `mocha test glob missed ${required}`).toContain(required);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue