Skip to content

Commit abfa49d

Browse files
committed
msw: Implement GET /api/v1/summary request handler
1 parent f5a509b commit abfa49d

File tree

3 files changed

+208
-0
lines changed

3 files changed

+208
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { http, HttpResponse } from 'msw';
2+
3+
import { db } from '../index.js';
4+
import { serializeCategory } from '../serializers/category.js';
5+
import { serializeCrate } from '../serializers/crate.js';
6+
import { serializeKeyword } from '../serializers/keyword.js';
7+
import { compareDates } from '../utils/dates.js';
8+
9+
export default [
10+
http.get('/api/v1/summary', () => {
11+
let crates = db.crate.findMany({});
12+
13+
let just_updated = crates.sort((a, b) => compareDates(b.updated_at, a.updated_at)).slice(0, 10);
14+
let most_downloaded = crates.sort((a, b) => b.downloads - a.downloads).slice(0, 10);
15+
let new_crates = crates.sort((a, b) => b.id - a.id).slice(0, 10);
16+
let most_recently_downloaded = crates.sort((a, b) => b.recent_downloads - a.recent_downloads).slice(0, 10);
17+
18+
let num_crates = crates.length;
19+
// eslint-disable-next-line unicorn/no-array-reduce
20+
let num_downloads = crates.reduce((sum, crate) => sum + crate.downloads, 0);
21+
22+
let popularCategories = db.category.findMany({ take: 10 });
23+
let popularKeywords = db.keyword.findMany({ take: 10 });
24+
25+
return HttpResponse.json({
26+
just_updated: just_updated.map(c => serializeCrate(c)),
27+
most_downloaded: most_downloaded.map(c => serializeCrate(c)),
28+
new_crates: new_crates.map(c => serializeCrate(c)),
29+
most_recently_downloaded: most_recently_downloaded.map(c => serializeCrate(c)),
30+
num_crates,
31+
num_downloads,
32+
popular_categories: popularCategories.map(it => serializeCategory(it)),
33+
popular_keywords: popularKeywords.map(it => serializeKeyword(it)),
34+
});
35+
}),
36+
];
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import { assert, test } from 'vitest';
2+
3+
import { db } from '../index.js';
4+
5+
test('empty case', async function () {
6+
let response = await fetch('/api/v1/summary');
7+
assert.strictEqual(response.status, 200);
8+
assert.deepEqual(await response.json(), {
9+
just_updated: [],
10+
most_downloaded: [],
11+
most_recently_downloaded: [],
12+
new_crates: [],
13+
num_crates: 0,
14+
num_downloads: 0,
15+
popular_categories: [],
16+
popular_keywords: [],
17+
});
18+
});
19+
20+
test('returns the data for the front page', async function () {
21+
Array.from({ length: 15 }, () => db.category.create());
22+
Array.from({ length: 25 }, () => db.keyword.create());
23+
let crates = Array.from({ length: 20 }, () => db.crate.create());
24+
crates.forEach(crate => db.version.create({ crate }));
25+
26+
let response = await fetch('/api/v1/summary');
27+
assert.strictEqual(response.status, 200);
28+
29+
let responsePayload = await response.json();
30+
31+
assert.strictEqual(responsePayload.just_updated.length, 10);
32+
assert.deepEqual(responsePayload.just_updated[0], {
33+
id: 'crate-1',
34+
badges: [],
35+
categories: null,
36+
created_at: '2010-06-16T21:30:45Z',
37+
default_version: '1.0.0',
38+
description: 'This is the description for the crate called "crate-1"',
39+
documentation: null,
40+
downloads: 37_035,
41+
homepage: null,
42+
keywords: null,
43+
links: {
44+
owner_team: '/api/v1/crates/crate-1/owner_team',
45+
owner_user: '/api/v1/crates/crate-1/owner_user',
46+
reverse_dependencies: '/api/v1/crates/crate-1/reverse_dependencies',
47+
version_downloads: '/api/v1/crates/crate-1/downloads',
48+
versions: '/api/v1/crates/crate-1/versions',
49+
},
50+
max_version: '1.0.0',
51+
max_stable_version: '1.0.0',
52+
name: 'crate-1',
53+
newest_version: '1.0.0',
54+
recent_downloads: 321,
55+
repository: null,
56+
updated_at: '2017-02-24T12:34:56Z',
57+
versions: null,
58+
yanked: false,
59+
});
60+
61+
assert.strictEqual(responsePayload.most_downloaded.length, 10);
62+
assert.deepEqual(responsePayload.most_downloaded[0], {
63+
id: 'crate-4',
64+
badges: [],
65+
categories: null,
66+
created_at: '2010-06-16T21:30:45Z',
67+
default_version: '1.0.3',
68+
description: 'This is the description for the crate called "crate-4"',
69+
documentation: null,
70+
downloads: 148_140,
71+
homepage: null,
72+
keywords: null,
73+
links: {
74+
owner_team: '/api/v1/crates/crate-4/owner_team',
75+
owner_user: '/api/v1/crates/crate-4/owner_user',
76+
reverse_dependencies: '/api/v1/crates/crate-4/reverse_dependencies',
77+
version_downloads: '/api/v1/crates/crate-4/downloads',
78+
versions: '/api/v1/crates/crate-4/versions',
79+
},
80+
max_version: '1.0.3',
81+
max_stable_version: '1.0.3',
82+
name: 'crate-4',
83+
newest_version: '1.0.3',
84+
repository: null,
85+
recent_downloads: 963,
86+
updated_at: '2017-02-24T12:34:56Z',
87+
versions: null,
88+
yanked: false,
89+
});
90+
91+
assert.strictEqual(responsePayload.most_recently_downloaded.length, 10);
92+
assert.deepEqual(responsePayload.most_recently_downloaded[0], {
93+
id: 'crate-11',
94+
badges: [],
95+
categories: null,
96+
created_at: '2010-06-16T21:30:45Z',
97+
default_version: '1.0.10',
98+
description: 'This is the description for the crate called "crate-11"',
99+
documentation: null,
100+
downloads: 86_415,
101+
homepage: null,
102+
keywords: null,
103+
links: {
104+
owner_team: '/api/v1/crates/crate-11/owner_team',
105+
owner_user: '/api/v1/crates/crate-11/owner_user',
106+
reverse_dependencies: '/api/v1/crates/crate-11/reverse_dependencies',
107+
version_downloads: '/api/v1/crates/crate-11/downloads',
108+
versions: '/api/v1/crates/crate-11/versions',
109+
},
110+
max_version: '1.0.10',
111+
max_stable_version: '1.0.10',
112+
name: 'crate-11',
113+
newest_version: '1.0.10',
114+
repository: null,
115+
recent_downloads: 3852,
116+
updated_at: '2017-02-24T12:34:56Z',
117+
versions: null,
118+
yanked: false,
119+
});
120+
121+
assert.strictEqual(responsePayload.new_crates.length, 10);
122+
assert.deepEqual(responsePayload.new_crates[0], {
123+
id: 'crate-20',
124+
badges: [],
125+
categories: null,
126+
created_at: '2010-06-16T21:30:45Z',
127+
default_version: '1.0.19',
128+
description: 'This is the description for the crate called "crate-20"',
129+
documentation: null,
130+
downloads: 98_760,
131+
homepage: null,
132+
keywords: null,
133+
links: {
134+
owner_team: '/api/v1/crates/crate-20/owner_team',
135+
owner_user: '/api/v1/crates/crate-20/owner_user',
136+
reverse_dependencies: '/api/v1/crates/crate-20/reverse_dependencies',
137+
version_downloads: '/api/v1/crates/crate-20/downloads',
138+
versions: '/api/v1/crates/crate-20/versions',
139+
},
140+
max_version: '1.0.19',
141+
max_stable_version: '1.0.19',
142+
name: 'crate-20',
143+
newest_version: '1.0.19',
144+
repository: null,
145+
recent_downloads: 1605,
146+
updated_at: '2017-02-24T12:34:56Z',
147+
versions: null,
148+
yanked: false,
149+
});
150+
151+
assert.strictEqual(responsePayload.num_crates, 20);
152+
assert.strictEqual(responsePayload.num_downloads, 1_518_435);
153+
154+
assert.strictEqual(responsePayload.popular_categories.length, 10);
155+
assert.deepEqual(responsePayload.popular_categories[0], {
156+
id: 'category-1',
157+
category: 'Category 1',
158+
crates_cnt: 0,
159+
created_at: '2010-06-16T21:30:45Z',
160+
description: 'This is the description for the category called "Category 1"',
161+
slug: 'category-1',
162+
});
163+
164+
assert.strictEqual(responsePayload.popular_keywords.length, 10);
165+
assert.deepEqual(responsePayload.popular_keywords[0], {
166+
id: 'keyword-1',
167+
crates_cnt: 0,
168+
keyword: 'keyword-1',
169+
});
170+
});

packages/crates-io-msw/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import inviteHandlers from './handlers/invites.js';
66
import keywordHandlers from './handlers/keywords.js';
77
import metadataHandlers from './handlers/metadata.js';
88
import sessionHandlers from './handlers/sessions.js';
9+
import summaryHandlers from './handlers/summary.js';
910
import teamHandlers from './handlers/teams.js';
1011
import userHandlers from './handlers/users.js';
1112
import versionHandlers from './handlers/versions.js';
@@ -32,6 +33,7 @@ export const handlers = [
3233
...keywordHandlers,
3334
...metadataHandlers,
3435
...sessionHandlers,
36+
...summaryHandlers,
3537
...teamHandlers,
3638
...userHandlers,
3739
...versionHandlers,

0 commit comments

Comments
 (0)