@xivdyetools/auth 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -158
- package/dist/hmac.d.ts.map +1 -1
- package/dist/hmac.js +4 -3
- package/dist/hmac.js.map +1 -1
- package/dist/jwt.js.map +1 -1
- package/dist/timing.d.ts.map +1 -1
- package/dist/timing.js +4 -2
- package/dist/timing.js.map +1 -1
- package/package.json +75 -71
- package/src/discord.test.ts +243 -243
- package/src/discord.ts +143 -143
- package/src/hmac.test.ts +325 -325
- package/src/hmac.ts +223 -222
- package/src/index.ts +54 -54
- package/src/jwt.test.ts +337 -337
- package/src/jwt.ts +265 -265
- package/src/timing.test.ts +114 -117
- package/src/timing.ts +86 -84
package/src/discord.test.ts
CHANGED
|
@@ -1,243 +1,243 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Discord Request Verification
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, vi, beforeEach
|
|
5
|
-
import {
|
|
6
|
-
verifyDiscordRequest,
|
|
7
|
-
unauthorizedResponse,
|
|
8
|
-
badRequestResponse,
|
|
9
|
-
} from './discord.js';
|
|
10
|
-
|
|
11
|
-
// Mock discord-interactions
|
|
12
|
-
vi.mock('discord-interactions', () => ({
|
|
13
|
-
verifyKey: vi.fn(),
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
import { verifyKey } from 'discord-interactions';
|
|
17
|
-
|
|
18
|
-
describe('discord.ts', () => {
|
|
19
|
-
const mockPublicKey = 'test-public-key-123';
|
|
20
|
-
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
vi.clearAllMocks();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('verifyDiscordRequest', () => {
|
|
26
|
-
it('should return valid result for valid signature', async () => {
|
|
27
|
-
vi.mocked(verifyKey).mockResolvedValue(true);
|
|
28
|
-
|
|
29
|
-
const request = new Request('https://example.com/interactions', {
|
|
30
|
-
method: 'POST',
|
|
31
|
-
headers: {
|
|
32
|
-
'Content-Type': 'application/json',
|
|
33
|
-
'X-Signature-Ed25519': 'valid-signature',
|
|
34
|
-
'X-Signature-Timestamp': '1234567890',
|
|
35
|
-
'Content-Length': '50',
|
|
36
|
-
},
|
|
37
|
-
body: JSON.stringify({ type: 1 }),
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
41
|
-
|
|
42
|
-
expect(result.isValid).toBe(true);
|
|
43
|
-
expect(result.body).toBe(JSON.stringify({ type: 1 }));
|
|
44
|
-
expect(result.error).toBeUndefined();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should return invalid result for invalid signature', async () => {
|
|
48
|
-
vi.mocked(verifyKey).mockResolvedValue(false);
|
|
49
|
-
|
|
50
|
-
const request = new Request('https://example.com/interactions', {
|
|
51
|
-
method: 'POST',
|
|
52
|
-
headers: {
|
|
53
|
-
'Content-Type': 'application/json',
|
|
54
|
-
'X-Signature-Ed25519': 'invalid-signature',
|
|
55
|
-
'X-Signature-Timestamp': '1234567890',
|
|
56
|
-
},
|
|
57
|
-
body: JSON.stringify({ type: 1 }),
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
61
|
-
|
|
62
|
-
expect(result.isValid).toBe(false);
|
|
63
|
-
expect(result.error).toBe('Invalid signature');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should reject request with missing signature header', async () => {
|
|
67
|
-
const request = new Request('https://example.com/interactions', {
|
|
68
|
-
method: 'POST',
|
|
69
|
-
headers: {
|
|
70
|
-
'Content-Type': 'application/json',
|
|
71
|
-
'X-Signature-Timestamp': '1234567890',
|
|
72
|
-
},
|
|
73
|
-
body: JSON.stringify({ type: 1 }),
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
77
|
-
|
|
78
|
-
expect(result.isValid).toBe(false);
|
|
79
|
-
expect(result.error).toBe('Missing signature headers');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('should reject request with missing timestamp header', async () => {
|
|
83
|
-
const request = new Request('https://example.com/interactions', {
|
|
84
|
-
method: 'POST',
|
|
85
|
-
headers: {
|
|
86
|
-
'Content-Type': 'application/json',
|
|
87
|
-
'X-Signature-Ed25519': 'some-signature',
|
|
88
|
-
},
|
|
89
|
-
body: JSON.stringify({ type: 1 }),
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
93
|
-
|
|
94
|
-
expect(result.isValid).toBe(false);
|
|
95
|
-
expect(result.error).toBe('Missing signature headers');
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should reject request with Content-Length exceeding limit', async () => {
|
|
99
|
-
const request = new Request('https://example.com/interactions', {
|
|
100
|
-
method: 'POST',
|
|
101
|
-
headers: {
|
|
102
|
-
'Content-Type': 'application/json',
|
|
103
|
-
'X-Signature-Ed25519': 'some-signature',
|
|
104
|
-
'X-Signature-Timestamp': '1234567890',
|
|
105
|
-
'Content-Length': '200000', // 200KB, exceeds 100KB limit
|
|
106
|
-
},
|
|
107
|
-
body: JSON.stringify({ type: 1 }),
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
111
|
-
|
|
112
|
-
expect(result.isValid).toBe(false);
|
|
113
|
-
expect(result.error).toBe('Request body too large');
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('should reject request with actual body exceeding limit', async () => {
|
|
117
|
-
// Create a large body
|
|
118
|
-
const largeBody = 'x'.repeat(150_000); // 150KB
|
|
119
|
-
|
|
120
|
-
const request = new Request('https://example.com/interactions', {
|
|
121
|
-
method: 'POST',
|
|
122
|
-
headers: {
|
|
123
|
-
'Content-Type': 'application/json',
|
|
124
|
-
'X-Signature-Ed25519': 'some-signature',
|
|
125
|
-
'X-Signature-Timestamp': '1234567890',
|
|
126
|
-
// No Content-Length header to bypass first check
|
|
127
|
-
},
|
|
128
|
-
body: largeBody,
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
132
|
-
|
|
133
|
-
expect(result.isValid).toBe(false);
|
|
134
|
-
expect(result.error).toBe('Request body too large');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should respect custom maxBodySize option', async () => {
|
|
138
|
-
const request = new Request('https://example.com/interactions', {
|
|
139
|
-
method: 'POST',
|
|
140
|
-
headers: {
|
|
141
|
-
'Content-Type': 'application/json',
|
|
142
|
-
'X-Signature-Ed25519': 'some-signature',
|
|
143
|
-
'X-Signature-Timestamp': '1234567890',
|
|
144
|
-
'Content-Length': '500', // 500 bytes
|
|
145
|
-
},
|
|
146
|
-
body: JSON.stringify({ type: 1 }),
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const result = await verifyDiscordRequest(request, mockPublicKey, {
|
|
150
|
-
maxBodySize: 100, // Only allow 100 bytes
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
expect(result.isValid).toBe(false);
|
|
154
|
-
expect(result.error).toBe('Request body too large');
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should handle verifyKey throwing an error', async () => {
|
|
158
|
-
vi.mocked(verifyKey).mockRejectedValue(new Error('Verification error'));
|
|
159
|
-
|
|
160
|
-
const request = new Request('https://example.com/interactions', {
|
|
161
|
-
method: 'POST',
|
|
162
|
-
headers: {
|
|
163
|
-
'Content-Type': 'application/json',
|
|
164
|
-
'X-Signature-Ed25519': 'some-signature',
|
|
165
|
-
'X-Signature-Timestamp': '1234567890',
|
|
166
|
-
},
|
|
167
|
-
body: JSON.stringify({ type: 1 }),
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
171
|
-
|
|
172
|
-
expect(result.isValid).toBe(false);
|
|
173
|
-
expect(result.error).toBe('Verification error');
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should handle non-Error exceptions from verifyKey', async () => {
|
|
177
|
-
vi.mocked(verifyKey).mockRejectedValue('string error');
|
|
178
|
-
|
|
179
|
-
const request = new Request('https://example.com/interactions', {
|
|
180
|
-
method: 'POST',
|
|
181
|
-
headers: {
|
|
182
|
-
'Content-Type': 'application/json',
|
|
183
|
-
'X-Signature-Ed25519': 'some-signature',
|
|
184
|
-
'X-Signature-Timestamp': '1234567890',
|
|
185
|
-
},
|
|
186
|
-
body: JSON.stringify({ type: 1 }),
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
190
|
-
|
|
191
|
-
expect(result.isValid).toBe(false);
|
|
192
|
-
expect(result.error).toBe('Verification failed');
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('should include body in result even on invalid signature', async () => {
|
|
196
|
-
vi.mocked(verifyKey).mockResolvedValue(false);
|
|
197
|
-
|
|
198
|
-
const bodyContent = JSON.stringify({ type: 2, data: { name: 'test' } });
|
|
199
|
-
const request = new Request('https://example.com/interactions', {
|
|
200
|
-
method: 'POST',
|
|
201
|
-
headers: {
|
|
202
|
-
'Content-Type': 'application/json',
|
|
203
|
-
'X-Signature-Ed25519': 'invalid-signature',
|
|
204
|
-
'X-Signature-Timestamp': '1234567890',
|
|
205
|
-
},
|
|
206
|
-
body: bodyContent,
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
210
|
-
|
|
211
|
-
expect(result.isValid).toBe(false);
|
|
212
|
-
expect(result.body).toBe(bodyContent);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
describe('unauthorizedResponse', () => {
|
|
217
|
-
it('should return 401 response with default message', () => {
|
|
218
|
-
const response = unauthorizedResponse();
|
|
219
|
-
|
|
220
|
-
expect(response.status).toBe(401);
|
|
221
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should return 401 response with custom message', async () => {
|
|
225
|
-
const response = unauthorizedResponse('Custom error message');
|
|
226
|
-
const body = await response.json()
|
|
227
|
-
|
|
228
|
-
expect(response.status).toBe(401);
|
|
229
|
-
expect(body.error).toBe('Custom error message');
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
describe('badRequestResponse', () => {
|
|
234
|
-
it('should return 400 response with message', async () => {
|
|
235
|
-
const response = badRequestResponse('Bad request error');
|
|
236
|
-
const body = await response.json()
|
|
237
|
-
|
|
238
|
-
expect(response.status).toBe(400);
|
|
239
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
240
|
-
expect(body.error).toBe('Bad request error');
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Discord Request Verification
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
verifyDiscordRequest,
|
|
7
|
+
unauthorizedResponse,
|
|
8
|
+
badRequestResponse,
|
|
9
|
+
} from './discord.js';
|
|
10
|
+
|
|
11
|
+
// Mock discord-interactions
|
|
12
|
+
vi.mock('discord-interactions', () => ({
|
|
13
|
+
verifyKey: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
import { verifyKey } from 'discord-interactions';
|
|
17
|
+
|
|
18
|
+
describe('discord.ts', () => {
|
|
19
|
+
const mockPublicKey = 'test-public-key-123';
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
vi.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('verifyDiscordRequest', () => {
|
|
26
|
+
it('should return valid result for valid signature', async () => {
|
|
27
|
+
vi.mocked(verifyKey).mockResolvedValue(true);
|
|
28
|
+
|
|
29
|
+
const request = new Request('https://example.com/interactions', {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
'X-Signature-Ed25519': 'valid-signature',
|
|
34
|
+
'X-Signature-Timestamp': '1234567890',
|
|
35
|
+
'Content-Length': '50',
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({ type: 1 }),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
41
|
+
|
|
42
|
+
expect(result.isValid).toBe(true);
|
|
43
|
+
expect(result.body).toBe(JSON.stringify({ type: 1 }));
|
|
44
|
+
expect(result.error).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should return invalid result for invalid signature', async () => {
|
|
48
|
+
vi.mocked(verifyKey).mockResolvedValue(false);
|
|
49
|
+
|
|
50
|
+
const request = new Request('https://example.com/interactions', {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type': 'application/json',
|
|
54
|
+
'X-Signature-Ed25519': 'invalid-signature',
|
|
55
|
+
'X-Signature-Timestamp': '1234567890',
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify({ type: 1 }),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
61
|
+
|
|
62
|
+
expect(result.isValid).toBe(false);
|
|
63
|
+
expect(result.error).toBe('Invalid signature');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should reject request with missing signature header', async () => {
|
|
67
|
+
const request = new Request('https://example.com/interactions', {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
'X-Signature-Timestamp': '1234567890',
|
|
72
|
+
},
|
|
73
|
+
body: JSON.stringify({ type: 1 }),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
77
|
+
|
|
78
|
+
expect(result.isValid).toBe(false);
|
|
79
|
+
expect(result.error).toBe('Missing signature headers');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should reject request with missing timestamp header', async () => {
|
|
83
|
+
const request = new Request('https://example.com/interactions', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
'X-Signature-Ed25519': 'some-signature',
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({ type: 1 }),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
93
|
+
|
|
94
|
+
expect(result.isValid).toBe(false);
|
|
95
|
+
expect(result.error).toBe('Missing signature headers');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should reject request with Content-Length exceeding limit', async () => {
|
|
99
|
+
const request = new Request('https://example.com/interactions', {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: {
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
'X-Signature-Ed25519': 'some-signature',
|
|
104
|
+
'X-Signature-Timestamp': '1234567890',
|
|
105
|
+
'Content-Length': '200000', // 200KB, exceeds 100KB limit
|
|
106
|
+
},
|
|
107
|
+
body: JSON.stringify({ type: 1 }),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
111
|
+
|
|
112
|
+
expect(result.isValid).toBe(false);
|
|
113
|
+
expect(result.error).toBe('Request body too large');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should reject request with actual body exceeding limit', async () => {
|
|
117
|
+
// Create a large body
|
|
118
|
+
const largeBody = 'x'.repeat(150_000); // 150KB
|
|
119
|
+
|
|
120
|
+
const request = new Request('https://example.com/interactions', {
|
|
121
|
+
method: 'POST',
|
|
122
|
+
headers: {
|
|
123
|
+
'Content-Type': 'application/json',
|
|
124
|
+
'X-Signature-Ed25519': 'some-signature',
|
|
125
|
+
'X-Signature-Timestamp': '1234567890',
|
|
126
|
+
// No Content-Length header to bypass first check
|
|
127
|
+
},
|
|
128
|
+
body: largeBody,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
132
|
+
|
|
133
|
+
expect(result.isValid).toBe(false);
|
|
134
|
+
expect(result.error).toBe('Request body too large');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should respect custom maxBodySize option', async () => {
|
|
138
|
+
const request = new Request('https://example.com/interactions', {
|
|
139
|
+
method: 'POST',
|
|
140
|
+
headers: {
|
|
141
|
+
'Content-Type': 'application/json',
|
|
142
|
+
'X-Signature-Ed25519': 'some-signature',
|
|
143
|
+
'X-Signature-Timestamp': '1234567890',
|
|
144
|
+
'Content-Length': '500', // 500 bytes
|
|
145
|
+
},
|
|
146
|
+
body: JSON.stringify({ type: 1 }),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const result = await verifyDiscordRequest(request, mockPublicKey, {
|
|
150
|
+
maxBodySize: 100, // Only allow 100 bytes
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(result.isValid).toBe(false);
|
|
154
|
+
expect(result.error).toBe('Request body too large');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should handle verifyKey throwing an error', async () => {
|
|
158
|
+
vi.mocked(verifyKey).mockRejectedValue(new Error('Verification error'));
|
|
159
|
+
|
|
160
|
+
const request = new Request('https://example.com/interactions', {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers: {
|
|
163
|
+
'Content-Type': 'application/json',
|
|
164
|
+
'X-Signature-Ed25519': 'some-signature',
|
|
165
|
+
'X-Signature-Timestamp': '1234567890',
|
|
166
|
+
},
|
|
167
|
+
body: JSON.stringify({ type: 1 }),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
171
|
+
|
|
172
|
+
expect(result.isValid).toBe(false);
|
|
173
|
+
expect(result.error).toBe('Verification error');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should handle non-Error exceptions from verifyKey', async () => {
|
|
177
|
+
vi.mocked(verifyKey).mockRejectedValue('string error');
|
|
178
|
+
|
|
179
|
+
const request = new Request('https://example.com/interactions', {
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: {
|
|
182
|
+
'Content-Type': 'application/json',
|
|
183
|
+
'X-Signature-Ed25519': 'some-signature',
|
|
184
|
+
'X-Signature-Timestamp': '1234567890',
|
|
185
|
+
},
|
|
186
|
+
body: JSON.stringify({ type: 1 }),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
190
|
+
|
|
191
|
+
expect(result.isValid).toBe(false);
|
|
192
|
+
expect(result.error).toBe('Verification failed');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should include body in result even on invalid signature', async () => {
|
|
196
|
+
vi.mocked(verifyKey).mockResolvedValue(false);
|
|
197
|
+
|
|
198
|
+
const bodyContent = JSON.stringify({ type: 2, data: { name: 'test' } });
|
|
199
|
+
const request = new Request('https://example.com/interactions', {
|
|
200
|
+
method: 'POST',
|
|
201
|
+
headers: {
|
|
202
|
+
'Content-Type': 'application/json',
|
|
203
|
+
'X-Signature-Ed25519': 'invalid-signature',
|
|
204
|
+
'X-Signature-Timestamp': '1234567890',
|
|
205
|
+
},
|
|
206
|
+
body: bodyContent,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const result = await verifyDiscordRequest(request, mockPublicKey);
|
|
210
|
+
|
|
211
|
+
expect(result.isValid).toBe(false);
|
|
212
|
+
expect(result.body).toBe(bodyContent);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe('unauthorizedResponse', () => {
|
|
217
|
+
it('should return 401 response with default message', () => {
|
|
218
|
+
const response = unauthorizedResponse();
|
|
219
|
+
|
|
220
|
+
expect(response.status).toBe(401);
|
|
221
|
+
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should return 401 response with custom message', async () => {
|
|
225
|
+
const response = unauthorizedResponse('Custom error message');
|
|
226
|
+
const body = (await response.json()) as Record<string, unknown>;
|
|
227
|
+
|
|
228
|
+
expect(response.status).toBe(401);
|
|
229
|
+
expect(body.error).toBe('Custom error message');
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('badRequestResponse', () => {
|
|
234
|
+
it('should return 400 response with message', async () => {
|
|
235
|
+
const response = badRequestResponse('Bad request error');
|
|
236
|
+
const body = (await response.json()) as Record<string, unknown>;
|
|
237
|
+
|
|
238
|
+
expect(response.status).toBe(400);
|
|
239
|
+
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
240
|
+
expect(body.error).toBe('Bad request error');
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|