jest.mock("../middleware/auth", () => (req, res, next) => { req.user = { id: 42, role: "user" }; next(); }); jest.mock("../middleware/optional-auth", () => (req, res, next) => next()); jest.mock("../services/group-invites.service", () => { const actual = jest.requireActual("../services/group-invites.service"); return { ...actual, acceptInviteLink: jest.fn(), createInviteLink: jest.fn(), deleteInviteLink: jest.fn(), getGroupJoinPolicy: jest.fn(), getInviteLinkSummaryByToken: jest.fn(), listInviteLinks: jest.fn(), resolveManagedGroupId: jest.fn(), revokeInviteLink: jest.fn(), reviveInviteLink: jest.fn(), setGroupJoinPolicy: jest.fn(), }; }); const request = require("supertest"); const invitesService = require("../services/group-invites.service"); const app = require("../app"); describe("group invites routes", () => { beforeEach(() => { invitesService.resolveManagedGroupId.mockResolvedValue(1); invitesService.listInviteLinks.mockResolvedValue([]); invitesService.createInviteLink.mockResolvedValue({ id: 1, token: "abcd", status: "ACTIVE", }); invitesService.getInviteLinkSummaryByToken.mockResolvedValue({ id: 1, token: "abcd", group_name: "Test Group", status: "ACTIVE", active_policy: "AUTO_ACCEPT", }); }); test("admin-only checks are enforced on invite management routes", async () => { invitesService.createInviteLink.mockRejectedValue( new invitesService.InviteServiceError( "FORBIDDEN", "Admin or owner role required", 403 ) ); const response = await request(app).post("/api/groups/invites").send({ policy: "AUTO_ACCEPT", singleUse: false, ttlDays: 3, }); expect(response.status).toBe(403); expect(response.body.error.code).toBe("FORBIDDEN"); expect(response.body.request_id).toBeTruthy(); }); test("request_id is present in invite responses", async () => { const response = await request(app).get("/api/invite-links/abcd1234"); expect(response.status).toBe(200); expect(response.body.request_id).toBeTruthy(); expect(response.body.link).toBeTruthy(); }); });