Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/services/admin/admin-email-workspace.server.test.ts
T

141 lines
3.8 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
threadList: vi.fn(),
threadDetail: vi.fn(),
contacts: vi.fn(),
deals: vi.fn(),
policy: vi.fn(),
scheduled: vi.fn(),
bulkRuns: vi.fn(),
reminders: vi.fn(),
mailboxes: vi.fn(),
audit: vi.fn(),
}));
vi.mock("@hivegrid/db/admin-sales-core.server", () => ({
writeAdminSalesAudit: mocks.audit,
}));
vi.mock("~/utils/db.server", () => ({
db: {
adminEmailThread: {
findMany: mocks.threadList,
findFirst: mocks.threadDetail,
},
adminContact: { findMany: mocks.contacts },
adminDeal: { findMany: mocks.deals },
adminEmailOutboundPolicy: { findUnique: mocks.policy },
adminScheduledEmail: { findMany: mocks.scheduled },
adminBulkEmailRun: { findMany: mocks.bulkRuns },
adminNoReplyReminder: { findMany: mocks.reminders },
adminMailbox: { findMany: mocks.mailboxes },
},
}));
import {
readAdminEmailInbox,
readAdminEmailScheduled,
} from "./admin-email-workspace.server";
describe("admin email team scope", () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.threadList.mockResolvedValue([]);
mocks.contacts.mockResolvedValue([]);
mocks.deals.mockResolvedValue([]);
mocks.policy.mockResolvedValue(null);
mocks.scheduled.mockResolvedValue([]);
mocks.bulkRuns.mockResolvedValue([]);
mocks.reminders.mockResolvedValue([]);
mocks.mailboxes.mockResolvedValue([]);
mocks.threadDetail.mockResolvedValue({
id: "thread-b",
adminUserId: "sales-b",
normalizedSubject: "Team-Anfrage",
messages: [],
});
});
it("reads a selected team thread only with read-all and audits actor, owner and target", async () => {
const actor = vi.fn((reason: string) => ({
adminUserId: "manager",
email: "manager@example.test",
reason,
}));
await readAdminEmailInbox(
{
adminUserId: "manager",
canReadAllCommunication: true,
actor,
} as never,
"thread-b"
);
expect(mocks.threadList).toHaveBeenCalledWith(
expect.objectContaining({ where: { archivedAt: null } })
);
expect(mocks.threadDetail).toHaveBeenCalledWith(
expect.objectContaining({
where: { id: "thread-b", archivedAt: null },
})
);
expect(mocks.audit).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
action: "admin.sales.email.foreignThread.read",
targetType: "AdminEmailThread",
targetId: "thread-b",
after: {
dataOwnerAdminUserId: "sales-b",
accessKind: "read",
},
})
);
});
it("audits every foreign scheduled communication target exposed to the manager", async () => {
mocks.scheduled.mockResolvedValue([
{
id: "scheduled-b",
adminUserId: "sales-b",
subject: "Follow-up",
toAddresses: ["buyer@example.test"],
scheduledFor: new Date("2026-07-26T10:00:00.000Z"),
status: "queued",
noReplyAfterDays: null,
lastErrorMessageKey: null,
},
]);
await readAdminEmailScheduled({
adminUserId: "manager",
canReadAllCommunication: true,
actor: (reason: string) => ({
adminUserId: "manager",
email: "manager@example.test",
reason,
}),
} as never);
expect(mocks.audit).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
action: "admin.sales.email.foreignScheduled.read",
targetType: "AdminScheduledEmail",
targetId: "scheduled-b",
after: {
foreignTargets: [
{
targetType: "AdminScheduledEmail",
targetId: "scheduled-b",
dataOwnerAdminUserId: "sales-b",
},
],
accessKind: "read",
},
})
);
});
});