Make coverage filing sync explicit
This commit is contained in:
86
e2e/watchlist.spec.ts
Normal file
86
e2e/watchlist.spec.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { expect, test, type Page } from '@playwright/test';
|
||||
|
||||
const PASSWORD = 'Sup3rSecure!123';
|
||||
|
||||
test.describe.configure({ mode: 'serial' });
|
||||
|
||||
function uniqueEmail(prefix: string) {
|
||||
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}@example.com`;
|
||||
}
|
||||
|
||||
async function gotoAuthPage(page: Page, path: string) {
|
||||
await page.goto(path, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForLoadState('networkidle');
|
||||
}
|
||||
|
||||
async function signUp(page: Page, email: string) {
|
||||
await gotoAuthPage(page, '/auth/signup');
|
||||
await page.locator('input[autocomplete="name"]').fill('Playwright Watchlist User');
|
||||
await page.locator('input[autocomplete="email"]').fill(email);
|
||||
await page.locator('input[autocomplete="new-password"]').first().fill(PASSWORD);
|
||||
await page.locator('input[autocomplete="new-password"]').nth(1).fill(PASSWORD);
|
||||
await page.getByRole('button', { name: 'Create account' }).click();
|
||||
}
|
||||
|
||||
async function expectStableDashboard(page: Page) {
|
||||
await expect(page.getByRole('heading', { name: 'Command Center' })).toBeVisible({ timeout: 30_000 });
|
||||
await expect(page).toHaveURL(/\/$/, { timeout: 30_000 });
|
||||
}
|
||||
|
||||
async function countSyncTasks(page: Page, ticker: string) {
|
||||
return await page.evaluate(async (requestedTicker) => {
|
||||
const response = await fetch('/api/tasks?limit=20', {
|
||||
credentials: 'include',
|
||||
cache: 'no-store'
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Unable to load tasks: ${response.status}`);
|
||||
}
|
||||
|
||||
const payload = await response.json() as {
|
||||
tasks?: Array<{
|
||||
task_type?: string;
|
||||
payload?: {
|
||||
ticker?: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
|
||||
return (payload.tasks ?? []).filter((task) => (
|
||||
task.task_type === 'sync_filings'
|
||||
&& task.payload?.ticker === requestedTicker
|
||||
)).length;
|
||||
}, ticker);
|
||||
}
|
||||
|
||||
test('coverage save stays metadata-only until sync filings is clicked', async ({ page }) => {
|
||||
await signUp(page, uniqueEmail('playwright-watchlist-sync'));
|
||||
await expectStableDashboard(page);
|
||||
|
||||
await page.goto('/watchlist', { waitUntil: 'domcontentloaded' });
|
||||
await expect(page.getByRole('heading', { name: 'Coverage', exact: true })).toBeVisible({ timeout: 30_000 });
|
||||
|
||||
await page.getByLabel('Coverage ticker').fill('NVDA');
|
||||
await page.getByLabel('Coverage company name').fill('NVIDIA Corporation');
|
||||
await page.getByLabel('Coverage sector').fill('Technology');
|
||||
await page.getByLabel('Coverage category').fill('core');
|
||||
await page.getByLabel('Coverage tags').fill('semis, ai');
|
||||
await page.getByRole('button', { name: 'Save coverage' }).click();
|
||||
|
||||
const coverageRow = page.locator('tr').filter({ hasText: 'NVDA' });
|
||||
await expect(coverageRow).toContainText('NVIDIA Corporation');
|
||||
|
||||
const notice = page.getByTestId('watchlist-post-create-notice');
|
||||
await expect(notice).toContainText('NVDA added to coverage. Filing sync has not started yet.');
|
||||
await expect(notice.getByRole('button', { name: 'Sync filings' })).toBeVisible();
|
||||
await expect(coverageRow.getByRole('button', { name: 'Sync filings' })).toBeVisible();
|
||||
|
||||
await page.waitForTimeout(1_000);
|
||||
expect(await countSyncTasks(page, 'NVDA')).toBe(0);
|
||||
|
||||
await notice.getByRole('button', { name: 'Sync filings' }).click();
|
||||
|
||||
await expect(notice).toContainText('NVDA added to coverage. Filing sync is queued.');
|
||||
await expect.poll(async () => await countSyncTasks(page, 'NVDA')).toBe(1);
|
||||
});
|
||||
Reference in New Issue
Block a user