Skip to content
Source
Sign inSign up
Open History to see the last commit

thread-route-hydration.test.ts

155 lines4.8 KB

1import * as Option from "effect/Option";
2import { describe, expect, it } from "vite-plus/test";
3​
4import {
5 threadDetailErrorIsCurrent,
6 threadRouteIsHydrating,
7 threadRouteOpensDraft,
8} from "./thread-route-hydration";
9​
10const settled = {
11 isLoadingConnections: false,
12 environmentRegistered: true,
13 localCacheRead: true,
14 connectionState: "connected" as const,
15 shellStatus: "live" as const,
16 shellHasError: false,
17 detailStatus: "live" as const,
18 detailHasError: false,
19};
20​
21describe("threadRouteIsHydrating", () => {
22 it("waits for shell and thread detail hydration", () => {
23 expect(threadRouteIsHydrating({ ...settled, shellStatus: "synchronizing" })).toBe(true);
24 expect(threadRouteIsHydrating({ ...settled, shellStatus: "empty" })).toBe(true);
25 expect(threadRouteIsHydrating({ ...settled, detailStatus: "synchronizing" })).toBe(true);
26 expect(threadRouteIsHydrating({ ...settled, detailStatus: "empty" })).toBe(true);
27 });
28​
29 it("waits for the local cache before trusting an offline connection", () => {
30 const offline = {
31 ...settled,
32 connectionState: "offline" as const,
33 detailStatus: "empty" as const,
34 };
35 expect(threadRouteIsHydrating({ ...offline, localCacheRead: false })).toBe(true);
36 expect(threadRouteIsHydrating(offline)).toBe(false);
37 expect(threadRouteIsHydrating({ ...offline, connectionState: "reconnecting" })).toBe(false);
38 expect(threadRouteIsHydrating({ ...offline, connectionState: "connecting" })).toBe(true);
39 expect(
40 threadRouteIsHydrating({ ...offline, localCacheRead: false, environmentRegistered: false }),
41 ).toBe(false);
42 });
43​
44 it("stops waiting once an empty detail has an actionable outcome", () => {
45 expect(
46 threadRouteIsHydrating({
47 ...settled,
48 shellStatus: "empty",
49 shellHasError: true,
50 detailStatus: "deleted",
51 }),
52 ).toBe(false);
53 expect(
54 threadRouteIsHydrating({
55 ...settled,
56 detailStatus: "empty",
57 detailHasError: true,
58 }),
59 ).toBe(false);
60 expect(
61 threadRouteIsHydrating({
62 ...settled,
63 connectionState: "available",
64 detailStatus: "empty",
65 }),
66 ).toBe(false);
67 expect(threadRouteIsHydrating({ ...settled, detailStatus: "deleted" })).toBe(false);
68 });
69​
70 it("prioritizes terminal outcomes over unrelated hydration", () => {
71 expect(
72 threadRouteIsHydrating({
73 ...settled,
74 connectionState: "reconnecting",
75 shellStatus: "synchronizing",
76 detailStatus: "deleted",
77 }),
78 ).toBe(false);
79 expect(
80 threadRouteIsHydrating({
81 ...settled,
82 connectionState: "reconnecting",
83 shellStatus: "synchronizing",
84 detailHasError: true,
85 }),
86 ).toBe(false);
87 expect(
88 threadRouteIsHydrating({
89 ...settled,
90 connectionState: "offline",
91 shellStatus: "synchronizing",
92 detailStatus: "synchronizing",
93 }),
94 ).toBe(false);
95 });
96});
97​
98describe("threadRouteOpensDraft", () => {
99 it("keeps the route while a reconnecting environment may still deliver the thread", () => {
100 expect(threadRouteOpensDraft({ connectionState: "reconnecting", detailStatus: "empty" })).toBe(
101 false,
102 );
103 });
104​
105 it("keeps the route while Reconnect retries a thread that failed to sync", () => {
106 const failedDetail = {
107 ...settled,
108 connectionState: "connecting" as const,
109 detailStatus: "empty" as const,
110 detailHasError: true,
111 };
112 expect(threadRouteIsHydrating(failedDetail)).toBe(false);
113 expect(threadRouteOpensDraft(failedDetail)).toBe(false);
114 });
115​
116 it("opens a draft once the thread can't arrive", () => {
117 expect(
118 threadRouteOpensDraft({ connectionState: "reconnecting", detailStatus: "deleted" }),
119 ).toBe(true);
120 expect(threadRouteOpensDraft({ connectionState: "offline", detailStatus: "empty" })).toBe(true);
121 });
122});
123​
124describe("threadDetailErrorIsCurrent", () => {
125 const oldError = Option.some("Could not synchronize the thread.");
126​
127 it("ignores the error a thread kept from before the connection came back", () => {
128 const detailHasError = threadDetailErrorIsCurrent({
129 connectionState: "connected",
130 error: oldError,
131 errorBeforeConnected: oldError,
132 });
133 expect(detailHasError).toBe(false);
134 expect(threadRouteIsHydrating({ ...settled, detailStatus: "empty", detailHasError })).toBe(
135 true,
136 );
137 });
138​
139 it("counts an error the live connection reported", () => {
140 expect(
141 threadDetailErrorIsCurrent({
142 connectionState: "connected",
143 error: Option.some("Could not synchronize the thread."),
144 errorBeforeConnected: oldError,
145 }),
146 ).toBe(true);
147 expect(
148 threadDetailErrorIsCurrent({
149 connectionState: "reconnecting",
150 error: oldError,
151 errorBeforeConnected: oldError,
152 }),
153 ).toBe(true);
154 });
155});