import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import type { ReactNode } from "react";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("./lib/api", () => ({
clearPlatformSession: vi.fn(),
confirmTask: vi.fn(),
createTask: vi.fn(),
deleteTask: vi.fn(),
getHistoryTasks: vi.fn(),
getPlatformReadiness: vi.fn(),
getPlatformSession: vi.fn(),
getTask: vi.fn(),
getTaskCandidates: vi.fn(),
getTaskReport: vi.fn(),
preparePlatform: vi.fn(),
retryTaskPlatform: vi.fn()
}));
import { NewTaskPage, SessionPreparePage } from "./App";
import {
clearPlatformSession,
getHistoryTasks,
getPlatformReadiness,
getPlatformSession,
preparePlatform
} from "./lib/api";
function renderWithProviders(node: ReactNode, initialEntries?: string[]) {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false
}
}
});
return render(
{initialEntries ? (
{node}
) : (
{node}
)}
);
}
describe("task composer and session console", () => {
beforeEach(() => {
vi.mocked(getPlatformReadiness).mockResolvedValue({
platforms: [
{
platform: "tmall",
ready: true,
status: "ready",
searchRequirement: "recommended",
reason: "当前工作区存在可复用会话,创建任务时会再次校验。",
lastPreparedAt: "2026-04-02T12:00:00.000Z",
expiresAt: "2026-04-03T12:00:00.000Z"
},
{
platform: "jd",
ready: false,
status: "missing",
searchRequirement: "required",
reason: "需要先完成会话准备,否则系统会标记为 SearchBlocked。"
}
]
} as any);
vi.mocked(getHistoryTasks).mockResolvedValue({
tasks: [
{
taskId: "task-1",
query: "Nintendo Switch 2",
taskStatus: "Completed",
updatedAt: "2026-04-02T12:00:00.000Z",
hasReport: true,
defaultReportVersion: 2,
failedPlatforms: [],
blockedPlatforms: []
},
{
taskId: "task-2",
query: "DJI Pocket 3",
taskStatus: "AwaitingConfirmation",
updatedAt: "2026-04-02T11:30:00.000Z",
hasReport: false,
failedPlatforms: [],
blockedPlatforms: ["jd"]
}
]
} as any);
vi.mocked(getPlatformSession).mockResolvedValue({
session: {
platform: "jd",
ready: true,
status: "ready",
searchRequirement: "required",
scope: "workspace",
ttlHours: 24,
lastPreparedAt: "2026-04-02T10:00:00.000Z",
expiresAt: "2026-04-03T10:00:00.000Z",
encryptedSnapshotAvailable: true,
cipherLabel: "mock-aes-gcm-v1"
}
} as any);
vi.mocked(clearPlatformSession).mockResolvedValue(undefined);
vi.mocked(preparePlatform).mockResolvedValue({
platform: "jd",
session_ready: true,
status: "ready",
last_prepared_at: "2026-04-02T10:00:00.000Z",
expires_at: "2026-04-03T10:00:00.000Z",
encrypted_snapshot_available: true
} as any);
});
afterEach(() => {
cleanup();
vi.clearAllMocks();
});
it("shows readiness details and recent task shortcuts on the new task page", async () => {
renderWithProviders();
expect(await screen.findByText("最近任务捷径")).toBeInTheDocument();
expect(await screen.findByText("Nintendo Switch 2")).toBeInTheDocument();
expect(await screen.findByText("DJI Pocket 3")).toBeInTheDocument();
expect(await screen.findByText("搜索要求:建议预热")).toBeInTheDocument();
expect(
await screen.findByText(/当前工作区已有可复用会话,有效至/)
).toBeInTheDocument();
});
it("shows session details and allows clearing the current session", async () => {
const user = userEvent.setup();
renderWithProviders(
} path="/sessions/:platform/prepare" />
,
["/sessions/jd/prepare?from=/tasks/new"]
);
expect(await screen.findByText("已加密保存")).toBeInTheDocument();
expect(screen.getByText(/完成后将返回:\/tasks\/new/)).toBeInTheDocument();
await user.click(screen.getByRole("button", { name: "清理当前会话" }));
await waitFor(() => {
expect(clearPlatformSession).toHaveBeenCalledWith("jd");
});
});
});