feat: add Ops and Watchlists tests (144 total frontend tests)

This commit is contained in:
Celes Renata
2026-04-21 07:20:29 +00:00
parent 7eff484434
commit 58a63408c7
2 changed files with 218 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
import { describe, it, expect } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { renderRoute } from './render';
describe('Pipeline Health page', () => {
it('renders page title', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'Pipeline Health' })).toBeInTheDocument();
});
});
it('renders queue depths section', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Queue Depths')).toBeInTheDocument();
});
});
it('renders document stages section', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Document Stages')).toBeInTheDocument();
});
// Mock has { status: 'extracted', doc_count: 5 }
expect(screen.getByText('5')).toBeInTheDocument();
});
it('renders parsing quality section', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Parsing Quality')).toBeInTheDocument();
});
});
it('renders extraction validation section', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Extraction Validation')).toBeInTheDocument();
});
});
it('renders trend generation section', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Trend Generation')).toBeInTheDocument();
});
});
it('renders pipeline toggle button', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Pipeline ON')).toBeInTheDocument();
});
});
it('renders queue labels', async () => {
renderRoute('/ops/pipeline');
await waitFor(() => {
expect(screen.getByText('Queue Depths')).toBeInTheDocument();
});
// Queue labels are rendered inside the Queue Depths card
expect(screen.getByText('Aggregation')).toBeInTheDocument();
expect(screen.getByText('Recommendation')).toBeInTheDocument();
});
});
describe('Ingestion Monitor page', () => {
it('renders page title', async () => {
renderRoute('/ops/ingestion');
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'Ingestion Monitor' })).toBeInTheDocument();
});
});
it('renders summary stat cards', async () => {
renderRoute('/ops/ingestion');
await waitFor(() => {
expect(screen.getByText('Total Runs')).toBeInTheDocument();
});
expect(screen.getByText('Items Fetched')).toBeInTheDocument();
expect(screen.getByText('New Items')).toBeInTheDocument();
});
it('renders summary values from mock data', async () => {
renderRoute('/ops/ingestion');
await waitFor(() => {
// mock: total_runs: 10, completed: 8, failed: 2, total_items_fetched: 50, total_items_new: 12
expect(screen.getByText('10')).toBeInTheDocument();
});
expect(screen.getByText('8')).toBeInTheDocument();
expect(screen.getByText('50')).toBeInTheDocument();
expect(screen.getByText('12')).toBeInTheDocument();
});
it('renders throughput chart section', async () => {
renderRoute('/ops/ingestion');
await waitFor(() => {
expect(screen.getByText('Throughput')).toBeInTheDocument();
});
});
it('renders bucket selector buttons', async () => {
renderRoute('/ops/ingestion');
await waitFor(() => {
expect(screen.getByText('Ingestion Monitor')).toBeInTheDocument();
});
// Bucket selector has 15m, 1h, 6h, 1d — just verify the group exists
expect(screen.getByText('15m')).toBeInTheDocument();
});
});
describe('Model Performance page', () => {
it('renders page title', async () => {
renderRoute('/ops/model');
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'Model Performance' })).toBeInTheDocument();
});
});
it('renders key metric cards', async () => {
renderRoute('/ops/model');
await waitFor(() => {
expect(screen.getByText('Total Extractions')).toBeInTheDocument();
});
expect(screen.getByText('Success Rate')).toBeInTheDocument();
expect(screen.getByText('Avg Latency')).toBeInTheDocument();
expect(screen.getByText('Retry Rate')).toBeInTheDocument();
expect(screen.getByText('Avg Confidence')).toBeInTheDocument();
});
it('renders metric values from mock data', async () => {
renderRoute('/ops/model');
await waitFor(() => {
// mock: total_extractions: 20, success_rate: 0.9, avg_duration_ms: 1500, retry_rate: 0.05, avg_confidence: 0.8
expect(screen.getByText('20')).toBeInTheDocument();
});
expect(screen.getByText('90.0%')).toBeInTheDocument();
expect(screen.getByText('1500ms')).toBeInTheDocument();
expect(screen.getByText('5.0%')).toBeInTheDocument();
expect(screen.getByText('80%')).toBeInTheDocument();
});
it('renders recent failures section', async () => {
renderRoute('/ops/model');
await waitFor(() => {
expect(screen.getByText('Recent Failures (0)')).toBeInTheDocument();
});
expect(screen.getByText('No recent failures')).toBeInTheDocument();
});
});
describe('Source Coverage page', () => {
it('renders page title', async () => {
renderRoute('/ops/coverage');
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'Source Coverage' })).toBeInTheDocument();
});
});
it('renders coverage matrix section', async () => {
renderRoute('/ops/coverage');
await waitFor(() => {
expect(screen.getByText('Company × Source Type Matrix')).toBeInTheDocument();
});
});
});
+51
View File
@@ -0,0 +1,51 @@
import { describe, it, expect } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderRoute } from './render';
describe('Watchlists page', () => {
it('renders page title', async () => {
renderRoute('/watchlists');
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'Watchlists' })).toBeInTheDocument();
});
});
it('renders New Watchlist button', async () => {
renderRoute('/watchlists');
await waitFor(() => {
expect(screen.getByText('New Watchlist')).toBeInTheDocument();
});
});
it('shows create form on button click', async () => {
const user = userEvent.setup();
renderRoute('/watchlists');
await waitFor(() => {
expect(screen.getByText('New Watchlist')).toBeInTheDocument();
});
await user.click(screen.getByText('New Watchlist'));
await waitFor(() => {
expect(screen.getByLabelText('Watchlist name')).toBeInTheDocument();
});
expect(screen.getByLabelText('Watchlist description')).toBeInTheDocument();
expect(screen.getByText('Create')).toBeInTheDocument();
expect(screen.getByText('Cancel')).toBeInTheDocument();
});
it('cancel closes the create form', async () => {
const user = userEvent.setup();
renderRoute('/watchlists');
await waitFor(() => {
expect(screen.getByText('New Watchlist')).toBeInTheDocument();
});
await user.click(screen.getByText('New Watchlist'));
await waitFor(() => {
expect(screen.getByText('Cancel')).toBeInTheDocument();
});
await user.click(screen.getByText('Cancel'));
await waitFor(() => {
expect(screen.queryByLabelText('Watchlist name')).not.toBeInTheDocument();
});
});
});