Files
CA/frontend/e2e/overview.spec.ts

120 lines
4.3 KiB
TypeScript
Raw Normal View History

/**
* (/overview)
*
* user-flows.spec.ts addInitScript cbpoa_token
* page.route /api/** 使 hermetic无需 :8000/wuhan_districts.geojson
* dev server Leaflet
*/
import { test, expect, Page } from '@playwright/test';
import { TESTIDS } from '../src/utils/testids';
/** 13 区里造两条数据,断言 choropleth 能着色、toggle 能切换。 */
function districtPayload() {
return {
districts: [
{ district: '武昌区', outpatient: 120, inpatient: 30, total: 150, outpatient_ratio: 0.8, inpatient_ratio: 0.2 },
{ district: '江岸', outpatient: 60, inpatient: 10, total: 70, outpatient_ratio: 0.86, inpatient_ratio: 0.14 },
],
total: 220,
};
}
async function seedAuthAndMockApi(page: Page) {
await page.addInitScript(() => {
localStorage.setItem('cbpoa_token', 'e2e-test-token');
});
await page.route('/api/**', (route) => {
const url = route.request().url();
const json = (body: unknown) =>
route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(body) });
if (url.includes('/alerts')) {
return json({ alerts: [], total: 0 });
}
if (url.includes('/cases/stats')) {
return json({
total_outpatient: 1000,
total_inpatient: 200,
date_range: { start: '2023-01-01', end: '2023-12-01' },
top_districts: [],
top_diagnoses: [
{ diagnosis: '上呼吸道感染', outpatient: 300, inpatient: 40 },
{ diagnosis: '肺炎', outpatient: 120, inpatient: 80 },
],
});
}
if (url.includes('/cases/trend')) {
return json({
trend: [
{ date: '2023-11-01', outpatient: 10, inpatient: 2, total: 12 },
{ date: '2023-11-02', outpatient: 14, inpatient: 3, total: 17 },
],
summary: {
total_outpatient: 24,
total_inpatient: 5,
period_count: 2,
avg_daily_outpatient: 12,
avg_daily_inpatient: 2.5,
},
});
}
if (url.includes('/cases/districts')) {
return json(districtPayload());
}
if (url.includes('/risk/stats')) {
return json({ high_risk_count: 7, total_grids: 100, avg_risk: 0.4 });
}
if (url.includes('/environment/pollutants')) {
return json({ data: [{ date: '2023-11-01', AQI: 80 }, { date: '2023-11-02', AQI: 95 }] });
}
return json({ data: [], items: [], total: 0 });
});
}
test.describe('Overview 大屏', () => {
test.use({ viewport: { width: 1280, height: 900 } });
test.beforeEach(async ({ page }) => {
await seedAuthAndMockApi(page);
});
test('renders kpi-row, choropleth, as-of badge and metric toggle', async ({ page }) => {
await page.goto('/overview');
await expect(page.locator(`[data-testid="${TESTIDS.pageOverview}"]`)).toBeVisible();
await expect(page.locator(`[data-testid="${TESTIDS.kpiRow}"]`)).toBeVisible();
await expect(page.locator(`[data-testid="${TESTIDS.choroplethWrapper}"]`)).toBeVisible();
// Literal honesty badge — exact text.
const badge = page.locator(`[data-testid="${TESTIDS.asofBadge}"]`);
await expect(badge).toBeVisible();
await expect(badge).toHaveText('数据截至2023-12');
});
test('门诊/住院 toggle switches active segment without error', async ({ page }) => {
await page.goto('/overview');
await expect(page.locator(`[data-testid="${TESTIDS.choroplethWrapper}"]`)).toBeVisible();
const outBtn = page.locator(`[data-testid="${TESTIDS.outinpatientToggle}-outpatient"]`);
const inBtn = page.locator(`[data-testid="${TESTIDS.outinpatientToggle}-inpatient"]`);
const allBtn = page.locator(`[data-testid="${TESTIDS.outinpatientToggle}-all"]`);
// Default: 全部 active (primary background).
await expect(allBtn).toHaveClass(/bg-primary/);
await outBtn.click();
await expect(outBtn).toHaveClass(/bg-primary/);
await expect(allBtn).not.toHaveClass(/bg-primary/);
await inBtn.click();
await expect(inBtn).toHaveClass(/bg-primary/);
await expect(outBtn).not.toHaveClass(/bg-primary/);
// Wrapper still mounted after toggling — no render crash.
await expect(page.locator(`[data-testid="${TESTIDS.choroplethWrapper}"]`)).toBeVisible();
});
});