Spaces:
Sleeping
Sleeping
| import { beforeEach, expect, it, vi } from "vitest"; | |
| import { act, render, screen } from "@testing-library/react"; | |
| import userEvent from "@testing-library/user-event"; | |
| import App from "./App"; | |
| import { getModelInfo, getModels } from "./api"; | |
| // Every tab's data dependency is mocked: hidden tabs are pre-rendered by | |
| // <Activity>, so their fetches fire even before the user visits them. | |
| vi.mock("./api", () => ({ | |
| analyze: vi.fn(), | |
| explainText: vi.fn(), | |
| analyzeCsv: vi.fn(), | |
| getModelInfo: vi.fn(), | |
| getModels: vi.fn(), | |
| compareModels: vi.fn(), | |
| compareAiDetectors: vi.fn(), | |
| })); | |
| beforeEach(() => { | |
| vi.mocked(getModels).mockResolvedValue({ | |
| models: [ | |
| { | |
| id: "twitter-roberta", | |
| name: "cardiffnlp/twitter-roberta-base-sentiment-latest", | |
| task: "sentiment", | |
| labels: ["negative", "neutral", "positive"], | |
| domain: "social / short English text", | |
| note: "", | |
| default: true, | |
| loaded: true, | |
| }, | |
| ], | |
| }); | |
| vi.mocked(getModelInfo).mockResolvedValue({ | |
| name: "cardiffnlp/twitter-roberta-base-sentiment-latest", | |
| labels: ["negative", "neutral", "positive"], | |
| max_tokens: 512, | |
| device: "mps", | |
| description: "RoBERTa-base fine-tuned on tweets.", | |
| }); | |
| }); | |
| // Hidden tabs suspend while their promises settle, so React 19 requires the | |
| // initial render inside an awaited act(). | |
| const renderApp = () => act(async () => render(<App />)); | |
| it("shows the wordmark and five tabs with Analyze active by default", async () => { | |
| await renderApp(); | |
| expect(screen.getByText("SentimentScope")).toBeInTheDocument(); | |
| const tabs = screen.getAllByRole("tab"); | |
| expect(tabs.map((t) => t.textContent)).toEqual([ | |
| "Analyze", | |
| "Batch", | |
| "Compare Sentiment", | |
| "AI Detector", | |
| "How it works", | |
| ]); | |
| expect(screen.getByRole("tab", { name: "Analyze" })).toHaveAttribute("aria-selected", "true"); | |
| expect(screen.getByPlaceholderText(/type or paste text/i)).toBeVisible(); | |
| }); | |
| it("switches the visible panel when a tab is clicked", async () => { | |
| const user = userEvent.setup(); | |
| await renderApp(); | |
| await user.click(screen.getByRole("tab", { name: "Compare Sentiment" })); | |
| expect(await screen.findByRole("button", { name: "Compare models" })).toBeVisible(); | |
| expect(screen.getByPlaceholderText(/type or paste text/i)).not.toBeVisible(); | |
| await user.click(screen.getByRole("tab", { name: "How it works" })); | |
| expect(await screen.findByRole("heading", { name: /tokenization/i })).toBeVisible(); | |
| }); | |
| it("preserves in-progress tab state when switching away and back", async () => { | |
| const user = userEvent.setup(); | |
| await renderApp(); | |
| await user.type(screen.getByPlaceholderText(/type or paste text/i), "battery life is incredible"); | |
| await user.click(screen.getByRole("tab", { name: "How it works" })); | |
| await user.click(screen.getByRole("tab", { name: "Analyze" })); | |
| expect(screen.getByPlaceholderText(/type or paste text/i)).toHaveValue("battery life is incredible"); | |
| }); | |