Skip to content

Commit 4f8e1fb

Browse files
committed
msw/user: Implement PUT /api/v1/users/:id endpoint
1 parent 8e8d2a7 commit 4f8e1fb

File tree

3 files changed

+130
-2
lines changed

3 files changed

+130
-2
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import { siteMetadata } from './metadata.js';
2-
import { findUser } from './users.js';
2+
import { findUser, updateUser } from './users.js';
33

4-
export const handlers = [siteMetadata, findUser];
4+
export const handlers = [siteMetadata, findUser, updateUser];

packages/crates-io-msw/handlers/users.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { http, HttpResponse } from 'msw';
22

33
import { db } from '../db.js';
4+
import { getSession } from '../utils/session.js';
45
import { underscore } from '../utils/strings.js';
56
import { notFound } from './-utils.js';
67

@@ -15,6 +16,48 @@ export const findUser = http.get('/api/v1/users/:login', ({ params }) => {
1516
return HttpResponse.json({ user: serializeUser(user) });
1617
});
1718

19+
export const updateUser = http.put('/api/v1/users/:id', async ({ params, request }) => {
20+
let { user } = getSession(db);
21+
if (!user) {
22+
// unfortunately, it's hard to tell from the Rust code if this is the correct response
23+
// in this case, but since it's used elsewhere I will assume for now that it's correct.
24+
return HttpResponse.json({ errors: [{ detail: 'must be logged in to perform that action' }] }, { status: 403 });
25+
}
26+
27+
if (user.id.toString() !== params.id) {
28+
return HttpResponse.json({ errors: [{ detail: 'current user does not match requested user' }] }, { status: 400 });
29+
}
30+
31+
let json = await request.json();
32+
if (!json || !json.user) {
33+
return HttpResponse.json({ errors: [{ detail: 'invalid json request' }] }, { status: 400 });
34+
}
35+
36+
if (json.user.publish_notifications !== undefined) {
37+
db.user.update({
38+
where: { id: { equals: user.id } },
39+
data: { publishNotifications: json.user.publish_notifications },
40+
});
41+
}
42+
43+
if (json.user.email !== undefined) {
44+
if (!json.user.email) {
45+
return HttpResponse.json({ errors: [{ detail: 'empty email rejected' }] }, { status: 400 });
46+
}
47+
48+
db.user.update({
49+
where: { id: { equals: user.id } },
50+
data: {
51+
email: json.user.email,
52+
emailVerified: false,
53+
emailVerificationToken: 'secret123',
54+
},
55+
});
56+
}
57+
58+
return HttpResponse.json({ ok: true });
59+
});
60+
1861
function serializeUser(user) {
1962
user = serializeModel(user);
2063

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { describe, test } from 'vitest';
2+
3+
import { db } from '../../db.js';
4+
5+
describe('PUT /api/v1/users/:id', () => {
6+
test('updates the user with a new email address', async ({ expect }) => {
7+
let user = db.user.create({ email: '[email protected]' });
8+
db.mswSession.create({ user });
9+
10+
let body = JSON.stringify({ user: { email: '[email protected]' } });
11+
let response = await fetch(`/api/v1/users/${user.id}`, { method: 'PUT', body });
12+
expect(response.status).toBe(200);
13+
expect(await response.json()).toEqual({ ok: true });
14+
15+
user = db.user.findFirst({ where: { id: user.id } });
16+
expect(user.email).toBe('[email protected]');
17+
expect(user.emailVerified).toBe(false);
18+
expect(user.emailVerificationToken).toBe('secret123');
19+
});
20+
21+
test('updates the `publish_notifications` settings', async ({ expect }) => {
22+
let user = db.user.create();
23+
db.mswSession.create({ user });
24+
expect(user.publishNotifications).toBe(true);
25+
26+
let body = JSON.stringify({ user: { publish_notifications: false } });
27+
let response = await fetch(`/api/v1/users/${user.id}`, { method: 'PUT', body });
28+
expect(response.status).toBe(200);
29+
expect(await response.json()).toEqual({ ok: true });
30+
31+
user = db.user.findFirst({ where: { id: user.id } });
32+
expect(user.publishNotifications).toBe(false);
33+
});
34+
35+
test('returns 403 when not logged in', async ({ expect }) => {
36+
let user = db.user.create({ email: '[email protected]' });
37+
38+
let body = JSON.stringify({ user: { email: '[email protected]' } });
39+
let response = await fetch(`/api/v1/users/${user.id}`, { method: 'PUT', body });
40+
expect(response.status).toBe(403);
41+
expect(await response.json()).toEqual({ errors: [{ detail: 'must be logged in to perform that action' }] });
42+
43+
user = db.user.findFirst({ where: { id: user.id } });
44+
expect(user.email).toBe('[email protected]');
45+
});
46+
47+
test('returns 400 when requesting the wrong user id', async ({ expect }) => {
48+
let user = db.user.create({ email: '[email protected]' });
49+
db.mswSession.create({ user });
50+
51+
let body = JSON.stringify({ user: { email: '[email protected]' } });
52+
let response = await fetch(`/api/v1/users/wrong-id`, { method: 'PUT', body });
53+
expect(response.status).toBe(400);
54+
expect(await response.json()).toEqual({ errors: [{ detail: 'current user does not match requested user' }] });
55+
56+
user = db.user.findFirst({ where: { id: user.id } });
57+
expect(user.email).toBe('[email protected]');
58+
});
59+
60+
test('returns 400 when sending an invalid payload', async ({ expect }) => {
61+
let user = db.user.create({ email: '[email protected]' });
62+
db.mswSession.create({ user });
63+
64+
let body = JSON.stringify({});
65+
let response = await fetch(`/api/v1/users/${user.id}`, { method: 'PUT', body });
66+
expect(response.status).toBe(400);
67+
expect(await response.json()).toEqual({ errors: [{ detail: 'invalid json request' }] });
68+
69+
user = db.user.findFirst({ where: { id: user.id } });
70+
expect(user.email).toBe('[email protected]');
71+
});
72+
73+
test('returns 400 when sending an empty email address', async ({ expect }) => {
74+
let user = db.user.create({ email: '[email protected]' });
75+
db.mswSession.create({ user });
76+
77+
let body = JSON.stringify({ user: { email: '' } });
78+
let response = await fetch(`/api/v1/users/${user.id}`, { method: 'PUT', body });
79+
expect(response.status).toBe(400);
80+
expect(await response.json()).toEqual({ errors: [{ detail: 'empty email rejected' }] });
81+
82+
user = db.user.findFirst({ where: { id: user.id } });
83+
expect(user.email).toBe('[email protected]');
84+
});
85+
});

0 commit comments

Comments
 (0)