@ethlete/query 6.0.0-next.51 → 6.0.0-next.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/fesm2022/ethlete-query-ngrx-toolkit.mjs +393 -0
- package/fesm2022/ethlete-query-ngrx-toolkit.mjs.map +1 -0
- package/fesm2022/ethlete-query-testing.mjs +67 -25
- package/fesm2022/ethlete-query-testing.mjs.map +1 -1
- package/fesm2022/ethlete-query.mjs +7895 -7226
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/generators/generators.json +5 -0
- package/generators/migrate-from-ngrx-toolkit/args-assignability.js +140 -0
- package/generators/migrate-from-ngrx-toolkit/consumers.js +521 -0
- package/generators/migrate-from-ngrx-toolkit/creators.js +301 -0
- package/generators/migrate-from-ngrx-toolkit/facade.js +295 -0
- package/generators/migrate-from-ngrx-toolkit/feature.js +513 -0
- package/generators/migrate-from-ngrx-toolkit/migration.js +140 -0
- package/generators/migrate-from-ngrx-toolkit/report.js +154 -0
- package/generators/migrate-from-ngrx-toolkit/schema.json +42 -0
- package/generators/migrate-from-ngrx-toolkit/store-removal.js +633 -0
- package/generators/migrate-from-ngrx-toolkit/ts-edits.js +128 -0
- package/generators/migrate-query-opt-in-features/migration.js +10 -9
- package/generators/migrate-to-query-v3/auth-provider-scaffold.js +29 -2
- package/generators/migrate-to-query-v3/cleanup-migration.js +163 -53
- package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +39 -2
- package/generators/migrate-to-query-v3/migration-scope.js +2 -0
- package/generators/migrate-to-query-v3/migration.js +5 -4
- package/generators/migrate-to-query-v3/module-graph.js +41 -29
- package/generators/migrate-to-query-v3/query-client-migration.js +209 -126
- package/generators/migrate-to-query-v3/rename-symbols.js +38 -11
- package/generators/migrate-to-query-v3/report.js +40 -7
- package/generators/migrate-to-query-v3/shared.js +46 -1
- package/generators/prep-for-query-v3/migration.js +400 -57
- package/migrations/query-field-default-types.md +43 -0
- package/migrations/search-query-field-string.md +43 -0
- package/migrations.json +16 -0
- package/package.json +5 -1
- package/types/ethlete-query-ngrx-toolkit.d.ts +143 -0
- package/types/ethlete-query-testing.d.ts +28 -11
- package/types/ethlete-query.d.ts +789 -584
|
@@ -73,7 +73,7 @@ const setupAuthTest = (config) => {
|
|
|
73
73
|
const refreshHelper = (token, response) => {
|
|
74
74
|
TestBed.runInInjectionContext(() => {
|
|
75
75
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
-
auth.queries.refresh.execute({ body: { token } });
|
|
76
|
+
auth.queries.refresh.execute((buildRefreshArgs?.(token) ?? { body: { token } }));
|
|
77
77
|
});
|
|
78
78
|
const fullUrl = `${querySetup.baseUrl}${refreshPath}`;
|
|
79
79
|
expectFlushAndWait(querySetup.httpTesting, fullUrl, response);
|
|
@@ -98,13 +98,18 @@ const setupAuthTest = (config) => {
|
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
101
|
+
// Captured at import, before a spec can call `vi.useFakeTimers()`: delivery must not wait on a faked clock.
|
|
102
|
+
const nodeSetImmediate = globalThis.setImmediate;
|
|
103
|
+
const scheduleTask = nodeSetImmediate
|
|
104
|
+
? nodeSetImmediate.bind(globalThis)
|
|
105
|
+
: setTimeout.bind(globalThis);
|
|
101
106
|
/**
|
|
102
107
|
* Replaces `globalThis.BroadcastChannel` with an in-memory bus.
|
|
103
108
|
*
|
|
104
109
|
* Messages are structured-cloned at post time (so a non-cloneable payload throws exactly like the
|
|
105
|
-
* real API does), delivered
|
|
106
|
-
* channel that posted them - all three matching browser behavior.
|
|
107
|
-
*
|
|
110
|
+
* real API does), delivered as a task (never synchronously, and after every pending microtask), and
|
|
111
|
+
* never delivered back to the channel that posted them - all three matching browser behavior. Delivery
|
|
112
|
+
* does not depend on fake timers; `await flushMultiTabSync()` in a spec flushes it.
|
|
108
113
|
*/
|
|
109
114
|
const installFakeBroadcastChannel = () => {
|
|
110
115
|
const original = globalThis.BroadcastChannel;
|
|
@@ -125,7 +130,7 @@ const installFakeBroadcastChannel = () => {
|
|
|
125
130
|
for (const instance of instances) {
|
|
126
131
|
if (instance === this || instance.closed || instance.name !== this.name)
|
|
127
132
|
continue;
|
|
128
|
-
|
|
133
|
+
scheduleTask(() => {
|
|
129
134
|
if (instance.closed)
|
|
130
135
|
return;
|
|
131
136
|
instance.onmessage?.({ data: structuredClone(clone) });
|
|
@@ -284,11 +289,11 @@ const installFakeWebLocks = () => {
|
|
|
284
289
|
};
|
|
285
290
|
};
|
|
286
291
|
/**
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* tab's release needs one await per hop.
|
|
292
|
+
* Waits for the fakes' pending work - message delivery (a task) and lock grants (a microtask) - even
|
|
293
|
+
* under fake timers. Awaiting it once is enough for a single hop; a grant that has to wait for another
|
|
294
|
+
* tab's release, or a reply to a delivered message, needs one await per hop.
|
|
290
295
|
*/
|
|
291
|
-
const flushMultiTabSync = () => Promise
|
|
296
|
+
const flushMultiTabSync = () => new Promise((resolve) => scheduleTask(resolve));
|
|
292
297
|
|
|
293
298
|
const quotaError = () => new DOMException('The quota has been exceeded.', 'QuotaExceededError');
|
|
294
299
|
const createFakeQueryPersistenceStore = () => {
|
|
@@ -323,11 +328,12 @@ const createFakeQueryPersistenceStore = () => {
|
|
|
323
328
|
};
|
|
324
329
|
const read = async (key) => {
|
|
325
330
|
calls.read++;
|
|
331
|
+
const entry = store.get(key);
|
|
332
|
+
const snapshot = entry ? { body: clone(entry.body), version: entry.version } : null;
|
|
326
333
|
if (isDeferringReads) {
|
|
327
334
|
await new Promise((resolve) => deferredReads.push(resolve));
|
|
328
335
|
}
|
|
329
|
-
|
|
330
|
-
return entry ? { body: clone(entry.body), version: entry.version } : null;
|
|
336
|
+
return snapshot;
|
|
331
337
|
};
|
|
332
338
|
const write = async (entries) => {
|
|
333
339
|
calls.write++;
|
|
@@ -496,7 +502,11 @@ const createWebSocketTestDouble = () => {
|
|
|
496
502
|
const sent = [];
|
|
497
503
|
const delivered = [];
|
|
498
504
|
const buffered = [];
|
|
499
|
-
const listeners =
|
|
505
|
+
const listeners = {
|
|
506
|
+
connect: [],
|
|
507
|
+
disconnect: [],
|
|
508
|
+
connect_error: [],
|
|
509
|
+
};
|
|
500
510
|
const anyListeners = [];
|
|
501
511
|
const outgoingListeners = [];
|
|
502
512
|
let connection = null;
|
|
@@ -506,6 +516,8 @@ const createWebSocketTestDouble = () => {
|
|
|
506
516
|
let connectRequested = false;
|
|
507
517
|
let disconnected = false;
|
|
508
518
|
let connected = false;
|
|
519
|
+
let active = false;
|
|
520
|
+
let connectCalls = 0;
|
|
509
521
|
let pingExpired = false;
|
|
510
522
|
let recovered = false;
|
|
511
523
|
const deliver = (message) => {
|
|
@@ -513,9 +525,30 @@ const createWebSocketTestDouble = () => {
|
|
|
513
525
|
listener(message.event, message.data);
|
|
514
526
|
delivered.push(message);
|
|
515
527
|
};
|
|
528
|
+
const recordHandshake = () => {
|
|
529
|
+
if (auth)
|
|
530
|
+
auth((data) => handshakes.push(data));
|
|
531
|
+
else
|
|
532
|
+
handshakes.push(null);
|
|
533
|
+
};
|
|
534
|
+
const disconnect = (reason) => {
|
|
535
|
+
connected = false;
|
|
536
|
+
pingExpired = false;
|
|
537
|
+
for (const listener of listeners.disconnect)
|
|
538
|
+
listener(reason);
|
|
539
|
+
};
|
|
516
540
|
const socket = {
|
|
517
|
-
connect: () =>
|
|
518
|
-
|
|
541
|
+
connect: () => {
|
|
542
|
+
connectRequested = true;
|
|
543
|
+
active = true;
|
|
544
|
+
connectCalls++;
|
|
545
|
+
},
|
|
546
|
+
disconnect: () => {
|
|
547
|
+
disconnected = true;
|
|
548
|
+
active = false;
|
|
549
|
+
if (connected)
|
|
550
|
+
disconnect('io client disconnect');
|
|
551
|
+
},
|
|
519
552
|
emit: (event, data) => {
|
|
520
553
|
sent.push({ event, data });
|
|
521
554
|
if (connected && !pingExpired)
|
|
@@ -523,12 +556,15 @@ const createWebSocketTestDouble = () => {
|
|
|
523
556
|
else
|
|
524
557
|
buffered.push({ event, data });
|
|
525
558
|
},
|
|
526
|
-
on: (event, listener) => void listeners.
|
|
559
|
+
on: (event, listener) => void listeners[event].push(listener),
|
|
527
560
|
onAny: (listener) => void anyListeners.push(listener),
|
|
528
561
|
onAnyOutgoing: (listener) => void outgoingListeners.push(listener),
|
|
529
562
|
get recovered() {
|
|
530
563
|
return recovered;
|
|
531
564
|
},
|
|
565
|
+
get active() {
|
|
566
|
+
return active;
|
|
567
|
+
},
|
|
532
568
|
};
|
|
533
569
|
return {
|
|
534
570
|
io: (url, options) => {
|
|
@@ -542,23 +578,29 @@ const createWebSocketTestDouble = () => {
|
|
|
542
578
|
handshakes: () => [...handshakes],
|
|
543
579
|
sent: () => [...sent],
|
|
544
580
|
delivered: () => [...delivered],
|
|
545
|
-
state: () => ({ connectRequested, disconnected }),
|
|
581
|
+
state: () => ({ connectRequested, disconnected, active, connectCalls }),
|
|
546
582
|
serverConnect: (options) => {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
else
|
|
550
|
-
handshakes.push(null);
|
|
583
|
+
recordHandshake();
|
|
584
|
+
active = true;
|
|
551
585
|
recovered = options?.recovered ?? false;
|
|
552
586
|
connected = true;
|
|
553
587
|
pingExpired = false;
|
|
554
588
|
for (const message of buffered.splice(0))
|
|
555
589
|
deliver(message);
|
|
556
|
-
listeners.
|
|
590
|
+
for (const listener of listeners.connect)
|
|
591
|
+
listener();
|
|
557
592
|
},
|
|
558
|
-
serverDisconnect: () => {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
593
|
+
serverDisconnect: (options) => {
|
|
594
|
+
const reason = options?.reason ?? 'transport close';
|
|
595
|
+
if (reason === 'io server disconnect')
|
|
596
|
+
active = false;
|
|
597
|
+
disconnect(reason);
|
|
598
|
+
},
|
|
599
|
+
serverRejectHandshake: (message) => {
|
|
600
|
+
recordHandshake();
|
|
601
|
+
active = false;
|
|
602
|
+
for (const listener of listeners.connect_error)
|
|
603
|
+
listener(new Error(message ?? 'unauthorized'));
|
|
562
604
|
},
|
|
563
605
|
serverPingExpire: () => void (pingExpired = true),
|
|
564
606
|
serverSend: (message) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ethlete-query-testing.mjs","sources":["../../../../libs/query/testing/query-test-utils.ts","../../../../libs/query/testing/auth-test-utils.ts","../../../../libs/query/testing/multi-tab-test-utils.ts","../../../../libs/query/testing/persistence-test-utils.ts","../../../../libs/query/testing/query-test-setup.ts","../../../../libs/query/testing/web-socket-test-utils.ts","../../../../libs/query/testing/ethlete-query-testing.ts"],"sourcesContent":["import { HttpTestingController } from '@angular/common/http/testing';\nimport { TestBed } from '@angular/core/testing';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport const expectAndFlush = <T = unknown>(\n httpTesting: HttpTestingController,\n url: string,\n response: T,\n statusOpts?: { status: number; statusText: string },\n): void => {\n const req = httpTesting.expectOne(url);\n if (statusOpts) {\n req.flush(response as any, statusOpts);\n } else {\n req.flush(response as any);\n }\n};\n\nexport const expectFlushAndWait = <T = unknown>(\n httpTesting: HttpTestingController,\n url: string,\n response: T,\n statusOpts?: { status: number; statusText: string },\n): void => {\n expectAndFlush(httpTesting, url, response, statusOpts);\n TestBed.tick();\n};\n","import { DestroyRef } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\nimport {\n AnyQueryBuilder,\n AuthQueryBuilder,\n BearerAuthProvider,\n BearerAuthProviderFeatureContext,\n createBearerAuthProvider,\n TokenRefreshQueryBuilder,\n TokenRefreshQueryConfig,\n withAuthenticationQuery,\n withRefreshQuery,\n} from '@ethlete/query';\nimport { QueryTestSetup } from './query-test-setup';\nimport { expectFlushAndWait } from './query-test-utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFeatureBuilder = (context: BearerAuthProviderFeatureContext<any, readonly AnyQueryBuilder[]>) => {\n type: string;\n instance: unknown;\n};\n\nexport type AuthTestSetupConfig<\n TLoginArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TRefreshArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TFeatures extends readonly AnyFeatureBuilder[] = [],\n TBearerData = unknown,\n> = {\n /** The query test setup instance */\n querySetup: QueryTestSetup;\n /** Login endpoint path. Default: '/auth/login' */\n loginPath?: string;\n /** Refresh endpoint path. Default: '/auth/refresh' */\n refreshPath?: string;\n /** Whether to enable auto-retry on 401. Default: false */\n autoRetryOn401?: boolean;\n /** Function to extract tokens from login response */\n extractLoginTokens?: (response: TLoginArgs['response']) => { accessToken: string; refreshToken: string };\n /** Function to extract tokens from refresh response */\n extractRefreshTokens?: (response: TRefreshArgs['response']) => { accessToken: string; refreshToken: string };\n /** Builds the refresh request from the refresh token. See TokenRefreshQueryConfig for details */\n buildRefreshArgs?: TokenRefreshQueryConfig<TRefreshArgs>['buildArgs'];\n /** Feature builders for additional auth functionality */\n features?: [...TFeatures];\n /** Custom bearer decrypt function for testing */\n bearerDecryptFn?: (token: string) => TBearerData;\n /** Refresh strategy configuration. See TokenRefreshQueryConfig for details */\n refreshStrategy?: TokenRefreshQueryConfig<TRefreshArgs>['refreshStrategy'];\n /** Minimum refresh interval in milliseconds */\n minRefreshInterval?: number;\n /** Whether to refresh if token is already expired */\n refreshIfExpired?: boolean;\n /** Property name for expiration in JWT */\n expiresInPropertyName?: string;\n /** What to do when the refresh query fails for good. Defaults to the provider's own policy */\n onRefreshFailure?: TokenRefreshQueryConfig<TRefreshArgs>['onRefreshFailure'];\n};\n\nexport type AuthTestSetup<\n TLoginArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TRefreshArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TFeatures extends readonly AnyFeatureBuilder[] = [],\n TBearerData = unknown,\n> = {\n /** The bearer auth provider instance */\n auth: BearerAuthProvider<\n [AuthQueryBuilder<'login', TLoginArgs>, TokenRefreshQueryBuilder<'refresh', TRefreshArgs>],\n TFeatures,\n TBearerData\n >;\n /** Helper to login a user and flush the HTTP request */\n login: (credentials: TLoginArgs['body'], response: TLoginArgs['response']) => void;\n /** Helper to trigger a refresh and flush the HTTP request */\n refresh: (token: string, response: TRefreshArgs['response']) => void;\n /** Helper to make a secure request that requires authentication */\n makeSecureRequest: (route: string) => void;\n};\n\nexport const setupAuthTest = <\n TLoginArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TRefreshArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TFeatures extends readonly AnyFeatureBuilder[] = readonly AnyFeatureBuilder[],\n TBearerData = unknown,\n>(\n config: AuthTestSetupConfig<TLoginArgs, TRefreshArgs, TFeatures, TBearerData>,\n): AuthTestSetup<TLoginArgs, TRefreshArgs, TFeatures, TBearerData> => {\n const {\n querySetup,\n loginPath = '/auth/login',\n refreshPath = '/auth/refresh',\n autoRetryOn401 = false,\n extractLoginTokens = (response) => ({\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n }),\n extractRefreshTokens = (response) => ({\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n }),\n buildRefreshArgs,\n features,\n bearerDecryptFn,\n refreshStrategy,\n minRefreshInterval,\n refreshIfExpired,\n expiresInPropertyName,\n onRefreshFailure,\n } = config;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const login = querySetup.createPost<TLoginArgs>(loginPath as any, {} as any) as any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const refresh = querySetup.createPost<TRefreshArgs>(refreshPath as any, {} as any) as any;\n\n const { inject: injectAuth } = createBearerAuthProvider({\n name: 'test-auth',\n queryClientRef: querySetup.queryClientRef,\n queries: [\n withAuthenticationQuery('login', {\n queryCreator: login,\n extractTokens: extractLoginTokens,\n }),\n withRefreshQuery('refresh', {\n queryCreator: refresh,\n extractTokens: extractRefreshTokens,\n buildArgs: buildRefreshArgs,\n autoRetryOn401,\n refreshStrategy,\n minRefreshInterval,\n refreshIfExpired,\n expiresInPropertyName,\n onRefreshFailure,\n }),\n ] as [AuthQueryBuilder<'login', TLoginArgs>, TokenRefreshQueryBuilder<'refresh', TRefreshArgs>],\n features: (features ?? ([] as const)) as unknown as TFeatures,\n bearerDecryptFn,\n });\n\n const auth = TestBed.runInInjectionContext(() => {\n const provider = injectAuth();\n if (!provider) {\n throw new Error('Failed to create auth provider in test setup');\n }\n return provider;\n });\n\n const loginHelper = (credentials: TLoginArgs['body'], response: TLoginArgs['response']) => {\n TestBed.runInInjectionContext(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth.queries.login.execute({ body: credentials } as any);\n });\n const fullUrl = `${querySetup.baseUrl}${loginPath}`;\n expectFlushAndWait(querySetup.httpTesting, fullUrl, response);\n };\n\n const refreshHelper = (token: string, response: TRefreshArgs['response']) => {\n TestBed.runInInjectionContext(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth.queries.refresh.execute({ body: { token } as any } as any);\n });\n const fullUrl = `${querySetup.baseUrl}${refreshPath}`;\n expectFlushAndWait(querySetup.httpTesting, fullUrl, response);\n };\n\n const makeSecureRequest = (route: string) => {\n TestBed.runInInjectionContext(() => {\n querySetup.queryClient.repository.request({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n route: route as any,\n method: 'GET',\n isSecure: true,\n consumerDestroyRef: TestBed.inject(DestroyRef),\n });\n });\n };\n\n return {\n auth,\n login: loginHelper,\n refresh: refreshHelper,\n makeSecureRequest,\n };\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Test doubles for the two browser APIs the query client's multi-tab sync is built on:\n * `BroadcastChannel` and the Web Locks API (`navigator.locks`).\n *\n * Both fakes are process-wide and shared between every consumer created while they are installed,\n * which is exactly what makes \"two tabs\" testable: create two query clients in one test and they\n * talk to each other over the fake bus and contend for the same fake locks, going through the real\n * production code path on both sides.\n *\n * Neither jsdom nor happy-dom can stand in here - jsdom ships a `BroadcastChannel` that never\n * delivers to other instances, and no `navigator.locks` at all.\n */\n\n/** Something posted on the fake bus, as seen by a receiver. */\nexport type FakeBroadcastMessage = {\n /** The channel name it was posted on. */\n channel: string;\n\n /** The structured-cloned payload. */\n data: unknown;\n};\n\nexport type FakeBroadcastChannelHandle = {\n /** Every message posted on the bus, in order, across all channel names. */\n posted: FakeBroadcastMessage[];\n\n /** Uninstalls the fake and restores whatever `BroadcastChannel` was there before. */\n restore: () => void;\n};\n\ntype FakeChannelInstance = {\n name: string;\n closed: boolean;\n onmessage: ((event: MessageEvent<unknown>) => void) | null;\n};\n\n/**\n * Replaces `globalThis.BroadcastChannel` with an in-memory bus.\n *\n * Messages are structured-cloned at post time (so a non-cloneable payload throws exactly like the\n * real API does), delivered on a microtask (never synchronously), and never delivered back to the\n * channel that posted them - all three matching browser behavior. `await Promise.resolve()` in a\n * spec is enough to flush delivery.\n */\nexport const installFakeBroadcastChannel = (): FakeBroadcastChannelHandle => {\n const original = (globalThis as any).BroadcastChannel;\n const instances = new Set<FakeChannelInstance>();\n const posted: FakeBroadcastMessage[] = [];\n\n class FakeBroadcastChannel implements FakeChannelInstance {\n closed = false;\n onmessage: ((event: MessageEvent<unknown>) => void) | null = null;\n\n constructor(public name: string) {\n instances.add(this);\n }\n\n postMessage(data: unknown) {\n if (this.closed) throw new DOMException('Channel is closed', 'InvalidStateError');\n\n const clone = structuredClone(data);\n\n posted.push({ channel: this.name, data: clone });\n\n for (const instance of instances) {\n if (instance === this || instance.closed || instance.name !== this.name) continue;\n\n queueMicrotask(() => {\n if (instance.closed) return;\n\n instance.onmessage?.({ data: structuredClone(clone) } as MessageEvent<unknown>);\n });\n }\n }\n\n close() {\n this.closed = true;\n instances.delete(this);\n }\n\n addEventListener() {\n throw new Error('The fake BroadcastChannel only supports `onmessage`.');\n }\n }\n\n (globalThis as any).BroadcastChannel = FakeBroadcastChannel;\n\n return {\n posted,\n restore: () => {\n for (const instance of [...instances]) {\n instance.closed = true;\n }\n\n instances.clear();\n (globalThis as any).BroadcastChannel = original;\n },\n };\n};\n\nexport type FakeWebLocksHandle = {\n /** The names currently held, in no particular order. */\n heldNames: () => string[];\n\n /** The names with at least one request queued behind the holder. */\n pendingNames: () => string[];\n\n /** Uninstalls the fake and restores whatever `navigator.locks` was there before. */\n restore: () => void;\n};\n\ntype FakeLockWaiter = {\n callback: (lock: Lock | null) => unknown;\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n granted: boolean;\n releaseSignal: () => void;\n};\n\n/**\n * Installs an in-memory `navigator.locks` implementing exclusive locks: one holder per name, the\n * rest queued FIFO, granted on a microtask (never synchronously), released when the callback's\n * promise settles. `signal` is honored for queued requests and - as in the real API - ignored once a\n * request has been granted.\n *\n * `ifAvailable` is a try-lock: a request that cannot be granted straight away runs its callback with\n * `null` instead of queueing, exactly as the real API does. `steal` releases the current holder -\n * rejecting its request with an `AbortError` - and is granted ahead of everything queued.\n *\n * `mode: 'shared'` is not implemented; nothing in the library uses it.\n */\nexport const installFakeWebLocks = (): FakeWebLocksHandle => {\n const originalDescriptor = Object.getOwnPropertyDescriptor(navigator, 'locks');\n const holders = new Map<string, FakeLockWaiter>();\n const queues = new Map<string, FakeLockWaiter[]>();\n\n const abortError = () => new DOMException('The lock request was aborted', 'AbortError');\n\n const pump = (name: string) => {\n if (holders.has(name)) return;\n\n const waiter = queues.get(name)?.shift();\n\n if (!waiter) return;\n\n waiter.granted = true;\n holders.set(name, waiter);\n\n const settle = (settleWaiter: () => void) => {\n // Only if this waiter is still the holder: a stolen lock already has a new one, and the callback\n // of the tab it was taken from settles afterwards.\n if (holders.get(name) === waiter) holders.delete(name);\n\n waiter.releaseSignal();\n settleWaiter();\n pump(name);\n };\n\n // `pump` itself only ever runs from a microtask, so calling the callback right here keeps the\n // grant exactly one microtask away from the `request()` call - which is what makes a single\n // `flushMultiTabSync()` per hop enough in specs.\n try {\n Promise.resolve(waiter.callback({ name, mode: 'exclusive' } as Lock)).then(\n (value) => settle(() => waiter.resolve(value)),\n (error) => settle(() => waiter.reject(error)),\n );\n } catch (error) {\n settle(() => waiter.reject(error));\n }\n };\n\n const request = (name: string, optionsOrCallback: unknown, maybeCallback?: unknown) => {\n const options = (typeof optionsOrCallback === 'function' ? {} : (optionsOrCallback ?? {})) as LockOptions;\n const callback = (typeof optionsOrCallback === 'function' ? optionsOrCallback : maybeCallback) as (\n lock: Lock | null,\n ) => unknown;\n\n return new Promise((resolve, reject) => {\n if (options.signal?.aborted) {\n reject(abortError());\n\n return;\n }\n\n const waiter: FakeLockWaiter = { callback, resolve, reject, granted: false, releaseSignal: () => undefined };\n const signal = options.signal;\n\n if (signal) {\n const onAbort = () => {\n waiter.releaseSignal();\n\n if (waiter.granted) return;\n\n const queue = queues.get(name);\n\n if (queue)\n queues.set(\n name,\n queue.filter((entry) => entry !== waiter),\n );\n\n reject(abortError());\n };\n\n signal.addEventListener('abort', onAbort);\n waiter.releaseSignal = () => {\n waiter.releaseSignal = () => undefined;\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n if (options.steal) {\n queueMicrotask(() => {\n const holder = holders.get(name);\n\n if (holder) {\n holders.delete(name);\n holder.reject(abortError());\n }\n\n queues.set(name, [waiter, ...(queues.get(name) ?? [])]);\n pump(name);\n });\n\n return;\n }\n\n // Availability is decided a microtask out, not here: that is when the real API decides it too, so\n // two try-locks requested in the same tick still resolve to one winner and one `null`.\n if (options.ifAvailable) {\n queueMicrotask(() => {\n if (holders.has(name) || (queues.get(name)?.length ?? 0) > 0) {\n waiter.releaseSignal();\n Promise.resolve(callback(null)).then(resolve, reject);\n\n return;\n }\n\n queues.set(name, [waiter]);\n pump(name);\n });\n\n return;\n }\n\n queues.set(name, [...(queues.get(name) ?? []), waiter]);\n queueMicrotask(() => pump(name));\n });\n };\n\n // Both lists are reported, because a queued request is how a tab that is *not* the holder still\n // shows up - which is what the auth leader election counts its tabs by.\n const query = () =>\n Promise.resolve({\n held: [...holders.keys()].map((name) => ({ name, mode: 'exclusive' as const })),\n pending: [...queues.entries()].flatMap(([name, waiters]) =>\n waiters.map(() => ({ name, mode: 'exclusive' as const })),\n ),\n });\n\n Object.defineProperty(navigator, 'locks', {\n value: {\n request,\n query,\n },\n configurable: true,\n writable: true,\n });\n\n return {\n heldNames: () => [...holders.keys()],\n pendingNames: () => [...queues.entries()].filter(([, queue]) => queue.length > 0).map(([name]) => name),\n restore: () => {\n for (const waiter of [...holders.values(), ...[...queues.values()].flat()]) waiter.releaseSignal();\n\n holders.clear();\n queues.clear();\n\n if (originalDescriptor) {\n Object.defineProperty(navigator, 'locks', originalDescriptor);\n } else {\n delete (navigator as any).locks;\n }\n },\n };\n};\n\n/**\n * Flushes the microtask queue, which is where both fakes schedule their work - message delivery and\n * lock grants. Awaiting it once is enough for a single hop; a grant that has to wait for another\n * tab's release needs one await per hop.\n */\nexport const flushMultiTabSync = () => Promise.resolve();\n","import type { PersistedQueryEntry, PersistedQueryEntryMeta, QueryPersistenceAdapter } from '@ethlete/query';\n\n/**\n * An in-memory stand-in for the query client's persisted response store.\n *\n * jsdom has no IndexedDB at all, so this is how persistence is tested - and because the storage\n * adapter is a documented seam rather than a mock of one, a spec running against this exercises the\n * real engine, repository and request code on both the write and the read side.\n *\n * Everything resolves on a microtask, never synchronously, matching the real thing: `await\n * Promise.resolve()` (or `flushMicrotasks`) is what lets a hydration land in a spec.\n */\nexport type FakeQueryPersistenceStoreHandle = {\n /** Pass this as `persistence: { adapter }`. Two clients sharing one handle share one store. */\n adapter: QueryPersistenceAdapter;\n\n /** Pre-populates the store, as if a previous session had written these entries. */\n seed: (entries: PersistedQueryEntry[]) => void;\n\n /** Every entry currently held, in insertion order. */\n entries: () => PersistedQueryEntry[];\n\n /** The entry held under `key`, or `undefined`. */\n entry: (key: string) => PersistedQueryEntry | undefined;\n\n /** How often each adapter method has been called. */\n calls: () => Record<'loadIndex' | 'read' | 'write' | 'remove' | 'clear', number>;\n\n /** Makes the next `count` writes reject - a full disk, by default. */\n failNextWrites: (count: number, error?: unknown) => void;\n\n /** Makes the next `count` removals reject. */\n failNextRemoves: (count: number, error?: unknown) => void;\n\n /** Makes the next `loadIndex` reject. */\n failNextLoadIndex: (error?: unknown) => void;\n\n /**\n * Holds every subsequent `read` pending until {@link flushReads} is called, for testing the window\n * between a cold mount and its hydration (a slow disk, or a mount that happened before startup\n * finished).\n */\n deferReads: () => void;\n\n /** Settles the reads held by {@link deferReads} and stops deferring. */\n flushReads: () => Promise<void>;\n\n /**\n * Holds every subsequent `loadIndex` pending until {@link flushLoadIndex} is called, for testing\n * what happens to the store while a client's startup is still reading its index (a real disk takes\n * milliseconds). The snapshot each held load returns is the one it would have read when it started.\n */\n deferLoadIndex: () => void;\n\n /** Settles the index loads held by {@link deferLoadIndex} and stops deferring. */\n flushLoadIndex: () => Promise<void>;\n};\n\nconst quotaError = () => new DOMException('The quota has been exceeded.', 'QuotaExceededError');\n\nexport const createFakeQueryPersistenceStore = (): FakeQueryPersistenceStoreHandle => {\n const store = new Map<string, PersistedQueryEntry>();\n const calls = { loadIndex: 0, read: 0, write: 0, remove: 0, clear: 0 };\n const deferredReads: Array<() => void> = [];\n const deferredLoadIndexes: Array<() => void> = [];\n\n let failingWrites = 0;\n let writeError: unknown = null;\n let failingRemoves = 0;\n let removeError: unknown = null;\n let loadIndexError: unknown = null;\n let isDeferringReads = false;\n let isDeferringLoadIndex = false;\n\n // Cloning on the way in and on the way out is not pedantry: a real store hands back a copy, so a\n // spec (or the engine) mutating a hydrated body must not be able to change what is \"on disk\".\n const clone = <T>(value: T): T => structuredClone(value);\n\n const loadIndex = async () => {\n calls.loadIndex++;\n\n if (loadIndexError !== null) {\n const error = loadIndexError;\n loadIndexError = null;\n\n throw error;\n }\n\n // Taken before the gate, not after: a real store answers with what it held when the read started,\n // so anything that empties it while a deferred load is held must not change what that load returns.\n const snapshot = Array.from(store.values()).map(\n ({ body: _body, ...meta }) => clone(meta) satisfies PersistedQueryEntryMeta,\n );\n\n if (isDeferringLoadIndex) {\n await new Promise<void>((resolve) => deferredLoadIndexes.push(resolve));\n }\n\n return snapshot;\n };\n\n const read = async (key: string) => {\n calls.read++;\n\n if (isDeferringReads) {\n await new Promise<void>((resolve) => deferredReads.push(resolve));\n }\n\n const entry = store.get(key);\n\n return entry ? { body: clone(entry.body), version: entry.version } : null;\n };\n\n const write = async (entries: PersistedQueryEntry[]) => {\n calls.write++;\n\n if (failingWrites > 0) {\n failingWrites--;\n\n throw writeError ?? quotaError();\n }\n\n for (const entry of entries) {\n store.set(entry.key, clone(entry));\n }\n };\n\n const remove = async (keys: string[]) => {\n calls.remove++;\n\n if (failingRemoves > 0) {\n failingRemoves--;\n\n throw removeError ?? new Error('The removal failed.');\n }\n\n for (const key of keys) {\n store.delete(key);\n }\n };\n\n const clear = async () => {\n calls.clear++;\n store.clear();\n };\n\n return {\n adapter: { loadIndex, read, write, remove, clear, isSupported: true },\n seed: (entries) => {\n for (const entry of entries) {\n store.set(entry.key, clone(entry));\n }\n },\n entries: () => Array.from(store.values()).map(clone),\n entry: (key) => {\n const entry = store.get(key);\n\n return entry ? clone(entry) : undefined;\n },\n calls: () => ({ ...calls }),\n failNextWrites: (count, error) => {\n failingWrites = count;\n writeError = error ?? null;\n },\n failNextRemoves: (count, error) => {\n failingRemoves = count;\n removeError = error ?? null;\n },\n failNextLoadIndex: (error) => {\n loadIndexError = error ?? quotaError();\n },\n deferReads: () => {\n isDeferringReads = true;\n },\n flushReads: async () => {\n isDeferringReads = false;\n\n const pending = deferredReads.splice(0, deferredReads.length);\n\n for (const resolve of pending) {\n resolve();\n }\n\n await Promise.resolve();\n },\n deferLoadIndex: () => {\n isDeferringLoadIndex = true;\n },\n flushLoadIndex: async () => {\n isDeferringLoadIndex = false;\n\n const pending = deferredLoadIndexes.splice(0, deferredLoadIndexes.length);\n\n for (const resolve of pending) {\n resolve();\n }\n\n await Promise.resolve();\n },\n };\n};\n","import { HttpClient, provideHttpClient } from '@angular/common/http';\nimport { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';\nimport { EnvironmentProviders, ErrorHandler, Injector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\nimport { provideRouter } from '@angular/router';\nimport {\n AnyCreateQueryClientResult,\n createDeleteQuery,\n createGetQuery,\n createPatchQuery,\n createPostQuery,\n createPutQuery,\n createQueryClient,\n QueryClientRef,\n} from '@ethlete/query';\n\nexport type QueryTestSetup = {\n queryClient: NonNullable<ReturnType<AnyCreateQueryClientResult['inject']>>;\n queryClientRef: QueryClientRef;\n httpClient: HttpClient;\n httpTesting: HttpTestingController;\n injector: Injector;\n baseUrl: string;\n createGet: ReturnType<typeof createGetQuery>;\n createPost: ReturnType<typeof createPostQuery>;\n createPut: ReturnType<typeof createPutQuery>;\n createPatch: ReturnType<typeof createPatchQuery>;\n createDelete: ReturnType<typeof createDeleteQuery>;\n\n /**\n * Puts back the `console.warn` / `console.error` that were installed before the first\n * {@link setupQueryTest} call. Idempotent, and safe to call from any of the setups a file created.\n */\n restoreConsole: () => void;\n};\n\nexport type QueryTestSetupConfig = {\n baseUrl?: string;\n name?: string;\n mockErrorHandler?: boolean;\n};\n\nlet originalWarn: typeof console.warn | null = null;\nlet originalError: typeof console.error | null = null;\n\nconst filteredWarn = (...args: unknown[]) => {\n const message = args[0];\n\n if (typeof message === 'string' && message.includes('auto-refresh')) {\n return;\n }\n\n originalWarn?.(...args);\n};\n\nconst filteredError = (...args: unknown[]) => {\n const message = args[0];\n\n if (message && typeof message === 'object' && 'name' in message && message.name === 'HttpErrorResponse') {\n return;\n }\n\n if (typeof message === 'string' && message.includes('Failed to decrypt bearer token')) {\n return;\n }\n\n if (typeof message === 'string' && message.includes('Failed to extract tokens from')) {\n return;\n }\n\n originalError?.(...args);\n};\n\n// Capture only what is not already the wrapper, so repeated calls reinstall the one filter instead\n// of nesting a new closure over the previous one and stranding the pristine handlers.\nconst installConsoleFilters = () => {\n if (console.warn !== filteredWarn) originalWarn = console.warn;\n if (console.error !== filteredError) originalError = console.error;\n\n console.warn = filteredWarn;\n console.error = filteredError;\n};\n\nconst restoreConsole = () => {\n if (originalWarn && console.warn === filteredWarn) console.warn = originalWarn;\n if (originalError && console.error === filteredError) console.error = originalError;\n\n originalWarn = null;\n originalError = null;\n};\n\nexport const setupQueryTest = (config?: QueryTestSetupConfig): QueryTestSetup => {\n const baseUrl = config?.baseUrl ?? 'https://api.test.com';\n const name = config?.name ?? 'test';\n const mockErrorHandler = config?.mockErrorHandler !== false;\n\n installConsoleFilters();\n\n const providers: (EnvironmentProviders | object)[] = [\n provideHttpClient(),\n provideHttpClientTesting(),\n provideRouter([]),\n ];\n\n if (mockErrorHandler) {\n providers.push({\n provide: ErrorHandler,\n useValue: { handleError: () => undefined },\n });\n }\n\n TestBed.configureTestingModule({ providers });\n\n const queryClientRef = createQueryClient({ baseUrl, name });\n\n return TestBed.runInInjectionContext(() => {\n const { inject } = queryClientRef;\n const queryClient = inject();\n\n if (!queryClient) {\n throw new Error('Failed to create query client in test setup');\n }\n\n return {\n queryClient,\n queryClientRef,\n httpClient: TestBed.inject(HttpClient),\n httpTesting: TestBed.inject(HttpTestingController),\n injector: TestBed.inject(Injector),\n baseUrl,\n createGet: createGetQuery(queryClientRef),\n createPost: createPostQuery(queryClientRef),\n createPut: createPutQuery(queryClientRef),\n createPatch: createPatchQuery(queryClientRef),\n createDelete: createDeleteQuery(queryClientRef),\n restoreConsole,\n };\n });\n};\n","import type {\n SocketMessageView,\n WebSocketClientIo,\n WebSocketClientIoOptions,\n WebSocketClientSocket,\n} from '@ethlete/query';\n\n/** A scripted stand-in for `socket.io-client`'s `io`, driven from a spec. */\nexport type WebSocketTestDouble = {\n /** Pass this as `createWebSocketClient({ io })`. */\n io: WebSocketClientIo;\n\n /** The url and options the client called the factory with, or `null` until it did. */\n connection: () => { url: string; transports: string[] | undefined } | null;\n\n /** The `withCredentials` the client asked the factory for, or `null` until it called it. */\n withCredentials: () => boolean | null;\n\n /** The auth payload of every handshake, oldest first - `null` for one made without `auth`. */\n handshakes: () => (object | null)[];\n\n /** Every message the client emitted, newest last - room joins and leaves included, buffered ones too. */\n sent: () => { event: string; data: unknown }[];\n\n /** Every message that reached the server, newest last. An emit buffered while offline lands here on the next connect. */\n delivered: () => { event: string; data: unknown }[];\n\n /** Whether the client asked the socket to connect, and whether it has since disconnected it. */\n state: () => { connectRequested: boolean; disconnected: boolean };\n\n /**\n * Complete the handshake: flush every buffered emit, then turn the client's `isConnected` true. Pass\n * `recovered: true` for a connection-state-recovered reconnect, in which the server kept the rooms.\n */\n serverConnect: (options?: { recovered?: boolean }) => void;\n\n /** Drop the connection, so `isConnected` turns false. */\n serverDisconnect: () => void;\n\n /**\n * Let the ping expire: the socket still reports itself connected, but buffers every emit like socket.io\n * does until it notices and closes. Follow it with {@link serverDisconnect}.\n */\n serverPingExpire: () => void;\n\n /** Deliver a message the way the server would. */\n serverSend: (message: SocketMessageView) => void;\n\n /** Deliver a raw frame, for the malformed-payload path. */\n serverSendRaw: (frame: string) => void;\n};\n\n/**\n * A socket io test double, for specs around `createWebSocketClient` - which takes its `io` factory as\n * an option precisely so a spec (or an app that never opens a socket) needs no `socket.io-client`.\n *\n * Nothing here connects on its own: the client's own `connect()` only flips\n * {@link WebSocketTestDouble.state}, and it is {@link WebSocketTestDouble.serverConnect} that fires\n * the `connect` listener. That split is what makes \"joined a room while disconnected, and it was\n * re-joined after a reconnect\" testable.\n */\nexport const createWebSocketTestDouble = (): WebSocketTestDouble => {\n const sent: { event: string; data: unknown }[] = [];\n const delivered: { event: string; data: unknown }[] = [];\n const buffered: { event: string; data: unknown }[] = [];\n const listeners = new Map<'connect' | 'disconnect', () => void>();\n const anyListeners: ((eventName: string, ...args: unknown[]) => void)[] = [];\n const outgoingListeners: ((eventName: string, ...args: unknown[]) => void)[] = [];\n\n let connection: { url: string; transports: string[] | undefined } | null = null;\n let withCredentials: boolean | null = null;\n let auth: WebSocketClientIoOptions['auth'];\n const handshakes: (object | null)[] = [];\n let connectRequested = false;\n let disconnected = false;\n let connected = false;\n let pingExpired = false;\n let recovered = false;\n\n const deliver = (message: { event: string; data: unknown }) => {\n for (const listener of outgoingListeners) listener(message.event, message.data);\n delivered.push(message);\n };\n\n const socket: WebSocketClientSocket = {\n connect: () => void (connectRequested = true),\n disconnect: () => void (disconnected = true),\n emit: (event, data) => {\n sent.push({ event, data });\n\n if (connected && !pingExpired) deliver({ event, data });\n else buffered.push({ event, data });\n },\n on: (event, listener) => void listeners.set(event, listener),\n onAny: (listener) => void anyListeners.push(listener),\n onAnyOutgoing: (listener) => void outgoingListeners.push(listener),\n get recovered() {\n return recovered;\n },\n };\n\n return {\n io: (url, options) => {\n connection = { url, transports: options.transports };\n withCredentials = options.withCredentials;\n auth = options.auth;\n return socket;\n },\n connection: () => connection,\n withCredentials: () => withCredentials,\n handshakes: () => [...handshakes],\n sent: () => [...sent],\n delivered: () => [...delivered],\n state: () => ({ connectRequested, disconnected }),\n serverConnect: (options) => {\n if (auth) auth((data) => handshakes.push(data));\n else handshakes.push(null);\n\n recovered = options?.recovered ?? false;\n connected = true;\n pingExpired = false;\n\n for (const message of buffered.splice(0)) deliver(message);\n\n listeners.get('connect')?.();\n },\n serverDisconnect: () => {\n connected = false;\n pingExpired = false;\n listeners.get('disconnect')?.();\n },\n serverPingExpire: () => void (pingExpired = true),\n serverSend: (message) => {\n const frame = JSON.stringify(message);\n for (const listener of anyListeners) listener('message', frame);\n },\n serverSendRaw: (frame) => {\n for (const listener of anyListeners) listener('message', frame);\n },\n };\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ethlete-query-testing.mjs","sources":["../../../../libs/query/testing/query-test-utils.ts","../../../../libs/query/testing/auth-test-utils.ts","../../../../libs/query/testing/multi-tab-test-utils.ts","../../../../libs/query/testing/persistence-test-utils.ts","../../../../libs/query/testing/query-test-setup.ts","../../../../libs/query/testing/web-socket-test-utils.ts","../../../../libs/query/testing/ethlete-query-testing.ts"],"sourcesContent":["import { HttpTestingController } from '@angular/common/http/testing';\nimport { TestBed } from '@angular/core/testing';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport const expectAndFlush = <T = unknown>(\n httpTesting: HttpTestingController,\n url: string,\n response: T,\n statusOpts?: { status: number; statusText: string },\n): void => {\n const req = httpTesting.expectOne(url);\n if (statusOpts) {\n req.flush(response as any, statusOpts);\n } else {\n req.flush(response as any);\n }\n};\n\nexport const expectFlushAndWait = <T = unknown>(\n httpTesting: HttpTestingController,\n url: string,\n response: T,\n statusOpts?: { status: number; statusText: string },\n): void => {\n expectAndFlush(httpTesting, url, response, statusOpts);\n TestBed.tick();\n};\n","import { DestroyRef } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\nimport {\n AnyQueryBuilder,\n AuthQueryBuilder,\n BearerAuthProvider,\n BearerAuthProviderFeatureContext,\n createBearerAuthProvider,\n TokenRefreshQueryBuilder,\n TokenRefreshQueryConfig,\n withAuthenticationQuery,\n withRefreshQuery,\n} from '@ethlete/query';\nimport { QueryTestSetup } from './query-test-setup';\nimport { expectFlushAndWait } from './query-test-utils';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFeatureBuilder = (context: BearerAuthProviderFeatureContext<any, readonly AnyQueryBuilder[]>) => {\n type: string;\n instance: unknown;\n};\n\nexport type AuthTestSetupConfig<\n TLoginArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TRefreshArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TFeatures extends readonly AnyFeatureBuilder[] = [],\n TBearerData = unknown,\n> = {\n /** The query test setup instance */\n querySetup: QueryTestSetup;\n /** Login endpoint path. Default: '/auth/login' */\n loginPath?: string;\n /** Refresh endpoint path. Default: '/auth/refresh' */\n refreshPath?: string;\n /** Whether to enable auto-retry on 401. Default: false */\n autoRetryOn401?: boolean;\n /** Function to extract tokens from login response */\n extractLoginTokens?: (response: TLoginArgs['response']) => { accessToken: string; refreshToken: string };\n /** Function to extract tokens from refresh response */\n extractRefreshTokens?: (response: TRefreshArgs['response']) => { accessToken: string; refreshToken: string };\n /** Builds the refresh request from the refresh token. See TokenRefreshQueryConfig for details */\n buildRefreshArgs?: TokenRefreshQueryConfig<TRefreshArgs>['buildArgs'];\n /** Feature builders for additional auth functionality */\n features?: [...TFeatures];\n /** Custom bearer decrypt function for testing */\n bearerDecryptFn?: (token: string) => TBearerData;\n /** Refresh strategy configuration. See TokenRefreshQueryConfig for details */\n refreshStrategy?: TokenRefreshQueryConfig<TRefreshArgs>['refreshStrategy'];\n /** Minimum refresh interval in milliseconds */\n minRefreshInterval?: number;\n /** Whether to refresh if token is already expired */\n refreshIfExpired?: boolean;\n /** Property name for expiration in JWT */\n expiresInPropertyName?: string;\n /** What to do when the refresh query fails for good. Defaults to the provider's own policy */\n onRefreshFailure?: TokenRefreshQueryConfig<TRefreshArgs>['onRefreshFailure'];\n};\n\nexport type AuthTestSetup<\n TLoginArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TRefreshArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TFeatures extends readonly AnyFeatureBuilder[] = [],\n TBearerData = unknown,\n> = {\n /** The bearer auth provider instance */\n auth: BearerAuthProvider<\n [AuthQueryBuilder<'login', TLoginArgs>, TokenRefreshQueryBuilder<'refresh', TRefreshArgs>],\n TFeatures,\n TBearerData\n >;\n /** Helper to login a user and flush the HTTP request */\n login: (credentials: TLoginArgs['body'], response: TLoginArgs['response']) => void;\n /** Helper to trigger a refresh and flush the HTTP request. Sends `buildRefreshArgs(token)` when configured, else `{ body: { token } }` */\n refresh: (token: string, response: TRefreshArgs['response']) => void;\n /** Helper to make a secure request that requires authentication */\n makeSecureRequest: (route: string) => void;\n};\n\nexport const setupAuthTest = <\n TLoginArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TRefreshArgs extends { body: Record<string, unknown>; response: { accessToken: string; refreshToken: string } } = {\n body: Record<string, unknown>;\n response: { accessToken: string; refreshToken: string };\n },\n TFeatures extends readonly AnyFeatureBuilder[] = readonly AnyFeatureBuilder[],\n TBearerData = unknown,\n>(\n config: AuthTestSetupConfig<TLoginArgs, TRefreshArgs, TFeatures, TBearerData>,\n): AuthTestSetup<TLoginArgs, TRefreshArgs, TFeatures, TBearerData> => {\n const {\n querySetup,\n loginPath = '/auth/login',\n refreshPath = '/auth/refresh',\n autoRetryOn401 = false,\n extractLoginTokens = (response) => ({\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n }),\n extractRefreshTokens = (response) => ({\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n }),\n buildRefreshArgs,\n features,\n bearerDecryptFn,\n refreshStrategy,\n minRefreshInterval,\n refreshIfExpired,\n expiresInPropertyName,\n onRefreshFailure,\n } = config;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const login = querySetup.createPost<TLoginArgs>(loginPath as any, {} as any) as any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const refresh = querySetup.createPost<TRefreshArgs>(refreshPath as any, {} as any) as any;\n\n const { inject: injectAuth } = createBearerAuthProvider({\n name: 'test-auth',\n queryClientRef: querySetup.queryClientRef,\n queries: [\n withAuthenticationQuery('login', {\n queryCreator: login,\n extractTokens: extractLoginTokens,\n }),\n withRefreshQuery('refresh', {\n queryCreator: refresh,\n extractTokens: extractRefreshTokens,\n buildArgs: buildRefreshArgs,\n autoRetryOn401,\n refreshStrategy,\n minRefreshInterval,\n refreshIfExpired,\n expiresInPropertyName,\n onRefreshFailure,\n }),\n ] as [AuthQueryBuilder<'login', TLoginArgs>, TokenRefreshQueryBuilder<'refresh', TRefreshArgs>],\n features: (features ?? ([] as const)) as unknown as TFeatures,\n bearerDecryptFn,\n });\n\n const auth = TestBed.runInInjectionContext(() => {\n const provider = injectAuth();\n if (!provider) {\n throw new Error('Failed to create auth provider in test setup');\n }\n return provider;\n });\n\n const loginHelper = (credentials: TLoginArgs['body'], response: TLoginArgs['response']) => {\n TestBed.runInInjectionContext(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth.queries.login.execute({ body: credentials } as any);\n });\n const fullUrl = `${querySetup.baseUrl}${loginPath}`;\n expectFlushAndWait(querySetup.httpTesting, fullUrl, response);\n };\n\n const refreshHelper = (token: string, response: TRefreshArgs['response']) => {\n TestBed.runInInjectionContext(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth.queries.refresh.execute((buildRefreshArgs?.(token) ?? { body: { token } }) as any);\n });\n const fullUrl = `${querySetup.baseUrl}${refreshPath}`;\n expectFlushAndWait(querySetup.httpTesting, fullUrl, response);\n };\n\n const makeSecureRequest = (route: string) => {\n TestBed.runInInjectionContext(() => {\n querySetup.queryClient.repository.request({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n route: route as any,\n method: 'GET',\n isSecure: true,\n consumerDestroyRef: TestBed.inject(DestroyRef),\n });\n });\n };\n\n return {\n auth,\n login: loginHelper,\n refresh: refreshHelper,\n makeSecureRequest,\n };\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Test doubles for the two browser APIs the query client's multi-tab sync is built on:\n * `BroadcastChannel` and the Web Locks API (`navigator.locks`).\n *\n * Both fakes are process-wide and shared between every consumer created while they are installed,\n * which is exactly what makes \"two tabs\" testable: create two query clients in one test and they\n * talk to each other over the fake bus and contend for the same fake locks, going through the real\n * production code path on both sides.\n *\n * Neither jsdom nor happy-dom can stand in here - jsdom ships a `BroadcastChannel` that never\n * delivers to other instances, and no `navigator.locks` at all.\n */\n\n/** Something posted on the fake bus, as seen by a receiver. */\nexport type FakeBroadcastMessage = {\n /** The channel name it was posted on. */\n channel: string;\n\n /** The structured-cloned payload. */\n data: unknown;\n};\n\nexport type FakeBroadcastChannelHandle = {\n /** Every message posted on the bus, in order, across all channel names. */\n posted: FakeBroadcastMessage[];\n\n /** Uninstalls the fake and restores whatever `BroadcastChannel` was there before. */\n restore: () => void;\n};\n\n// Captured at import, before a spec can call `vi.useFakeTimers()`: delivery must not wait on a faked clock.\nconst nodeSetImmediate = (globalThis as { setImmediate?: (callback: () => void) => unknown }).setImmediate;\nconst scheduleTask: (callback: () => void) => void = nodeSetImmediate\n ? nodeSetImmediate.bind(globalThis)\n : setTimeout.bind(globalThis);\n\ntype FakeChannelInstance = {\n name: string;\n closed: boolean;\n onmessage: ((event: MessageEvent<unknown>) => void) | null;\n};\n\n/**\n * Replaces `globalThis.BroadcastChannel` with an in-memory bus.\n *\n * Messages are structured-cloned at post time (so a non-cloneable payload throws exactly like the\n * real API does), delivered as a task (never synchronously, and after every pending microtask), and\n * never delivered back to the channel that posted them - all three matching browser behavior. Delivery\n * does not depend on fake timers; `await flushMultiTabSync()` in a spec flushes it.\n */\nexport const installFakeBroadcastChannel = (): FakeBroadcastChannelHandle => {\n const original = (globalThis as any).BroadcastChannel;\n const instances = new Set<FakeChannelInstance>();\n const posted: FakeBroadcastMessage[] = [];\n\n class FakeBroadcastChannel implements FakeChannelInstance {\n closed = false;\n onmessage: ((event: MessageEvent<unknown>) => void) | null = null;\n\n constructor(public name: string) {\n instances.add(this);\n }\n\n postMessage(data: unknown) {\n if (this.closed) throw new DOMException('Channel is closed', 'InvalidStateError');\n\n const clone = structuredClone(data);\n\n posted.push({ channel: this.name, data: clone });\n\n for (const instance of instances) {\n if (instance === this || instance.closed || instance.name !== this.name) continue;\n\n scheduleTask(() => {\n if (instance.closed) return;\n\n instance.onmessage?.({ data: structuredClone(clone) } as MessageEvent<unknown>);\n });\n }\n }\n\n close() {\n this.closed = true;\n instances.delete(this);\n }\n\n addEventListener() {\n throw new Error('The fake BroadcastChannel only supports `onmessage`.');\n }\n }\n\n (globalThis as any).BroadcastChannel = FakeBroadcastChannel;\n\n return {\n posted,\n restore: () => {\n for (const instance of [...instances]) {\n instance.closed = true;\n }\n\n instances.clear();\n (globalThis as any).BroadcastChannel = original;\n },\n };\n};\n\nexport type FakeWebLocksHandle = {\n /** The names currently held, in no particular order. */\n heldNames: () => string[];\n\n /** The names with at least one request queued behind the holder. */\n pendingNames: () => string[];\n\n /** Uninstalls the fake and restores whatever `navigator.locks` was there before. */\n restore: () => void;\n};\n\ntype FakeLockWaiter = {\n callback: (lock: Lock | null) => unknown;\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n granted: boolean;\n releaseSignal: () => void;\n};\n\n/**\n * Installs an in-memory `navigator.locks` implementing exclusive locks: one holder per name, the\n * rest queued FIFO, granted on a microtask (never synchronously), released when the callback's\n * promise settles. `signal` is honored for queued requests and - as in the real API - ignored once a\n * request has been granted.\n *\n * `ifAvailable` is a try-lock: a request that cannot be granted straight away runs its callback with\n * `null` instead of queueing, exactly as the real API does. `steal` releases the current holder -\n * rejecting its request with an `AbortError` - and is granted ahead of everything queued.\n *\n * `mode: 'shared'` is not implemented; nothing in the library uses it.\n */\nexport const installFakeWebLocks = (): FakeWebLocksHandle => {\n const originalDescriptor = Object.getOwnPropertyDescriptor(navigator, 'locks');\n const holders = new Map<string, FakeLockWaiter>();\n const queues = new Map<string, FakeLockWaiter[]>();\n\n const abortError = () => new DOMException('The lock request was aborted', 'AbortError');\n\n const pump = (name: string) => {\n if (holders.has(name)) return;\n\n const waiter = queues.get(name)?.shift();\n\n if (!waiter) return;\n\n waiter.granted = true;\n holders.set(name, waiter);\n\n const settle = (settleWaiter: () => void) => {\n // Only if this waiter is still the holder: a stolen lock already has a new one, and the callback\n // of the tab it was taken from settles afterwards.\n if (holders.get(name) === waiter) holders.delete(name);\n\n waiter.releaseSignal();\n settleWaiter();\n pump(name);\n };\n\n // `pump` itself only ever runs from a microtask, so calling the callback right here keeps the\n // grant exactly one microtask away from the `request()` call - which is what makes a single\n // `flushMultiTabSync()` per hop enough in specs.\n try {\n Promise.resolve(waiter.callback({ name, mode: 'exclusive' } as Lock)).then(\n (value) => settle(() => waiter.resolve(value)),\n (error) => settle(() => waiter.reject(error)),\n );\n } catch (error) {\n settle(() => waiter.reject(error));\n }\n };\n\n const request = (name: string, optionsOrCallback: unknown, maybeCallback?: unknown) => {\n const options = (typeof optionsOrCallback === 'function' ? {} : (optionsOrCallback ?? {})) as LockOptions;\n const callback = (typeof optionsOrCallback === 'function' ? optionsOrCallback : maybeCallback) as (\n lock: Lock | null,\n ) => unknown;\n\n return new Promise((resolve, reject) => {\n if (options.signal?.aborted) {\n reject(abortError());\n\n return;\n }\n\n const waiter: FakeLockWaiter = { callback, resolve, reject, granted: false, releaseSignal: () => undefined };\n const signal = options.signal;\n\n if (signal) {\n const onAbort = () => {\n waiter.releaseSignal();\n\n if (waiter.granted) return;\n\n const queue = queues.get(name);\n\n if (queue)\n queues.set(\n name,\n queue.filter((entry) => entry !== waiter),\n );\n\n reject(abortError());\n };\n\n signal.addEventListener('abort', onAbort);\n waiter.releaseSignal = () => {\n waiter.releaseSignal = () => undefined;\n signal.removeEventListener('abort', onAbort);\n };\n }\n\n if (options.steal) {\n queueMicrotask(() => {\n const holder = holders.get(name);\n\n if (holder) {\n holders.delete(name);\n holder.reject(abortError());\n }\n\n queues.set(name, [waiter, ...(queues.get(name) ?? [])]);\n pump(name);\n });\n\n return;\n }\n\n // Availability is decided a microtask out, not here: that is when the real API decides it too, so\n // two try-locks requested in the same tick still resolve to one winner and one `null`.\n if (options.ifAvailable) {\n queueMicrotask(() => {\n if (holders.has(name) || (queues.get(name)?.length ?? 0) > 0) {\n waiter.releaseSignal();\n Promise.resolve(callback(null)).then(resolve, reject);\n\n return;\n }\n\n queues.set(name, [waiter]);\n pump(name);\n });\n\n return;\n }\n\n queues.set(name, [...(queues.get(name) ?? []), waiter]);\n queueMicrotask(() => pump(name));\n });\n };\n\n // Both lists are reported, because a queued request is how a tab that is *not* the holder still\n // shows up - which is what the auth leader election counts its tabs by.\n const query = () =>\n Promise.resolve({\n held: [...holders.keys()].map((name) => ({ name, mode: 'exclusive' as const })),\n pending: [...queues.entries()].flatMap(([name, waiters]) =>\n waiters.map(() => ({ name, mode: 'exclusive' as const })),\n ),\n });\n\n Object.defineProperty(navigator, 'locks', {\n value: {\n request,\n query,\n },\n configurable: true,\n writable: true,\n });\n\n return {\n heldNames: () => [...holders.keys()],\n pendingNames: () => [...queues.entries()].filter(([, queue]) => queue.length > 0).map(([name]) => name),\n restore: () => {\n for (const waiter of [...holders.values(), ...[...queues.values()].flat()]) waiter.releaseSignal();\n\n holders.clear();\n queues.clear();\n\n if (originalDescriptor) {\n Object.defineProperty(navigator, 'locks', originalDescriptor);\n } else {\n delete (navigator as any).locks;\n }\n },\n };\n};\n\n/**\n * Waits for the fakes' pending work - message delivery (a task) and lock grants (a microtask) - even\n * under fake timers. Awaiting it once is enough for a single hop; a grant that has to wait for another\n * tab's release, or a reply to a delivered message, needs one await per hop.\n */\nexport const flushMultiTabSync = () => new Promise<void>((resolve) => scheduleTask(resolve));\n","import type { PersistedQueryEntry, PersistedQueryEntryMeta, QueryPersistenceAdapter } from '@ethlete/query';\n\n/**\n * An in-memory stand-in for the query client's persisted response store.\n *\n * jsdom has no IndexedDB at all, so this is how persistence is tested - and because the storage\n * adapter is a documented seam rather than a mock of one, a spec running against this exercises the\n * real engine, repository and request code on both the write and the read side.\n *\n * Everything resolves on a microtask, never synchronously, matching the real thing: `await\n * Promise.resolve()` (or `flushMicrotasks`) is what lets a hydration land in a spec.\n */\nexport type FakeQueryPersistenceStoreHandle = {\n /** Pass this as `persistence: { adapter }`. Two clients sharing one handle share one store. */\n adapter: QueryPersistenceAdapter;\n\n /** Pre-populates the store, as if a previous session had written these entries. */\n seed: (entries: PersistedQueryEntry[]) => void;\n\n /** Every entry currently held, in insertion order. */\n entries: () => PersistedQueryEntry[];\n\n /** The entry held under `key`, or `undefined`. */\n entry: (key: string) => PersistedQueryEntry | undefined;\n\n /** How often each adapter method has been called. */\n calls: () => Record<'loadIndex' | 'read' | 'write' | 'remove' | 'clear', number>;\n\n /** Makes the next `count` writes reject - a full disk, by default. */\n failNextWrites: (count: number, error?: unknown) => void;\n\n /** Makes the next `count` removals reject. */\n failNextRemoves: (count: number, error?: unknown) => void;\n\n /** Makes the next `loadIndex` reject. */\n failNextLoadIndex: (error?: unknown) => void;\n\n /**\n * Holds every subsequent `read` pending until {@link flushReads} is called, for testing the window\n * between a cold mount and its hydration (a slow disk, or a mount that happened before startup\n * finished). Each held read returns what the store held when it started, as `loadIndex` does.\n */\n deferReads: () => void;\n\n /** Settles the reads held by {@link deferReads} and stops deferring. */\n flushReads: () => Promise<void>;\n\n /**\n * Holds every subsequent `loadIndex` pending until {@link flushLoadIndex} is called, for testing\n * what happens to the store while a client's startup is still reading its index (a real disk takes\n * milliseconds). The snapshot each held load returns is the one it would have read when it started.\n */\n deferLoadIndex: () => void;\n\n /** Settles the index loads held by {@link deferLoadIndex} and stops deferring. */\n flushLoadIndex: () => Promise<void>;\n};\n\nconst quotaError = () => new DOMException('The quota has been exceeded.', 'QuotaExceededError');\n\nexport const createFakeQueryPersistenceStore = (): FakeQueryPersistenceStoreHandle => {\n const store = new Map<string, PersistedQueryEntry>();\n const calls = { loadIndex: 0, read: 0, write: 0, remove: 0, clear: 0 };\n const deferredReads: Array<() => void> = [];\n const deferredLoadIndexes: Array<() => void> = [];\n\n let failingWrites = 0;\n let writeError: unknown = null;\n let failingRemoves = 0;\n let removeError: unknown = null;\n let loadIndexError: unknown = null;\n let isDeferringReads = false;\n let isDeferringLoadIndex = false;\n\n // Cloning on the way in and on the way out is not pedantry: a real store hands back a copy, so a\n // spec (or the engine) mutating a hydrated body must not be able to change what is \"on disk\".\n const clone = <T>(value: T): T => structuredClone(value);\n\n const loadIndex = async () => {\n calls.loadIndex++;\n\n if (loadIndexError !== null) {\n const error = loadIndexError;\n loadIndexError = null;\n\n throw error;\n }\n\n // Taken before the gate, not after: a real store answers with what it held when the read started,\n // so anything that empties it while a deferred load is held must not change what that load returns.\n const snapshot = Array.from(store.values()).map(\n ({ body: _body, ...meta }) => clone(meta) satisfies PersistedQueryEntryMeta,\n );\n\n if (isDeferringLoadIndex) {\n await new Promise<void>((resolve) => deferredLoadIndexes.push(resolve));\n }\n\n return snapshot;\n };\n\n const read = async (key: string) => {\n calls.read++;\n\n const entry = store.get(key);\n const snapshot = entry ? { body: clone(entry.body), version: entry.version } : null;\n\n if (isDeferringReads) {\n await new Promise<void>((resolve) => deferredReads.push(resolve));\n }\n\n return snapshot;\n };\n\n const write = async (entries: PersistedQueryEntry[]) => {\n calls.write++;\n\n if (failingWrites > 0) {\n failingWrites--;\n\n throw writeError ?? quotaError();\n }\n\n for (const entry of entries) {\n store.set(entry.key, clone(entry));\n }\n };\n\n const remove = async (keys: string[]) => {\n calls.remove++;\n\n if (failingRemoves > 0) {\n failingRemoves--;\n\n throw removeError ?? new Error('The removal failed.');\n }\n\n for (const key of keys) {\n store.delete(key);\n }\n };\n\n const clear = async () => {\n calls.clear++;\n store.clear();\n };\n\n return {\n adapter: { loadIndex, read, write, remove, clear, isSupported: true },\n seed: (entries) => {\n for (const entry of entries) {\n store.set(entry.key, clone(entry));\n }\n },\n entries: () => Array.from(store.values()).map(clone),\n entry: (key) => {\n const entry = store.get(key);\n\n return entry ? clone(entry) : undefined;\n },\n calls: () => ({ ...calls }),\n failNextWrites: (count, error) => {\n failingWrites = count;\n writeError = error ?? null;\n },\n failNextRemoves: (count, error) => {\n failingRemoves = count;\n removeError = error ?? null;\n },\n failNextLoadIndex: (error) => {\n loadIndexError = error ?? quotaError();\n },\n deferReads: () => {\n isDeferringReads = true;\n },\n flushReads: async () => {\n isDeferringReads = false;\n\n const pending = deferredReads.splice(0, deferredReads.length);\n\n for (const resolve of pending) {\n resolve();\n }\n\n await Promise.resolve();\n },\n deferLoadIndex: () => {\n isDeferringLoadIndex = true;\n },\n flushLoadIndex: async () => {\n isDeferringLoadIndex = false;\n\n const pending = deferredLoadIndexes.splice(0, deferredLoadIndexes.length);\n\n for (const resolve of pending) {\n resolve();\n }\n\n await Promise.resolve();\n },\n };\n};\n","import { HttpClient, provideHttpClient } from '@angular/common/http';\nimport { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';\nimport { EnvironmentProviders, ErrorHandler, Injector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\nimport { provideRouter } from '@angular/router';\nimport {\n AnyCreateQueryClientResult,\n createDeleteQuery,\n createGetQuery,\n createPatchQuery,\n createPostQuery,\n createPutQuery,\n createQueryClient,\n QueryClientRef,\n} from '@ethlete/query';\n\nexport type QueryTestSetup = {\n queryClient: NonNullable<ReturnType<AnyCreateQueryClientResult['inject']>>;\n queryClientRef: QueryClientRef;\n httpClient: HttpClient;\n httpTesting: HttpTestingController;\n injector: Injector;\n baseUrl: string;\n createGet: ReturnType<typeof createGetQuery>;\n createPost: ReturnType<typeof createPostQuery>;\n createPut: ReturnType<typeof createPutQuery>;\n createPatch: ReturnType<typeof createPatchQuery>;\n createDelete: ReturnType<typeof createDeleteQuery>;\n\n /**\n * Puts back the `console.warn` / `console.error` that were installed before the first\n * {@link setupQueryTest} call. Idempotent, and safe to call from any of the setups a file created.\n */\n restoreConsole: () => void;\n};\n\nexport type QueryTestSetupConfig = {\n baseUrl?: string;\n name?: string;\n mockErrorHandler?: boolean;\n};\n\nlet originalWarn: typeof console.warn | null = null;\nlet originalError: typeof console.error | null = null;\n\nconst filteredWarn = (...args: unknown[]) => {\n const message = args[0];\n\n if (typeof message === 'string' && message.includes('auto-refresh')) {\n return;\n }\n\n originalWarn?.(...args);\n};\n\nconst filteredError = (...args: unknown[]) => {\n const message = args[0];\n\n if (message && typeof message === 'object' && 'name' in message && message.name === 'HttpErrorResponse') {\n return;\n }\n\n if (typeof message === 'string' && message.includes('Failed to decrypt bearer token')) {\n return;\n }\n\n if (typeof message === 'string' && message.includes('Failed to extract tokens from')) {\n return;\n }\n\n originalError?.(...args);\n};\n\n// Capture only what is not already the wrapper, so repeated calls reinstall the one filter instead\n// of nesting a new closure over the previous one and stranding the pristine handlers.\nconst installConsoleFilters = () => {\n if (console.warn !== filteredWarn) originalWarn = console.warn;\n if (console.error !== filteredError) originalError = console.error;\n\n console.warn = filteredWarn;\n console.error = filteredError;\n};\n\nconst restoreConsole = () => {\n if (originalWarn && console.warn === filteredWarn) console.warn = originalWarn;\n if (originalError && console.error === filteredError) console.error = originalError;\n\n originalWarn = null;\n originalError = null;\n};\n\nexport const setupQueryTest = (config?: QueryTestSetupConfig): QueryTestSetup => {\n const baseUrl = config?.baseUrl ?? 'https://api.test.com';\n const name = config?.name ?? 'test';\n const mockErrorHandler = config?.mockErrorHandler !== false;\n\n installConsoleFilters();\n\n const providers: (EnvironmentProviders | object)[] = [\n provideHttpClient(),\n provideHttpClientTesting(),\n provideRouter([]),\n ];\n\n if (mockErrorHandler) {\n providers.push({\n provide: ErrorHandler,\n useValue: { handleError: () => undefined },\n });\n }\n\n TestBed.configureTestingModule({ providers });\n\n const queryClientRef = createQueryClient({ baseUrl, name });\n\n return TestBed.runInInjectionContext(() => {\n const { inject } = queryClientRef;\n const queryClient = inject();\n\n if (!queryClient) {\n throw new Error('Failed to create query client in test setup');\n }\n\n return {\n queryClient,\n queryClientRef,\n httpClient: TestBed.inject(HttpClient),\n httpTesting: TestBed.inject(HttpTestingController),\n injector: TestBed.inject(Injector),\n baseUrl,\n createGet: createGetQuery(queryClientRef),\n createPost: createPostQuery(queryClientRef),\n createPut: createPutQuery(queryClientRef),\n createPatch: createPatchQuery(queryClientRef),\n createDelete: createDeleteQuery(queryClientRef),\n restoreConsole,\n };\n });\n};\n","import type {\n SocketMessageView,\n WebSocketClientIo,\n WebSocketClientIoOptions,\n WebSocketClientSocket,\n} from '@ethlete/query';\n\n/** A scripted stand-in for `socket.io-client`'s `io`, driven from a spec. */\nexport type WebSocketTestDouble = {\n /** Pass this as `createWebSocketClient({ io })`. */\n io: WebSocketClientIo;\n\n /** The url and options the client called the factory with, or `null` until it did. */\n connection: () => { url: string; transports: string[] | undefined } | null;\n\n /** The `withCredentials` the client asked the factory for, or `null` until it called it. */\n withCredentials: () => boolean | null;\n\n /** The auth payload of every handshake, oldest first - `null` for one made without `auth`. */\n handshakes: () => (object | null)[];\n\n /** Every message the client emitted, newest last - room joins and leaves included, buffered ones too. */\n sent: () => { event: string; data: unknown }[];\n\n /** Every message that reached the server, newest last. An emit buffered while offline lands here on the next connect. */\n delivered: () => { event: string; data: unknown }[];\n\n /**\n * Whether the client asked the socket to connect, and whether it has since disconnected it. `active` is\n * socket.io's own flag - `false` after a server disconnect or a rejected handshake, until the next\n * `connect()`; `connectCalls` counts every `connect()`.\n */\n state: () => { connectRequested: boolean; disconnected: boolean; active: boolean; connectCalls: number };\n\n /**\n * Complete the handshake: flush every buffered emit, then turn the client's `isConnected` true. Pass\n * `recovered: true` for a connection-state-recovered reconnect, in which the server kept the rooms.\n */\n serverConnect: (options?: { recovered?: boolean }) => void;\n\n /**\n * Drop the connection, so `isConnected` turns false. The default reason, `'transport close'`, is one\n * socket.io recovers from itself; `'io server disconnect'` is the server kicking the socket, after which\n * socket.io only reconnects when `connect()` is called again.\n */\n serverDisconnect: (options?: { reason?: 'transport close' | 'io server disconnect' }) => void;\n\n /**\n * Reject the handshake the way a server middleware does: the `auth` payload is recorded in\n * {@link handshakes}, `connect_error` fires and the socket stops reconnecting on its own.\n */\n serverRejectHandshake: (message?: string) => void;\n\n /**\n * Let the ping expire: the socket still reports itself connected, but buffers every emit like socket.io\n * does until it notices and closes. Follow it with {@link serverDisconnect}.\n */\n serverPingExpire: () => void;\n\n /** Deliver a message the way the server would. */\n serverSend: (message: SocketMessageView) => void;\n\n /** Deliver a raw frame, for the malformed-payload path. */\n serverSendRaw: (frame: string) => void;\n};\n\n/**\n * A socket io test double, for specs around `createWebSocketClient` - which takes its `io` factory as\n * an option precisely so a spec (or an app that never opens a socket) needs no `socket.io-client`.\n *\n * Nothing here connects on its own: the client's own `connect()` only flips\n * {@link WebSocketTestDouble.state}, and it is {@link WebSocketTestDouble.serverConnect} that fires\n * the `connect` listener. That split is what makes \"joined a room while disconnected, and it was\n * re-joined after a reconnect\" testable.\n */\nexport const createWebSocketTestDouble = (): WebSocketTestDouble => {\n const sent: { event: string; data: unknown }[] = [];\n const delivered: { event: string; data: unknown }[] = [];\n const buffered: { event: string; data: unknown }[] = [];\n const listeners = {\n connect: [] as (() => void)[],\n disconnect: [] as ((reason: string) => void)[],\n connect_error: [] as ((error: Error) => void)[],\n };\n const anyListeners: ((eventName: string, ...args: unknown[]) => void)[] = [];\n const outgoingListeners: ((eventName: string, ...args: unknown[]) => void)[] = [];\n\n let connection: { url: string; transports: string[] | undefined } | null = null;\n let withCredentials: boolean | null = null;\n let auth: WebSocketClientIoOptions['auth'];\n const handshakes: (object | null)[] = [];\n let connectRequested = false;\n let disconnected = false;\n let connected = false;\n let active = false;\n let connectCalls = 0;\n let pingExpired = false;\n let recovered = false;\n\n const deliver = (message: { event: string; data: unknown }) => {\n for (const listener of outgoingListeners) listener(message.event, message.data);\n delivered.push(message);\n };\n\n const recordHandshake = () => {\n if (auth) auth((data) => handshakes.push(data));\n else handshakes.push(null);\n };\n\n const disconnect = (reason: string) => {\n connected = false;\n pingExpired = false;\n for (const listener of listeners.disconnect) listener(reason);\n };\n\n const socket: WebSocketClientSocket = {\n connect: () => {\n connectRequested = true;\n active = true;\n connectCalls++;\n },\n disconnect: () => {\n disconnected = true;\n active = false;\n if (connected) disconnect('io client disconnect');\n },\n emit: (event, data) => {\n sent.push({ event, data });\n\n if (connected && !pingExpired) deliver({ event, data });\n else buffered.push({ event, data });\n },\n on: (event: 'connect' | 'disconnect' | 'connect_error', listener: (arg: never) => void) =>\n void (listeners[event] as ((arg: never) => void)[]).push(listener),\n onAny: (listener) => void anyListeners.push(listener),\n onAnyOutgoing: (listener) => void outgoingListeners.push(listener),\n get recovered() {\n return recovered;\n },\n get active() {\n return active;\n },\n };\n\n return {\n io: (url, options) => {\n connection = { url, transports: options.transports };\n withCredentials = options.withCredentials;\n auth = options.auth;\n return socket;\n },\n connection: () => connection,\n withCredentials: () => withCredentials,\n handshakes: () => [...handshakes],\n sent: () => [...sent],\n delivered: () => [...delivered],\n state: () => ({ connectRequested, disconnected, active, connectCalls }),\n serverConnect: (options) => {\n recordHandshake();\n\n active = true;\n recovered = options?.recovered ?? false;\n connected = true;\n pingExpired = false;\n\n for (const message of buffered.splice(0)) deliver(message);\n\n for (const listener of listeners.connect) listener();\n },\n serverDisconnect: (options) => {\n const reason = options?.reason ?? 'transport close';\n\n if (reason === 'io server disconnect') active = false;\n\n disconnect(reason);\n },\n serverRejectHandshake: (message) => {\n recordHandshake();\n\n active = false;\n\n for (const listener of listeners.connect_error) listener(new Error(message ?? 'unauthorized'));\n },\n serverPingExpire: () => void (pingExpired = true),\n serverSend: (message) => {\n const frame = JSON.stringify(message);\n for (const listener of anyListeners) listener('message', frame);\n },\n serverSendRaw: (frame) => {\n for (const listener of anyListeners) listener('message', frame);\n },\n };\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|