Skip to content

Commit 8bc4108

Browse files
committed
mirage: Add route handler for PUT /api/v1/confirm/:token endpoint
1 parent a8c74a8 commit 8bc4108

File tree

5 files changed

+78
-39
lines changed

5 files changed

+78
-39
lines changed

mirage/factories/user.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ export default Factory.extend({
1818

1919
avatar: 'https://avatars1.githubusercontent.com/u/14631425?v=4',
2020

21-
emailVerified: true,
22-
emailVerificationSent: true,
21+
emailVerified: null,
22+
emailVerificationToken: null,
23+
24+
afterCreate(model) {
25+
if (model.emailVerified === null) {
26+
model.update({ emailVerified: !model.emailVerificationToken });
27+
}
28+
},
2329
});

mirage/route-handlers/me.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,17 @@ export function register(server) {
1616

1717
return json;
1818
});
19+
20+
server.put('/api/v1/confirm/:token', (schema, request) => {
21+
let { token } = request.params;
22+
23+
let user = schema.users.findBy({ emailVerificationToken: token });
24+
if (!user) {
25+
return new Response(400, {}, { errors: [{ detail: 'Email belonging to token not found.' }] });
26+
}
27+
28+
user.update({ emailVerified: true, emailVerificationToken: null });
29+
30+
return { ok: true };
31+
});
1932
}

mirage/serializers/user.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ export default BaseSerializer.extend({
2323
if (removePrivateData) {
2424
delete hash.email;
2525
delete hash.email_verified;
26-
delete hash.email_verification_sent;
26+
} else {
27+
hash.email_verification_sent = hash.email_verified || Boolean(hash.email_verification_token);
2728
}
29+
30+
delete hash.email_verification_token;
2831
},
2932
});

tests/acceptance/email-confirmation-test.js

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { module, test } from 'qunit';
22
import { setupApplicationTest } from 'ember-qunit';
33
import { currentURL } from '@ember/test-helpers';
44
import window, { setupWindowMock } from 'ember-window-mock';
5-
import { Response } from 'ember-cli-mirage';
65

76
import { visit } from '../helpers/visit-ignoring-abort';
87
import setupMirage from '../helpers/setup-mirage';
@@ -13,60 +12,36 @@ module('Acceptance | Email Confirmation', function (hooks) {
1312
setupMirage(hooks);
1413

1514
test('unauthenticated happy path', async function (assert) {
16-
assert.expect(3);
17-
18-
this.server.put('/api/v1/confirm/:token', (schema, request) => {
19-
assert.equal(request.params.token, 'badc0ffee');
20-
return { ok: true };
21-
});
15+
let user = this.server.create('user', { emailVerificationToken: 'badc0ffee' });
16+
assert.strictEqual(user.emailVerified, false);
2217

2318
await visit('/confirm/badc0ffee');
2419
assert.equal(currentURL(), '/confirm/badc0ffee');
2520
assert.dom('[data-test-success-message]').exists();
21+
22+
user.reload();
23+
assert.strictEqual(user.emailVerified, true);
2624
});
2725

2826
test('authenticated happy path', async function (assert) {
29-
assert.expect(4);
30-
31-
let emailVerified = false;
27+
let user = this.server.create('user', { emailVerificationToken: 'badc0ffee' });
28+
assert.strictEqual(user.emailVerified, false);
3229

30+
this.server.create('mirage-session', { user });
3331
window.localStorage.setItem('isLoggedIn', '1');
3432

35-
this.server.get('/api/v1/me', () => ({
36-
user: {
37-
id: 42,
38-
login: 'johnnydee',
39-
email_verified: emailVerified,
40-
email_verification_sent: true,
41-
name: 'John Doe',
42-
43-
avatar: 'https://avatars2.githubusercontent.com/u/1234567?v=4',
44-
url: 'https://github.com/johnnydee',
45-
},
46-
owned_crates: [],
47-
}));
48-
49-
this.server.put('/api/v1/confirm/:token', (schema, request) => {
50-
assert.equal(request.params.token, 'badc0ffee');
51-
52-
emailVerified = true;
53-
54-
return { ok: true };
55-
});
56-
5733
await visit('/confirm/badc0ffee');
5834
assert.equal(currentURL(), '/confirm/badc0ffee');
5935
assert.dom('[data-test-success-message]').exists();
6036

6137
let { currentUser } = this.owner.lookup('service:session');
6238
assert.strictEqual(currentUser.email_verified, true);
39+
40+
user.reload();
41+
assert.strictEqual(user.emailVerified, true);
6342
});
6443

6544
test('error case', async function (assert) {
66-
this.server.put('/api/v1/confirm/:token', () => {
67-
return new Response(400, {}, { errors: [{ detail: 'Email belonging to token not found.' }] });
68-
});
69-
7045
await visit('/confirm/badc0ffee');
7146
assert.equal(currentURL(), '/');
7247
assert.dom('[data-test-flash-message]').hasText('Unknown error in email confirmation');

tests/mirage/me-test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,46 @@ module('Mirage | /me', function (hooks) {
4444
});
4545
});
4646
});
47+
48+
module('GET /api/v1/confirm/:token', function () {
49+
test('returns `ok: true` for a known token (unauthenticated)', async function (assert) {
50+
let user = this.server.create('user', { emailVerificationToken: 'foo' });
51+
assert.strictEqual(user.emailVerified, false);
52+
53+
let response = await fetch('/api/v1/confirm/foo', { method: 'PUT' });
54+
assert.equal(response.status, 200);
55+
56+
let responsePayload = await response.json();
57+
assert.deepEqual(responsePayload, { ok: true });
58+
59+
user.reload();
60+
assert.strictEqual(user.emailVerified, true);
61+
});
62+
63+
test('returns `ok: true` for a known token (authenticated)', async function (assert) {
64+
let user = this.server.create('user', { emailVerificationToken: 'foo' });
65+
assert.strictEqual(user.emailVerified, false);
66+
67+
this.server.create('mirage-session', { user });
68+
69+
let response = await fetch('/api/v1/confirm/foo', { method: 'PUT' });
70+
assert.equal(response.status, 200);
71+
72+
let responsePayload = await response.json();
73+
assert.deepEqual(responsePayload, { ok: true });
74+
75+
user.reload();
76+
assert.strictEqual(user.emailVerified, true);
77+
});
78+
79+
test('returns an error for unknown tokens', async function (assert) {
80+
let response = await fetch('/api/v1/confirm/unknown', { method: 'PUT' });
81+
assert.equal(response.status, 400);
82+
83+
let responsePayload = await response.json();
84+
assert.deepEqual(responsePayload, {
85+
errors: [{ detail: 'Email belonging to token not found.' }],
86+
});
87+
});
88+
});
4789
});

0 commit comments

Comments
 (0)