pomanalyzer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ // This file contains utility functions for file operations, such as reading files.
2
+
3
+ import fs from 'fs';
4
+
5
+ /**
6
+ * Reads a file and returns its content.
7
+ * @param {string} filePath - The path to the file to read.
8
+ * @returns {Promise<string>} - A promise that resolves to the file content.
9
+ */
10
+ export const readFile = (filePath) => {
11
+ return new Promise((resolve, reject) => {
12
+ fs.readFile(filePath, 'utf-8', (err, data) => {
13
+ if (err) {
14
+ return reject(err);
15
+ }
16
+ resolve(data);
17
+ });
18
+ });
19
+ };
@@ -0,0 +1,14 @@
1
+
2
+ /**
3
+ * Prints a list of dependencies in a table format.
4
+ * @param {Array} dependencies - The list of dependencies to print.
5
+ * @param {string} title - The title to display before the table.
6
+ */
7
+ export const printTable = (dependencies, title) => {
8
+ if (dependencies && dependencies.length > 0) {
9
+ console.log(title);
10
+ console.table(dependencies);
11
+ } else {
12
+ console.log(`${title}: No data available.`);
13
+ }
14
+ };
@@ -0,0 +1,88 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Generates and saves an HTML table for the given dependencies.
6
+ * @param {Array} dependencies - The list of dependencies to include in the table.
7
+ * @param {Array} duplicateDependencies - The list of duplicate dependencies to include in the table.
8
+ * @param {string} title - The title to display before the table.
9
+ * @param {string} [folderPath='.'] - The folder path to save the HTML file.
10
+ */
11
+ export const printHTMLTable = (dependencies, duplicateDependencies, title, folderPath = '.') => {
12
+ // Construct a rich HTML report with embedded CSS.
13
+ const style = `<style>
14
+ body { font-family: Arial, sans-serif; margin: 20px; }
15
+ h2 { color: #333; }
16
+ table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
17
+ th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
18
+ th { background-color: #f2f2f2; }
19
+ .duplicate { background-color: #ffcccc; }
20
+ </style>`;
21
+
22
+ // Maven Dependencies table.
23
+ const depHeaders = Object.keys(dependencies[0] || {});
24
+ const dependenciesTable = `
25
+ <h2>${title}</h2>
26
+ <table>
27
+ <thead>
28
+ <tr>
29
+ ${depHeaders.map(key => `<th>${key}</th>`).join('')}
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ ${dependencies.map(dep => `
34
+ <tr>
35
+ ${Object.values(dep).map(val => `<td>${val}</td>`).join('')}
36
+ </tr>
37
+ `).join('')}
38
+ </tbody>
39
+ </table>
40
+ `;
41
+
42
+ // Duplicate Dependencies table (if any).
43
+ let duplicateTable = '';
44
+ if (duplicateDependencies && duplicateDependencies.length > 0) {
45
+ const dupHeaders = Object.keys(duplicateDependencies[0] || {});
46
+ duplicateTable = `
47
+ <h2>Duplicate Dependencies</h2>
48
+ <table>
49
+ <thead>
50
+ <tr>
51
+ ${dupHeaders.map(key => `<th>${key}</th>`).join('')}
52
+ </tr>
53
+ </thead>
54
+ <tbody>
55
+ ${duplicateDependencies.map(dep => `
56
+ <tr class="duplicate">
57
+ ${Object.values(dep).map(val => `<td>${val}</td>`).join('')}
58
+ </tr>
59
+ `).join('')}
60
+ </tbody>
61
+ </table>
62
+ `;
63
+ }
64
+
65
+ const htmlContent = `
66
+ <html>
67
+ <head>
68
+ <meta charset="UTF-8">
69
+ <title>${title} Report</title>
70
+ ${style}
71
+ </head>
72
+ <body>
73
+ ${dependenciesTable}
74
+ ${duplicateTable}
75
+ </body>
76
+ </html>
77
+ `;
78
+
79
+ const filePath = path.join(folderPath, `${title.replace(/\s+/g, '_')}_report.html`);
80
+
81
+ // Ensure the folder exists
82
+ if (!fs.existsSync(folderPath)) {
83
+ fs.mkdirSync(folderPath, { recursive: true });
84
+ }
85
+
86
+ fs.writeFileSync(filePath, htmlContent);
87
+ console.log(`HTML report saved to ${filePath}`);
88
+ };
@@ -0,0 +1,50 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Generates and saves a Markdown table for the given dependencies.
6
+ * @param {Array} dependencies - The list of dependencies to include in the table.
7
+ * @param {Array} duplicateDependencies - The list of duplicate dependencies to include in the table.
8
+ * @param {string} title - The title to display before the table.
9
+ * @param {string} [folderPath='.'] - The folder path to save the Markdown file.
10
+ */
11
+ export const printMarkdownTable = (dependencies, duplicateDependencies, title, folderPath = '.') => {
12
+ const depHeaders = Object.keys(dependencies[0] || {});
13
+ const dependenciesTable = `
14
+ ## ${title}
15
+
16
+ | ${depHeaders.join(' | ')} |
17
+ | ${depHeaders.map(() => '---').join(' | ')} |
18
+ ${dependencies.map(dep => `| ${Object.values(dep).join(' | ')} |`).join('\n')}
19
+ `;
20
+
21
+ let duplicateTable = '';
22
+ if (duplicateDependencies && duplicateDependencies.length > 0) {
23
+ const dupHeaders = Object.keys(duplicateDependencies[0] || {});
24
+ duplicateTable = `
25
+ ## Duplicate Dependencies
26
+
27
+ | ${dupHeaders.join(' | ')} |
28
+ | ${dupHeaders.map(() => '---').join(' | ')} |
29
+ ${duplicateDependencies.map(dep => `| ${Object.values(dep).join(' | ')} | <!-- duplicate row -->`).join('\n')}
30
+ `;
31
+ }
32
+
33
+ const markdownContent = `
34
+ # Report
35
+
36
+ ${dependenciesTable}
37
+
38
+ ${duplicateTable}
39
+ `;
40
+
41
+ const filePath = path.join(folderPath, `${title.replace(/\s+/g, '_')}_report.md`);
42
+
43
+ // Ensure the folder exists
44
+ if (!fs.existsSync(folderPath)) {
45
+ fs.mkdirSync(folderPath, { recursive: true });
46
+ }
47
+
48
+ fs.writeFileSync(filePath, markdownContent.trim());
49
+ console.log(`Markdown report saved to ${filePath}`);
50
+ };
@@ -0,0 +1,21 @@
1
+ // src/utils/xmlParser.js
2
+
3
+ import xml2js from 'xml2js';
4
+
5
+ /**
6
+ * Parses XML content and returns a JavaScript object.
7
+ * @param {string} xmlContent - The XML content to parse.
8
+ * @returns {Promise<Object>} - A promise that resolves to the parsed object.
9
+ */
10
+ export const parseXml = (xmlContent) => {
11
+ return new Promise((resolve, reject) => {
12
+ const parser = new xml2js.Parser();
13
+ parser.parseString(xmlContent, (err, result) => {
14
+ if (err) {
15
+ reject(new Error('Error parsing XML: ' + err.message));
16
+ } else {
17
+ resolve(result);
18
+ }
19
+ });
20
+ });
21
+ };
package/test/Test1.xml ADDED
@@ -0,0 +1,56 @@
1
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
2
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
4
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+ <modelVersion>4.0.0</modelVersion>
6
+
7
+ <groupId>com.example</groupId>
8
+ <artifactId>test-project</artifactId>
9
+ <version>1.0.0</version>
10
+ <packaging>jar</packaging>
11
+
12
+ <dependencies>
13
+ <!-- Dependency with version provided -->
14
+ <dependency>
15
+ <groupId>org.springframework</groupId>
16
+ <artifactId>spring-core</artifactId>
17
+ <version>5.3.9</version>
18
+ </dependency>
19
+ <!-- Duplicate dependency with version provided -->
20
+ <dependency>
21
+ <groupId>org.springframework</groupId>
22
+ <artifactId>spring-core</artifactId>
23
+ <version>5.3.9</version>
24
+ </dependency>
25
+
26
+ <!-- Dependency missing version -->
27
+ <dependency>
28
+ <groupId>org.apache.commons</groupId>
29
+ <artifactId>commons-lang3</artifactId>
30
+ </dependency>
31
+ <!-- Duplicate dependency missing version -->
32
+ <dependency>
33
+ <groupId>org.apache.commons</groupId>
34
+ <artifactId>commons-lang3</artifactId>
35
+ </dependency>
36
+
37
+ <!-- Dependency with version provided -->
38
+ <dependency>
39
+ <groupId>junit</groupId>
40
+ <artifactId>junit</artifactId>
41
+ <version>4.13.2</version>
42
+ <scope>test</scope>
43
+ </dependency>
44
+
45
+ <!-- Dependency missing version -->
46
+ <dependency>
47
+ <groupId>com.google.guava</groupId>
48
+ <artifactId>guava</artifactId>
49
+ </dependency>
50
+ <!-- Duplicate dependency missing version -->
51
+ <dependency>
52
+ <groupId>com.google.guava</groupId>
53
+ <artifactId>guava</artifactId>
54
+ </dependency>
55
+ </dependencies>
56
+ </project>
@@ -0,0 +1,58 @@
1
+ import { resolveVersion } from '../src/utils/dependencyResolver';
2
+
3
+ describe('resolveVersion', () => {
4
+ it('should return the resolved version for a valid property reference', () => {
5
+ const properties = { myVersion: ['1.0.0'] };
6
+ const version = '${myVersion}';
7
+ const resolved = resolveVersion(version, properties);
8
+ expect(resolved).toBe('1.0.0');
9
+ });
10
+
11
+ it('should return "N/A" for an unknown property reference', () => {
12
+ const properties = { myVersion: ['1.0.0'] };
13
+ const version = '${unknownVersion}';
14
+ const resolved = resolveVersion(version, properties);
15
+ expect(resolved).toBe('N/A');
16
+ });
17
+
18
+ it('should return the version string if it is not a property reference', () => {
19
+ const properties = {};
20
+ const version = '2.0.0';
21
+ const resolved = resolveVersion(version, properties);
22
+ expect(resolved).toBe('2.0.0');
23
+ });
24
+
25
+ it('should return "N/A" for an undefined version', () => {
26
+ const properties = {};
27
+ const version = undefined;
28
+ const resolved = resolveVersion(version, properties);
29
+ expect(resolved).toBe('N/A');
30
+ });
31
+
32
+ it('should return "N/A" for a null version', () => {
33
+ const properties = {};
34
+ const version = null;
35
+ const resolved = resolveVersion(version, properties);
36
+ expect(resolved).toBe('N/A');
37
+ });
38
+
39
+ it('should handle nested property references', () => {
40
+ const properties = {
41
+ 'outer.version': ['${inner.version}'],
42
+ 'inner.version': ['1.2.3']
43
+ };
44
+ const version = '${outer.version}';
45
+ // Note: The current implementation doesn't resolve nested properties,
46
+ // this test confirms current behavior
47
+ const resolved = resolveVersion(version, properties);
48
+ expect(resolved).toBe('${inner.version}');
49
+ });
50
+
51
+ it('should handle property references with whitespace', () => {
52
+ const properties = { 'my.version': ['1.0.0'] };
53
+ const version = '${ my.version }'; // Notice the whitespace
54
+ // Current implementation doesn't trim property names
55
+ const resolved = resolveVersion(version, properties);
56
+ expect(resolved).toBe('N/A');
57
+ });
58
+ });
@@ -0,0 +1,310 @@
1
+ import { readPomXml } from '../src/services/dependencyService';
2
+ import { readFile } from '../src/utils/fileUtils';
3
+ import { parseXml } from '../src/utils/xmlParser';
4
+ import { resolveVersion } from '../src/utils/dependencyResolver';
5
+
6
+ jest.mock('../src/utils/fileUtils');
7
+ jest.mock('../src/utils/xmlParser');
8
+ jest.mock('../src/utils/dependencyResolver');
9
+
10
+ describe('Dependency Service', () => {
11
+ const mockFilePath = 'mock/path/to/pom.xml';
12
+ const mockXmlContent = '<project></project>';
13
+
14
+ beforeEach(() => {
15
+ jest.clearAllMocks();
16
+ readFile.mockResolvedValue(mockXmlContent);
17
+ resolveVersion.mockImplementation((version) => version === 'N/A' ? 'N/A' : version);
18
+ });
19
+
20
+ it('should read and parse pom.xml file correctly with regular dependencies', async () => {
21
+ const mockParsedXml = {
22
+ project: {
23
+ dependencies: [{
24
+ dependency: [
25
+ {
26
+ groupId: ['com.example'],
27
+ artifactId: ['example-artifact'],
28
+ version: ['1.0.0']
29
+ }
30
+ ]
31
+ }]
32
+ }
33
+ };
34
+ parseXml.mockResolvedValue(mockParsedXml);
35
+
36
+ const dependencies = await readPomXml(mockFilePath);
37
+ expect(readFile).toHaveBeenCalledWith(mockFilePath);
38
+ expect(parseXml).toHaveBeenCalledWith(mockXmlContent);
39
+ expect(dependencies).toEqual([
40
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' }
41
+ ]);
42
+ });
43
+
44
+ it('should handle dependency management section', async () => {
45
+ const mockParsedXml = {
46
+ project: {
47
+ dependencyManagement: [{
48
+ dependencies: [{
49
+ dependency: [
50
+ {
51
+ groupId: ['org.managed'],
52
+ artifactId: ['managed-artifact'],
53
+ version: ['2.0.0']
54
+ }
55
+ ]
56
+ }]
57
+ }]
58
+ }
59
+ };
60
+ parseXml.mockResolvedValue(mockParsedXml);
61
+
62
+ const dependencies = await readPomXml(mockFilePath);
63
+ expect(dependencies).toEqual([
64
+ { groupId: 'org.managed', artifactId: 'managed-artifact', version: '2.0.0' }
65
+ ]);
66
+ });
67
+
68
+ it('should handle both regular dependencies and dependency management', async () => {
69
+ const mockParsedXml = {
70
+ project: {
71
+ dependencies: [{
72
+ dependency: [
73
+ {
74
+ groupId: ['com.example'],
75
+ artifactId: ['example-artifact'],
76
+ version: ['1.0.0']
77
+ }
78
+ ]
79
+ }],
80
+ dependencyManagement: [{
81
+ dependencies: [{
82
+ dependency: [
83
+ {
84
+ groupId: ['org.managed'],
85
+ artifactId: ['managed-artifact'],
86
+ version: ['2.0.0']
87
+ }
88
+ ]
89
+ }]
90
+ }]
91
+ }
92
+ };
93
+ parseXml.mockResolvedValue(mockParsedXml);
94
+
95
+ const dependencies = await readPomXml(mockFilePath);
96
+ expect(dependencies).toHaveLength(2);
97
+ expect(dependencies).toContainEqual({ groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' });
98
+ expect(dependencies).toContainEqual({ groupId: 'org.managed', artifactId: 'managed-artifact', version: '2.0.0' });
99
+ });
100
+
101
+ it('should handle dependencies with missing fields', async () => {
102
+ const mockParsedXml = {
103
+ project: {
104
+ dependencies: [{
105
+ dependency: [
106
+ {
107
+ // Missing groupId
108
+ artifactId: ['example-artifact'],
109
+ version: ['1.0.0']
110
+ },
111
+ {
112
+ groupId: ['com.example'],
113
+ // Missing artifactId
114
+ version: ['1.0.0']
115
+ },
116
+ {
117
+ groupId: ['com.example2'],
118
+ artifactId: ['example-artifact2']
119
+ // Missing version
120
+ }
121
+ ]
122
+ }]
123
+ }
124
+ };
125
+ parseXml.mockResolvedValue(mockParsedXml);
126
+
127
+ const dependencies = await readPomXml(mockFilePath);
128
+ expect(dependencies).toEqual([
129
+ { groupId: 'unknown', artifactId: 'example-artifact', version: '1.0.0' },
130
+ { groupId: 'com.example', artifactId: 'unknown', version: '1.0.0' },
131
+ { groupId: 'com.example2', artifactId: 'example-artifact2', version: 'N/A' }
132
+ ]);
133
+ });
134
+
135
+ it('should handle property resolution in versions', async () => {
136
+ const mockParsedXml = {
137
+ project: {
138
+ properties: [{ 'project.version': ['3.0.0'] }],
139
+ dependencies: [{
140
+ dependency: [
141
+ {
142
+ groupId: ['com.example'],
143
+ artifactId: ['example-artifact'],
144
+ version: ['${project.version}']
145
+ }
146
+ ]
147
+ }]
148
+ }
149
+ };
150
+ parseXml.mockResolvedValue(mockParsedXml);
151
+ resolveVersion.mockImplementation((version) => version === '${project.version}' ? '3.0.0' : version);
152
+
153
+ const dependencies = await readPomXml(mockFilePath);
154
+ expect(dependencies).toEqual([
155
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '3.0.0' }
156
+ ]);
157
+ });
158
+
159
+ it('should return empty array if no project element in XML', async () => {
160
+ parseXml.mockResolvedValue({});
161
+ const dependencies = await readPomXml(mockFilePath);
162
+ expect(dependencies).toEqual([]);
163
+ });
164
+
165
+ it('should return empty array if no dependencies in project', async () => {
166
+ parseXml.mockResolvedValue({ project: {} });
167
+ const dependencies = await readPomXml(mockFilePath);
168
+ expect(dependencies).toEqual([]);
169
+ });
170
+
171
+ it('should handle errors when reading the file', async () => {
172
+ readFile.mockRejectedValue(new Error('File read error'));
173
+ await expect(readPomXml(mockFilePath)).rejects.toThrow('Error reading pom.xml: File read error');
174
+ });
175
+
176
+ it('should handle errors when parsing XML', async () => {
177
+ readFile.mockResolvedValue(mockXmlContent);
178
+ parseXml.mockRejectedValue(new Error('XML parse error'));
179
+ await expect(readPomXml(mockFilePath)).rejects.toThrow('Error reading pom.xml: XML parse error');
180
+ });
181
+
182
+ it('should handle empty dependencies array in project', async () => {
183
+ const mockParsedXml = {
184
+ project: {
185
+ dependencies: [{
186
+ dependency: []
187
+ }]
188
+ }
189
+ };
190
+ parseXml.mockResolvedValue(mockParsedXml);
191
+
192
+ const dependencies = await readPomXml(mockFilePath);
193
+ expect(dependencies).toEqual([]);
194
+ });
195
+
196
+ it('should handle empty dependencyManagement array in project', async () => {
197
+ const mockParsedXml = {
198
+ project: {
199
+ dependencyManagement: [{
200
+ dependencies: [{
201
+ dependency: []
202
+ }]
203
+ }]
204
+ }
205
+ };
206
+ parseXml.mockResolvedValue(mockParsedXml);
207
+
208
+ const dependencies = await readPomXml(mockFilePath);
209
+ expect(dependencies).toEqual([]);
210
+ });
211
+
212
+ it('should handle missing dependencyManagement section', async () => {
213
+ const mockParsedXml = {
214
+ project: {
215
+ dependencies: [{
216
+ dependency: [
217
+ {
218
+ groupId: ['com.example'],
219
+ artifactId: ['example-artifact'],
220
+ version: ['1.0.0']
221
+ }
222
+ ]
223
+ }]
224
+ }
225
+ };
226
+ parseXml.mockResolvedValue(mockParsedXml);
227
+
228
+ const dependencies = await readPomXml(mockFilePath);
229
+ expect(dependencies).toEqual([
230
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' }
231
+ ]);
232
+ });
233
+
234
+ it('should handle missing dependencies section', async () => {
235
+ const mockParsedXml = {
236
+ project: {
237
+ dependencyManagement: [{
238
+ dependencies: [{
239
+ dependency: [
240
+ {
241
+ groupId: ['org.managed'],
242
+ artifactId: ['managed-artifact'],
243
+ version: ['2.0.0']
244
+ }
245
+ ]
246
+ }]
247
+ }]
248
+ }
249
+ };
250
+ parseXml.mockResolvedValue(mockParsedXml);
251
+
252
+ const dependencies = await readPomXml(mockFilePath);
253
+ expect(dependencies).toEqual([
254
+ { groupId: 'org.managed', artifactId: 'managed-artifact', version: '2.0.0' }
255
+ ]);
256
+ });
257
+
258
+ it('should handle missing properties section', async () => {
259
+ const mockParsedXml = {
260
+ project: {
261
+ dependencies: [{
262
+ dependency: [
263
+ {
264
+ groupId: ['com.example'],
265
+ artifactId: ['example-artifact'],
266
+ version: ['${project.version}']
267
+ }
268
+ ]
269
+ }]
270
+ }
271
+ };
272
+ parseXml.mockResolvedValue(mockParsedXml);
273
+ resolveVersion.mockImplementation((version) => version === '${project.version}' ? 'N/A' : version);
274
+
275
+ const dependencies = await readPomXml(mockFilePath);
276
+ expect(dependencies).toEqual([
277
+ { groupId: 'com.example', artifactId: 'example-artifact', version: 'N/A' }
278
+ ]);
279
+ });
280
+
281
+ it('should handle empty project object', async () => {
282
+ const mockParsedXml = { project: {} };
283
+ parseXml.mockResolvedValue(mockParsedXml);
284
+
285
+ const dependencies = await readPomXml(mockFilePath);
286
+ expect(dependencies).toEqual([]);
287
+ });
288
+
289
+ it('should handle null version in dependency', async () => {
290
+ const mockParsedXml = {
291
+ project: {
292
+ dependencies: [{
293
+ dependency: [
294
+ {
295
+ groupId: ['com.example'],
296
+ artifactId: ['example-artifact'],
297
+ version: [null]
298
+ }
299
+ ]
300
+ }]
301
+ }
302
+ };
303
+ parseXml.mockResolvedValue(mockParsedXml);
304
+
305
+ const dependencies = await readPomXml(mockFilePath);
306
+ expect(dependencies).toEqual([
307
+ { groupId: 'com.example', artifactId: 'example-artifact', version: 'N/A' }
308
+ ]);
309
+ });
310
+ });
@@ -0,0 +1,67 @@
1
+ import { checkForDuplicates } from '../src/services/duplicateChecker';
2
+
3
+ describe('checkForDuplicates', () => {
4
+ it('should return an empty array when there are no duplicates', () => {
5
+ const dependencies = [
6
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' },
7
+ { groupId: 'org.sample', artifactId: 'sample-artifact', version: '2.0.0' },
8
+ ];
9
+ const result = checkForDuplicates(dependencies);
10
+ expect(result).toEqual([]);
11
+ });
12
+
13
+ it('should identify duplicates based on groupId and artifactId', () => {
14
+ const dependencies = [
15
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' },
16
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.1.0' },
17
+ { groupId: 'org.sample', artifactId: 'sample-artifact', version: '2.0.0' },
18
+ { groupId: 'org.sample', artifactId: 'sample-artifact', version: '2.1.0' },
19
+ ];
20
+ const result = checkForDuplicates(dependencies);
21
+
22
+ expect(result).toHaveLength(2);
23
+ expect(result[0]).toHaveLength(2);
24
+ expect(result[0][0]).toEqual({ groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' });
25
+ expect(result[0][1]).toEqual({ groupId: 'com.example', artifactId: 'example-artifact', version: '1.1.0' });
26
+
27
+ expect(result[1]).toHaveLength(2);
28
+ expect(result[1][0]).toEqual({ groupId: 'org.sample', artifactId: 'sample-artifact', version: '2.0.0' });
29
+ expect(result[1][1]).toEqual({ groupId: 'org.sample', artifactId: 'sample-artifact', version: '2.1.0' });
30
+ });
31
+
32
+ it('should not consider different artifactIds as duplicates even with same groupId', () => {
33
+ const dependencies = [
34
+ { groupId: 'com.example', artifactId: 'example-artifact-1', version: '1.0.0' },
35
+ { groupId: 'com.example', artifactId: 'example-artifact-2', version: '1.0.0' },
36
+ ];
37
+ const result = checkForDuplicates(dependencies);
38
+ expect(result).toEqual([]);
39
+ });
40
+
41
+ it('should not consider different groupIds as duplicates even with same artifactId', () => {
42
+ const dependencies = [
43
+ { groupId: 'com.example1', artifactId: 'example-artifact', version: '1.0.0' },
44
+ { groupId: 'com.example2', artifactId: 'example-artifact', version: '1.0.0' },
45
+ ];
46
+ const result = checkForDuplicates(dependencies);
47
+ expect(result).toEqual([]);
48
+ });
49
+
50
+ it('should handle an empty array of dependencies', () => {
51
+ const dependencies = [];
52
+ const result = checkForDuplicates(dependencies);
53
+ expect(result).toEqual([]);
54
+ });
55
+
56
+ it('should include multiple versions in the duplicate groups', () => {
57
+ const dependencies = [
58
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.0.0' },
59
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.1.0' },
60
+ { groupId: 'com.example', artifactId: 'example-artifact', version: '1.2.0' },
61
+ ];
62
+ const result = checkForDuplicates(dependencies);
63
+
64
+ expect(result).toHaveLength(1);
65
+ expect(result[0]).toHaveLength(3);
66
+ });
67
+ });