|
1 | 1 | import { describe, expect, it } from 'vitest'; |
2 | | - |
3 | | -/** |
4 | | - * The version guard logic extracted for testability. |
5 | | - * The real guard lives at the top of src/index.ts as imperative code. |
6 | | - * These tests verify the parsing and threshold logic. |
7 | | - */ |
8 | | - |
9 | | -function parseMajorVersion(nodeVersion: string): number { |
10 | | - return Number(nodeVersion.split('.')[0]); |
11 | | -} |
12 | | - |
13 | | -function shouldRejectVersion(nodeVersion: string): boolean { |
14 | | - return parseMajorVersion(nodeVersion) < 20; |
15 | | -} |
16 | | - |
17 | | -describe('Node.js version guard logic', () => { |
18 | | - it('rejects Node 18.x', () => { |
19 | | - expect(shouldRejectVersion('18.19.1')).toBe(true); |
20 | | - }); |
21 | | - |
22 | | - it('rejects Node 16.x', () => { |
23 | | - expect(shouldRejectVersion('16.20.2')).toBe(true); |
| 2 | +import { |
| 3 | + MIN_SUPPORTED_NODE_MAJOR, |
| 4 | + parseMajorVersion, |
| 5 | + shouldRejectNodeVersion, |
| 6 | +} from './version-guard.js'; |
| 7 | + |
| 8 | +// These tests exercise the REAL guard functions used by src/index.ts, |
| 9 | +// imported here rather than re-declared, so a regression in the source is |
| 10 | +// actually caught. |
| 11 | + |
| 12 | +describe('parseMajorVersion', () => { |
| 13 | + it('extracts the leading major from a semver string', () => { |
| 14 | + expect(parseMajorVersion('20.11.1')).toBe(20); |
| 15 | + expect(parseMajorVersion('18.0.0')).toBe(18); |
| 16 | + expect(parseMajorVersion('22.3.0')).toBe(22); |
24 | 17 | }); |
25 | 18 |
|
26 | | - it('rejects Node 14.x', () => { |
27 | | - expect(shouldRejectVersion('14.21.3')).toBe(true); |
| 19 | + it('returns NaN for a non-numeric version string', () => { |
| 20 | + expect(Number.isNaN(parseMajorVersion('not-a-version'))).toBe(true); |
28 | 21 | }); |
| 22 | +}); |
29 | 23 |
|
30 | | - it('accepts Node 20.x', () => { |
31 | | - expect(shouldRejectVersion('20.11.0')).toBe(false); |
| 24 | +describe('shouldRejectNodeVersion', () => { |
| 25 | + it('rejects majors below the supported floor', () => { |
| 26 | + expect(shouldRejectNodeVersion('18.19.1')).toBe(true); |
| 27 | + expect(shouldRejectNodeVersion('16.20.2')).toBe(true); |
| 28 | + expect(shouldRejectNodeVersion('14.21.3')).toBe(true); |
32 | 29 | }); |
33 | 30 |
|
34 | | - it('accepts Node 22.x', () => { |
35 | | - expect(shouldRejectVersion('22.1.0')).toBe(false); |
| 31 | + it('accepts the supported floor and above', () => { |
| 32 | + expect(shouldRejectNodeVersion('20.0.0')).toBe(false); |
| 33 | + expect(shouldRejectNodeVersion('20.11.0')).toBe(false); |
| 34 | + expect(shouldRejectNodeVersion('21.0.0')).toBe(false); |
| 35 | + expect(shouldRejectNodeVersion('22.1.0')).toBe(false); |
36 | 36 | }); |
37 | 37 |
|
38 | | - it('accepts Node 21.x', () => { |
39 | | - expect(shouldRejectVersion('21.0.0')).toBe(false); |
| 38 | + it(`treats exactly ${MIN_SUPPORTED_NODE_MAJOR} as supported (boundary)`, () => { |
| 39 | + expect(shouldRejectNodeVersion(`${MIN_SUPPORTED_NODE_MAJOR}.0.0`)).toBe(false); |
| 40 | + expect(shouldRejectNodeVersion(`${MIN_SUPPORTED_NODE_MAJOR - 1}.9.9`)).toBe(true); |
40 | 41 | }); |
41 | 42 |
|
42 | | - it('parses major version correctly from semver string', () => { |
43 | | - expect(parseMajorVersion('20.11.1')).toBe(20); |
44 | | - expect(parseMajorVersion('18.0.0')).toBe(18); |
45 | | - expect(parseMajorVersion('22.3.0')).toBe(22); |
| 43 | + it('does not reject an unparseable version (guard never blocks on garbage)', () => { |
| 44 | + expect(shouldRejectNodeVersion('not-a-version')).toBe(false); |
46 | 45 | }); |
47 | 46 |
|
48 | 47 | it('the running Node satisfies the guard (meta-test)', () => { |
49 | | - // This test is running on Node >= 20, so it must pass the guard. |
50 | | - expect(shouldRejectVersion(process.versions.node)).toBe(false); |
| 48 | + // The test suite itself runs on a supported Node, so the guard must pass. |
| 49 | + expect(shouldRejectNodeVersion(process.versions.node)).toBe(false); |
51 | 50 | }); |
52 | 51 | }); |
0 commit comments