File
Blob: tests/e2e/specs/04-read-only-controllers.spec.ts
| 1 | import { |
| 2 | test, |
| 3 | expect, |
| 4 | createTestPage, |
| 5 | createShareLink, |
| 6 | expectNoChangeFor, |
| 7 | waitForPersistedSnapshot, |
| 8 | } from "../fixtures/bland-test"; |
| 9 | |
| 10 | test.describe("read-only controller suppression", () => { |
| 11 | test("formatting toolbar appears on selection in editable mode, absent in read-only", async ({ |
| 12 | authenticatedPage: { page, accessToken }, |
| 13 | e2eWorkspace, |
| 14 | browser, |
| 15 | }) => { |
| 16 | // Create a page with text content |
| 17 | const testPage = await createTestPage(page, accessToken, "Controller Test", e2eWorkspace); |
| 18 | await page.goto(`/${testPage.workspaceSlug}/${testPage.pageId}`); |
| 19 | |
| 20 | const editor = page.locator(".tiptap[contenteditable='true']"); |
| 21 | await editor.waitFor({ timeout: 30_000 }); |
| 22 | await editor.click(); |
| 23 | await page.keyboard.type("Some text to select"); |
| 24 | |
| 25 | // Wait for content to appear and sync to complete |
| 26 | await expect(editor).toContainText("Some text to select"); |
| 27 | await expect(page.getByText("Connected")).toBeVisible({ timeout: 15_000 }); |
| 28 | await waitForPersistedSnapshot(page, accessToken, { ...testPage, expectedText: "Some text to select" }); |
| 29 | |
| 30 | // Select all text with keyboard (ControlOrMeta for cross-platform) |
| 31 | await page.keyboard.press("ControlOrMeta+A"); |
| 32 | |
| 33 | // Verify the formatting toolbar appears in editable mode |
| 34 | const toolbar = page.locator(".tiptap-toolbar"); |
| 35 | await toolbar.waitFor({ state: "visible", timeout: 5_000 }); |
| 36 | |
| 37 | // Verify drag handle is present in editable mode |
| 38 | await expect(page.locator(".drag-handle")).toHaveCount(1); |
| 39 | |
| 40 | // Create a view-only share link and open it |
| 41 | const share = await createShareLink(page, accessToken, testPage.pageId, "view"); |
| 42 | |
| 43 | const anonContext = await browser.newContext(); |
| 44 | const anonPage = await anonContext.newPage(); |
| 45 | await anonPage.goto(`/s/${share.token}`); |
| 46 | |
| 47 | const readOnlyEditor = anonPage.locator(".tiptap[contenteditable='false']"); |
| 48 | await readOnlyEditor.waitFor({ timeout: 30_000 }); |
| 49 | |
| 50 | // Verify content is present |
| 51 | await expect(readOnlyEditor).toContainText("Some text to select"); |
| 52 | |
| 53 | // Verify no drag handle in read-only mode |
| 54 | await expect(anonPage.locator(".drag-handle")).toHaveCount(0); |
| 55 | |
| 56 | // Try to select text -- formatting toolbar should NOT appear |
| 57 | await readOnlyEditor.click(); |
| 58 | await anonPage.keyboard.press("ControlOrMeta+A"); |
| 59 | await expect(anonPage.locator(".tiptap-toolbar")).toHaveCount(0); |
| 60 | await expectNoChangeFor(() => anonPage.locator(".tiptap-toolbar").count(), 2_000); |
| 61 | |
| 62 | await anonContext.close(); |
| 63 | }); |
| 64 | }); |