📄 src/downloader/test/cache-mock.ts
D-OPEN SOVEREIGN
Documentation & Insights
Installs a fresh in-memory `caches` global and returns it.Installs a `navigator.storage.estimate()` mock returning the given usage/quota.1// Minimal in-memory CacheStorage/Cache polyfill for unit tests — Node has no
2// Cache Storage API. Only implements what src/downloader actually calls
3// (open/match/put/delete/keys), keyed by request URL like the real API.
4
5class MockCache {
6 private store = new Map<string, Response>();
7
8 async match(request: RequestInfo): Promise<Response | undefined> {
9 const key = requestKey(request);
10 const resp = this.store.get(key);
11 return resp ? resp.clone() : undefined;
12 }
13
14 async put(request: RequestInfo, response: Response): Promise<void> {
15 const key = requestKey(request);
16 this.store.set(key, response.clone());
17 }
18
19 async delete(request: RequestInfo): Promise<boolean> {
20 const key = requestKey(request);
21 return this.store.delete(key);
22 }
23
24 async keys(): Promise<Request[]> {
25 return [...this.store.keys()].map(url => new Request(url));
26 }
27}
28
29function toAbsolute(url: string): string {
30 return url.startsWith('http') ? url : `https://mock.local${url}`;
31}
32
33// Requests/strings are always normalized to an absolute URL so a key looked up
34// via a plain string (put/match/delete by path) and via a Request object
35// returned from keys() (real Cache.delete(request) usage) resolve to the same
36// map entry — mirroring how the real Cache API keys by full request URL.
37function requestKey(request: RequestInfo): string {
38 return toAbsolute(typeof request === 'string' ? request : request.url);
39}
40
41class MockCacheStorage {
42 private named = new Map<string, MockCache>();
43
44 async open(name: string): Promise<MockCache> {
45 let c = this.named.get(name);
46 if (!c) {
47 c = new MockCache();
48 this.named.set(name, c);
49 }
50 return c;
51 }
52
53 async delete(name: string): Promise<boolean> {
54 return this.named.delete(name);
55 }
56
57 async has(name: string): Promise<boolean> {
58 return this.named.has(name);
59 }
60}
61
62/** Installs a fresh in-memory `caches` global and returns it. */
63export function installCacheMock(): MockCacheStorage {
64 const storage = new MockCacheStorage();
65 (globalThis as unknown as { caches: MockCacheStorage }).caches = storage;
66 return storage;
67}
68
69/** Installs a `navigator.storage.estimate()` mock returning the given usage/quota. */
70export function installStorageEstimate(usage: number, quota: number): void {
71 (globalThis.navigator as unknown as { storage: StorageManager }).storage = {
72 estimate: async () => ({ usage, quota }),
73 } as StorageManager;
74}
75