mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-05 02:59:27 +02:00
Some checks are pending
Build: Benchmark Image / build (push) Waiting to run
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (22.22.3) (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (24.15.0) (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Util: Sync API Docs / sync-public-api (push) Waiting to run
Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
73 lines
2.5 KiB
TypeScript
73 lines
2.5 KiB
TypeScript
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
// @ts-expect-error — JS module without types; runtime export is what we test.
|
|
import { buildArgs, resolveMapPath } from './select-affected-e2e.mjs';
|
|
|
|
// The wrapper is the bridge between CI (raw changed-files list) and janitor
|
|
// select-e2e. Its only job is to keep selection FAIL-OPEN: any failure in
|
|
// locating the map must degrade to broad — never throw, never hide selection.
|
|
|
|
describe('select-affected-e2e wrapper — fail-open contract', () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'select-wrapper-')));
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('resolveMapPath()', () => {
|
|
it('returns null when the committed map is missing (wrapper degrades to broad)', () => {
|
|
const missing = path.join(tempDir, 'never-existed.json');
|
|
expect(resolveMapPath({ mapPath: missing })).toBeNull();
|
|
});
|
|
|
|
it('returns the path when the map exists and is readable', () => {
|
|
const p = path.join(tempDir, 'present.json');
|
|
fs.writeFileSync(p, '{}');
|
|
expect(resolveMapPath({ mapPath: p })).toBe(p);
|
|
});
|
|
|
|
it('returns null on an unreadable map (e.g. perms), never throws', () => {
|
|
// On non-root environments chmod 000 makes accessSync(R_OK) throw.
|
|
// Skip the assertion on root (CI sometimes runs as root and can read anything).
|
|
if (process.getuid?.() === 0) return;
|
|
const p = path.join(tempDir, 'unreadable.json');
|
|
fs.writeFileSync(p, '{}');
|
|
fs.chmodSync(p, 0o000);
|
|
try {
|
|
expect(resolveMapPath({ mapPath: p })).toBeNull();
|
|
} finally {
|
|
fs.chmodSync(p, 0o644);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('buildArgs()', () => {
|
|
// Omitting --map is exactly how the wrapper signals fail-open broad to
|
|
// the janitor CLI — assert by absence, not by a placeholder value.
|
|
it('omits --map when mapPath is null (fail-open broad)', () => {
|
|
const args = buildArgs({ changedFiles: 'a.ts,b.ts', mapPath: null });
|
|
expect(args).toEqual(['select-e2e', '--changed-files=a.ts,b.ts']);
|
|
expect(args.some((a: string) => a.startsWith('--map='))).toBe(false);
|
|
});
|
|
|
|
it('passes --map and --all-specs through when provided', () => {
|
|
expect(
|
|
buildArgs({ changedFiles: 'a.ts', mapPath: '/tmp/m.json', allSpecs: '/tmp/s.txt' }),
|
|
).toEqual([
|
|
'select-e2e',
|
|
'--changed-files=a.ts',
|
|
'--map=/tmp/m.json',
|
|
'--all-specs=/tmp/s.txt',
|
|
]);
|
|
});
|
|
});
|
|
});
|