auth.controller.spec.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { Test, TestingModule } from '@nestjs/testing';
  2. import { AuthController } from './auth.controller';
  3. import { UsersService } from 'src/users/user.service';
  4. import { WebauthnService } from 'src/auth/webauthn.service';
  5. import { JwtService } from '@nestjs/jwt';
  6. import type { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/server';
  7. describe('AuthController', () => {
  8. let controller: AuthController;
  9. let usersService: jest.Mocked<UsersService>;
  10. let webauthnService: jest.Mocked<WebauthnService>;
  11. beforeEach(async () => {
  12. const module: TestingModule = await Test.createTestingModule({
  13. controllers: [AuthController],
  14. providers: [
  15. { provide: UsersService, useValue: { findByEmail: jest.fn(), createUser: jest.fn() } },
  16. { provide: WebauthnService, useValue: { generateRegistrationOptions: jest.fn() } },
  17. { provide: JwtService, useValue: { sign: jest.fn().mockReturnValue('mock-jwt') } },
  18. ],
  19. }).compile();
  20. controller = module.get<AuthController>(AuthController);
  21. usersService = module.get(UsersService);
  22. webauthnService = module.get(WebauthnService);
  23. });
  24. describe('webauthn-register-options', () => {
  25. it('should return registration options for a valid user', async () => {
  26. const session: Record<string, any> = {};
  27. const mockUser = { id: 'u123', username: 'u123@user.com', devices: [] };
  28. // Mock DB + WebAuthn
  29. jest.spyOn(controller, 'getUserFromDb').mockResolvedValue(mockUser);
  30. webauthnService.generateRegistrationOptions.mockResolvedValueOnce(
  31. createMockRegistrationOptions({ challenge: 'abc123' }),
  32. );
  33. const result = await controller.getRegistrationOptions({ username: 'u123' }, session);
  34. expect(result.challenge).toBe('abc123');
  35. expect(session.challenge).toBe('abc123');
  36. expect(webauthnService.generateRegistrationOptions).toHaveBeenCalledWith(mockUser);
  37. });
  38. });
  39. });
  40. /**
  41. * Factory for mock registration options
  42. */
  43. export function createMockRegistrationOptions(
  44. overrides: Partial<PublicKeyCredentialCreationOptionsJSON> = {},
  45. ): PublicKeyCredentialCreationOptionsJSON {
  46. return {
  47. challenge: 'mock-challenge',
  48. rp: { name: 'Mock RP' },
  49. user: {
  50. id: 'user-id',
  51. name: 'test@example.com',
  52. displayName: 'Test User',
  53. },
  54. pubKeyCredParams: [{ type: 'public-key', alg: -7 }],
  55. ...overrides,
  56. };
  57. }
  58. /**
  59. * Factory for mock authentication (login) options
  60. */
  61. export function createMockAuthenticationOptions(
  62. overrides: Partial<PublicKeyCredentialRequestOptionsJSON> = {},
  63. ): PublicKeyCredentialRequestOptionsJSON {
  64. return {
  65. challenge: 'mock-challenge',
  66. timeout: 60000,
  67. rpId: 'localhost',
  68. allowCredentials: [],
  69. userVerification: 'preferred',
  70. ...overrides,
  71. };
  72. }