Skip to content
File

Blob: tests/e2e/specs/12-canonical-page-cold-deep-link.spec.ts

typescript130 lines
1import {
2 test,
3 expect,
4 createTestPage,
5 loginPage,
6 waitForDocEditorReady,
7 waitForPersistedSnapshot,
8} from "../fixtures/bland-test";
9 
10const SEEDED_BODY_TEXT = "Cold deep link preserves existing body content";
11 
12test.describe("canonical page route - cold deep-link", () => {
13 test("cold deep-link hydrates existing body content without a leading blank block", async ({
14 authenticatedPage: { page, accessToken },
15 e2eWorkspace,
16 browser,
17 }) => {
18 const testPage = await createTestPage(page, accessToken, "Cold Deep Link Page", e2eWorkspace);
19 await page.goto(`/${testPage.workspaceSlug}/${testPage.pageId}`);
20 
21 const seedEditor = await waitForDocEditorReady(page, { editable: true });
22 await seedEditor.click();
23 await page.keyboard.type(SEEDED_BODY_TEXT);
24 await expect(seedEditor).toContainText(SEEDED_BODY_TEXT);
25 await waitForPersistedSnapshot(page, accessToken, { ...testPage, expectedText: SEEDED_BODY_TEXT });
26 
27 const coldContext = await browser.newContext();
28 const coldPage = await coldContext.newPage();
29 await loginPage(coldPage);
30 
31 const contextCalls: string[] = [];
32 const workspacesListCalls: string[] = [];
33 const pagesListCalls: string[] = [];
34 const membersCalls: string[] = [];
35 const pageErrors: string[] = [];
36 
37 coldPage.on("pageerror", (err) => pageErrors.push(err.message));
38 coldPage.on("request", (req) => {
39 const url = new URL(req.url());
40 if (url.pathname === `/api/v1/pages/${testPage.pageId}/context`) {
41 contextCalls.push(req.url());
42 } else if (url.pathname === "/api/v1/workspaces") {
43 workspacesListCalls.push(req.url());
44 } else if (url.pathname === `/api/v1/workspaces/${testPage.workspaceId}/pages`) {
45 pagesListCalls.push(req.url());
46 } else if (url.pathname === `/api/v1/workspaces/${testPage.workspaceId}/members`) {
47 membersCalls.push(req.url());
48 }
49 });
50 
51 await coldPage.goto(`/${testPage.workspaceSlug}/${testPage.pageId}`);
52 
53 const editor = coldPage.locator(".tiptap[contenteditable='true']");
54 await editor.waitFor({ timeout: 30_000 });
55 await expect(editor).toContainText(SEEDED_BODY_TEXT);
56 
57 await editor.click();
58 await coldPage.keyboard.type(" Cold deep link works");
59 await expect(editor).toContainText(SEEDED_BODY_TEXT);
60 await expect(editor).toContainText("Cold deep link works");
61 
62 expect(contextCalls.length).toBeGreaterThanOrEqual(1);
63 expect(contextCalls.length).toBeLessThanOrEqual(2);
64 expect(pagesListCalls.length).toBeGreaterThanOrEqual(1);
65 expect(membersCalls.length).toBeGreaterThanOrEqual(1);
66 expect(workspacesListCalls).toHaveLength(0);
67 expect(pageErrors).toEqual([]);
68 
69 await coldContext.close();
70 });
71 
72 test("brand-new cold deep-link waits for first sync when no persisted snapshot exists yet", async ({
73 authenticatedPage: { page, accessToken },
74 e2eWorkspace,
75 browser,
76 }) => {
77 const testPage = await createTestPage(page, accessToken, "Cold Empty Page", e2eWorkspace);
78 
79 const coldContext = await browser.newContext();
80 const coldPage = await coldContext.newPage();
81 await loginPage(coldPage);
82 
83 const snapshotStatuses: number[] = [];
84 const pageErrors: string[] = [];
85 coldPage.on("pageerror", (err) => pageErrors.push(err.message));
86 coldPage.on("response", (response) => {
87 const url = new URL(response.url());
88 if (url.pathname === `/api/v1/workspaces/${testPage.workspaceId}/pages/${testPage.pageId}/snapshot`) {
89 snapshotStatuses.push(response.status());
90 }
91 });
92 
93 await coldPage.goto(`/${testPage.workspaceSlug}/${testPage.pageId}`);
94 
95 const editor = coldPage.locator(".tiptap[contenteditable='true']");
96 await editor.waitFor({ timeout: 30_000 });
97 await editor.click();
98 await coldPage.keyboard.type("Fresh cold path works");
99 await expect(editor).toContainText("Fresh cold path works");
100 
101 expect(snapshotStatuses).toContain(204);
102 expect(pageErrors).toEqual([]);
103 
104 await coldContext.close();
105 });
106 
107 test("cold deep-link to a canvas page mounts the canvas surface, not the editor", async ({
108 authenticatedPage: { page, accessToken },
109 e2eWorkspace,
110 browser,
111 }) => {
112 const canvasPage = await createTestPage(page, accessToken, "Canvas Cold Deep Link", e2eWorkspace, "canvas");
113 
114 const coldContext = await browser.newContext();
115 const coldPage = await coldContext.newPage();
116 await loginPage(coldPage);
117 
118 const pageErrors: string[] = [];
119 coldPage.on("pageerror", (err) => pageErrors.push(err.message));
120 
121 await coldPage.goto(`/${canvasPage.workspaceSlug}/${canvasPage.pageId}`);
122 
123 await coldPage.locator(".excalidraw").waitFor({ state: "attached", timeout: 30_000 });
124 await expect(coldPage.locator(".tiptap")).toHaveCount(0);
125 expect(pageErrors).toEqual([]);
126 
127 await coldContext.close();
128 });
129});