grocery-app/backend/tests/households.controller.test.js

159 lines
4.7 KiB
JavaScript

jest.mock("../models/household.model", () => ({
getUserRole: jest.fn(),
reorderUserHouseholds: jest.fn(),
transferOwnership: jest.fn(),
updateMemberRole: jest.fn(),
}));
jest.mock("../utils/logger", () => ({
logError: jest.fn(),
}));
const householdModel = require("../models/household.model");
const controller = require("../controllers/households.controller");
function createResponse() {
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
return res;
}
describe("households.controller updateMemberRole", () => {
beforeEach(() => {
jest.clearAllMocks();
householdModel.getUserRole.mockResolvedValue("member");
householdModel.transferOwnership.mockResolvedValue({ user_id: 7, role: "owner" });
householdModel.updateMemberRole.mockResolvedValue({ user_id: 7, role: "admin" });
});
test("owner can transfer household ownership", async () => {
const req = {
params: { householdId: "3", userId: "7" },
body: { role: "owner" },
user: { id: 1 },
household: { id: 3, role: "owner" },
};
const res = createResponse();
await controller.updateMemberRole(req, res);
expect(householdModel.transferOwnership).toHaveBeenCalledWith("3", 1, 7);
expect(householdModel.updateMemberRole).not.toHaveBeenCalled();
expect(res.json).toHaveBeenCalledWith({
message: "Household ownership transferred successfully",
member: { user_id: 7, role: "owner" },
});
});
test("admin cannot transfer household ownership", async () => {
const req = {
params: { householdId: "3", userId: "7" },
body: { role: "owner" },
user: { id: 1 },
household: { id: 3, role: "admin" },
};
const res = createResponse();
await controller.updateMemberRole(req, res);
expect(householdModel.transferOwnership).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(403);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
error: expect.objectContaining({
message: "Only the household owner can transfer ownership",
}),
})
);
});
test("owner can still update a member to admin without transfer flow", async () => {
const req = {
params: { householdId: "3", userId: "7" },
body: { role: "admin" },
user: { id: 1 },
household: { id: 3, role: "owner" },
};
const res = createResponse();
await controller.updateMemberRole(req, res);
expect(householdModel.updateMemberRole).toHaveBeenCalledWith("3", "7", "admin");
expect(householdModel.transferOwnership).not.toHaveBeenCalled();
expect(res.json).toHaveBeenCalledWith({
message: "Member role updated successfully",
member: { user_id: 7, role: "admin" },
});
});
});
describe("households.controller reorderHouseholds", () => {
beforeEach(() => {
jest.clearAllMocks();
householdModel.reorderUserHouseholds.mockResolvedValue([
{ id: 3, name: "Third" },
{ id: 1, name: "First" },
]);
});
test("updates the current user's household order", async () => {
const req = {
body: { household_ids: [3, 1] },
user: { id: 9 },
};
const res = createResponse();
await controller.reorderHouseholds(req, res);
expect(householdModel.reorderUserHouseholds).toHaveBeenCalledWith(9, [3, 1]);
expect(res.json).toHaveBeenCalledWith({
message: "Household order updated successfully",
households: [
{ id: 3, name: "Third" },
{ id: 1, name: "First" },
],
});
});
test("rejects duplicate household IDs", async () => {
const req = {
body: { household_ids: [3, 3] },
user: { id: 9 },
};
const res = createResponse();
await controller.reorderHouseholds(req, res);
expect(householdModel.reorderUserHouseholds).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
error: expect.objectContaining({
message: "household_ids must contain unique positive household IDs",
}),
})
);
});
test("rejects orders that do not match current memberships", async () => {
householdModel.reorderUserHouseholds.mockResolvedValue(null);
const req = {
body: { household_ids: [999] },
user: { id: 9 },
};
const res = createResponse();
await controller.reorderHouseholds(req, res);
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
error: expect.objectContaining({
message: "Household order must include every household you belong to",
}),
})
);
});
});