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
205
206
207
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import {
assert,
assertEquals,
assertFalse,
assertRejects,
assertThrows,
} from "./test_util.ts";
Deno.test(async function cacheStorage() {
const cacheName = "cache-v1";
const _cache = await caches.open(cacheName);
assert(await caches.has(cacheName));
assert(await caches.delete(cacheName));
assertFalse(await caches.has(cacheName));
});
Deno.test(async function cacheApi() {
const cacheName = "cache-v1";
const cache = await caches.open(cacheName);
// Test cache.put() with url string as key.
{
const req = "https://deno.com";
await cache.put(req, new Response("deno.com - key is string"));
const res = await cache.match(req);
assertEquals(await res?.text(), "deno.com - key is string");
assert(await cache.delete(req));
}
// Test cache.put() with url instance as key.
{
const req = new URL("https://deno.com");
await cache.put(req, new Response("deno.com - key is URL"));
const res = await cache.match(req);
assertEquals(await res?.text(), "deno.com - key is URL");
assert(await cache.delete(req));
}
// Test cache.put() with request instance as key.
{
const req = new Request("https://deno.com");
await cache.put(req, new Response("deno.com - key is Request"));
const res = await cache.match(req);
assertEquals(await res?.text(), "deno.com - key is Request");
assert(await cache.delete(req));
}
// Test cache.put() throws with response Vary header set to *.
{
const req = new Request("https://deno.com");
assertRejects(
async () => {
await cache.put(
req,
new Response("deno.com - key is Request", {
headers: { Vary: "*" },
}),
);
},
TypeError,
"Vary header must not contain '*'",
);
}
// Test cache.match() with same url but different values for Vary header.
{
await cache.put(
new Request("https://example.com/", {
headers: {
"Accept": "application/json",
},
}),
Response.json({ msg: "hello world" }, {
headers: {
"Content-Type": "application/json",
"Vary": "Accept",
},
}),
);
const res = await cache.match("https://example.com/");
assertEquals(res, undefined);
const res2 = await cache.match(
new Request("https://example.com/", {
headers: { "Accept": "text/html" },
}),
);
assertEquals(res2, undefined);
const res3 = await cache.match(
new Request("https://example.com/", {
headers: { "Accept": "application/json" },
}),
);
assertEquals(await res3?.json(), { msg: "hello world" });
}
assert(await caches.delete(cacheName));
assertFalse(await caches.has(cacheName));
});
Deno.test(function cacheIllegalConstructor() {
assertThrows(() => new Cache(), TypeError, "Illegal constructor");
// @ts-expect-error illegal constructor
assertThrows(() => new Cache("foo", "bar"), TypeError, "Illegal constructor");
});
Deno.test(async function cachePutReaderLock() {
const cacheName = "cache-v1";
const cache = await caches.open(cacheName);
const response = new Response("consumed");
const promise = cache.put(
new Request("https://example.com/"),
response,
);
await assertRejects(
async () => {
await response.arrayBuffer();
},
TypeError,
"Body already consumed",
);
await promise;
});
Deno.test(async function cachePutResourceLeak() {
const cacheName = "cache-v1";
const cache = await caches.open(cacheName);
const stream = new ReadableStream({
start(controller) {
controller.error(new Error("leak"));
},
});
await assertRejects(
async () => {
await cache.put(
new Request("https://example.com/leak"),
new Response(stream),
);
},
Error,
"leak",
);
});
Deno.test(async function cachePutFailedBody() {
const cacheName = "cache-v1";
const cache = await caches.open(cacheName);
const request = new Request("https://example.com/failed-body");
const stream = new ReadableStream({
start(controller) {
controller.error(new Error("corrupt"));
},
});
await assertRejects(
async () => {
await cache.put(
request,
new Response(stream),
);
},
Error,
"corrupt",
);
const response = await cache.match(request);
// if it fails to read the body, the cache should be empty
assertEquals(response, undefined);
});
Deno.test(async function cachePutOverwrite() {
const cacheName = "cache-v1";
const cache = await caches.open(cacheName);
const request = new Request("https://example.com/overwrite");
const res1 = new Response("res1");
const res2 = new Response("res2");
await cache.put(request, res1);
const res = await cache.match(request);
assertEquals(await res?.text(), "res1");
await cache.put(request, res2);
const res_ = await cache.match(request);
assertEquals(await res_?.text(), "res2");
});
// Ensure that we can successfully put a response backed by a resource
Deno.test(async function cachePutResource() {
const tempFile = Deno.makeTempFileSync({ prefix: "deno-", suffix: ".txt" });
Deno.writeTextFileSync(tempFile, "Contents".repeat(1024));
const file = Deno.openSync(tempFile);
const cacheName = "cache-v1";
const cache = await caches.open(cacheName);
const request = new Request("https://example.com/file");
await cache.put(request, new Response(file.readable));
const res = await cache.match(request);
assertEquals(await res?.text(), "Contents".repeat(1024));
});
|