mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-02 17:40:02 +02:00
71 lines
3.6 KiB
TypeScript
71 lines
3.6 KiB
TypeScript
import { describe, expect, test } from 'bun:test';
|
|
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
import { compareDiagnostics, parseDiagnostics, readBaseline } from '../scripts/typecheck-test';
|
|
|
|
const output = [
|
|
"test/a.test.ts(3,5): error TS2339: Property 'questions' does not exist on type 'Plan'.",
|
|
"test/a.test.ts(9,5): error TS2339: Property 'questions' does not exist on type 'Plan'.",
|
|
'test/b.test.ts(1,1): error TS2345: Argument of type \'string\' is not assignable to parameter of type \'number\'.',
|
|
" Type 'string' is not assignable to type 'number'.",
|
|
'Found 3 errors.',
|
|
].join('\n');
|
|
|
|
describe('test typecheck ratchet', () => {
|
|
test('counts repeated identical diagnostics instead of collapsing them', () => {
|
|
expect(parseDiagnostics(output)).toEqual({
|
|
"test/a.test.ts\tTS2339\tProperty 'questions' does not exist on type 'Plan'.": 2,
|
|
"test/b.test.ts\tTS2345\tArgument of type 'string' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'.": 1,
|
|
});
|
|
});
|
|
|
|
test('strips the checkout root from messages so every clone shares one identity', () => {
|
|
const line = "test/d.test.ts(1,1): error TS2322: Type 'import(\"/tmp/clone-a/lib/x\").A' is not assignable to type 'B'.";
|
|
const a = parseDiagnostics(line, '/tmp/clone-a');
|
|
const b = parseDiagnostics(line.replace('/tmp/clone-a', '/home/ci/work/gstack'), '/home/ci/work/gstack');
|
|
expect(Object.keys(a)).toEqual(Object.keys(b));
|
|
expect(Object.keys(a)[0]).toContain('import(\"lib/x\")');
|
|
});
|
|
|
|
test('ignores line and column so moving code does not churn the baseline', () => {
|
|
const moved = output.replace('(3,5)', '(30,7)').replace('(9,5)', '(90,1)');
|
|
expect(parseDiagnostics(moved)).toEqual(parseDiagnostics(output));
|
|
});
|
|
|
|
test('a duplicate of an existing diagnostic and a new identity both fail', () => {
|
|
const baseline = parseDiagnostics(output);
|
|
const current = parseDiagnostics(output + "\ntest/a.test.ts(12,5): error TS2339: Property 'questions' does not exist on type 'Plan'.\ntest/c.test.ts(1,1): error TS2304: Cannot find name 'join'.");
|
|
const { added, fixed } = compareDiagnostics(baseline, current);
|
|
expect(added.map(d => [d.identity.split('\t')[0], d.baseline, d.current])).toEqual([
|
|
['test/a.test.ts', 2, 3],
|
|
['test/c.test.ts', 0, 1],
|
|
]);
|
|
expect(fixed).toEqual([]);
|
|
});
|
|
|
|
test('a fixed diagnostic is reported so the smaller allowance gets locked in', () => {
|
|
const baseline = parseDiagnostics(output);
|
|
const { added, fixed } = compareDiagnostics(baseline, parseDiagnostics(output.split('\n').slice(1).join('\n')));
|
|
expect(added).toEqual([]);
|
|
expect(fixed).toHaveLength(1);
|
|
expect(fixed[0]).toMatchObject({ baseline: 2, current: 1 });
|
|
});
|
|
|
|
test('a missing or malformed baseline fails closed with the regeneration command', () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'typecheck-baseline-'));
|
|
try {
|
|
expect(() => readBaseline(path.join(dir, 'missing.json'))).toThrow('bun run typecheck:test --write-baseline');
|
|
fs.writeFileSync(path.join(dir, 'bad.json'), JSON.stringify({ version: 1, diagnostics: { x: 0 } }));
|
|
expect(() => readBaseline(path.join(dir, 'bad.json'))).toThrow('malformed');
|
|
} finally {
|
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('the committed baseline is readable and non-empty', () => {
|
|
const baseline = readBaseline(path.join(import.meta.dir, '..', 'scripts', 'typecheck-test-baseline.json'));
|
|
expect(Object.keys(baseline).length).toBeGreaterThan(0);
|
|
});
|
|
});
|