Files
jobtrackingapp/job-tracker-ui/e2e/csv-export.spec.ts
T
2026-09-28 17:26:02 +02:00

40 lines
2.4 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { readFile } from "node:fs/promises";
const apiUrl = "http://localhost:5302/api";
test("CSV export has safe cells and headers, and browser download preserves its UTF-8 bytes", async ({ page }) => {
await page.addInitScript(() => window.localStorage.setItem("uiLanguage", "en"));
expect((await page.request.post(`${apiUrl}/auth/login`, { data: { email: "e2e@example.test", password: "E2ePassword123!" } })).status()).toBe(200);
const me = await (await page.request.get(`${apiUrl}/auth/me`)).json();
const csrf = (await page.context().cookies()).find(cookie => cookie.name === "XSRF-TOKEN")!.value;
const headers = { "X-CSRF-TOKEN": csrf, "X-Session-Context": me.sessionContext };
const companyName = `B05 Ærlig Økonomi Ås ${Date.now()}`;
const createdCompany = await page.request.post(`${apiUrl}/companies`, { headers, data: { name: companyName } });
expect(createdCompany.status()).toBe(201);
const company = await createdCompany.json();
const createdJob = await page.request.post(`${apiUrl}/jobapplications`, {
headers, data: { companyId: company.id, jobTitle: "=1+1", status: "Saved", notes: " \t+SUM(1,2)\r\næøå" },
});
expect(createdJob.status()).toBe(201);
const job = await createdJob.json();
const response = await page.request.get(`${apiUrl}/export/jobs?format=csv`);
expect(response.status()).toBe(200);
expect(response.headers()["content-type"]).toBe("text/csv; charset=utf-8");
expect(response.headers()["content-disposition"]).toMatch(/^attachment; filename=job-tracker-export-\d{4}-\d{2}-\d{2}\.csv;/);
const bytes = await response.body();
expect([...bytes.subarray(0, 3)]).toEqual([0xef, 0xbb, 0xbf]);
expect(bytes.toString("utf8")).toContain(`${companyName},,,'=1+1,Saved,`);
expect(bytes.toString("utf8")).toContain('"\' \t+SUM(1,2)\r\næøå"');
const raw = await (await page.request.get(`${apiUrl}/export/jobs?format=json`)).json();
expect(raw.find((item: { Id: number }) => item.Id === job.id)).toMatchObject({ JobTitle: "=1+1", Notes: " \t+SUM(1,2)\r\næøå" });
await page.goto("/settings");
const pending = page.waitForEvent("download");
await page.getByRole("button", { name: "Export CSV", exact: true }).click();
const download = await pending;
expect(download.suggestedFilename()).toMatch(/^job-tracker-export-\d{4}-\d{2}-\d{2}\.csv$/);
expect(await readFile((await download.path())!)).toEqual(bytes);
});