Skip to content

Commit a779adc

Browse files
committed
test: add duplicates tests
1 parent 1ad7868 commit a779adc

File tree

2 files changed

+237
-0
lines changed

2 files changed

+237
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`scanForDuplicates > should report duplicates when threshold is exceeded 1`] = `
4+
[
5+
"## ⚠️ Duplicate Dependencies (threshold: 1)
6+
7+
| 📦 Package | 📋 Versions |
8+
| --- | --- |
9+
| package-a | <details><summary>2 versions</summary><br><ul><li>[email protected]<ul><li>**[email protected]**</li></ul></li></ul><br><ul><li>[email protected]<ul><li>[email protected]<ul><li>**[email protected]**</li></ul></li></ul></li></ul><br></details> |
10+
11+
💡 To find out what depends on a specific package, run: \`npm ls example-package\`",
12+
]
13+
`;
14+
15+
exports[`scanForDuplicates > should truncate long parent paths in the report 1`] = `
16+
[
17+
"## ⚠️ Duplicate Dependencies (threshold: 1)
18+
19+
| 📦 Package | 📋 Versions |
20+
| --- | --- |
21+
| package-a | <details><summary>2 versions</summary><br><ul><li>[email protected]<ul><li>**[email protected]**</li></ul></li></ul><br><ul><li>[email protected]<ul><li>[email protected]<ul><li>...<ul><li>[email protected]<ul><li>[email protected]<ul><li>**[email protected]**</li></ul></li></ul></li></ul></li></ul></li></ul></li></ul><br></details> |
22+
23+
💡 To find out what depends on a specific package, run: \`npm ls example-package\`",
24+
]
25+
`;

