Repository navigation
Expand file tree
/
Copy pathoffline-first.browser.ts
More file actions
99 lines (86 loc) · 3.45 KB
/
Copy pathoffline-first.browser.ts
File metadata and controls
99 lines (86 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { expect, test, type APIRequestContext, type Page } from "@playwright/test"
type InspectionCall =
| { actorId: string; operation: "record"; argumentsValue: { findingId: string; note: string } }
| { actorId: string; operation: "snapshot"; argumentsValue?: never }
function callInspection(page: Page, call: InspectionCall): Promise<unknown> {
return page.evaluate(
async ({ modulePath, callValue }) => {
const { callActor } = await import(modulePath)
return callActor(callValue)
},
{ modulePath: "/examples/guides/offline-first/page.js", callValue: call },
)
}
async function serverFindingIds(request: APIRequestContext, actorId: string): Promise<string[]> {
const response = await request.get(`/inspections/state?actorId=${actorId}`)
const body = (await response.json()) as { findings: { findingId: string }[] }
return body.findings.map((finding) => finding.findingId)
}
test("records findings offline in two tabs and syncs them once, in order", async ({
context,
request,
baseURL,
}) => {
test.setTimeout(60_000)
const actorId = `site-${Date.now()}`
await context.addCookies([{ name: "device", value: "tablet-7", url: baseURL ?? "" }])
await request.post("/inspections/network?online=false")
const firstTab = await context.newPage()
const secondTab = await context.newPage()
await firstTab.goto("/")
await secondTab.goto("/")
await callInspection(firstTab, {
actorId,
operation: "record",
argumentsValue: { findingId: "finding-1", note: "Crack in the north wall" },
})
await callInspection(firstTab, {
actorId,
operation: "record",
argumentsValue: { findingId: "finding-2", note: "Loose handrail" },
})
await callInspection(secondTab, {
actorId,
operation: "record",
argumentsValue: { findingId: "finding-3", note: "Exit sign is dark" },
})
await firstTab.waitForTimeout(1_500)
expect(await serverFindingIds(request, actorId)).toEqual([])
await request.post("/inspections/network?online=true")
await expect
.poll(() => serverFindingIds(request, actorId), { timeout: 30_000 })
.toEqual(["finding-1", "finding-2", "finding-3"])
await firstTab.waitForTimeout(1_500)
expect(await serverFindingIds(request, actorId)).toEqual(["finding-1", "finding-2", "finding-3"])
})
test("keeps the local findings after a reload", async ({ page }) => {
const actorId = `site-reload-${Date.now()}`
await page.goto("/")
await callInspection(page, {
actorId,
operation: "record",
argumentsValue: { findingId: "finding-1", note: "Crack in the north wall" },
})
await page.reload()
const snapshot = (await callInspection(page, { actorId, operation: "snapshot" })) as {
findings: { findingId: string }[]
}
expect(snapshot.findings.map((finding) => finding.findingId)).toEqual(["finding-1"])
})
test("loses edits that wait in page memory when the page reloads", async ({ page }) => {
const modulePath = "/examples/guides/offline-first/memory-outbox.js"
await page.goto("/")
const before = await page.evaluate(async (path) => {
const outbox = await import(path)
outbox.queueFinding({ findingId: "finding-1", note: "Crack in the north wall" })
outbox.queueFinding({ findingId: "finding-2", note: "Loose handrail" })
return outbox.pendingFindings()
}, modulePath)
expect(before).toBe(2)
await page.reload()
const after = await page.evaluate(
async (path) => (await import(path)).pendingFindings(),
modulePath,
)
expect(after).toBe(0)
})