Skip to content

Commit d43b3eb

Browse files
committed
feat: fixing the pagination, token and token refresh and tests
1 parent b4650e8 commit d43b3eb

19 files changed

+919
-619
lines changed

package-lock.json

Lines changed: 516 additions & 482 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@aws-sdk/client-ssm": "^3.759.0",
2727
"compression": "^1.8.0",
2828
"cookie-parser": "^1.4.7",
29+
"cors": "^2.8.5",
2930
"dotenv": "^16.4.7",
3031
"express": "^4.21.2",
3132
"express-rate-limit": "^7.5.0",
@@ -48,6 +49,7 @@
4849
"@eslint/js": "^9.22.0",
4950
"@types/compression": "^1.7.5",
5051
"@types/cookie-parser": "^1.4.8",
52+
"@types/cors": "^2.8.17",
5153
"@types/express": "^4.17.21",
5254
"@types/jest": "^29.5.14",
5355
"@types/jsonwebtoken": "^9.0.9",

src/__tests__/repositories/GenericRepository.test.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,24 @@ describe('GenericRepository', () => {
358358
const entities = [testEntity, { ...testEntity, id: 2 }];
359359
mockRepository.findAndCount.mockResolvedValue([entities, 2]);
360360

361-
const skip = 0;
362-
const take = 2;
363-
const result = await testRepository.getEntitiesWithPagination(skip, take);
361+
const page = 1;
362+
const perPage = 2;
363+
const expectedSkip = 0;
364+
const expectedTake = 2;
365+
366+
const result = await testRepository.getEntitiesWithPagination(
367+
page,
368+
perPage,
369+
);
364370

365371
expect(result).toEqual({ data: entities, count: 2 });
366-
expect(mockRepository.findAndCount).toHaveBeenCalledWith({ skip, take });
372+
expect(mockRepository.findAndCount).toHaveBeenCalledWith({
373+
skip: expectedSkip,
374+
take: expectedTake,
375+
});
367376
expect(logger.info).toHaveBeenCalledWith(
368377
expect.stringContaining(
369-
`Retrieved ${entities.length} records (Page size: ${take})`,
378+
`Retrieved ${entities.length} records (Page: ${page}, PerPage: ${perPage})`,
370379
),
371380
);
372381
});

