Browse Source

RHL-003-test(auth): add unit tests for login functionality with various scenarios

Code_Uwe 1 week ago
parent
commit
4dbc667bda
1 changed files with 171 additions and 0 deletions
  1. 171 0
      app/api/auth/login/route.test.js

+ 171 - 0
app/api/auth/login/route.test.js

@@ -0,0 +1,171 @@
+import { describe, it, expect, vi, beforeEach } from "vitest";
+
+// 1) Mocks
+
+vi.mock("@/lib/db", () => ({
+	default: vi.fn(),
+}));
+
+vi.mock("@/models/user", () => ({
+	default: {
+		findOne: vi.fn(),
+	},
+}));
+
+vi.mock("@/lib/auth/session", () => ({
+	createSession: vi.fn(),
+}));
+
+vi.mock("bcryptjs", () => {
+	const compare = vi.fn();
+	return {
+		default: { compare },
+		compare,
+	};
+});
+
+// 2) Imports NACH den Mocks
+
+import dbConnect from "@/lib/db";
+import User from "@/models/user";
+import { createSession } from "@/lib/auth/session";
+import { compare as bcryptCompare } from "bcryptjs";
+import { POST } from "./route";
+
+function createRequestStub(body) {
+	return {
+		async json() {
+			return body;
+		},
+	};
+}
+
+describe("POST /api/auth/login", () => {
+	beforeEach(() => {
+		vi.clearAllMocks();
+		dbConnect.mockResolvedValue(undefined);
+	});
+
+	it("logs in successfully with correct credentials", async () => {
+		const user = {
+			_id: "507f1f77bcf86cd799439011",
+			username: "branchuser",
+			passwordHash: "hashed-password",
+			role: "branch",
+			branchId: "NL01",
+		};
+
+		User.findOne.mockReturnValue({
+			exec: vi.fn().mockResolvedValue(user),
+		});
+
+		bcryptCompare.mockResolvedValue(true);
+
+		const request = createRequestStub({
+			username: "BranchUser", // mixed case, should be normalized
+			password: "secret-password",
+		});
+
+		const response = await POST(request);
+		const json = await response.json();
+
+		expect(response.status).toBe(200);
+		expect(json).toEqual({ ok: true });
+
+		expect(dbConnect).toHaveBeenCalledTimes(1);
+		expect(User.findOne).toHaveBeenCalledWith({ username: "branchuser" });
+
+		expect(bcryptCompare).toHaveBeenCalledWith(
+			"secret-password",
+			"hashed-password"
+		);
+
+		expect(createSession).toHaveBeenCalledWith({
+			userId: "507f1f77bcf86cd799439011",
+			role: "branch",
+			branchId: "NL01",
+		});
+	});
+
+	it("returns 401 when user does not exist", async () => {
+		User.findOne.mockReturnValue({
+			exec: vi.fn().mockResolvedValue(null),
+		});
+
+		const request = createRequestStub({
+			username: "unknownuser",
+			password: "some-password",
+		});
+
+		const response = await POST(request);
+		const json = await response.json();
+
+		expect(response.status).toBe(401);
+		expect(json).toEqual({ error: "Invalid credentials" });
+
+		expect(createSession).not.toHaveBeenCalled();
+	});
+
+	it("returns 401 when password is incorrect", async () => {
+		const user = {
+			_id: "507f1f77bcf86cd799439012",
+			username: "branchuser",
+			passwordHash: "hashed-password",
+			role: "branch",
+			branchId: "NL02",
+		};
+
+		User.findOne.mockReturnValue({
+			exec: vi.fn().mockResolvedValue(user),
+		});
+
+		bcryptCompare.mockResolvedValue(false);
+
+		const request = createRequestStub({
+			username: "branchuser",
+			password: "wrong-password",
+		});
+
+		const response = await POST(request);
+		const json = await response.json();
+
+		expect(response.status).toBe(401);
+		expect(json).toEqual({ error: "Invalid credentials" });
+
+		expect(createSession).not.toHaveBeenCalled();
+	});
+
+	it("returns 400 when username or password is missing", async () => {
+		const request = createRequestStub({
+			username: "only-username",
+		});
+
+		const response = await POST(request);
+		const json = await response.json();
+
+		expect(response.status).toBe(400);
+		expect(json).toEqual({ error: "Missing username or password" });
+
+		expect(User.findOne).not.toHaveBeenCalled();
+		expect(createSession).not.toHaveBeenCalled();
+	});
+
+	it("returns 500 when an unexpected error occurs", async () => {
+		User.findOne.mockImplementation(() => {
+			throw new Error("DB failure");
+		});
+
+		const request = createRequestStub({
+			username: "branchuser",
+			password: "secret-password",
+		});
+
+		const response = await POST(request);
+		const json = await response.json();
+
+		expect(response.status).toBe(500);
+		expect(json).toEqual({ error: "Internal server error" });
+
+		expect(createSession).not.toHaveBeenCalled();
+	});
+});