| 1 | import { act } from "react"; |
| 2 | import type { RemoteSessionApi } from "../../lib/useRemoteSession"; |
| 3 | type Check = (value: boolean, label: string) => void; |
| 4 | |
| 5 | export async function verifyRemoteSubmissionLifecycle(getProbe: () => RemoteSessionApi | undefined, setError: (error: Error | undefined) => void, tape: string[], flush: () => Promise<unknown>, ok: Check) { |
| 6 | ok(Object.values(getProbe()?.transcript.localSubmissions ?? {}).find(submission => submission.text === "run tests")?.status === "accepted", |
| 7 | "remote RPC success accepts the echo without removing it"); |
| 8 | const realNow = Date.now; |
| 9 | try { |
| 10 | Date.now = () => 123456789; |
| 11 | await act(async () => { await Promise.all([getProbe()?.submit("same millisecond A"), getProbe()?.submit("same millisecond B")]); await flush(); }); |
| 12 | } finally { Date.now = realNow; } |
| 13 | const sameTick = Object.values(getProbe()?.transcript.localSubmissions ?? {}).filter(submission => submission.text.startsWith("same millisecond")); |
| 14 | ok(sameTick.length === 2 && new Set(sameTick.map(submission => submission.submissionId)).size === 2, |
| 15 | "remote submissions within the same millisecond retain distinct identities"); |
| 16 | setError(new Error("explicit rejection")); |
| 17 | await act(async () => { await getProbe()?.submit("rejected remote").catch(() => {}); await flush(); }); |
| 18 | ok(Object.values(getProbe()?.transcript.localSubmissions ?? {}).find(submission => submission.text === "rejected remote")?.status === "failed", |
| 19 | "remote explicit rejection preserves a failed echo"); |
| 20 | setError(new Error("network timeout")); |
| 21 | await act(async () => { await getProbe()?.submit("unknown remote").catch(() => {}); await flush(); }); |
| 22 | ok(Object.values(getProbe()?.transcript.localSubmissions ?? {}).find(submission => submission.text === "unknown remote")?.status === "unknown", |
| 23 | "remote transport timeout preserves an unknown echo"); |
| 24 | ok(tape.filter(entry => entry === "submit:tab-remote-2:unknown remote").length === 1, |
| 25 | "unknown remote result is not automatically resubmitted"); |
| 26 | setError(undefined); |
| 27 | } |
| 28 | |
| 29 | export async function verifyRemoteSubmissionTabIsolation(getProbe: () => RemoteSessionApi | undefined, render: (tabId: string) => void, flush: () => Promise<unknown>, ok: Check) { |
| 30 | const retainedSubmissionIds = Object.keys(getProbe()?.transcript.localSubmissions ?? {}); |
| 31 | await act(async () => { |
| 32 | render("tab-other-submissions"); |
| 33 | await flush(); |
| 34 | }); |
| 35 | ok(getProbe()?.transcript.localSubmissionOrder.length === 0, "remote tab hydration cannot copy another tab's pending echoes"); |
| 36 | await act(async () => { |
| 37 | render("tab-remote-2"); |
| 38 | await flush(); |
| 39 | }); |
| 40 | ok(retainedSubmissionIds.length > 0 && retainedSubmissionIds.every(id => Boolean(getProbe()?.transcript.localSubmissions[id])), |
| 41 | "switching back retains unresolved echoes in their original remote session"); |
| 42 | } |
| 43 |