Files
formbricks/apps/web/modules/ee/mailing/lib/mailing-subscription.test.ts
Anshuman Pandey a31e7bfaa5 feat: security signup ui (#7088)
Co-authored-by: Johannes <johannes@formbricks.com>
2026-01-14 16:45:21 +00:00

206 lines
6.5 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { logger } from "@formbricks/logger";
import { subscribeToMailingList, subscribeUserToMailingList } from "./mailing-subscription";
vi.mock("@formbricks/logger", () => ({
logger: {
error: vi.fn(),
info: vi.fn(),
},
}));
vi.mock("@/lib/utils/validate", () => ({
validateInputs: vi.fn(),
}));
globalThis.fetch = vi.fn();
describe("subscribeToMailingList", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
test("should successfully subscribe to security mailing list", async () => {
vi.mocked(globalThis.fetch).mockResolvedValueOnce(new Response(null, { status: 200 }));
const result = await subscribeToMailingList({
email: "test@example.com",
listId: "security",
});
expect(result).toEqual({ success: true });
expect(globalThis.fetch).toHaveBeenCalledWith(
"https://ee.formbricks.com/api/v1/public/mailing/security/subscriptions",
expect.objectContaining({
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "test@example.com" }),
})
);
expect(logger.info).toHaveBeenCalledWith(
{ listId: "security" },
"Successfully subscribed to security mailing list"
);
});
test("should successfully subscribe to product-updates mailing list", async () => {
vi.mocked(globalThis.fetch).mockResolvedValueOnce(new Response(null, { status: 200 }));
const result = await subscribeToMailingList({
email: "test@example.com",
listId: "product-updates",
});
expect(result).toEqual({ success: true });
expect(globalThis.fetch).toHaveBeenCalledWith(
"https://ee.formbricks.com/api/v1/public/mailing/product-updates/subscriptions",
expect.objectContaining({
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "test@example.com" }),
})
);
});
test("should return error when API returns non-ok response", async () => {
vi.mocked(globalThis.fetch).mockResolvedValueOnce(
new Response("Bad Request", { status: 400, statusText: "Bad Request" })
);
const result = await subscribeToMailingList({
email: "test@example.com",
listId: "security",
});
expect(result).toEqual({ success: false, error: "Failed to subscribe: 400" });
expect(logger.error).toHaveBeenCalledWith(
{ status: 400, error: "Bad Request" },
"Failed to subscribe to security mailing list"
);
});
test("should return error when fetch throws an error", async () => {
vi.mocked(globalThis.fetch).mockRejectedValueOnce(new Error("Network error"));
const result = await subscribeToMailingList({
email: "test@example.com",
listId: "security",
});
expect(result).toEqual({ success: false, error: "Failed to subscribe to mailing list" });
expect(logger.error).toHaveBeenCalledWith(
expect.any(Error),
"Error subscribing to security mailing list"
);
});
test("should return timeout error when request times out", async () => {
const abortError = new Error("Aborted");
abortError.name = "AbortError";
vi.mocked(globalThis.fetch).mockRejectedValueOnce(abortError);
const result = await subscribeToMailingList({
email: "test@example.com",
listId: "security",
});
expect(result).toEqual({ success: false, error: "Request timed out" });
expect(logger.error).toHaveBeenCalledWith(
{ listId: "security" },
"Mailing subscription request timed out"
);
});
});
describe("subscribeUserToMailingList", () => {
beforeEach(() => {
vi.clearAllMocks();
});
test("should subscribe to product-updates when isFormbricksCloud is true and subscribeToProductUpdates is true", async () => {
vi.mocked(globalThis.fetch).mockResolvedValueOnce(new Response(null, { status: 200 }));
await subscribeUserToMailingList({
email: "test@example.com",
isFormbricksCloud: true,
subscribeToProductUpdates: true,
subscribeToSecurityUpdates: false,
});
expect(globalThis.fetch).toHaveBeenCalledWith(
"https://ee.formbricks.com/api/v1/public/mailing/product-updates/subscriptions",
expect.any(Object)
);
});
test("should not subscribe when isFormbricksCloud is true but subscribeToProductUpdates is false", async () => {
await subscribeUserToMailingList({
email: "test@example.com",
isFormbricksCloud: true,
subscribeToProductUpdates: false,
subscribeToSecurityUpdates: true,
});
expect(globalThis.fetch).not.toHaveBeenCalled();
});
test("should subscribe to security when isFormbricksCloud is false and subscribeToSecurityUpdates is true", async () => {
vi.mocked(globalThis.fetch).mockResolvedValueOnce(new Response(null, { status: 200 }));
await subscribeUserToMailingList({
email: "test@example.com",
isFormbricksCloud: false,
subscribeToSecurityUpdates: true,
subscribeToProductUpdates: false,
});
expect(globalThis.fetch).toHaveBeenCalledWith(
"https://ee.formbricks.com/api/v1/public/mailing/security/subscriptions",
expect.any(Object)
);
});
test("should not subscribe when isFormbricksCloud is false but subscribeToSecurityUpdates is false", async () => {
await subscribeUserToMailingList({
email: "test@example.com",
isFormbricksCloud: false,
subscribeToSecurityUpdates: false,
subscribeToProductUpdates: true,
});
expect(globalThis.fetch).not.toHaveBeenCalled();
});
test("should not subscribe when both subscription flags are undefined", async () => {
await subscribeUserToMailingList({
email: "test@example.com",
isFormbricksCloud: true,
});
expect(globalThis.fetch).not.toHaveBeenCalled();
});
test("should prioritize product-updates for cloud users even if security is also true", async () => {
vi.mocked(globalThis.fetch).mockResolvedValueOnce(new Response(null, { status: 200 }));
await subscribeUserToMailingList({
email: "test@example.com",
isFormbricksCloud: true,
subscribeToProductUpdates: true,
subscribeToSecurityUpdates: true,
});
// Should only call product-updates endpoint for cloud users
expect(globalThis.fetch).toHaveBeenCalledTimes(1);
expect(globalThis.fetch).toHaveBeenCalledWith(
"https://ee.formbricks.com/api/v1/public/mailing/product-updates/subscriptions",
expect.any(Object)
);
});
});