src/__tests__/repositories/SellRepository.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,19 @@ describe('SellRepository', () => {
219219
it('should return paginated sell entities', async () => {
220220
mockRepository.findAndCount.mockResolvedValue([[testSell], 1]);
221221

222-
const result = await sellRepository.getEntitiesWithPagination(0, 10);
222+
const page = 1;
223+
const perPage = 10;
224+
const expectedSkip = (page - 1) * perPage;
225+
226+
const result = await sellRepository.getEntitiesWithPagination(
227+
page,
228+
perPage,
229+
);
223230

224231
expect(result).toEqual({ data: [testSell], count: 1 });
225232
expect(mockRepository.findAndCount).toHaveBeenCalledWith({
226-
skip: 0,
227-
take: 10,
233+
skip: expectedSkip,
234+
take: perPage,
228235
});
229236
});
230237

src/__tests__/services/AuthenticationService.test.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
authenticate as cognitoAuthenticate,
66
registerUser as cognitoRegisterUser,
77
resendConfirmationCode as cognitoResendConfirmation,
8+
refreshToken as cognitoRefreshToken,
89
} from '../../utils/cognitoUtil';
910

1011
// Mock dependencies
@@ -21,7 +22,10 @@ describe('AuthenticationService', () => {
2122
const testUsername = 'testuser';
2223
const testPassword = 'TestPassword123!';
2324
const testEmail = 'test@example.com';
24-
const testToken = 'mock-id-token';
25+
const testToken = {
26+
idToken: 'fake-jwt-token',
27+
refreshToken: 'fake-refresh-token',
28+
};
2529
const testConfirmationCode = '123456';
2630

2731
beforeEach(() => {
@@ -78,7 +82,7 @@ describe('AuthenticationService', () => {
7882
);
7983

8084
// Assert
81-
expect(result).toBe(testToken);
85+
expect(result).toStrictEqual(testToken);
8286
expect(cognitoAuthenticate).toHaveBeenCalledWith(
8387
testUsername,
8488
testPassword,
@@ -241,4 +245,31 @@ describe('AuthenticationService', () => {
241245
expect(logCalls.join(' ')).not.toContain(testPassword);
242246
});
243247
});
248+
describe('refreshUserToken', () => {
249+
const validRefreshToken = 'valid-refresh-token';
250+
251+
it('should refresh the token successfully', async () => {
252+
(cognitoRefreshToken as jest.Mock).mockResolvedValue('new-id-token');
253+
254+
const result = await authService.refreshUserToken(validRefreshToken);
255+
256+
expect(result).toBe('new-id-token');
257+
expect(cognitoRefreshToken).toHaveBeenCalledWith(validRefreshToken);
258+
expect(logger.info).toHaveBeenCalledWith(
259+
expect.stringContaining('Refreshing token for user with refresh token'),
260+
);
261+
expect(logger.info).toHaveBeenCalledWith(
262+
expect.stringContaining('Token refreshed successfully'),
263+
);
264+
});
265+
266+
it('should throw error when refresh fails', async () => {
267+
const error = new Error('Refresh failed');
268+
(cognitoRefreshToken as jest.Mock).mockRejectedValue(error);
269+
270+
await expect(
271+
authService.refreshUserToken(validRefreshToken),
272+
).rejects.toThrow('Refresh failed');
273+
});
274+
});
244275
});

src/__tests__/services/GenericService.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ describe('GenericService', () => {
257257
count: 2,
258258
});
259259

260-
const result = await testService.findWithPagination(0, 2);
260+
const result = await testService.findPaginated(0, 2);
261261

262262
expect(result).toEqual({ data: entities, count: 2 });
263263
expect(mockRepository.getEntitiesWithPagination).toHaveBeenCalledWith(
@@ -280,7 +280,7 @@ describe('GenericService', () => {
280280
const cacheKey = 'testentity:pagination:skip=0:take=2';
281281
mockCache.get.mockResolvedValue(JSON.stringify(paginatedResult));
282282

283-
const result = await testService.findWithPagination(0, 2);
283+
const result = await testService.findPaginated(0, 2);
284284

285285
expect(result).toEqual(paginatedResult);
286286
expect(mockRepository.getEntitiesWithPagination).not.toHaveBeenCalled();

src/__tests__/services/UserService.test.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ describe('UserService', () => {
6868
confirmUserRegistration: jest.fn(),
6969
resendConfirmationCode: jest.fn(),
7070
authenticateUser: jest.fn(),
71+
refreshUserToken: jest.fn(),
7172
} as unknown as jest.Mocked<AuthenticationService>;
7273

7374
// Mocked PasswordService
@@ -262,7 +263,11 @@ describe('UserService', () => {
262263
describe('authenticate', () => {
263264
it('should authenticate a user successfully (cache miss, DB hit)', async () => {
264265
// Arrange
265-
mockAuthService.authenticateUser.mockResolvedValue('fake-jwt-token');
266+
mockAuthService.authenticateUser.mockResolvedValue({
267+
idToken: 'fake-jwt-token',
268+
refreshToken: 'fake-refresh-token',
269+
});
270+
266271
// user not in cache
267272
mockCache.get.mockResolvedValue(null);
268273
// user found in DB
@@ -275,7 +280,11 @@ describe('UserService', () => {
275280
);
276281

277282
// Assert
278-
expect(result).toEqual({ token: 'fake-jwt-token' });
283+
expect(result).toEqual({
284+
token: 'fake-jwt-token',
285+
refreshToken: 'fake-refresh-token',
286+
});
287+
279288
expect(mockAuthService.authenticateUser).toHaveBeenCalledWith(
280289
testUser.username,
281290
'some-password',
@@ -295,7 +304,11 @@ describe('UserService', () => {
295304
});
296305

297306
it('should authenticate a user successfully (cache hit)', async () => {
298-
mockAuthService.authenticateUser.mockResolvedValue('fake-jwt-token');
307+
mockAuthService.authenticateUser.mockResolvedValue({
308+
idToken: 'fake-jwt-token',
309+
refreshToken: 'fake-refresh-token',
310+
});
311+
299312
// user found in cache
300313
mockCache.get.mockResolvedValue(JSON.stringify(testUser));
301314

@@ -304,7 +317,11 @@ describe('UserService', () => {
304317
'some-password',
305318
);
306319

307-
expect(result).toEqual({ token: 'fake-jwt-token' });
320+
expect(result).toEqual({
321+
token: 'fake-jwt-token',
322+
refreshToken: 'fake-refresh-token',
323+
});
324+
308325
expect(mockAuthService.authenticateUser).toHaveBeenCalledWith(
309326
testUser.username,
310327
'some-password',
@@ -316,7 +333,11 @@ describe('UserService', () => {
316333
});
317334

318335
it('should throw NotFoundError if user not found in DB', async () => {
319-
mockAuthService.authenticateUser.mockResolvedValue('fake-jwt-token');
336+
mockAuthService.authenticateUser.mockResolvedValue({
337+
idToken: 'fake-jwt-token',
338+
refreshToken: 'fake-refresh-token',
339+
});
340+
320341
mockCache.get.mockResolvedValue(null);
321342
mockUserRepository.findUserByUsername.mockResolvedValue(null);
322343

@@ -484,4 +505,28 @@ describe('UserService', () => {
484505
);
485506
});
486507
});
508+
describe('refreshUserToken', () => {
509+
it('should refresh the token successfully', async () => {
510+
mockAuthService.refreshUserToken.mockResolvedValue('new-id-token');
511+
512+
const result = await userService.refreshUserToken('valid-refresh-token');
513+
514+
expect(result).toBe('new-id-token');
515+
expect(mockAuthService.refreshUserToken).toHaveBeenCalledWith(
516+
'valid-refresh-token',
517+
);
518+
expect(logger.info).toHaveBeenCalledWith(
519+
expect.stringContaining('Token refreshed successfully'),
520+
);
521+
});
522+
523+
it('should propagate errors from authService', async () => {
524+
const error = new Error('Refresh failed');
525+
mockAuthService.refreshUserToken.mockRejectedValue(error);
526+
527+
await expect(
528+
userService.refreshUserToken('invalid-token'),
529+
).rejects.toThrow(error);
530+
});
531+
});
487532
});

0 commit comments

Comments
 (0)