import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import React from "react"; import { ToastContext, type ToastContextValue } from "@/hooks/useToast"; vi.mock("next/navigation", () => ({ useRouter: () => ({ push: vi.fn(), back: vi.fn(), }), })); vi.mock("@/lib/userId", () => ({ getUserId: vi.fn().mockReturnValue("user-1"), getCachedPreferences: vi.fn().mockReturnValue({}), })); vi.mock("@/lib/sceneConfig", () => ({ SCENES: ["eat", "drinks"], getSceneConfig: vi.fn().mockReturnValue({ key: "eat", label: "餐厅", emoji: "🍜", verb: "吃", poiTypes: "050000", defaultImage: "", hotTags: ["火锅", "日料", "烧烤"], priceOptions: [{ label: "不限", value: "any" }], tagLabel: "口味", tagPlaceholder: "想吃什么?", loadingText: "正在搜索...", emptyError: "没找到", subtitle: "一起选餐厅", inviteText: "邀请你", shareTitle: "分享", shareText: "一起来", qrSubtitle: "扫码加入", }), })); vi.mock("@/hooks/useGeolocation", () => ({ useGeolocation: vi.fn().mockReturnValue({ status: "success", coords: { lat: 31.2, lng: 121.4 }, locationName: "上海", retry: vi.fn(), }), })); vi.mock("@/lib/room", () => ({ joinRoom: vi.fn().mockResolvedValue(undefined), })); const mockFetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ suggestions: [] }), }); vi.stubGlobal("fetch", mockFetch); import PanicPage from "./page"; const toastCtx: ToastContextValue = { show: vi.fn() }; function renderPage() { return render( React.createElement( ToastContext.Provider, { value: toastCtx }, React.createElement(PanicPage), ), ); } beforeEach(() => { vi.clearAllMocks(); }); describe("PanicPage", () => { it("renders page title", () => { renderPage(); expect(screen.getByText("极速救场")).toBeInTheDocument(); }); it("renders location search input", () => { renderPage(); expect(screen.getByPlaceholderText(/搜索位置/)).toBeInTheDocument(); }); it("renders distance options", () => { renderPage(); expect(screen.getByText("1km")).toBeInTheDocument(); expect(screen.getByText("3km")).toBeInTheDocument(); expect(screen.getByText("5km")).toBeInTheDocument(); }); it("renders scene selector with labels", () => { renderPage(); expect(screen.getAllByText("餐厅").length).toBeGreaterThanOrEqual(1); }); });