-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtestAuthStoresAndErrors.js
More file actions
204 lines (167 loc) · 6.37 KB
/
testAuthStoresAndErrors.js
File metadata and controls
204 lines (167 loc) · 6.37 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import { AsyncAuthStore, LocalAuthStore, ClientResponseError } from "bosbase";
const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms));
async function waitForPersist(persisted, count, timeoutMs = 500) {
const start = Date.now();
while (persisted.length < count) {
if (Date.now() - start > timeoutMs) {
throw new Error(
`Timed out waiting for ${count} persisted operations (have ${persisted.length})`,
);
}
await sleep(10);
}
await sleep(0); // allow the queue microtask to finish
}
async function testAsyncAuthStoreQueueAndInitial() {
console.log("[INFO] Testing AsyncAuthStore initial load and queue ordering...");
const persisted = [];
let clearedCount = 0;
const store = new AsyncAuthStore({
save: async (payload) => {
persisted.push(payload);
},
clear: async () => {
clearedCount += 1;
persisted.push("CLEARED");
},
initial: Promise.resolve(
JSON.stringify({
token: "init-token",
record: { id: "init", collectionName: "users" },
}),
),
});
await waitForPersist(persisted, 1);
if (store.token !== "init-token" || store.record?.id !== "init") {
throw new Error("AsyncAuthStore did not hydrate the initial payload");
}
const parsedInitial = JSON.parse(persisted[0]);
if (parsedInitial.token !== "init-token" || parsedInitial.record?.id !== "init") {
throw new Error("Initial payload was not persisted through the save queue");
}
store.save("next-token", { id: "next", collectionName: "_superusers" });
store.save("final-token");
await waitForPersist(persisted, 3);
if (!persisted[1].includes("next-token") || !persisted[2].includes("final-token")) {
throw new Error("AsyncAuthStore save queue did not preserve call order");
}
store.clear();
await waitForPersist(persisted, 4);
if (clearedCount !== 1 || persisted[3] !== "CLEARED") {
throw new Error("AsyncAuthStore clear did not call the provided clear function");
}
if (store.token !== "" || store.record !== null) {
throw new Error("AsyncAuthStore clear did not reset the in-memory state");
}
console.log(
"[SUCCESS] AsyncAuthStore initial data, queueing, and custom clear behavior verified",
);
}
async function testLocalAuthStoreFallbackAndStorageEvents() {
console.log("[INFO] Testing LocalAuthStore fallback storage and storage events...");
const originalWindow = global.window;
try {
delete global.window;
const fallbackStore = new LocalAuthStore("local_auth_fallback_test");
fallbackStore.save("local-token", { id: "loc-1", collectionName: "users" });
if (fallbackStore.token !== "local-token" || fallbackStore.record?.id !== "loc-1") {
throw new Error("LocalAuthStore fallback storage did not retain saved state");
}
fallbackStore.clear();
if (fallbackStore.token !== "" || fallbackStore.record !== null) {
throw new Error("LocalAuthStore clear did not reset fallback storage");
}
const mockStorage = {};
const listeners = {};
global.window = {
localStorage: {
getItem: (key) => (key in mockStorage ? mockStorage[key] : null),
setItem: (key, value) => {
mockStorage[key] = String(value);
},
removeItem: (key) => {
delete mockStorage[key];
},
},
addEventListener: (type, cb) => {
listeners[type] = cb;
},
dispatchEvent: (event) => {
listeners[event.type]?.(event);
},
};
const windowStore = new LocalAuthStore("local_auth_window_test");
windowStore.save("tab-token", { id: "tab-1", collectionName: "users" });
if (!mockStorage["local_auth_window_test"]) {
throw new Error("LocalAuthStore did not persist data to localStorage");
}
mockStorage["local_auth_window_test"] = JSON.stringify({
token: "event-token",
record: { id: "tab-2", collectionName: "_superusers" },
});
window.dispatchEvent({ type: "storage", key: "local_auth_window_test" });
if (windowStore.token !== "event-token" || windowStore.record?.id !== "tab-2") {
throw new Error("LocalAuthStore did not react to storage event updates");
}
console.log(
"[SUCCESS] LocalAuthStore fallback behavior and cross-tab sync via storage events verified",
);
} finally {
if (typeof originalWindow === "undefined") {
delete global.window;
} else {
global.window = originalWindow;
}
}
}
function testClientResponseErrorNormalization() {
console.log("[INFO] Testing ClientResponseError normalization and fallbacks...");
const structured = new ClientResponseError({
status: 422,
url: "/demo",
response: { message: "Invalid payload", data: { field: "name" } },
});
if (
structured.status !== 422 ||
structured.url !== "/demo" ||
structured.message !== "Invalid payload" ||
structured.data !== structured.response ||
structured.data?.data?.field !== "name"
) {
throw new Error("ClientResponseError did not preserve structured response details");
}
const abortInput =
typeof DOMException !== "undefined"
? new DOMException("Aborted", "AbortError")
: { isAbort: true };
const aborted = new ClientResponseError(abortInput);
if (!aborted.isAbort || !String(aborted.message).includes("autocancelled")) {
throw new Error("ClientResponseError did not normalize aborted requests");
}
if (aborted.originalError !== abortInput && aborted.cause !== abortInput) {
throw new Error("ClientResponseError did not keep the original abort error");
}
const upstreamCause = new Error("service offline");
const wrapped = new ClientResponseError({
status: 503,
originalError: upstreamCause,
data: { foo: "bar" },
});
if (wrapped.cause !== upstreamCause || wrapped.message !== "Something went wrong.") {
throw new Error("ClientResponseError did not wrap arbitrary upstream errors correctly");
}
console.log("[SUCCESS] ClientResponseError message and cause handling verified");
}
async function main() {
try {
await testAsyncAuthStoreQueueAndInitial();
await testLocalAuthStoreFallbackAndStorageEvents();
testClientResponseErrorNormalization();
console.log("\n========== Auth store and error helper tests completed ==========");
} catch (error) {
console.error("[ERROR] Auth store / error helper test failed:");
console.error(error?.stack || error);
process.exit(1);
}
}
main();