Repository navigation
Expand file tree
/
Copy pathvalidate_github_communication_test_budget.test.ts
More file actions
82 lines (70 loc) · 3.31 KB
/
Copy pathvalidate_github_communication_test_budget.test.ts
File metadata and controls
82 lines (70 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
interface CommunicationBudgetLedger {
readonly version: number;
readonly baseline: string;
readonly budgets: readonly {
readonly id: string;
readonly spec: string;
readonly requiredCases: number;
readonly allocatedCases: number;
readonly files: readonly { readonly path: string; readonly qualifyingCases: number }[];
}[];
}
interface CommunicationBudgetValidator {
countQualifyingDeclarations(root: string, baseline: string, testPath: string): number;
readLedger(root?: string): CommunicationBudgetLedger;
validateCommunicationTestBudget(root: string, ledger: CommunicationBudgetLedger): string[];
}
const {
countQualifyingDeclarations,
readLedger,
validateCommunicationTestBudget,
} = require('../../../scripts/validate-github-communication-test-budget.cjs') as CommunicationBudgetValidator;
function mutableLedger(): any {
return structuredClone(readLedger(process.cwd()));
}
describe('GitHub communication test-budget validator', () => {
it('keeps both specification budgets above target with disjoint test files', () => {
const ledger = readLedger(process.cwd());
expect(validateCommunicationTestBudget(process.cwd(), ledger)).toEqual([]);
expect(ledger.budgets.map(budget => ({
id: budget.id,
required: budget.requiredCases,
}))).toEqual([
{ id: 'semantic-github-publication', required: 135 },
{ id: 'repository-locale-localization', required: 146 },
]);
for (const budget of ledger.budgets) {
expect(budget.allocatedCases).toBe(budget.files.reduce((total, entry) => total + entry.qualifyingCases, 0));
expect(budget.allocatedCases).toBeGreaterThanOrEqual(budget.requiredCases);
for (const entry of budget.files) {
expect(countQualifyingDeclarations(process.cwd(), ledger.baseline, entry.path))
.toBeGreaterThanOrEqual(entry.qualifyingCases);
}
}
});
it('rejects cross-budget test-file double counting', () => {
const ledger = mutableLedger();
ledger.budgets[1].files[0].path = ledger.budgets[0].files[0].path;
expect(validateCommunicationTestBudget(process.cwd(), ledger)).toContain(
`${ledger.budgets[0].files[0].path} is allocated to more than one communication budget.`,
);
});
it('rejects an allocation total that no longer matches its evidence rows', () => {
const ledger = mutableLedger();
const total = ledger.budgets[0].files.reduce((sum: number, entry: { qualifyingCases: number }) => sum + entry.qualifyingCases, 0);
ledger.budgets[0].allocatedCases -= 1;
expect(validateCommunicationTestBudget(process.cwd(), ledger)).toContain(
`semantic-github-publication allocatedCases is ${total - 1} but its file allocation totals ${total}.`,
);
});
it('rejects unsafe paths and case allocations larger than the retained tests', () => {
const ledger = mutableLedger();
ledger.budgets[0].files[0] = { path: '../outside.test.ts', qualifyingCases: 999 };
ledger.budgets[0].files[1].qualifyingCases = 999;
const errors = validateCommunicationTestBudget(process.cwd(), ledger);
expect(errors).toContain('semantic-github-publication has an invalid test path: ../outside.test.ts.');
expect(errors).toContain(
'src/domain/__tests__/git_object_id.test.ts has 2 qualifying test declarations since 0bb83b75^, below its allocation of 999.',
);
});
});