const mockDb = { User: { findOne: jest.fn() } }; const mockCheckPassword = jest.fn(); const mockCreateChallenge = jest.fn(); const mockSendOtp = jest.fn(); jest.mock("../../app/models", () => mockDb); jest.mock("../../app/utils/hashPassword.util", () => ({ checkPassword: mockCheckPassword })); jest.mock("../../app/services/auth/otp.service", () => ({ createLoginChallenge: mockCreateChallenge, verifyLoginChallenge: jest.fn() })); jest.mock("../../app/services/auth/email.service", () => ({ sendLoginOtp: mockSendOtp })); jest.mock("../../app/utils/idGen.util", () => ({ generateUserId: jest.fn(), generateId: jest.fn() })); jest.mock("../../app/services/auth/session.service", () => ({ createSession: jest.fn(), rotateSession: jest.fn() })); jest.mock("../../app/services/auth/oauth.service", () => ({ verifyGoogleToken: jest.fn(), verifyAppleToken: jest.fn() })); const { beginPasswordLogin } = require("../../app/services/auth/auth.service"); const req = { get: jest.fn(), ip: "127.0.0.1" }; describe("password login boundary", () => { beforeEach(() => { jest.clearAllMocks(); mockCheckPassword.mockResolvedValue(true); }); test.each(["PENDING_VERIFICATION", "SUSPENDED", "DEACTIVATED"])("rejects %s accounts", async (status) => { mockDb.User.findOne.mockResolvedValue({ id: "usr", password: "hash", accountStatus: status, accountType: "customer" }); await expect(beginPasswordLogin({ email: "x@example.com", password: "secret", rememberMe: false }, req)).rejects.toMatchObject({ code: "ACCOUNT_NOT_ACTIVE" }); }); test("uses a generic error for missing users and wrong passwords", async () => { mockDb.User.findOne.mockResolvedValue(null); await expect(beginPasswordLogin({ email: "x@example.com", password: "wrong" }, req)).rejects.toMatchObject({ code: "INVALID_CREDENTIALS" }); }); test("creates an OTP challenge but no session for valid credentials", async () => { const user = { id: "usr", password: "hash", accountStatus: "ACTIVE", accountType: "customer" }; mockDb.User.findOne.mockResolvedValue(user); mockCreateChallenge.mockResolvedValue({ challengeId: "challenge", otp: "123456" }); await expect(beginPasswordLogin({ email: "x@example.com", password: "secret", rememberMe: true }, req)).resolves.toEqual({ challengeId: "challenge" }); expect(mockSendOtp).toHaveBeenCalledWith(user, "123456"); }); });