/** * @vitest-environment jsdom */ import { cleanup, fireEvent, render, screen, waitFor, } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; import PriceForm from "./price-form"; globalThis.ResizeObserver = class ResizeObserver { observe() { return; } unobserve() { return; } disconnect() { return; } }; Element.prototype.scrollIntoView = function scrollIntoView() { return; }; vi.mock("react-i18next", () => ({ useTranslation: () => ({ t: (_key: string, fallback: string): string => fallback, }), })); const rules: API.PromoRule[] = [ { id: 1, name: "Campaign Rule", type: "campaign", params: {}, priority: 1, enabled: true, }, ]; const subscribes: API.SubscribeItem[] = [ { id: 8, name: "Monthly Plan", unit_price: 1200, unit_time: "Month", sold: 0, discount: [ { quantity: 3, discount: 90, }, ], }, ]; const subscribesWithoutDiscounts: API.SubscribeItem[] = [ { id: 8, name: "Monthly Plan", unit_price: 1200, unit_time: "Month", sold: 0, discount: [], }, ]; async function selectCombobox(index: number, option: string) { const combobox = screen.getAllByRole("combobox")[index]; if (!combobox) throw new Error(`Combobox ${index} not found`); fireEvent.click(combobox); fireEvent.click(await screen.findByText(option)); } afterEach(() => { cleanup(); vi.clearAllMocks(); }); describe("PriceForm", () => { it("submits promo price with promo_rule_id and selected quantity item", async () => { const onSubmit = vi.fn().mockResolvedValue(true); render( ); fireEvent.click(screen.getByRole("button", { name: "Create Promo Price" })); await selectCombobox(0, "Campaign Rule"); await selectCombobox(1, "Monthly Plan"); await selectCombobox(2, "3 x Month"); fireEvent.change(screen.getByPlaceholderText("Enter price"), { target: { value: "20" }, }); fireEvent.click(screen.getByRole("button", { name: "Confirm" })); await waitFor(() => expect(onSubmit).toHaveBeenCalledWith({ promo_rule_id: 1, items: [{ subscribe_id: 8, quantity: 3, promo_price: 2000 }], }) ); }); it("blocks submit when subscribe has no discount quantities", async () => { const onSubmit = vi.fn(); render( ); fireEvent.click(screen.getByRole("button", { name: "Create Promo Price" })); await selectCombobox(1, "Monthly Plan"); expect( screen.getByText( "This subscribe has no discount quantities and cannot be configured." ) ).not.toBeNull(); expect(screen.getByRole("button", { name: "Confirm" })).toHaveProperty( "disabled", true ); }); it("keeps the form open and shows an error when promo price reaches original price", async () => { const onSubmit = vi.fn(); render( ); fireEvent.click(screen.getByRole("button", { name: "Create Promo Price" })); await selectCombobox(0, "Campaign Rule"); await selectCombobox(1, "Monthly Plan"); await selectCombobox(2, "3 x Month"); fireEvent.change(screen.getByPlaceholderText("Enter price"), { target: { value: "36" }, }); fireEvent.click(screen.getByRole("button", { name: "Confirm" })); expect( await screen.findByText("Promo price must be lower than original price") ).not.toBeNull(); expect(onSubmit).not.toHaveBeenCalled(); }); });