Files
cozsweet-frontend-nextjs/src/app/_hooks/__tests__/use-payment-method-selection.test.tsx
T

121 lines
3.0 KiB
TypeScript

import { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { PayChannel } from "@/data/schemas/payment";
import type { PaymentMethodConfig } from "@/lib/payment/payment_method";
import { usePaymentMethodSelection } from "../use-payment-method-selection";
describe("usePaymentMethodSelection", () => {
let container: HTMLDivElement;
let root: Root;
beforeEach(() => {
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean })
.IS_REACT_ACT_ENVIRONMENT = true;
container = document.createElement("div");
document.body.appendChild(container);
root = createRoot(container);
});
afterEach(() => {
act(() => root.unmount());
container.remove();
});
it("forces Stripe when payment method selection is unavailable", () => {
const onChange = vi.fn();
renderHarness(root, {
config: {
canChoosePaymentMethod: false,
initialPayChannel: "stripe",
showPaymentMethodSelector: false,
},
currentPayChannel: "ezpay",
onChange,
});
expect(onChange).toHaveBeenCalledWith("stripe");
});
it("applies the default channel once when no return channel was requested", () => {
const onChange = vi.fn();
const config = {
canChoosePaymentMethod: true,
initialPayChannel: "ezpay",
showPaymentMethodSelector: true,
} as const;
renderHarness(root, {
config,
currentPayChannel: "stripe",
onChange,
});
renderHarness(root, {
config,
currentPayChannel: "ezpay",
onChange,
});
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith("ezpay");
});
it("preserves an explicit return channel and pauses while payment is busy", () => {
const onChange = vi.fn();
renderHarness(root, {
config: {
canChoosePaymentMethod: true,
initialPayChannel: "ezpay",
showPaymentMethodSelector: true,
},
currentPayChannel: "stripe",
requestedPayChannel: "stripe",
onChange,
});
renderHarness(root, {
config: {
canChoosePaymentMethod: false,
initialPayChannel: "stripe",
showPaymentMethodSelector: false,
},
currentPayChannel: "ezpay",
isPaymentBusy: true,
onChange,
});
expect(onChange).not.toHaveBeenCalled();
});
});
interface HarnessProps {
config: PaymentMethodConfig;
currentPayChannel: PayChannel;
requestedPayChannel?: PayChannel | null;
isPaymentBusy?: boolean;
onChange: (payChannel: PayChannel) => void;
}
function renderHarness(root: Root, props: HarnessProps): void {
act(() => {
root.render(<Harness {...props} />);
});
}
function Harness({
config,
currentPayChannel,
requestedPayChannel = null,
isPaymentBusy = false,
onChange,
}: HarnessProps) {
usePaymentMethodSelection({
config,
currentPayChannel,
requestedPayChannel,
isPaymentBusy,
onChange,
});
return null;
}