159 lines
4.8 KiB
TypeScript
159 lines
4.8 KiB
TypeScript
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(
|
|
<QueryClientProvider client={queryClient}>
|
|
{initialEntries ? (
|
|
<MemoryRouter initialEntries={initialEntries}>{node}</MemoryRouter>
|
|
) : (
|
|
<MemoryRouter>{node}</MemoryRouter>
|
|
)}
|
|
</QueryClientProvider>
|
|
);
|
|
}
|
|
|
|
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(<NewTaskPage />);
|
|
|
|
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(
|
|
<Routes>
|
|
<Route element={<SessionPreparePage />} path="/sessions/:platform/prepare" />
|
|
</Routes>,
|
|
["/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");
|
|
});
|
|
});
|
|
});
|