updating unit and integration tests

This commit is contained in:
jackiettran
2025-12-20 14:59:09 -05:00
parent 4e0a4ef019
commit bd1bd5014c
14 changed files with 2424 additions and 100 deletions

View File

@@ -40,6 +40,7 @@ describe('User Model - Email Verification', () => {
lastName: 'User',
verificationToken: null,
verificationTokenExpiry: null,
verificationAttempts: 0,
isVerified: false,
verifiedAt: null,
update: jest.fn().mockImplementation(function(updates) {
@@ -53,18 +54,17 @@ describe('User Model - Email Verification', () => {
});
describe('generateVerificationToken', () => {
it('should generate a random token and set 24-hour expiry', async () => {
const mockRandomBytes = Buffer.from('a'.repeat(32));
const mockToken = mockRandomBytes.toString('hex'); // This will be "61" repeated 32 times
crypto.randomBytes.mockReturnValue(mockRandomBytes);
it('should generate a 6-digit code and set 24-hour expiry', async () => {
const mockCode = 123456;
crypto.randomInt.mockReturnValue(mockCode);
await User.prototype.generateVerificationToken.call(mockUser);
expect(crypto.randomBytes).toHaveBeenCalledWith(32);
expect(crypto.randomInt).toHaveBeenCalledWith(100000, 999999);
expect(mockUser.update).toHaveBeenCalledWith(
expect.objectContaining({
verificationToken: mockToken
verificationToken: '123456',
verificationAttempts: 0,
})
);
@@ -77,40 +77,40 @@ describe('User Model - Email Verification', () => {
expect(expiryTime).toBeLessThan(expectedExpiry + 1000);
});
it('should update the user with token and expiry', async () => {
const mockRandomBytes = Buffer.from('b'.repeat(32));
const mockToken = mockRandomBytes.toString('hex');
crypto.randomBytes.mockReturnValue(mockRandomBytes);
it('should update the user with code and expiry', async () => {
const mockCode = 654321;
crypto.randomInt.mockReturnValue(mockCode);
const result = await User.prototype.generateVerificationToken.call(mockUser);
expect(mockUser.update).toHaveBeenCalledTimes(1);
expect(result.verificationToken).toBe(mockToken);
expect(result.verificationToken).toBe('654321');
expect(result.verificationTokenExpiry).toBeInstanceOf(Date);
});
it('should generate unique tokens on multiple calls', async () => {
const mockRandomBytes1 = Buffer.from('a'.repeat(32));
const mockRandomBytes2 = Buffer.from('b'.repeat(32));
crypto.randomBytes
.mockReturnValueOnce(mockRandomBytes1)
.mockReturnValueOnce(mockRandomBytes2);
it('should generate unique codes on multiple calls', async () => {
crypto.randomInt
.mockReturnValueOnce(111111)
.mockReturnValueOnce(222222);
await User.prototype.generateVerificationToken.call(mockUser);
const firstToken = mockUser.update.mock.calls[0][0].verificationToken;
const firstCode = mockUser.update.mock.calls[0][0].verificationToken;
await User.prototype.generateVerificationToken.call(mockUser);
const secondToken = mockUser.update.mock.calls[1][0].verificationToken;
const secondCode = mockUser.update.mock.calls[1][0].verificationToken;
expect(firstToken).not.toBe(secondToken);
expect(firstCode).not.toBe(secondCode);
});
});
describe('isVerificationTokenValid', () => {
beforeEach(() => {
// Mock timingSafeEqual to do a simple comparison
crypto.timingSafeEqual = jest.fn((a, b) => a.equals(b));
});
it('should return true for valid token and non-expired time', () => {
const validToken = 'valid-token-123';
const validToken = '123456';
const futureExpiry = new Date(Date.now() + 60 * 60 * 1000); // 1 hour from now
mockUser.verificationToken = validToken;
@@ -131,25 +131,25 @@ describe('User Model - Email Verification', () => {
});
it('should return false for missing expiry', () => {
mockUser.verificationToken = 'valid-token';
mockUser.verificationToken = '123456';
mockUser.verificationTokenExpiry = null;
const result = User.prototype.isVerificationTokenValid.call(mockUser, 'valid-token');
const result = User.prototype.isVerificationTokenValid.call(mockUser, '123456');
expect(result).toBe(false);
});
it('should return false for mismatched token', () => {
mockUser.verificationToken = 'correct-token';
mockUser.verificationToken = '123456';
mockUser.verificationTokenExpiry = new Date(Date.now() + 60 * 60 * 1000);
const result = User.prototype.isVerificationTokenValid.call(mockUser, 'wrong-token');
const result = User.prototype.isVerificationTokenValid.call(mockUser, '654321');
expect(result).toBe(false);
});
it('should return false for expired token', () => {
const validToken = 'valid-token-123';
const validToken = '123456';
const pastExpiry = new Date(Date.now() - 60 * 60 * 1000); // 1 hour ago
mockUser.verificationToken = validToken;
@@ -161,7 +161,7 @@ describe('User Model - Email Verification', () => {
});
it('should return false for token expiring in the past by 1 second', () => {
const validToken = 'valid-token-123';
const validToken = '123456';
const pastExpiry = new Date(Date.now() - 1000); // 1 second ago
mockUser.verificationToken = validToken;
@@ -173,7 +173,7 @@ describe('User Model - Email Verification', () => {
});
it('should handle edge case of token expiring exactly now', () => {
const validToken = 'valid-token-123';
const validToken = '123456';
// Set expiry 1ms in the future to handle timing precision
const nowExpiry = new Date(Date.now() + 1);
@@ -187,7 +187,7 @@ describe('User Model - Email Verification', () => {
});
it('should handle string dates correctly', () => {
const validToken = 'valid-token-123';
const validToken = '123456';
const futureExpiry = new Date(Date.now() + 60 * 60 * 1000).toISOString(); // String date
mockUser.verificationToken = validToken;
@@ -201,7 +201,7 @@ describe('User Model - Email Verification', () => {
describe('verifyEmail', () => {
it('should mark user as verified and clear token fields', async () => {
mockUser.verificationToken = 'some-token';
mockUser.verificationToken = '123456';
mockUser.verificationTokenExpiry = new Date();
await User.prototype.verifyEmail.call(mockUser);
@@ -245,19 +245,22 @@ describe('User Model - Email Verification', () => {
});
describe('Complete verification flow', () => {
beforeEach(() => {
crypto.timingSafeEqual = jest.fn((a, b) => a.equals(b));
});
it('should complete full verification flow successfully', async () => {
// Step 1: Generate verification token
const mockRandomBytes = Buffer.from('c'.repeat(32));
const mockToken = mockRandomBytes.toString('hex');
crypto.randomBytes.mockReturnValue(mockRandomBytes);
// Step 1: Generate verification code
const mockCode = 999888;
crypto.randomInt.mockReturnValue(mockCode);
await User.prototype.generateVerificationToken.call(mockUser);
expect(mockUser.verificationToken).toBe(mockToken);
expect(mockUser.verificationToken).toBe('999888');
expect(mockUser.verificationTokenExpiry).toBeInstanceOf(Date);
// Step 2: Validate token
const isValid = User.prototype.isVerificationTokenValid.call(mockUser, mockToken);
// Step 2: Validate code
const isValid = User.prototype.isVerificationTokenValid.call(mockUser, '999888');
expect(isValid).toBe(true);
// Step 3: Verify email
@@ -270,25 +273,23 @@ describe('User Model - Email Verification', () => {
});
it('should fail verification with wrong token', async () => {
// Generate token
const mockToken = 'd'.repeat(64);
const mockRandomBytes = Buffer.from('d'.repeat(32));
crypto.randomBytes.mockReturnValue(mockRandomBytes);
// Generate code
crypto.randomInt.mockReturnValue(123456);
await User.prototype.generateVerificationToken.call(mockUser);
// Try to validate with wrong token
const isValid = User.prototype.isVerificationTokenValid.call(mockUser, 'wrong-token');
// Try to validate with wrong code
const isValid = User.prototype.isVerificationTokenValid.call(mockUser, '654321');
expect(isValid).toBe(false);
});
it('should fail verification with expired token', async () => {
// Manually set an expired token
mockUser.verificationToken = 'expired-token';
mockUser.verificationToken = '123456';
mockUser.verificationTokenExpiry = new Date(Date.now() - 25 * 60 * 60 * 1000); // 25 hours ago
const isValid = User.prototype.isVerificationTokenValid.call(mockUser, 'expired-token');
const isValid = User.prototype.isVerificationTokenValid.call(mockUser, '123456');
expect(isValid).toBe(false);
});