|
1 | | -import type { Engines } from 'fast-npm-meta' |
2 | 1 | import { describe, expect, it } from 'vitest' |
3 | | -import { checkEngineMismatch } from '../../src/providers/diagnostics/rules/engine-mismatch' |
| 2 | +import { checkEngineMismatch, resolveEngineMismatches } from '../../src/providers/diagnostics/rules/engine-mismatch' |
4 | 3 | import { createContext } from './context' |
5 | 4 |
|
6 | | -function createEngineMismatchContext( |
7 | | - engines: Engines | undefined, |
8 | | - dependencyEngines: Engines | undefined, |
9 | | -) { |
10 | | - return createContext({ |
11 | | - name: 'foo', |
12 | | - version: '^1.0.0', |
13 | | - distTags: { latest: '1.0.0' }, |
14 | | - versionsMeta: { |
15 | | - '1.0.0': dependencyEngines ? { engines: dependencyEngines } : {}, |
16 | | - }, |
17 | | - engines, |
18 | | - }) |
19 | | -} |
20 | | - |
21 | | -describe('checkEngineMismatch', () => { |
22 | | - it('should flag when engine ranges do not overlap', async () => { |
23 | | - const ctx = createEngineMismatchContext( |
| 5 | +describe('resolveEngineMismatches', () => { |
| 6 | + it('should flag when engine ranges do not overlap', () => { |
| 7 | + expect(resolveEngineMismatches( |
24 | 8 | { node: '^18.0.0' }, |
25 | 9 | { node: '>=20' }, |
26 | | - ) |
27 | | - const result = await checkEngineMismatch(ctx) |
28 | | - |
29 | | - expect(result).toBeDefined() |
30 | | - expect(result!.code).toMatchObject({ value: 'engine-mismatch' }) |
31 | | - expect(result!.message).toContain('requires ">=20", but package supports "^18.0.0"') |
| 10 | + )).toMatchObject([ |
| 11 | + { |
| 12 | + engine: 'node', |
| 13 | + packageRange: '^18.0.0', |
| 14 | + dependencyRange: '>=20', |
| 15 | + hasIntersection: false, |
| 16 | + }, |
| 17 | + ]) |
32 | 18 | }) |
33 | 19 |
|
34 | | - it('should flag when engine ranges overlap but are not fully compatible', async () => { |
35 | | - const ctx = createEngineMismatchContext( |
| 20 | + it('should flag when engine ranges overlap but are not fully compatible', () => { |
| 21 | + expect(resolveEngineMismatches( |
36 | 22 | { node: '>=20', npm: '>=8 <11' }, |
37 | 23 | { node: '>=18', npm: '>=10 <12' }, |
38 | | - ) |
39 | | - const result = await checkEngineMismatch(ctx) |
40 | | - |
41 | | - expect(result).toBeDefined() |
42 | | - expect(result!.message).toContain('npm') |
43 | | - expect(result!.message).toContain('partial overlap') |
| 24 | + )).toMatchObject([{ |
| 25 | + engine: 'npm', |
| 26 | + hasIntersection: true, |
| 27 | + }]) |
44 | 28 | }) |
45 | 29 |
|
46 | | - it('should include multiple engine mismatches in one diagnostic', async () => { |
47 | | - const ctx = createEngineMismatchContext( |
| 30 | + it('should include multiple engine mismatches', () => { |
| 31 | + expect(resolveEngineMismatches( |
48 | 32 | { node: '^18.0.0', npm: '^9.0.0' }, |
49 | 33 | { node: '>=20', npm: '>=10' }, |
50 | | - ) |
51 | | - const result = await checkEngineMismatch(ctx) |
52 | | - |
53 | | - expect(result).toBeDefined() |
54 | | - expect(result!.message).toContain('node') |
55 | | - expect(result!.message).toContain('npm') |
| 34 | + )).toMatchObject([ |
| 35 | + { engine: 'node' }, |
| 36 | + { engine: 'npm' }, |
| 37 | + ]) |
56 | 38 | }) |
57 | 39 |
|
58 | | - it('should not flag when package ranges are compatible', async () => { |
59 | | - const ctx = createEngineMismatchContext( |
| 40 | + it('should not flag when package ranges are compatible', () => { |
| 41 | + expect(resolveEngineMismatches( |
60 | 42 | { node: '>=20', npm: '>=10' }, |
61 | 43 | { node: '>=18', npm: '>=10' }, |
62 | | - ) |
63 | | - |
64 | | - expect(await checkEngineMismatch(ctx)).toBeUndefined() |
| 44 | + )).toEqual([]) |
65 | 45 | }) |
66 | 46 |
|
67 | | - it('should not flag when package does not declare the dependency engine', async () => { |
68 | | - const ctx = createEngineMismatchContext( |
| 47 | + it('should not flag when package does not declare the dependency engine', () => { |
| 48 | + expect(resolveEngineMismatches( |
69 | 49 | { node: '>=20' }, |
70 | 50 | { npm: '>=10' }, |
71 | | - ) |
| 51 | + )).toEqual([]) |
| 52 | + }) |
72 | 53 |
|
73 | | - expect(await checkEngineMismatch(ctx)).toBeUndefined() |
| 54 | + it('should skip engines with non-standard semver values', () => { |
| 55 | + expect(resolveEngineMismatches( |
| 56 | + { node: '>=18' }, |
| 57 | + { node: 'lts' }, |
| 58 | + )).toEqual([]) |
74 | 59 | }) |
| 60 | +}) |
75 | 61 |
|
76 | | - it('should not flag when either engines is missing', async () => { |
77 | | - expect(await checkEngineMismatch(createEngineMismatchContext(undefined, { node: '>=18' }))).toBeUndefined() |
78 | | - expect(await checkEngineMismatch(createEngineMismatchContext({ node: '>=18' }, undefined))).toBeUndefined() |
| 62 | +describe('checkEngineMismatch', () => { |
| 63 | + it('should format a diagnostic when mismatches exist', async () => { |
| 64 | + const result = await checkEngineMismatch(createContext({ |
| 65 | + name: 'foo', |
| 66 | + version: '^1.0.0', |
| 67 | + distTags: { latest: '1.0.0' }, |
| 68 | + versionsMeta: { |
| 69 | + '1.0.0': { |
| 70 | + engines: { node: '>=20' }, |
| 71 | + }, |
| 72 | + }, |
| 73 | + engines: { node: '^18.0.0' }, |
| 74 | + })) |
| 75 | + |
| 76 | + expect(result).toBeDefined() |
| 77 | + expect(result!.code).toMatchObject({ value: 'engine-mismatch' }) |
| 78 | + expect(result!.message).toContain('requires ">=20", but package supports "^18.0.0"') |
79 | 79 | }) |
80 | 80 |
|
81 | | - it('should skip engines with non-standard semver values', async () => { |
82 | | - const ctx = createEngineMismatchContext( |
83 | | - { node: '>=18' }, |
84 | | - { node: 'lts' }, |
85 | | - ) |
| 81 | + it('should not flag when either engines is missing', async () => { |
| 82 | + expect(await checkEngineMismatch(createContext({ |
| 83 | + name: 'foo', |
| 84 | + version: '^1.0.0', |
| 85 | + distTags: { latest: '1.0.0' }, |
| 86 | + versionsMeta: { |
| 87 | + '1.0.0': { engines: { node: '>=18' } }, |
| 88 | + }, |
| 89 | + }))).toBeUndefined() |
86 | 90 |
|
87 | | - expect(await checkEngineMismatch(ctx)).toBeUndefined() |
| 91 | + expect(await checkEngineMismatch(createContext({ |
| 92 | + name: 'foo', |
| 93 | + version: '^1.0.0', |
| 94 | + distTags: { latest: '1.0.0' }, |
| 95 | + versionsMeta: { |
| 96 | + '1.0.0': {}, |
| 97 | + }, |
| 98 | + engines: { node: '>=18' }, |
| 99 | + }))).toBeUndefined() |
88 | 100 | }) |
89 | 101 | }) |
0 commit comments