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.
Files changed (35) hide show
  1. package/dist/simple-user/i18n/i18n-dict.d.ts +2 -0
  2. package/dist/simple-user/i18n/i18n-dict.js +157 -0
  3. package/dist/simple-user/i18n/i18n-dict.js.map +1 -0
  4. package/dist/simple-user/i18n/i18n-init.d.ts +8 -0
  5. package/dist/simple-user/i18n/i18n-init.js +14 -0
  6. package/dist/simple-user/i18n/i18n-init.js.map +1 -0
  7. package/dist/simple-user/i18n/i18n-middleware.d.ts +1 -0
  8. package/dist/simple-user/i18n/i18n-middleware.js +8 -0
  9. package/dist/simple-user/i18n/i18n-middleware.js.map +1 -0
  10. package/dist/simple-user/i18n/i18n-setup.service.d.ts +4 -0
  11. package/dist/simple-user/i18n/i18n-setup.service.js +26 -0
  12. package/dist/simple-user/i18n/i18n-setup.service.js.map +1 -0
  13. package/dist/simple-user/i18n/index.d.ts +3 -0
  14. package/dist/simple-user/i18n/index.js +20 -0
  15. package/dist/simple-user/i18n/index.js.map +1 -0
  16. package/dist/simple-user/index.d.ts +1 -0
  17. package/dist/simple-user/index.js +3 -0
  18. package/dist/simple-user/index.js.map +1 -1
  19. package/dist/simple-user/login/login.controller.js +2 -0
  20. package/dist/simple-user/login/login.controller.js.map +1 -1
  21. package/dist/simple-user/options.d.ts +1 -0
  22. package/dist/simple-user/send-code/send-code.controller.js +2 -0
  23. package/dist/simple-user/send-code/send-code.controller.js.map +1 -1
  24. package/dist/simple-user/send-code/send-code.service.js +3 -3
  25. package/dist/simple-user/send-code/send-code.service.js.map +1 -1
  26. package/dist/simple-user/simple-user/simple-user.service.js +5 -5
  27. package/dist/simple-user/simple-user/simple-user.service.js.map +1 -1
  28. package/dist/simple-user/simple-user.module.js +13 -2
  29. package/dist/simple-user/simple-user.module.js.map +1 -1
  30. package/dist/simple-user/user-center/user-center.controller.js +2 -0
  31. package/dist/simple-user/user-center/user-center.controller.js.map +1 -1
  32. package/dist/tsconfig.build.tsbuildinfo +1 -1
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +3 -2
  35. 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.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
+ });