Files
Zumri-Backend/tests/unit/otp.service.test.js
T
Sathira Sri Sathara 9d3d431416 feat: implement identity and security features
- Added account types and privileged account types constants.
- Created admin user controller for updating user security fields.
- Developed role assignment controller for managing user roles.
- Implemented validation middleware for request schemas.
- Defined user role and auth session models for database interactions.
- Created services for authentication, email notifications, and OTP handling.
- Developed OAuth service for Google and Apple authentication.
- Added JWT utility functions for token generation and verification.
- Implemented comprehensive tests for authentication, session management, and password policies.
- Created migration for updating user schema and adding new tables for auth sessions and user identities.
2026-09-03 13:56:18 +05:30

24 lines
1.3 KiB
JavaScript

const mockRedis = { set: jest.fn(), eval: jest.fn() };
jest.mock("../../app/config/redisClient", () => mockRedis);
const { generateOtp, otpHash, createLoginChallenge, verifyLoginChallenge } = require("../../app/services/auth/otp.service");
describe("login OTP service", () => {
beforeEach(() => jest.clearAllMocks());
test("generates six numeric digits cryptographically", () => expect(generateOtp()).toMatch(/^\d{6}$/));
test("stores only an OTP hash with TTL", async () => {
const result = await createLoginChallenge({ userId: "usr-1", rememberMe: true, context: {} });
const stored = JSON.parse(mockRedis.set.mock.calls[0][1]);
expect(stored.otpHash).toHaveLength(64);
expect(stored.otp).toBeUndefined();
expect(mockRedis.set.mock.calls[0]).toEqual(expect.arrayContaining(["EX", 900]));
expect(result.otp).toMatch(/^\d{6}$/);
expect(stored.otpHash).toBe(otpHash(result.challengeId, result.otp));
});
test("maps invalid, exhausted, and expired challenges to a generic failure", async () => {
for (const code of [-1, -2, -3]) {
mockRedis.eval.mockResolvedValueOnce([code]);
await expect(verifyLoginChallenge("00000000-0000-4000-8000-000000000000", "000000")).rejects.toMatchObject({ code: "INVALID_OTP", status: 401 });
}
});
});