Files
msd-core/tests/platform-guard.unit.test.cjs
2026-06-25 14:37:10 -04:00

382 lines
13 KiB
JavaScript

'use strict';
/**
* platform-guard.unit.test.cjs
*
* Unit tests for eslint-rules/lib/platform-guard.cjs.
* Verifies classifyPlatformTest and isWindowsExcludedNode shapes
* using espree to parse code snippets into ASTs.
*/
const { test, describe } = require('node:test');
const assert = require('node:assert/strict');
const espree = require('espree');
const { Linter } = require('eslint');
const { classifyPlatformTest, isWindowsExcludedNode } = require('../eslint-rules/lib/platform-guard.cjs');
const PARSE_OPTIONS = {
ecmaVersion: 2022,
sourceType: 'script',
range: true,
loc: true,
tokens: true,
comment: true,
};
function parse(code) {
return espree.parse(code, PARSE_OPTIONS);
}
// ─── classifyPlatformTest ─────────────────────────────────────────────────────
describe('classifyPlatformTest', () => {
test('process.platform === "win32" → windows', () => {
const ast = parse(`process.platform === 'win32'`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('"win32" === process.platform (reversed) → windows', () => {
const ast = parse(`'win32' === process.platform`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('process.platform !== "win32" → not-windows', () => {
const ast = parse(`process.platform !== 'win32'`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'not-windows');
});
test('os.platform() === "win32" → windows', () => {
const ast = parse(`os.platform() === 'win32'`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('os.platform() !== "win32" → not-windows', () => {
const ast = parse(`os.platform() !== 'win32'`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'not-windows');
});
test('isWindows identifier → windows', () => {
const ast = parse(`isWindows`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('IS_WINDOWS identifier → windows', () => {
const ast = parse(`IS_WINDOWS`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('isWin identifier → windows', () => {
const ast = parse(`isWin`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('onWindows identifier → windows', () => {
const ast = parse(`onWindows`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'windows');
});
test('!isWindows → not-windows', () => {
const ast = parse(`!isWindows`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), 'not-windows');
});
test('unrelated expression → null', () => {
const ast = parse(`x === 'linux'`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), null);
});
test('bare identifier "result" → null', () => {
const ast = parse(`result`);
const node = ast.body[0].expression;
assert.strictEqual(classifyPlatformTest(node), null);
});
});
// ─── isWindowsExcludedNode via Linter ────────────────────────────────────────
// We use the Linter + a custom rule to get real sourceCode with ancestors.
/**
* Build a mini rule that collects data about CallExpression nodes named
* "assert.equal" and checks isWindowsExcludedNode on them.
*/
function buildCollectorRule() {
return {
create(context) {
const sourceCode = context.sourceCode;
const results = [];
return {
CallExpression(node) {
if (
node.callee.type === 'MemberExpression' &&
node.callee.object.name === 'assert' &&
node.callee.property.name === 'equal'
) {
results.push(isWindowsExcludedNode(node, sourceCode));
}
},
'Program:exit'() {
context.report({ node: sourceCode.ast, messageId: 'result', data: { results: JSON.stringify(results) } });
},
};
},
meta: { type: 'suggestion', schema: [], messages: { result: '{{results}}' } },
};
}
function runCollector(code) {
const linter = new Linter({ configType: 'flat' });
const messages = linter.verify(
code,
[{ plugins: { t: { rules: { collector: buildCollectorRule() } } }, rules: { 't/collector': 'warn' }, languageOptions: { ecmaVersion: 2022, sourceType: 'script' } }],
{ filename: 'tests/x.test.cjs' }
);
// The rule emits exactly one message (Program:exit) with results as JSON
const msg = messages.find(m => m.ruleId === 't/collector');
if (!msg) return [];
return JSON.parse(msg.message);
}
describe('isWindowsExcludedNode — if (!windows) { assert } shape', () => {
test('assert inside if (process.platform !== "win32") block → excluded=true', () => {
const code = `
if (process.platform !== 'win32') {
assert.equal(path.join(a, b), '/x/y');
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('assert inside else of if (process.platform === "win32") block → excluded=true', () => {
const code = `
if (process.platform === 'win32') {
doWindows();
} else {
assert.equal(path.join(a, b), '/x/y');
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('assert NOT inside any guard → excluded=false', () => {
const code = `assert.equal(path.join(a, b), '/x/y');`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false]);
});
});
describe('isWindowsExcludedNode — early-return guard shape', () => {
test('if (process.platform === "win32") return; assert.equal(...) → excluded=true', () => {
const code = `
function test() {
if (process.platform === 'win32') return;
assert.equal(path.join(a, b), '/x/y');
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('if (process.platform === "win32") return t.skip(); assert.equal → excluded=true', () => {
const code = `
function test(t) {
if (process.platform === 'win32') return t.skip('no windows');
assert.equal(path.join(a, b), '/x/y');
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('guard appears AFTER the assert → excluded=false', () => {
const code = `
function test() {
assert.equal(path.join(a, b), '/x/y');
if (process.platform === 'win32') return;
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false]);
});
});
describe('isWindowsExcludedNode — hoisted isWindows guard shape', () => {
test('const isWindows = process.platform === "win32"; if (!isWindows) assert.equal → excluded=true', () => {
const code = `
const isWindows = process.platform === 'win32';
if (!isWindows) assert.equal(path.join(a, b), '/x/y');
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('const isWindows = …; if (isWindows) {} else { assert.equal } → excluded=true', () => {
const code = `
const isWindows = process.platform === 'win32';
if (isWindows) { doWindowsThing(); } else { assert.equal(path.join(a,b), '/x/y'); }
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
});
describe('isWindowsExcludedNode — arbitrary-named hoisted boolean (real hoisting)', () => {
test('const winFlag = process.platform === "win32"; if (!winFlag) assert.equal → excluded=true', () => {
const code = `
function test() {
const winFlag = process.platform === 'win32';
if (!winFlag) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('const winFlag = process.platform === "win32"; if (winFlag) return; assert.equal → excluded=true', () => {
const code = `
function test() {
const winFlag = process.platform === 'win32';
if (winFlag) return;
assert.equal(path.join(a, b), '/x/y');
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('unrelated variable used as guard is NOT excluded', () => {
const code = `
function test() {
const debugMode = true;
if (!debugMode) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false]);
});
test('winFlag declared AFTER the assert is NOT a guard → excluded=false', () => {
const code = `
function test() {
assert.equal(path.join(a, b), '/x/y');
const winFlag = process.platform === 'win32';
if (!winFlag) { doSomething(); }
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false]);
});
});
// ─── C2: early-return guard must climb ancestor blocks ────────────────────────
describe('C2 — early-return guard climbs ancestor blocks', () => {
test('C2: early-return in outer block before nested if-block → excluded=true', () => {
// The guard is in the function body; assert.equal is inside a nested if-block.
// Before the fix, _hasEarlyWindowsReturnBefore only checked the innermost block.
const code = `
function test() {
if (process.platform === 'win32') return;
if (cond) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true]);
});
test('C2: no early-return at all → excluded=false', () => {
const code = `
function test() {
if (cond) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false]);
});
});
// ─── C3: binding-aware identifier classification ──────────────────────────────
describe('C3 — binding-aware identifier classification', () => {
test('C3 case 1: const isWindows = false; if (!isWindows) assert.equal → excluded=false (FLAGGED)', () => {
// isWindows is in WINDOWS_BOOL_NAMES but its binding is `false`, not a platform test.
const code = `
function test() {
const isWindows = false;
if (!isWindows) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false], 'const isWindows = false should not be treated as a platform guard');
});
test('C3 case 2: let w = platform===win32; w = false; if (!w) assert.equal → excluded=false (FLAGGED)', () => {
// w starts as a platform test but is reassigned — should NOT be trusted.
const code = `
function test() {
let w = process.platform === 'win32';
w = false;
if (!w) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false], 'reassigned variable should not be treated as a platform guard');
});
test('C3 case 3: inner shadow const w = false wins over outer const w = platform test → excluded=false (FLAGGED)', () => {
// The inner const w = false shadows the outer const w = platform test.
const code = `
function test() {
const w = process.platform === 'win32';
{
const w = false;
if (!w) {
assert.equal(path.join(a, b), '/x/y');
}
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [false], 'inner shadow (w=false) should win over outer platform test');
});
test('C3 case 4: const w = platform test; if (!w) assert.equal → excluded=true (genuine guard)', () => {
// The canonical case — should still work.
const code = `
function test() {
const w = process.platform === 'win32';
if (!w) {
assert.equal(path.join(a, b), '/x/y');
}
}
`;
const results = runCollector(code);
assert.deepStrictEqual(results, [true], 'genuine platform guard should suppress the report');
});
});