|
1 | 1 | import { beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 2 |
|
3 | 3 | import { |
| 4 | + handleNotificationEmailPreviewAdmin, |
4 | 5 | handleNotificationPreferences, |
5 | 6 | handleNotificationRead, |
6 | 7 | handleNotificationRulePreviewAdmin, |
@@ -31,6 +32,7 @@ const createManualTestNotification = vi.hoisted(() => vi.fn()); |
31 | 32 | const createNotificationRulePreview = vi.hoisted(() => vi.fn()); |
32 | 33 | const runNotificationRuleManually = vi.hoisted(() => vi.fn()); |
33 | 34 | const runScheduledTask = vi.hoisted(() => vi.fn()); |
| 35 | +const renderNotificationEmail = vi.hoisted(() => vi.fn()); |
34 | 36 |
|
35 | 37 | vi.mock("@/lib/edge/admin-auth", () => ({ |
36 | 38 | requireActor, |
@@ -75,6 +77,10 @@ vi.mock("@/lib/edge/scheduled-task-runner", () => ({ |
75 | 77 | runScheduledTask, |
76 | 78 | })); |
77 | 79 |
|
| 80 | +vi.mock("@/lib/notifications/email-renderer", () => ({ |
| 81 | + renderNotificationEmail, |
| 82 | +})); |
| 83 | + |
78 | 84 | function request(path: string, body: Record<string, unknown>): Request { |
79 | 85 | return new Request(`https://edge.test${path}`, { |
80 | 86 | method: "POST", |
@@ -141,6 +147,11 @@ describe("admin notification handlers", () => { |
141 | 147 | summary: { emailFailed: 0 }, |
142 | 148 | messageCount: 0, |
143 | 149 | }); |
| 150 | + renderNotificationEmail.mockResolvedValue({ |
| 151 | + subject: "Preview", |
| 152 | + html: "<p>Preview</p>", |
| 153 | + text: "Preview text", |
| 154 | + }); |
144 | 155 | createManualTestNotification.mockResolvedValue({ |
145 | 156 | message: { id: "msg-test", deliveryStatus: "sent" }, |
146 | 157 | summary: { messagesCreated: 1 }, |
@@ -723,13 +734,78 @@ describe("admin notification handlers", () => { |
723 | 734 | request("/api/private/admin/notifications/test", { teamId: "team-1" }), |
724 | 735 | {} as never, |
725 | 736 | ), |
| 737 | + handleNotificationEmailPreviewAdmin( |
| 738 | + getRequest("/api/private/admin/notification-email-preview"), |
| 739 | + {} as never, |
| 740 | + new URL( |
| 741 | + "https://edge.test/api/private/admin/notification-email-preview", |
| 742 | + ), |
| 743 | + ), |
726 | 744 | ]); |
727 | 745 |
|
728 | 746 | expect(responses.map((response) => response.status)).toEqual([ |
729 | | - 401, 401, 401, 401, 401, 401, 401, |
| 747 | + 401, 401, 401, 401, 401, 401, 401, 401, |
730 | 748 | ]); |
731 | 749 | }); |
732 | 750 |
|
| 751 | + it("renders notification email previews for admins", async () => { |
| 752 | + requireActor.mockResolvedValue({ |
| 753 | + user: { id: "admin-1" }, |
| 754 | + isAdmin: true, |
| 755 | + }); |
| 756 | + |
| 757 | + const html = await handleNotificationEmailPreviewAdmin( |
| 758 | + getRequest("/api/private/admin/notification-email-preview?type=bad"), |
| 759 | + {} as never, |
| 760 | + new URL( |
| 761 | + "https://edge.test/api/private/admin/notification-email-preview?type=bad&locale=bad", |
| 762 | + ), |
| 763 | + ); |
| 764 | + const text = await handleNotificationEmailPreviewAdmin( |
| 765 | + getRequest("/api/private/admin/notification-email-preview?format=text"), |
| 766 | + {} as never, |
| 767 | + new URL( |
| 768 | + "https://edge.test/api/private/admin/notification-email-preview?type=health&format=text", |
| 769 | + ), |
| 770 | + ); |
| 771 | + const json = await handleNotificationEmailPreviewAdmin( |
| 772 | + getRequest("/api/private/admin/notification-email-preview?format=json"), |
| 773 | + {} as never, |
| 774 | + new URL( |
| 775 | + "https://edge.test/api/private/admin/notification-email-preview?type=test&format=json", |
| 776 | + ), |
| 777 | + ); |
| 778 | + |
| 779 | + expect(html.headers.get("content-type")).toContain("text/html"); |
| 780 | + expect(await html.text()).toBe("<p>Preview</p>"); |
| 781 | + expect(await text.text()).toBe("Preview text"); |
| 782 | + expect(await json.json()).toMatchObject({ |
| 783 | + ok: true, |
| 784 | + data: { subject: "Preview" }, |
| 785 | + }); |
| 786 | + expect(renderNotificationEmail).toHaveBeenCalledTimes(3); |
| 787 | + }); |
| 788 | + |
| 789 | + it("rejects non-admin and non-GET email preview requests", async () => { |
| 790 | + const forbidden = await handleNotificationEmailPreviewAdmin( |
| 791 | + getRequest("/api/private/admin/notification-email-preview"), |
| 792 | + {} as never, |
| 793 | + new URL("https://edge.test/api/private/admin/notification-email-preview"), |
| 794 | + ); |
| 795 | + requireActor.mockResolvedValueOnce({ |
| 796 | + user: { id: "admin-1" }, |
| 797 | + isAdmin: true, |
| 798 | + }); |
| 799 | + const method = await handleNotificationEmailPreviewAdmin( |
| 800 | + methodRequest("POST", "/api/private/admin/notification-email-preview"), |
| 801 | + {} as never, |
| 802 | + new URL("https://edge.test/api/private/admin/notification-email-preview"), |
| 803 | + ); |
| 804 | + |
| 805 | + expect(forbidden.status).toBe(403); |
| 806 | + expect(method.status).toBe(405); |
| 807 | + }); |
| 808 | + |
733 | 809 | it("returns method and validation errors for preferences and read handlers", async () => { |
734 | 810 | const unsupportedPreferences = await handleNotificationPreferences( |
735 | 811 | methodRequest("POST", "/api/private/notification-preferences", {}), |
|
0 commit comments