136 lines
4.6 KiB
TypeScript
136 lines
4.6 KiB
TypeScript
import { expect, test, type Download, type Page } from "@playwright/test";
|
|
import {
|
|
createMinimalOdp,
|
|
createMinimalOds,
|
|
createMinimalOdt,
|
|
type OdfFixture,
|
|
} from "../fixtures/odf";
|
|
|
|
const entry = "/deep/nested/office/";
|
|
|
|
async function openFixture(page: Page, fixture: OdfFixture) {
|
|
await page.goto(entry);
|
|
await page.getByTestId("office-file-input").setInputFiles(fixture);
|
|
await expect(page.getByText("Rendered locally", { exact: true })).toBeVisible(
|
|
{
|
|
timeout: 30_000,
|
|
},
|
|
);
|
|
}
|
|
|
|
async function find(page: Page, value: string) {
|
|
const search = page.getByRole("search");
|
|
await search.getByPlaceholder("Find in file").fill(value);
|
|
await search.getByRole("button", { name: "Find" }).click();
|
|
await expect(search.getByText("1 of 1", { exact: true })).toBeVisible();
|
|
}
|
|
|
|
async function downloadedBytes(download: Download): Promise<Uint8Array> {
|
|
const stream = await download.createReadStream();
|
|
const chunks: Uint8Array[] = [];
|
|
let total = 0;
|
|
for await (const chunk of stream) {
|
|
const bytes =
|
|
typeof chunk === "string"
|
|
? new TextEncoder().encode(chunk)
|
|
: new Uint8Array(chunk as ArrayBufferLike);
|
|
chunks.push(bytes);
|
|
total += bytes.byteLength;
|
|
}
|
|
const result = new Uint8Array(total);
|
|
let offset = 0;
|
|
for (const chunk of chunks) {
|
|
result.set(chunk, offset);
|
|
offset += chunk.byteLength;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
test("renders and searches a project-authored ODT in an isolated worker", async ({
|
|
page,
|
|
}) => {
|
|
const fixture = createMinimalOdt();
|
|
const externalHosts = new Set<string>();
|
|
const errors: string[] = [];
|
|
const workerScripts: URL[] = [];
|
|
page.on("request", (request) => {
|
|
const url = new URL(request.url());
|
|
if (
|
|
(url.protocol === "http:" || url.protocol === "https:") &&
|
|
url.hostname !== "127.0.0.1"
|
|
)
|
|
externalHosts.add(url.hostname);
|
|
if (url.pathname.includes("odf.worker")) workerScripts.push(url);
|
|
});
|
|
page.on("console", (message) => {
|
|
if (message.type() === "error") errors.push(message.text());
|
|
});
|
|
page.on("pageerror", (error) => errors.push(error.message));
|
|
|
|
await openFixture(page, fixture);
|
|
await expect(
|
|
page.getByRole("heading", { name: "OpenDocument Text Fixture" }),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole("table", { name: "Fixture table" }),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole("img", { name: "Project-authored fixture image" }),
|
|
).toBeVisible();
|
|
await find(page, "ODT Search Marker");
|
|
await page.getByRole("button", { name: "Zoom in" }).click();
|
|
await expect(page.getByText("110%", { exact: true })).toBeVisible();
|
|
|
|
const exactCopy = page.waitForEvent("download");
|
|
await page.getByRole("button", { name: "Save exact copy" }).click();
|
|
const exactBytes = await downloadedBytes(await exactCopy);
|
|
expect([...exactBytes]).toEqual([...fixture.buffer]);
|
|
|
|
expect(externalHosts).toEqual(new Set());
|
|
expect(errors).toEqual([]);
|
|
expect(workerScripts.length).toBeGreaterThan(0);
|
|
expect(
|
|
workerScripts.every(
|
|
(url) =>
|
|
url.origin === "http://127.0.0.1:4173" &&
|
|
url.pathname.startsWith("/deep/nested/office/assets/"),
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
test("renders, searches and switches sheets in a project-authored ODS", async ({
|
|
page,
|
|
}) => {
|
|
await openFixture(page, createMinimalOds());
|
|
await expect(page.getByText("sheet 1 of 2", { exact: true })).toBeVisible();
|
|
await expect(page.getByRole("grid")).toContainText("Office Tools Workbook");
|
|
await find(page, "ODS Search Marker");
|
|
await page.getByRole("button", { name: "Next sheet" }).click();
|
|
await expect(page.getByText("sheet 2 of 2", { exact: true })).toBeVisible();
|
|
await expect(page.getByRole("grid")).toContainText("Second sheet content");
|
|
const csvDownload = page.waitForEvent("download");
|
|
await page.getByRole("button", { name: "Export sheet CSV" }).click();
|
|
const csv = new TextDecoder().decode(
|
|
await downloadedBytes(await csvDownload),
|
|
);
|
|
expect(csv).toContain("Second sheet content");
|
|
});
|
|
|
|
test("renders, searches and navigates a project-authored ODP", async ({
|
|
page,
|
|
}) => {
|
|
await openFixture(page, createMinimalOdp());
|
|
await expect(page.getByText("slide 1 of 2", { exact: true })).toBeVisible();
|
|
await expect(
|
|
page.getByRole("heading", { name: "OpenDocument Presentation Fixture" }),
|
|
).toBeVisible();
|
|
await find(page, "ODP Search Marker");
|
|
await expect(page.getByText("slide 2 of 2", { exact: true })).toBeVisible();
|
|
await expect(
|
|
page.getByRole("heading", { name: "ODP Search Marker" }),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole("complementary", { name: "Speaker notes" }),
|
|
).toContainText("Second speaker note");
|
|
});
|