mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
853610bbbf
Co-authored-by: Pablo F.G <pablo.fernandez@prowler.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { unsubscribeAlertRecipient } from "./unsubscribe-alert-recipient";
|
|
|
|
const fetchMock = vi.fn();
|
|
|
|
const lastFetchCall = (): { url: string; init: RequestInit } => {
|
|
const call = fetchMock.mock.calls.at(-1);
|
|
if (!call) throw new Error("fetch was not called");
|
|
const [url, init] = call;
|
|
return { url: String(url), init: (init ?? {}) as RequestInit };
|
|
};
|
|
|
|
describe("unsubscribeAlertRecipient", () => {
|
|
beforeEach(() => {
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
vi.stubEnv("UI_API_BASE_URL", "https://api.example.com/api/v1");
|
|
fetchMock.mockResolvedValue(
|
|
new Response(
|
|
JSON.stringify({
|
|
state: "unsubscribed",
|
|
message:
|
|
"You have been unsubscribed. You will not receive further alerts at this address.",
|
|
}),
|
|
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
),
|
|
);
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
vi.unstubAllGlobals();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("calls the public unsubscribe endpoint without auth headers", async () => {
|
|
// When
|
|
const result = await unsubscribeAlertRecipient("token-1");
|
|
|
|
// Then
|
|
expect(result).toEqual({
|
|
ok: true,
|
|
state: "unsubscribed",
|
|
message:
|
|
"You have been unsubscribed. You will not receive further alerts at this address.",
|
|
});
|
|
const { url, init } = lastFetchCall();
|
|
expect(url).toBe(
|
|
"https://api.example.com/api/v1/alerts/recipients/unsubscribe?token=token-1",
|
|
);
|
|
expect(init).toEqual({
|
|
headers: { Accept: "application/json" },
|
|
cache: "no-store",
|
|
});
|
|
});
|
|
|
|
it("returns the API message for invalid tokens", async () => {
|
|
// Given
|
|
fetchMock.mockResolvedValueOnce(
|
|
new Response(
|
|
JSON.stringify({
|
|
state: "invalid_token",
|
|
message: "This link is invalid or has expired.",
|
|
}),
|
|
{ status: 400, headers: { "Content-Type": "application/json" } },
|
|
),
|
|
);
|
|
|
|
// When
|
|
const result = await unsubscribeAlertRecipient("expired-token");
|
|
|
|
// Then
|
|
expect(result).toEqual({
|
|
ok: false,
|
|
state: "invalid_token",
|
|
message: "This link is invalid or has expired.",
|
|
});
|
|
});
|
|
|
|
it("returns the API message for missing tokens", async () => {
|
|
// Given
|
|
fetchMock.mockResolvedValueOnce(
|
|
new Response(
|
|
JSON.stringify({
|
|
state: "missing_token",
|
|
message: "This link is missing a token.",
|
|
}),
|
|
{ status: 400, headers: { "Content-Type": "application/json" } },
|
|
),
|
|
);
|
|
|
|
// When
|
|
const result = await unsubscribeAlertRecipient();
|
|
|
|
// Then
|
|
expect(result).toEqual({
|
|
ok: false,
|
|
state: "missing_token",
|
|
message: "This link is missing a token.",
|
|
});
|
|
expect(lastFetchCall().url).toBe(
|
|
"https://api.example.com/api/v1/alerts/recipients/unsubscribe",
|
|
);
|
|
});
|
|
|
|
it("returns the fallback message when the API base URL is missing", async () => {
|
|
// Given - neither the new name nor its legacy fallback is set
|
|
vi.stubEnv("UI_API_BASE_URL", "");
|
|
vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "");
|
|
|
|
// When
|
|
const result = await unsubscribeAlertRecipient("token-1");
|
|
|
|
// Then
|
|
expect(result).toEqual({
|
|
ok: false,
|
|
state: "missing_api_base_url",
|
|
message:
|
|
"We could not process this unsubscribe link. Please try again later.",
|
|
});
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("falls back to the deprecated NEXT_PUBLIC_API_BASE_URL when UI_API_BASE_URL is unset", async () => {
|
|
// Given - only the legacy name is configured
|
|
vi.stubEnv("UI_API_BASE_URL", undefined);
|
|
vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "https://legacy.example.com/api/v1");
|
|
|
|
// When
|
|
const result = await unsubscribeAlertRecipient("token-1");
|
|
|
|
// Then
|
|
expect(result.ok).toBe(true);
|
|
expect(lastFetchCall().url).toBe(
|
|
"https://legacy.example.com/api/v1/alerts/recipients/unsubscribe?token=token-1",
|
|
);
|
|
});
|
|
});
|