46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
|
|
test("JobHistory shows jobs and job detail navigates", async ({ page }) => {
|
|
await page.goto("/stocks");
|
|
await page.waitForSelector("table tbody tr");
|
|
const firstRow = page.locator("tbody tr").first();
|
|
const symbol = (await firstRow.locator("td a").textContent()) || "";
|
|
const ticker = symbol.trim();
|
|
|
|
// Enqueue background analyze via API to get deterministic jobId
|
|
const base = new URL(page.url()).origin;
|
|
const resp = await page.request.post(`${base}/api/analyze`, {
|
|
data: { ticker, background: true },
|
|
});
|
|
expect([200, 202]).toContain(resp.status());
|
|
const body = await resp.json();
|
|
const jobId = body.jobId || body.job?.id;
|
|
expect(jobId).toBeTruthy();
|
|
|
|
// Navigate to stock detail page by clicking the symbol link (avoids aborted navigations)
|
|
const symbolLink = firstRow.locator('td a');
|
|
await symbolLink.click();
|
|
await page.waitForURL(new RegExp(`/stocks/${ticker}`), { timeout: 10000 });
|
|
|
|
// Wait up to 10s for JobHistory to show at least one job
|
|
await page.waitForSelector('text=Job History', { timeout: 10000 });
|
|
await page.waitForFunction((id) => {
|
|
const els = Array.from(document.querySelectorAll('div')).filter(el => el.textContent?.includes(id));
|
|
return els.length > 0;
|
|
}, jobId, { timeout: 10000 });
|
|
|
|
// Click Details for the job (opens internal route)
|
|
const detailsLink = page.locator(`a:has-text("Details")`).first();
|
|
await detailsLink.click();
|
|
|
|
// Should navigate to /jobs/:jobId
|
|
await page.waitForSelector('h1');
|
|
const h1 = await page.locator('h1').textContent();
|
|
expect(h1).toContain(jobId);
|
|
|
|
// Try cancelling the job via API - may be already processed, but endpoint should respond
|
|
const cancelResp = await page.request.post(`${base}/api/jobs/${jobId}/cancel`);
|
|
expect(cancelResp.ok()).toBeTruthy();
|
|
const cancelBody = await cancelResp.json();
|
|
expect(Object.prototype.hasOwnProperty.call(cancelBody, 'cancelled')).toBeTruthy();
|
|
}); |