eletrotupi / tcc/ api/tests/auth/activate.test.tsc901c35af9c84b6a29e5185545ced1129f33b8f4
5.0 KB | 169 lines Raw
1
import { describe, it, expect, afterAll, beforeEach } from 'vitest'
2
import request from 'supertest'
3
import { createApp } from '@app/createApp'
4
import {
5
  buildPrisma,
6
  cleanupTestDb,
7
  createTestUser,
8
  generateTestToken,
9
  expectPublicUser,
10
} from '../test-helper'
11

12
const app = createApp()
13
const db = buildPrisma()
14

15
afterAll(() => db.$disconnect())
16
beforeEach(() => cleanupTestDb(db))
17

18
async function seedActivationCode(
19
  userId: number,
20
  code = '123456',
21
  expiresInMs = 5 * 60 * 1000
22
) {
23
  return db.user.update({
24
    where: { id: userId },
25
    data: {
26
      activationCode: code,
27
      activationCodeExpiresAt: new Date(Date.now() + expiresInMs),
28
    },
29
  })
30
}
31

32
describe('POST /auth/activate', () => {
33
  it('activates the user and clears the code', async () => {
34
    const user = await createTestUser(db, { email: 'activate@example.com' })
35
    await seedActivationCode(user.id)
36

37
    const res = await request(app)
38
      .post('/auth/activate')
39
      .send({ code: '123456' })
40

41
    expect(res.status).toBe(200)
42
    expect(res.body.user.active).toBe(true)
43
    expectPublicUser(res.body.user)
44

45
    const dbUser = await db.user.findUnique({ where: { id: user.id } })
46
    expect(dbUser!.active).toBe(true)
47
    expect(dbUser!.activationCode).toBeNull()
48
    expect(dbUser!.activationCodeExpiresAt).toBeNull()
49
  })
50

51
  it('activates an account whose code begins with zero', async () => {
52
    const user = await createTestUser(db, { email: 'leading-zero@example.com' })
53
    await seedActivationCode(user.id, '012345')
54

55
    const res = await request(app)
56
      .post('/auth/activate')
57
      .send({ code: '012345' })
58

59
    expect(res.status).toBe(200)
60
    expect(res.body.user.active).toBe(true)
61

62
    const dbUser = await db.user.findUnique({ where: { id: user.id } })
63
    expect(dbUser!.active).toBe(true)
64
    expect(dbUser!.activationCode).toBeNull()
65
  })
66

67
  it('rejects a correctly issued code past its expiry', async () => {
68
    const user = await createTestUser(db, { email: 'expired@example.com' })
69
    await seedActivationCode(user.id, '123456', -1000)
70

71
    const res = await request(app)
72
      .post('/auth/activate')
73
      .send({ code: '123456' })
74

75
    expect(res.status).toBe(422)
76
    expect(res.body.error).toBeTruthy()
77
  })
78

79
  it('rejects a code recorded without an expiry', async () => {
80
    const user = await createTestUser(db, { email: 'no-expiry@example.com' })
81
    await db.user.update({
82
      where: { id: user.id },
83
      data: { activationCode: '123456', activationCodeExpiresAt: null },
84
    })
85

86
    const res = await request(app)
87
      .post('/auth/activate')
88
      .send({ code: '123456' })
89

90
    expect(res.status).toBe(422)
91
  })
92

93
  it('returns 422 for a well-formed but unknown code', async () => {
94
    await createTestUser(db, { email: 'activate@example.com' })
95

96
    const res = await request(app)
97
      .post('/auth/activate')
98
      .send({ code: '999999' })
99

100
    expect(res.status).toBe(422)
101
    expect(res.body.error).toBeTruthy()
102
  })
103

104
  it('cannot tell an expired code from an unknown one', async () => {
105
    const user = await createTestUser(db, { email: 'indistinct@example.com' })
106
    await seedActivationCode(user.id, '123456', -1000)
107

108
    const expired = await request(app)
109
      .post('/auth/activate')
110
      .send({ code: '123456' })
111

112
    const unknown = await request(app)
113
      .post('/auth/activate')
114
      .send({ code: '654321' })
115

116
    expect(expired.status).toBe(unknown.status)
117
    expect(expired.body).toEqual(unknown.body)
118
  })
119

120
  it('leaves the stored code in place when an expired code is rejected', async () => {
121
    const user = await createTestUser(db, { email: 'no-reissue@example.com' })
122
    await seedActivationCode(user.id, '123456', -1000)
123

124
    await request(app).post('/auth/activate').send({ code: '123456' })
125

126
    const dbUser = await db.user.findUnique({ where: { id: user.id } })
127
    expect(dbUser!.active).toBe(false)
128
    expect(dbUser!.activationCode).toBe('123456')
129
  })
130

131
  it.each([
132
    ['too short', '12345'],
133
    ['too long', '1234567'],
134
    ['non-digit', '12a456'],
135
    ['a number', 123456],
136
  ])('rejects a code that is %s as malformed', async (_shape, code) => {
137
    await createTestUser(db, { email: 'activate@example.com' })
138

139
    const res = await request(app)
140
      .post('/auth/activate')
141
      .send({ code })
142

143
    expect(res.status).toBe(400)
144
    expect(res.body.fields.code).toBeTruthy()
145
  })
146
})
147

148
describe('POST /auth/resend_code', () => {
149
  it('issues a fresh activation code for the authenticated user', async () => {
150
    const user = await createTestUser(db, { email: 'resend@example.com' })
151
    const token = generateTestToken(user.id, user.email)
152

153
    const res = await request(app)
154
      .post('/auth/resend_code')
155
      .set('Authorization', `Bearer ${token}`)
156

157
    expect(res.status).toBe(200)
158
    expectPublicUser(res.body.user)
159

160
    const dbUser = await db.user.findUnique({ where: { id: user.id } })
161
    expect(dbUser!.activationCode).toMatch(/^\d{6}$/)
162
    expect(dbUser!.activationCodeExpiresAt).not.toBeNull()
163
  })
164

165
  it('returns 401 without a token', async () => {
166
    const res = await request(app).post('/auth/resend_code')
167
    expect(res.status).toBe(401)
168
  })
169
})