Skip to content

Commit b8dd395

Browse files
committed
test: add dependents API response mapping unit tests
1 parent 143ad3f commit b8dd395

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { describe, expect, it } from 'vitest'
2+
3+
/**
4+
* Unit tests for the dependents API response parsing logic.
5+
*
6+
* The `/api/registry/dependents/[...pkg]` endpoint fetches from the npm
7+
* search API using a `dependencies:<name>` query and maps the response
8+
* to a simplified shape. These tests verify the mapping logic in isolation.
9+
*/
10+
11+
interface NpmSearchObject {
12+
package: {
13+
name: string
14+
version: string
15+
description?: string
16+
date?: string
17+
}
18+
score: { final: number }
19+
searchScore: number
20+
}
21+
22+
function mapNpmSearchResponse(
23+
objects: NpmSearchObject[],
24+
total: number,
25+
page: number,
26+
size: number,
27+
) {
28+
return {
29+
total,
30+
page,
31+
size,
32+
packages: objects.map(obj => ({
33+
name: obj.package.name,
34+
version: obj.package.version,
35+
description: obj.package.description ?? null,
36+
date: obj.package.date ?? null,
37+
score: obj.score.final,
38+
})),
39+
}
40+
}
41+
42+
describe('dependents API response mapping', () => {
43+
it('maps npm search objects to the expected package shape', () => {
44+
const objects: NpmSearchObject[] = [
45+
{
46+
package: { name: 'some-lib', version: '1.2.3', description: 'A library', date: '2024-01-01' },
47+
score: { final: 0.95 },
48+
searchScore: 100,
49+
},
50+
]
51+
52+
const result = mapNpmSearchResponse(objects, 42, 0, 20)
53+
54+
expect(result.total).toBe(42)
55+
expect(result.page).toBe(0)
56+
expect(result.size).toBe(20)
57+
expect(result.packages).toHaveLength(1)
58+
expect(result.packages[0]).toEqual({
59+
name: 'some-lib',
60+
version: '1.2.3',
61+
description: 'A library',
62+
date: '2024-01-01',
63+
score: 0.95,
64+
})
65+
})
66+
67+
it('falls back to null for missing optional fields', () => {
68+
const objects: NpmSearchObject[] = [
69+
{
70+
package: { name: 'minimal-pkg', version: '0.1.0' },
71+
score: { final: 0.5 },
72+
searchScore: 50,
73+
},
74+
]
75+
76+
const result = mapNpmSearchResponse(objects, 1, 0, 20)
77+
expect(result.packages[0].description).toBeNull()
78+
expect(result.packages[0].date).toBeNull()
79+
})
80+
81+
it('returns empty packages array when objects is empty', () => {
82+
const result = mapNpmSearchResponse([], 0, 0, 20)
83+
expect(result.packages).toHaveLength(0)
84+
expect(result.total).toBe(0)
85+
})
86+
87+
it('computes correct page offset for pagination', () => {
88+
// page=2, size=20 means from=40
89+
const page = 2
90+
const size = 20
91+
const from = page * size
92+
expect(from).toBe(40)
93+
})
94+
95+
it('caps size to a maximum of 50', () => {
96+
const raw = 200
97+
const capped = Math.min(50, Math.max(1, raw))
98+
expect(capped).toBe(50)
99+
})
100+
101+
it('enforces a minimum size of 1', () => {
102+
const raw = 0
103+
const capped = Math.min(50, Math.max(1, raw))
104+
expect(capped).toBe(1)
105+
})
106+
})

0 commit comments

Comments
 (0)