nicot-simple-user 2.0.0 → 2.0.1
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/dist/simple-user/i18n/i18n-dict.d.ts +2 -0
- package/dist/simple-user/i18n/i18n-dict.js +157 -0
- package/dist/simple-user/i18n/i18n-dict.js.map +1 -0
- package/dist/simple-user/i18n/i18n-init.d.ts +8 -0
- package/dist/simple-user/i18n/i18n-init.js +14 -0
- package/dist/simple-user/i18n/i18n-init.js.map +1 -0
- package/dist/simple-user/i18n/i18n-middleware.d.ts +1 -0
- package/dist/simple-user/i18n/i18n-middleware.js +8 -0
- package/dist/simple-user/i18n/i18n-middleware.js.map +1 -0
- package/dist/simple-user/i18n/i18n-setup.service.d.ts +4 -0
- package/dist/simple-user/i18n/i18n-setup.service.js +26 -0
- package/dist/simple-user/i18n/i18n-setup.service.js.map +1 -0
- package/dist/simple-user/i18n/index.d.ts +3 -0
- package/dist/simple-user/i18n/index.js +20 -0
- package/dist/simple-user/i18n/index.js.map +1 -0
- package/dist/simple-user/index.d.ts +1 -0
- package/dist/simple-user/index.js +3 -0
- package/dist/simple-user/index.js.map +1 -1
- package/dist/simple-user/login/login.controller.js +2 -0
- package/dist/simple-user/login/login.controller.js.map +1 -1
- package/dist/simple-user/options.d.ts +1 -0
- package/dist/simple-user/send-code/send-code.controller.js +2 -0
- package/dist/simple-user/send-code/send-code.controller.js.map +1 -1
- package/dist/simple-user/send-code/send-code.service.js +3 -3
- package/dist/simple-user/send-code/send-code.service.js.map +1 -1
- package/dist/simple-user/simple-user/simple-user.service.js +5 -5
- package/dist/simple-user/simple-user/simple-user.service.js.map +1 -1
- package/dist/simple-user/simple-user.module.js +13 -2
- package/dist/simple-user/simple-user.module.js.map +1 -1
- package/dist/simple-user/user-center/user-center.controller.js +2 -0
- package/dist/simple-user/user-center/user-center.controller.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/test/i18n.spec.ts +287 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nicot-simple-user",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Simple user module based on NICOT",
|
|
5
5
|
"author": "Nanahira <nanahira@momobako.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"**/*.(t|j)s"
|
|
94
94
|
],
|
|
95
95
|
"coverageDirectory": "../coverage",
|
|
96
|
-
"testEnvironment": "node"
|
|
96
|
+
"testEnvironment": "node",
|
|
97
|
+
"maxWorkers": 1
|
|
97
98
|
}
|
|
98
99
|
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { INestApplication } from '@nestjs/common';
|
|
3
|
+
import request from 'supertest';
|
|
4
|
+
import { AppModule } from './../src/app.module';
|
|
5
|
+
import { GenericReturnMessageDto } from 'nicot';
|
|
6
|
+
import { LoginResponseDto } from '../src/simple-user/simple-user/login.dto';
|
|
7
|
+
import { SIMPLE_USER_I18N_DICT } from '../src/simple-user/i18n/i18n-dict';
|
|
8
|
+
|
|
9
|
+
const dict = SIMPLE_USER_I18N_DICT;
|
|
10
|
+
|
|
11
|
+
describe('i18n (e2e)', () => {
|
|
12
|
+
let app: INestApplication;
|
|
13
|
+
let httpServer: any;
|
|
14
|
+
|
|
15
|
+
const EMAIL_CODE = '123456';
|
|
16
|
+
const SMS_CODE = '654321';
|
|
17
|
+
|
|
18
|
+
const rand = Math.random().toString(16).slice(2);
|
|
19
|
+
const email = `i18n_${rand}@example.com`;
|
|
20
|
+
const mobile = `86 1380000${rand.slice(0, 4)}`;
|
|
21
|
+
const ssaid = `ssaid_i18n_${rand}`;
|
|
22
|
+
const password = `P@ss_${rand}`;
|
|
23
|
+
|
|
24
|
+
let token: string;
|
|
25
|
+
|
|
26
|
+
beforeAll(async () => {
|
|
27
|
+
const moduleFixture: TestingModule = await Test.createTestingModule({
|
|
28
|
+
imports: [AppModule],
|
|
29
|
+
}).compile();
|
|
30
|
+
|
|
31
|
+
app = moduleFixture.createNestApplication();
|
|
32
|
+
await app.init();
|
|
33
|
+
httpServer = app.getHttpServer();
|
|
34
|
+
|
|
35
|
+
await request(httpServer)
|
|
36
|
+
.post('/send-code/send')
|
|
37
|
+
.set('x-client-ssaid', ssaid)
|
|
38
|
+
.send({ email, codePurpose: 'Login' });
|
|
39
|
+
|
|
40
|
+
const res = await request(httpServer)
|
|
41
|
+
.post('/login')
|
|
42
|
+
.set('x-client-ssaid', ssaid)
|
|
43
|
+
.send({ email, code: EMAIL_CODE, setPassword: password });
|
|
44
|
+
|
|
45
|
+
token = (res.body as GenericReturnMessageDto<LoginResponseDto>).data.token;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterAll(async () => {
|
|
49
|
+
await app.close();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const lang = (req: request.Test, locale?: string) =>
|
|
53
|
+
locale ? req.set('x-client-language', locale) : req;
|
|
54
|
+
|
|
55
|
+
// ──────────────────────────────────────────────────────────
|
|
56
|
+
// 403 Invalid password
|
|
57
|
+
// ──────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
describe('403 - invalid_password', () => {
|
|
60
|
+
const makeRequest = (locale?: string) =>
|
|
61
|
+
lang(
|
|
62
|
+
request(httpServer)
|
|
63
|
+
.post('/login')
|
|
64
|
+
.set('x-client-ssaid', ssaid)
|
|
65
|
+
.send({ email, password: 'WRONG_PASSWORD' }),
|
|
66
|
+
locale,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
it('default (en)', async () => {
|
|
70
|
+
const res = await makeRequest().expect(403);
|
|
71
|
+
expect(res.body.message).toBe(dict.en.invalid_password);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('zh', async () => {
|
|
75
|
+
const res = await makeRequest('zh').expect(403);
|
|
76
|
+
expect(res.body.message).toBe(dict.zh.invalid_password);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('zh-Hant', async () => {
|
|
80
|
+
const res = await makeRequest('zh-Hant').expect(403);
|
|
81
|
+
expect(res.body.message).toBe(dict['zh-Hant'].invalid_password);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('ja', async () => {
|
|
85
|
+
const res = await makeRequest('ja').expect(403);
|
|
86
|
+
expect(res.body.message).toBe(dict.ja.invalid_password);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('ko', async () => {
|
|
90
|
+
const res = await makeRequest('ko').expect(403);
|
|
91
|
+
expect(res.body.message).toBe(dict.ko.invalid_password);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('unknown locale falls back to en', async () => {
|
|
95
|
+
const res = await makeRequest('xx-YY').expect(403);
|
|
96
|
+
expect(res.body.message).toBe(dict.en.invalid_password);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// ──────────────────────────────────────────────────────────
|
|
101
|
+
// 403 Invalid verification code
|
|
102
|
+
// ──────────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
describe('403 - invalid_code', () => {
|
|
105
|
+
beforeAll(async () => {
|
|
106
|
+
await request(httpServer)
|
|
107
|
+
.post('/send-code/send')
|
|
108
|
+
.set('x-client-ssaid', ssaid)
|
|
109
|
+
.send({ email, codePurpose: 'Login' });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const makeRequest = (locale?: string) =>
|
|
113
|
+
lang(
|
|
114
|
+
request(httpServer)
|
|
115
|
+
.get('/send-code/verify')
|
|
116
|
+
.query({ email, codePurpose: 'Login', code: '000000' }),
|
|
117
|
+
locale,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
it('default (en)', async () => {
|
|
121
|
+
const res = await makeRequest().expect(403);
|
|
122
|
+
expect(res.body.message).toBe(dict.en.invalid_code);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('zh', async () => {
|
|
126
|
+
const res = await makeRequest('zh').expect(403);
|
|
127
|
+
expect(res.body.message).toBe(dict.zh.invalid_code);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('fr', async () => {
|
|
131
|
+
const res = await makeRequest('fr').expect(403);
|
|
132
|
+
expect(res.body.message).toBe(dict.fr.invalid_code);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('de', async () => {
|
|
136
|
+
const res = await makeRequest('de').expect(403);
|
|
137
|
+
expect(res.body.message).toBe(dict.de.invalid_code);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// ──────────────────────────────────────────────────────────
|
|
142
|
+
// 404 User does not exist (password login for unknown user)
|
|
143
|
+
// ──────────────────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
describe('404 - user_not_exist_provide_code', () => {
|
|
146
|
+
const nonExistentEmail = `nouser_${rand}@example.com`;
|
|
147
|
+
|
|
148
|
+
const makeRequest = (locale?: string) =>
|
|
149
|
+
lang(
|
|
150
|
+
request(httpServer)
|
|
151
|
+
.post('/login')
|
|
152
|
+
.set('x-client-ssaid', `ssaid_nouser_${rand}`)
|
|
153
|
+
.send({ email: nonExistentEmail, password: 'any' }),
|
|
154
|
+
locale,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
it('default (en)', async () => {
|
|
158
|
+
const res = await makeRequest().expect(404);
|
|
159
|
+
expect(res.body.message).toBe(dict.en.user_not_exist_provide_code);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('zh', async () => {
|
|
163
|
+
const res = await makeRequest('zh').expect(404);
|
|
164
|
+
expect(res.body.message).toBe(dict.zh.user_not_exist_provide_code);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('es', async () => {
|
|
168
|
+
const res = await makeRequest('es').expect(404);
|
|
169
|
+
expect(res.body.message).toBe(dict.es.user_not_exist_provide_code);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('ru', async () => {
|
|
173
|
+
const res = await makeRequest('ru').expect(404);
|
|
174
|
+
expect(res.body.message).toBe(dict.ru.user_not_exist_provide_code);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// ──────────────────────────────────────────────────────────
|
|
179
|
+
// 403 Current password is incorrect
|
|
180
|
+
// ──────────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
describe('403 - current_password_incorrect', () => {
|
|
183
|
+
const makeRequest = (locale?: string) =>
|
|
184
|
+
lang(
|
|
185
|
+
request(httpServer)
|
|
186
|
+
.post('/user-center/change-password')
|
|
187
|
+
.set('x-client-ssaid', ssaid)
|
|
188
|
+
.set('x-client-token', token)
|
|
189
|
+
.send({ currentPassword: 'WRONG', newPassword: 'Whatever1!' }),
|
|
190
|
+
locale,
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
it('default (en)', async () => {
|
|
194
|
+
const res = await makeRequest().expect(403);
|
|
195
|
+
expect(res.body.message).toBe(dict.en.current_password_incorrect);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('zh', async () => {
|
|
199
|
+
const res = await makeRequest('zh').expect(403);
|
|
200
|
+
expect(res.body.message).toBe(dict.zh.current_password_incorrect);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('zh-Hant', async () => {
|
|
204
|
+
const res = await makeRequest('zh-Hant').expect(403);
|
|
205
|
+
expect(res.body.message).toBe(
|
|
206
|
+
dict['zh-Hant'].current_password_incorrect,
|
|
207
|
+
);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('tr', async () => {
|
|
211
|
+
const res = await makeRequest('tr').expect(403);
|
|
212
|
+
expect(res.body.message).toBe(dict.tr.current_password_incorrect);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// ──────────────────────────────────────────────────────────
|
|
217
|
+
// 200 success messages should NOT be translated
|
|
218
|
+
// ──────────────────────────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
describe('200 success is not affected by i18n', () => {
|
|
221
|
+
it('GET /user-center/me with zh should still return success', async () => {
|
|
222
|
+
const res = await request(httpServer)
|
|
223
|
+
.get('/user-center/me')
|
|
224
|
+
.set('x-client-ssaid', ssaid)
|
|
225
|
+
.set('x-client-token', token)
|
|
226
|
+
.set('x-client-language', 'zh')
|
|
227
|
+
.expect(200);
|
|
228
|
+
|
|
229
|
+
expect(res.body.message).toBe('success');
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// ──────────────────────────────────────────────────────────
|
|
234
|
+
// Hierarchy fallback
|
|
235
|
+
// ──────────────────────────────────────────────────────────
|
|
236
|
+
|
|
237
|
+
describe('hierarchy fallback', () => {
|
|
238
|
+
const makeRequest = (locale: string) =>
|
|
239
|
+
request(httpServer)
|
|
240
|
+
.post('/login')
|
|
241
|
+
.set('x-client-ssaid', ssaid)
|
|
242
|
+
.set('x-client-language', locale)
|
|
243
|
+
.send({ email, password: 'WRONG_PASSWORD' });
|
|
244
|
+
|
|
245
|
+
it('zh-Hans-CN falls back to zh', async () => {
|
|
246
|
+
const res = await makeRequest('zh-Hans-CN').expect(403);
|
|
247
|
+
expect(res.body.message).toBe(dict.zh.invalid_password);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('zh-TW falls back to zh', async () => {
|
|
251
|
+
const res = await makeRequest('zh-TW').expect(403);
|
|
252
|
+
expect(res.body.message).toBe(dict.zh.invalid_password);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// ──────────────────────────────────────────────────────────
|
|
257
|
+
// Mobile errors also translated
|
|
258
|
+
// ──────────────────────────────────────────────────────────
|
|
259
|
+
|
|
260
|
+
describe('mobile errors are also i18n-translated', () => {
|
|
261
|
+
it('404 via mobile login (zh)', async () => {
|
|
262
|
+
const res = await request(httpServer)
|
|
263
|
+
.post('/login')
|
|
264
|
+
.set('x-client-ssaid', `ssaid_mob_${rand}`)
|
|
265
|
+
.set('x-client-language', 'zh')
|
|
266
|
+
.send({ mobile: '86 19900000000', password: 'any' })
|
|
267
|
+
.expect(404);
|
|
268
|
+
|
|
269
|
+
expect(res.body.message).toBe(dict.zh.user_not_exist_provide_code);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('403 invalid SMS code (ja)', async () => {
|
|
273
|
+
await request(httpServer)
|
|
274
|
+
.post('/send-code/send')
|
|
275
|
+
.set('x-client-ssaid', ssaid)
|
|
276
|
+
.send({ mobile, codePurpose: 'Login' });
|
|
277
|
+
|
|
278
|
+
const res = await request(httpServer)
|
|
279
|
+
.get('/send-code/verify')
|
|
280
|
+
.query({ mobile, codePurpose: 'Login', code: '000000' })
|
|
281
|
+
.set('x-client-language', 'ja')
|
|
282
|
+
.expect(403);
|
|
283
|
+
|
|
284
|
+
expect(res.body.message).toBe(dict.ja.invalid_code);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
});
|