import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import { PlanPage } from "./plan.page";
jest.mock("../env", () => ({
get: jest.fn(),
getStr: jest.fn(() => "")
}));
jest.mock("../components/summary", () => ({
Summary: () => null
}));
import { get as getEnv } from "../env";
const mockGetEnv = getEnv as jest.Mock;
const mockOnCompleted = jest.fn();
const MOCK_PLANS = [
{
value: "higher",
label: "Higher income",
description: "",
amount: "20",
currency: "GBP",
frequency: "monthly",
allowCustomAmount: false
},
{
value: "lower",
label: "Lower income",
description: "",
amount: "5",
currency: "GBP",
frequency: "monthly",
allowCustomAmount: false
},
{
value: "other",
label: "Other",
description: "",
amount: "1",
currency: "GBP",
frequency: "monthly",
allowCustomAmount: true
}
];
beforeEach(() => {
mockGetEnv.mockImplementation((key: string) => {
if (key === "MEMBERSHIP_PLANS") return MOCK_PLANS;
return false;
});
mockOnCompleted.mockClear();
});
describe("PlanPage — custom amount", () => {
test("typing a custom amount selects that tier instead of the default", async () => {
render(
);
const customInput = document.getElementById(
"other-amount"
) as HTMLInputElement;
expect(customInput).toBeInTheDocument();
fireEvent.change(customInput, { target: { value: "7" } });
fireEvent.submit(
screen.getByRole("button", { name: /continue/i }).closest("form")!
);
await waitFor(() => expect(mockOnCompleted).toHaveBeenCalled());
const submitted = mockOnCompleted.mock.calls[0][0];
expect(submitted.membership).toBe("other");
expect(Number(submitted.customMembershipAmount)).toBe(7);
});
test("the continue button spells out the amount about to be paid", async () => {
render(
);
expect(
screen.getByRole("button", { name: "Continue and pay £20 monthly" })
).toBeInTheDocument();
const customInput = document.getElementById(
"other-amount"
) as HTMLInputElement;
fireEvent.change(customInput, { target: { value: "7" } });
await waitFor(() =>
expect(
screen.getByRole("button", { name: "Continue and pay £7 monthly" })
).toBeInTheDocument()
);
});
test("submitting without touching the custom amount keeps the default tier", async () => {
render(
);
fireEvent.submit(
screen.getByRole("button", { name: /continue/i }).closest("form")!
);
await waitFor(() => expect(mockOnCompleted).toHaveBeenCalled());
expect(mockOnCompleted.mock.calls[0][0].membership).toBe("higher");
});
});
describe("PlanPage — redirecting plan", () => {
const PLANS_WITH_REDIRECT = [
...MOCK_PLANS,
{
value: "student",
label: "Student",
description: "",
amount: "3",
currency: "GBP",
frequency: "monthly",
allowCustomAmount: false,
redirectUrl: "https://example.org/students"
}
];
beforeEach(() => {
mockGetEnv.mockImplementation((key: string) => {
if (key === "MEMBERSHIP_PLANS") return PLANS_WITH_REDIRECT;
return false;
});
});
test("the continue button does not promise a payment that will not be taken", () => {
render(
);
expect(
screen.getByRole("button", { name: "Continue" })
).toBeInTheDocument();
});
test("switching from a paying plan to the redirecting plan drops the amount from the button", async () => {
render(
);
expect(
screen.getByRole("button", { name: "Continue and pay £20 monthly" })
).toBeInTheDocument();
fireEvent.click(document.getElementById("membership-Student")!);
await waitFor(() =>
expect(
screen.getByRole("button", { name: "Continue" })
).toBeInTheDocument()
);
});
});