test/checks/duplicates_test.ts

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import {describe, expect, it} from 'vitest';
2+
import {scanForDuplicates} from '../../src/checks/duplicates.js';
3+
import type {ParsedLockFile, ParsedDependency} from 'lockparse';
4+
5+
describe('scanForDuplicates', () => {
6+
it('should do nothing if no duplicates are found', () => {
7+
const messages: string[] = [];
8+
const threshold = 1;
9+
const dependencyMap = new Map<string, Set<string>>([
10+
['package-a', new Set(['1.0.0'])],
11+
['package-b', new Set(['2.0.0'])]
12+
]);
13+
const lockfilePath = 'package-lock.json';
14+
const lockfile: ParsedLockFile = {
15+
type: 'npm',
16+
packages: [],
17+
root: {
18+
name: 'root-package',
19+
version: '1.0.0',
20+
dependencies: [],
21+
devDependencies: [],
22+
optionalDependencies: [],
23+
peerDependencies: []
24+
}
25+
};
26+
27+
scanForDuplicates(
28+
messages,
29+
threshold,
30+
dependencyMap,
31+
lockfilePath,
32+
lockfile
33+
);
34+
35+
expect(messages).toHaveLength(0);
36+
});
37+
38+
it('should report duplicates when threshold is exceeded', () => {
39+
const messages: string[] = [];
40+
const threshold = 1;
41+
const dependencyMap = new Map<string, Set<string>>([
42+
['package-a', new Set(['1.0.0', '1.1.0'])],
43+
['package-b', new Set(['2.0.0'])]
44+
]);
45+
const lockfilePath = 'package-lock.json';
46+
const packageA: ParsedDependency = {
47+
name: 'package-a',
48+
version: '1.0.0',
49+
dependencies: [],
50+
devDependencies: [],
51+
optionalDependencies: [],
52+
peerDependencies: []
53+
};
54+
const packageAAlt: ParsedDependency = {
55+
name: 'package-a',
56+
version: '1.1.0',
57+
dependencies: [],
58+
devDependencies: [],
59+
optionalDependencies: [],
60+
peerDependencies: []
61+
};
62+
const packageB: ParsedDependency = {
63+
name: 'package-b',
64+
version: '2.0.0',
65+
dependencies: [packageAAlt],
66+
devDependencies: [],
67+
optionalDependencies: [],
68+
peerDependencies: []
69+
};
70+
const lockfile: ParsedLockFile = {
71+
type: 'npm',
72+
packages: [packageA, packageAAlt, packageB],
73+
root: {
74+
name: 'root-package',
75+
version: '1.0.0',
76+
dependencies: [packageA, packageB],
77+
devDependencies: [],
78+
optionalDependencies: [],
79+
peerDependencies: []
80+
}
81+
};
82+
83+
scanForDuplicates(
84+
messages,
85+
threshold,
86+
dependencyMap,
87+
lockfilePath,
88+
lockfile
89+
);
90+
91+
expect(messages).toMatchSnapshot();
92+
});
93+
94+
it('should do nothing when duplicates are below threshold', () => {
95+
const messages: string[] = [];
96+
const threshold = 2;
97+
const dependencyMap = new Map<string, Set<string>>([
98+
['package-a', new Set(['1.0.0', '1.1.0'])],
99+
['package-b', new Set(['2.0.0'])]
100+
]);
101+
const lockfilePath = 'package-lock.json';
102+
const packageA: ParsedDependency = {
103+
name: 'package-a',
104+
version: '1.0.0',
105+
dependencies: [],
106+
devDependencies: [],
107+
optionalDependencies: [],
108+
peerDependencies: []
109+
};
110+
const packageAAlt: ParsedDependency = {
111+
name: 'package-a',
112+
version: '1.1.0',
113+
dependencies: [],
114+
devDependencies: [],
115+
optionalDependencies: [],
116+
peerDependencies: []
117+
};
118+
const packageB: ParsedDependency = {
119+
name: 'package-b',
120+
version: '2.0.0',
121+
dependencies: [packageAAlt],
122+
devDependencies: [],
123+
optionalDependencies: [],
124+
peerDependencies: []
125+
};
126+
const lockfile: ParsedLockFile = {
127+
type: 'npm',
128+
packages: [packageA, packageAAlt, packageB],
129+
root: {
130+
name: 'root-package',
131+
version: '1.0.0',
132+
dependencies: [packageA, packageB],
133+
devDependencies: [],
134+
optionalDependencies: [],
135+
peerDependencies: []
136+
}
137+
};
138+
139+
scanForDuplicates(
140+
messages,
141+
threshold,
142+
dependencyMap,
143+
lockfilePath,
144+
lockfile
145+
);
146+
147+
expect(messages).toHaveLength(0);
148+
});
149+
150+
it('should truncate long parent paths in the report', () => {
151+
const messages: string[] = [];
152+
const threshold = 1;
153+
const dependencyMap = new Map<string, Set<string>>([
154+
['package-a', new Set(['1.0.0', '1.1.0'])]
155+
]);
156+
const lockfilePath = 'package-lock.json';
157+
const longPath: ParsedDependency[] = [];
158+
for (let i = 0; i < 20; i++) {
159+
longPath.push({
160+
name: `package-${i}`,
161+
version: '1.0.0',
162+
dependencies: [],
163+
devDependencies: [],
164+
optionalDependencies: [],
165+
peerDependencies: []
166+
});
167+
}
168+
const packageA: ParsedDependency = {
169+
name: 'package-a',
170+
version: '1.0.0',
171+
dependencies: [],
172+
devDependencies: [],
173+
optionalDependencies: [],
174+
peerDependencies: []
175+
};
176+
const packageAAlt: ParsedDependency = {
177+
name: 'package-a',
178+
version: '1.1.0',
179+
dependencies: [],
180+
devDependencies: [],
181+
optionalDependencies: [],
182+
peerDependencies: []
183+
};
184+
for (let i = longPath.length - 1; i > 0; i--) {
185+
longPath[i - 1].dependencies.push(longPath[i]);
186+
}
187+
longPath[longPath.length - 1].dependencies.push(packageAAlt);
188+
189+
const lockfile: ParsedLockFile = {
190+
type: 'npm',
191+
packages: [packageA, packageAAlt, ...longPath],
192+
root: {
193+
name: 'root-package',
194+
version: '1.0.0',
195+
dependencies: [packageA, longPath[0]],
196+
devDependencies: [],
197+
optionalDependencies: [],
198+
peerDependencies: []
199+
}
200+
};
201+
202+
scanForDuplicates(
203+
messages,
204+
threshold,
205+
dependencyMap,
206+
lockfilePath,
207+
lockfile
208+
);
209+
210+
expect(messages).toMatchSnapshot();
211+
});
212+
});

0 commit comments

Comments
 (0)