// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // The live note list (umbrella TS6.2 to TS6.6) in a real browser against the whole stack: a note // added, renamed and deleted in one tab appears, changes and goes in another without a reload; the // write answers ConusAI-Txid; another organization's member sees none of it and cannot open the // first organization's stream. Every screen passes axe. import { expect, test } from "@playwright/test" import { call, callRaw, makeOrganization, signIn, unique, violations } from "./support/app" test("a note written in one tab appears, changes and goes in another without a reload", async ({ browser }) => { const context = await browser.newContext() const watcher = await context.newPage() await signIn(watcher, `${unique("live")}@example.test`) const scope = await makeOrganization(watcher, "live") const list = `/${scope.org}/${scope.workspace}/${scope.project}/notes` await watcher.goto(list) await expect(watcher.getByText("No notes yet.")).toBeVisible() expect(await violations(watcher)).toEqual([]) // Mark the document: a reload would lose the mark, so finding it later proves there was none. await watcher.evaluate(() => { ;(window as unknown as { liveMark: string }).liveMark = "kept" }) const writer = await context.newPage() await writer.goto(list) const csrf = (await writer.locator('meta[name="csrf-token"]').getAttribute("content")) ?? "" const created = await callRaw(writer.request, csrf, "notes.note.create", { ...scope, title: "Live one", body: "b" }) expect(created.ok()).toBe(true) expect(created.headers()["conusai-txid"]).toMatch(/^\d+$/) const note = (await created.json()) as { noteId: string; version: number } await expect(watcher.getByRole("row", { name: /Live one/ })).toBeVisible() await call(writer, "notes.note.update", { ...scope, noteId: note.noteId, title: "Live renamed", body: "b", expectedVersion: note.version, }) await expect(watcher.getByRole("row", { name: /Live renamed/ })).toBeVisible() await call(writer, "notes.note.delete", { ...scope, noteId: note.noteId }) await expect(watcher.getByRole("row", { name: /Live renamed/ })).toHaveCount(0) expect(await watcher.evaluate(() => (window as unknown as { liveMark?: string }).liveMark)).toBe("kept") expect(await violations(watcher)).toEqual([]) // A read answers no transaction id. const read = await callRaw(writer.request, csrf, "notes.note.list", scope) expect(read.headers()["conusai-txid"]).toBeUndefined() // Another organization's member: refused the first organization's stream, and blind to its writes. const other = await (await browser.newContext()).newPage() await signIn(other, `${unique("outsider")}@example.test`) const theirs = await makeOrganization(other, "other") const otherCsrf = (await other.locator('meta[name="csrf-token"]').getAttribute("content")) ?? "" const foreign = await other.request.post(`/api/v1/orgs/${scope.org}/live`, { data: { protocol: "clp/1", after: null, entities: ["notes.note"], topics: [] }, headers: { "x-csrf-token": otherCsrf, "content-type": "application/json", "sec-fetch-site": "same-origin" }, }) expect(foreign.status()).toBe(404) await other.goto(`/${theirs.org}/${theirs.workspace}/${theirs.project}/notes`) await expect(other.getByText("No notes yet.")).toBeVisible() await call(writer, "notes.note.create", { ...scope, title: "Not for others", body: "b" }) await expect(watcher.getByRole("row", { name: /Not for others/ })).toBeVisible() await expect(other.getByText("No notes yet.")).toBeVisible() await expect(other.getByRole("row", { name: /Not for others/ })).toHaveCount(0) })