feat: add party-size queueing and call modes
This commit is contained in:
103
web/src/pages/VisitorTakeTicketPage.test.tsx
Normal file
103
web/src/pages/VisitorTakeTicketPage.test.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { MemoryRouter } from "react-router-dom";
|
||||
import { ApiError, api } from "../api";
|
||||
import { usePollingResource } from "../hooks/usePollingResource";
|
||||
import { VisitorTakeTicketForm } from "./VisitorTakeTicketPage";
|
||||
|
||||
vi.mock("../hooks/usePollingResource", () => ({ usePollingResource: vi.fn() }));
|
||||
|
||||
const mockedUsePollingResource = vi.mocked(usePollingResource);
|
||||
|
||||
beforeEach(() => {
|
||||
mockedUsePollingResource.mockReturnValue({
|
||||
data: {
|
||||
projects: [{ id: "project-a", name: "云岭漂流", status: "RUNNING", visitor_notice: "请在入口附近等候。", min_party_size: 1, max_party_size: 8 }],
|
||||
},
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
error: null,
|
||||
offline: false,
|
||||
lastClientSuccessAt: new Date().toISOString(),
|
||||
refresh: vi.fn(),
|
||||
resourceKey: "visitor-public-projects",
|
||||
});
|
||||
});
|
||||
|
||||
describe("VisitorTakeTicketForm", () => {
|
||||
it("允许清空默认同行人数后输入新值", () => {
|
||||
render(<MemoryRouter><VisitorTakeTicketForm /></MemoryRouter>);
|
||||
|
||||
const partySizeInput = screen.getByRole("spinbutton", { name: /同行人数/ });
|
||||
expect(partySizeInput).toHaveValue(1);
|
||||
|
||||
fireEvent.change(partySizeInput, { target: { value: "" } });
|
||||
expect(partySizeInput).toHaveValue(null);
|
||||
|
||||
fireEvent.change(partySizeInput, { target: { value: "5" } });
|
||||
expect(partySizeInput).toHaveValue(5);
|
||||
});
|
||||
|
||||
it("creates a ticket from the visitor form and offers the private status page", async () => {
|
||||
const createTicket = vi.spyOn(api, "publicCreateTicket").mockResolvedValueOnce({
|
||||
ticket: { id: "ticket-1", ticket_number: "00021", status: "WAITING", phone_last4: "8000", party_size: 3 },
|
||||
public_token: "visitor-token",
|
||||
public_url: "/visitor/visitor-token",
|
||||
revision: 4,
|
||||
});
|
||||
|
||||
try {
|
||||
render(<MemoryRouter><VisitorTakeTicketForm /></MemoryRouter>);
|
||||
|
||||
expect(screen.queryByText(/一个号码对应您填写的同行人数/)).not.toBeInTheDocument();
|
||||
expect(screen.getByLabelText("排队项目")).toHaveValue("project-a");
|
||||
fireEvent.change(screen.getByLabelText("手机号"), { target: { value: "13800138000" } });
|
||||
fireEvent.change(screen.getByLabelText("姓氏(选填)"), { target: { value: "李" } });
|
||||
fireEvent.change(screen.getByRole("spinbutton", { name: /同行人数/ }), { target: { value: "3" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "创建排队号码" }));
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("status")).toHaveTextContent("00021"));
|
||||
expect(createTicket).toHaveBeenCalledWith("project-a", {
|
||||
phone: "13800138000",
|
||||
party_size: 3,
|
||||
last_name: "李",
|
||||
honorific: "",
|
||||
allow_duplicate: false,
|
||||
}, expect.any(String));
|
||||
expect(screen.getByRole("link", { name: "查看排队状态" })).toHaveAttribute("href", "/visitor/visitor-token");
|
||||
} finally {
|
||||
createTicket.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("requires explicit confirmation before creating another active ticket for the same phone", async () => {
|
||||
const createTicket = vi.spyOn(api, "publicCreateTicket")
|
||||
.mockRejectedValueOnce(new ApiError("该手机号已有活动号码,请确认后继续", 409, undefined, "DUPLICATE_PHONE"))
|
||||
.mockResolvedValueOnce({
|
||||
ticket: { id: "ticket-2", ticket_number: "00022", status: "WAITING", phone_last4: "8000", party_size: 1 },
|
||||
public_token: "visitor-token-2",
|
||||
revision: 5,
|
||||
});
|
||||
|
||||
try {
|
||||
render(<MemoryRouter><VisitorTakeTicketForm /></MemoryRouter>);
|
||||
fireEvent.change(screen.getByLabelText("手机号"), { target: { value: "13800138000" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "创建排队号码" }));
|
||||
|
||||
await waitFor(() => expect(screen.getByText("该手机号已有活动号码")).toBeVisible());
|
||||
expect(screen.getByRole("button", { name: "确认继续取号" })).toBeVisible();
|
||||
fireEvent.click(screen.getByRole("button", { name: "确认继续取号" }));
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("status")).toHaveTextContent("00022"));
|
||||
expect(createTicket).toHaveBeenLastCalledWith("project-a", {
|
||||
phone: "13800138000",
|
||||
party_size: 1,
|
||||
last_name: "",
|
||||
honorific: "",
|
||||
allow_duplicate: true,
|
||||
}, expect.any(String));
|
||||
} finally {
|
||||
createTicket.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user