Files
trackgo-be/src/modules/auth/strategies/jwt.strategy.spec.ts
T
shancheas 8a61c94078 Add user and employee management enhancements with database schema updates
- Introduced new columns `status`, `created_by`, and `updated_by` in the `users` table to track user status and ownership.
- Updated the `employees` table to include a foreign key reference to the `users` table via `user_id`.
- Created migration script `0012_users_primary.sql` to apply these changes to the database schema.
- Enhanced the `EmployeesService` and `EmployeesRepository` to support user assignments and related data retrieval.
- Updated DTOs and service methods to reflect the new user and employee relationships.
- Added unit tests to validate the new functionality and ensure data integrity.
- Modified existing controllers to accommodate the new fields and relationships in user and employee management.
2026-08-26 15:29:18 +07:00

122 lines
3.3 KiB
TypeScript

import { UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { DateTime } from '../../../common/value-objects/date-time/date-time';
import { Status } from '../../../common/value-objects/status/status';
import type { User } from '../../users/user';
import { UsersService } from '../../users/users.service';
import { RevokedAccessTokensRepository } from '../revoked-access-tokens.repository';
import { JwtStrategy } from './jwt.strategy';
describe('JwtStrategy', () => {
let strategy: JwtStrategy;
let usersService: jest.Mocked<
Pick<UsersService, 'findById' | 'assertCanAuthenticate'>
>;
let revoked: jest.Mocked<Pick<RevokedAccessTokensRepository, 'exists'>>;
const now = DateTime.fromUnixMs(1_700_000_000_000);
const user: User = {
id: 'user-1',
username: 'alice',
passwordHash: 'hash',
privilegeId: null,
isSuperadmin: false,
status: Status.create('active'),
createdAt: now,
updatedAt: now,
createdBy: 'user-1',
updatedBy: 'user-1',
privilege: null,
employee: null,
createdByUser: { id: 'user-1', username: 'alice' },
updatedByUser: { id: 'user-1', username: 'alice' },
};
beforeEach(async () => {
usersService = {
findById: jest.fn(),
assertCanAuthenticate: jest.fn(),
};
revoked = { exists: jest.fn() };
const moduleRef: TestingModule = await Test.createTestingModule({
providers: [
JwtStrategy,
{
provide: ConfigService,
useValue: {
getOrThrow: () => 'test-secret-at-least-32-characters-long!!',
},
},
{ provide: UsersService, useValue: usersService },
{ provide: RevokedAccessTokensRepository, useValue: revoked },
],
}).compile();
strategy = moduleRef.get(JwtStrategy);
});
it('returns AuthUser for a valid access payload', async () => {
revoked.exists.mockResolvedValue(false);
usersService.findById.mockResolvedValue(user);
await expect(
strategy.validate({
sub: 'user-1',
username: 'alice',
jti: 'jti-1',
typ: 'access',
}),
).resolves.toEqual({
id: 'user-1',
username: 'alice',
jti: 'jti-1',
isSuperadmin: false,
});
});
it('maps isSuperadmin from the persisted user', async () => {
revoked.exists.mockResolvedValue(false);
usersService.findById.mockResolvedValue({ ...user, isSuperadmin: true });
await expect(
strategy.validate({
sub: 'user-1',
username: 'alice',
jti: 'jti-1',
typ: 'access',
}),
).resolves.toEqual({
id: 'user-1',
username: 'alice',
jti: 'jti-1',
isSuperadmin: true,
});
});
it('rejects revoked access tokens', async () => {
revoked.exists.mockResolvedValue(true);
await expect(
strategy.validate({
sub: 'user-1',
username: 'alice',
jti: 'jti-1',
typ: 'access',
}),
).rejects.toBeInstanceOf(UnauthorizedException);
});
it('rejects non-access token types', async () => {
await expect(
strategy.validate({
sub: 'user-1',
username: 'alice',
jti: 'jti-1',
typ: 'refresh' as 'access',
}),
).rejects.toBeInstanceOf(UnauthorizedException);
});
});