mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-09 01:16:15 -08:00
* chore(lint): hold tests to their own max-lines ceiling The flat 400-line cap treated a spec like a component. A spec is a flat list of independent cases, so hitting the cap there produces arbitrary `-2.spec.ts` splits and hides coverage instead of surfacing design debt — 65 of the 138 files over the limit were tests. Production code keeps 400. Tests (`**/*.spec.ts`, `**/*.e2e.ts`, and everything under `apps/*-e2e/**`) get 1200. Blank lines and comments no longer count, so a docblock can't be the reason a file must be split. Both limits now live in tools/eslint/max-lines-config.mjs, imported by eslint.config.mjs and the baseline generator alike. The generator decides who belongs on the list by running ESLint's own max-lines rule instead of counting lines itself — a private reimplementation would disagree with the rule the moment either side changed (a `//` inside a template literal is enough) and yield a baseline that turns CI red while looking correct. The baseline drops 126 -> 68 entries with nothing added, and six now-dead `eslint-disable max-lines` directives are removed. A new eslint-tools test asserts the committed baseline still matches what the generator produces, so a stale entry or a forgotten regeneration fails CI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(lint): classify eslint-tools in the coverage policy A project with a `test` target must be assigned a coverage tier, so adding eslint-tools broke `coverage:policy:check` before the unit suite even ran. Tier B alongside packaging and release-tools: these are Node tests over lint tooling, and a coverage percentage across a generated list would not mean anything. CI runs Tier B/C through its own `--run-non-tier-a` step, so the baseline-consistency test executes there rather than being skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
76 lines
2.5 KiB
JavaScript
76 lines
2.5 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { describe, it } from 'node:test';
|
|
|
|
import { maxLinesBaseline } from './max-lines-baseline.mjs';
|
|
import {
|
|
BASELINE_PATH,
|
|
computeOffenders,
|
|
renderBaseline,
|
|
} from './generate-max-lines-baseline.mjs';
|
|
import {
|
|
MAX_LINES_OPTIONS,
|
|
MAX_LINES_PROD,
|
|
MAX_LINES_TEST,
|
|
TEST_FILE_GLOBS,
|
|
} from './max-lines-config.mjs';
|
|
|
|
describe('max-lines baseline', () => {
|
|
it('matches what the generator produces', () => {
|
|
// The whole point of the baseline is that it lists files which really do
|
|
// exceed the limit. A stale entry silently exempts a file that was
|
|
// already split, and a missing entry turns CI red on an unrelated PR.
|
|
assert.equal(
|
|
readFileSync(BASELINE_PATH, 'utf8'),
|
|
renderBaseline(computeOffenders()),
|
|
'Baseline is out of date — run: node tools/eslint/generate-max-lines-baseline.mjs'
|
|
);
|
|
});
|
|
|
|
it('never lists a file twice', () => {
|
|
assert.equal(
|
|
new Set(maxLinesBaseline).size,
|
|
maxLinesBaseline.length,
|
|
'baseline contains duplicate entries'
|
|
);
|
|
});
|
|
|
|
it('stays sorted so regenerating produces a reviewable diff', () => {
|
|
assert.deepEqual(
|
|
maxLinesBaseline,
|
|
[...maxLinesBaseline].sort((a, b) => a.localeCompare(b))
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('max-lines config', () => {
|
|
it('gives tests more headroom than production code', () => {
|
|
// A spec is a flat list of independent cases; holding it to the
|
|
// production ceiling produces arbitrary `-2.spec.ts` splits.
|
|
assert.ok(
|
|
MAX_LINES_TEST > MAX_LINES_PROD,
|
|
`expected test ceiling (${MAX_LINES_TEST}) above production (${MAX_LINES_PROD})`
|
|
);
|
|
});
|
|
|
|
it('does not count comments or blank lines', () => {
|
|
// This repo mandates documentation, so a docblock must never be the
|
|
// reason a file has to be split.
|
|
assert.equal(MAX_LINES_OPTIONS.skipComments, true);
|
|
assert.equal(MAX_LINES_OPTIONS.skipBlankLines, true);
|
|
});
|
|
|
|
it('routes specs, e2e specs and e2e apps to the test ceiling', () => {
|
|
for (const glob of [
|
|
'**/*.spec.ts',
|
|
'**/*.e2e.ts',
|
|
'apps/*-e2e/**/*.ts',
|
|
]) {
|
|
assert.ok(
|
|
TEST_FILE_GLOBS.includes(glob),
|
|
`expected ${glob} among the test globs`
|
|
);
|
|
}
|
|
});
|
|
});
|