142 lines
6.8 KiB
TypeScript
142 lines
6.8 KiB
TypeScript
import AxeBuilder from "@axe-core/playwright";
|
|
import { expect, test } from "@playwright/test";
|
|
import { authenticatedStatePath } from "../global-setup";
|
|
import { expectAuthenticatedShell, fillMarkdown, openNewKnowledgePage, readMarkdown } from "./support/v2";
|
|
|
|
// Reuses the single shared login performed once in global-setup.ts (the login
|
|
// endpoint is rate-limited — see that file's comment) rather than each test signing
|
|
// in for itself; only auth-journey.spec.ts exercises the login endpoint directly.
|
|
test.use({ storageState: authenticatedStatePath });
|
|
|
|
test.describe("knowledge page editing journey", () => {
|
|
test("managed import markers stay stored and editable but never appear in the reader view", async ({ page }) => {
|
|
const uniqueTitle = `E2E-beheerde-bron ${Date.now()}`;
|
|
const notes = "Mijn byte-beschermde notitie.";
|
|
const markdown = [
|
|
"<!-- managed-source:start -->",
|
|
"# Veilige broninhoud",
|
|
"<!-- unknown-control -->",
|
|
"<script>alert('nooit uitvoeren')</script>",
|
|
"<!-- managed-source:end -->",
|
|
"",
|
|
"<!-- user-notes:start -->",
|
|
notes,
|
|
"<!-- user-notes:end -->"
|
|
].join("\n");
|
|
|
|
await page.goto("/");
|
|
await expectAuthenticatedShell(page);
|
|
await openNewKnowledgePage(page);
|
|
await page.getByLabel("Paginatitel").fill(uniqueTitle);
|
|
await fillMarkdown(page, markdown);
|
|
await page.getByLabel(/Labels/).fill("source:canvas, course:zc0026, managed-source");
|
|
await page.getByRole("button", { name: "Publiceren", exact: true }).click();
|
|
|
|
const article = page.locator("article.page-content");
|
|
await expect(article).toContainText("Veilige broninhoud");
|
|
await expect(article).toContainText(notes);
|
|
await expect(article).toContainText("unknown-control");
|
|
await expect(article).not.toContainText("managed-source");
|
|
await expect(article).not.toContainText("user-notes");
|
|
await expect(article.locator("script")).toHaveCount(0);
|
|
await expect(page.getByText("Broninformatie en beheerstatus")).toBeVisible();
|
|
await expect(page.locator(".tag-chip", { hasText: "source:canvas" })).toHaveCount(0);
|
|
|
|
await page.getByRole("button", { name: "Bewerken" }).click();
|
|
await expect(page.getByRole("note")).toContainText("Laat de vier importmarkeringen");
|
|
expect(await readMarkdown(page)).toBe(markdown);
|
|
|
|
const republished = markdown.replace("# Veilige broninhoud", "# Veilige broninhoud bijgewerkt");
|
|
await fillMarkdown(page, republished);
|
|
await page.getByRole("button", { name: "Wijzigingen publiceren" }).click();
|
|
await expect(article).toContainText("Veilige broninhoud bijgewerkt");
|
|
await expect(article).toContainText(notes);
|
|
await expect(article).not.toContainText("managed-source");
|
|
});
|
|
|
|
test("a page can be created, edited, moved to the trash and restored", async ({ page }) => {
|
|
const uniqueTitle = `E2E-testpagina ${Date.now()}`;
|
|
|
|
await page.goto("/");
|
|
await expectAuthenticatedShell(page);
|
|
|
|
// --- Create -----------------------------------------------------------------
|
|
await openNewKnowledgePage(page);
|
|
|
|
const createAccessibility = await new AxeBuilder({ page }).analyze();
|
|
expect(createAccessibility.violations).toEqual([]);
|
|
|
|
await page.getByLabel("Paginatitel").fill(uniqueTitle);
|
|
await fillMarkdown(page, "# Inleiding\n\nDit is een testpagina voor de E2E-suite.");
|
|
await page.getByRole("button", { name: "Publiceren", exact: true }).click();
|
|
|
|
await expect(page.getByRole("heading", { name: uniqueTitle })).toBeVisible();
|
|
await expect(page.getByText("Inleiding")).toBeVisible();
|
|
|
|
const viewAccessibility = await new AxeBuilder({ page }).analyze();
|
|
expect(viewAccessibility.violations).toEqual([]);
|
|
|
|
// --- Edit ---------------------------------------------------------------------
|
|
await page.getByRole("button", { name: "Bewerken" }).click();
|
|
await expect(page.getByRole("heading", { name: `Bewerken: ${uniqueTitle}` })).toBeVisible();
|
|
|
|
const updatedTitle = `${uniqueTitle} (bijgewerkt)`;
|
|
await page.getByLabel("Paginatitel").fill(updatedTitle);
|
|
await page.getByRole("button", { name: "Wijzigingen publiceren" }).click();
|
|
|
|
await expect(page.getByRole("heading", { name: updatedTitle })).toBeVisible();
|
|
|
|
// --- Trash and restore ---------------------------------------------------------
|
|
await page.getByRole("button", { name: "Meer pagina-acties" }).click();
|
|
await page.getByRole("menuitem", { name: "Naar prullenbak" }).click();
|
|
await expect(page.getByText("Deze pagina staat in de prullenbak.")).toBeVisible();
|
|
|
|
await page.getByRole("button", { name: "Herstellen" }).click();
|
|
await expect(page.getByText("Deze pagina staat in de prullenbak.")).not.toBeVisible();
|
|
});
|
|
|
|
test("publishing against a stale version shows an explicit conflict resolution flow", async ({
|
|
page,
|
|
context
|
|
}) => {
|
|
const uniqueTitle = `E2E-conflictpagina ${Date.now()}`;
|
|
|
|
await page.goto("/");
|
|
await expectAuthenticatedShell(page);
|
|
await openNewKnowledgePage(page);
|
|
await page.getByLabel("Paginatitel").fill(uniqueTitle);
|
|
await fillMarkdown(page, "Oorspronkelijke inhoud.");
|
|
await page.getByRole("button", { name: "Publiceren", exact: true }).click();
|
|
await expect(page.getByRole("heading", { name: uniqueTitle })).toBeVisible();
|
|
|
|
// A second tab opens the same shareable V2 deep link, simulating two concurrent
|
|
// editors without relying on transient component state.
|
|
const pageUrl = page.url();
|
|
const secondPage = await context.newPage();
|
|
await secondPage.goto(pageUrl);
|
|
await expectAuthenticatedShell(secondPage);
|
|
await expect(secondPage.getByRole("heading", { name: uniqueTitle })).toBeVisible();
|
|
await secondPage.getByRole("button", { name: "Bewerken" }).click();
|
|
await secondPage.getByLabel("Paginatitel").fill(`${uniqueTitle} (tweede editor)`);
|
|
|
|
// The first tab publishes first, advancing the page's revision/ETag.
|
|
await page.getByRole("button", { name: "Bewerken" }).click();
|
|
await page.getByLabel("Paginatitel").fill(`${uniqueTitle} (eerste editor)`);
|
|
await page.getByRole("button", { name: "Wijzigingen publiceren" }).click();
|
|
await expect(page.getByRole("heading", { name: `${uniqueTitle} (eerste editor)` })).toBeVisible();
|
|
|
|
// The second tab's publish attempt now targets a stale ETag and must surface an
|
|
// explicit conflict rather than silently overwriting the first editor's change.
|
|
await secondPage.getByRole("button", { name: "Wijzigingen publiceren" }).click();
|
|
await expect(secondPage.getByText("Versieconflict")).toBeVisible();
|
|
|
|
const conflictAccessibility = await new AxeBuilder({ page: secondPage }).analyze();
|
|
expect(conflictAccessibility.violations).toEqual([]);
|
|
|
|
await secondPage.getByRole("button", { name: "Serverversie gebruiken" }).click();
|
|
await expect(secondPage.getByLabel("Paginatitel")).toHaveValue(`${uniqueTitle} (eerste editor)`);
|
|
|
|
await secondPage.close();
|
|
});
|
|
});
|