sentiment-scope / frontend /src /App.test.tsx
melkholy's picture
Ship hardening wave: off-loop CSV inference, model_ids cap/dedupe, real detector Hub ids, comment fixes
019b6f4 verified
Raw
History Blame Contribute Delete
2.98 kB
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");
});