@vltpkg/vsr 0.0.0-26 → 0.0.0-27
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/LICENSE +10 -114
- package/dist/README.md +1 -0
- package/dist/assets/public/favicon.ico +0 -0
- package/dist/assets/public/fonts/courier-bold-italic.ttf +0 -0
- package/dist/assets/public/fonts/courier-bold.ttf +0 -0
- package/dist/assets/public/fonts/courier-italic.ttf +0 -0
- package/dist/assets/public/fonts/courier-regular.ttf +0 -0
- package/dist/assets/public/fonts/geist-mono.ttf +0 -0
- package/dist/assets/public/fonts/inter.ttf +0 -0
- package/dist/assets/public/index.html +70 -0
- package/dist/assets/public/index.js +1300 -0
- package/dist/assets/public/index.js.map +7 -0
- package/dist/assets/public/main.css +1 -0
- package/dist/bin/vsr.js +771 -0
- package/dist/index.js +28283 -0
- package/dist/index.js.map +8 -0
- package/package.json +6 -49
- package/DEPLOY.md +0 -163
- package/config.ts +0 -221
- package/drizzle.config.js +0 -40
- package/info/COMPARISONS.md +0 -37
- package/info/CONFIGURATION.md +0 -143
- package/info/CONTRIBUTING.md +0 -32
- package/info/DATABASE_SETUP.md +0 -108
- package/info/GRANULAR_ACCESS_TOKENS.md +0 -160
- package/info/PROJECT_STRUCTURE.md +0 -291
- package/info/ROADMAP.md +0 -27
- package/info/SUPPORT.md +0 -39
- package/info/TESTING.md +0 -301
- package/info/USER_SUPPORT.md +0 -31
- package/scripts/build-assets.js +0 -31
- package/scripts/build-bin.js +0 -62
- package/scripts/prepack.js +0 -27
- package/src/bin/vsr.ts +0 -484
- package/src/db/client.ts +0 -590
- package/src/db/migrations/0000_faulty_ricochet.sql +0 -14
- package/src/db/migrations/0000_initial.sql +0 -29
- package/src/db/migrations/0001_uuid_validation.sql +0 -35
- package/src/db/migrations/0001_wealthy_magdalene.sql +0 -7
- package/src/db/migrations/drop.sql +0 -3
- package/src/db/migrations/meta/0000_snapshot.json +0 -104
- package/src/db/migrations/meta/0001_snapshot.json +0 -155
- package/src/db/migrations/meta/_journal.json +0 -20
- package/src/db/schema.ts +0 -43
- package/src/index.ts +0 -434
- package/src/middleware/config.ts +0 -79
- package/src/middleware/telemetry.ts +0 -43
- package/src/queue/index.ts +0 -97
- package/src/routes/access.ts +0 -852
- package/src/routes/docs.ts +0 -63
- package/src/routes/misc.ts +0 -469
- package/src/routes/packages.ts +0 -2823
- package/src/routes/ping.ts +0 -39
- package/src/routes/search.ts +0 -131
- package/src/routes/static.ts +0 -74
- package/src/routes/tokens.ts +0 -259
- package/src/routes/users.ts +0 -68
- package/src/utils/auth.ts +0 -202
- package/src/utils/cache.ts +0 -587
- package/src/utils/config.ts +0 -50
- package/src/utils/database.ts +0 -69
- package/src/utils/docs.ts +0 -146
- package/src/utils/packages.ts +0 -453
- package/src/utils/response.ts +0 -125
- package/src/utils/routes.ts +0 -64
- package/src/utils/spa.ts +0 -52
- package/src/utils/tracing.ts +0 -52
- package/src/utils/upstream.ts +0 -172
- package/test/access.test.ts +0 -705
- package/test/audit.test.ts +0 -828
- package/test/dashboard.test.ts +0 -693
- package/test/dist-tags.test.ts +0 -678
- package/test/manifest.test.ts +0 -436
- package/test/packument.test.ts +0 -530
- package/test/ping.test.ts +0 -41
- package/test/search.test.ts +0 -472
- package/test/setup.ts +0 -130
- package/test/static.test.ts +0 -646
- package/test/tokens.test.ts +0 -389
- package/test/utils/auth.test.ts +0 -214
- package/test/utils/packages.test.ts +0 -235
- package/test/utils/response.test.ts +0 -184
- package/test/whoami.test.ts +0 -119
- package/tsconfig.json +0 -16
- package/tsconfig.worker.json +0 -3
- package/typedoc.mjs +0 -2
- package/types.ts +0 -598
- package/vitest.config.ts +0 -25
- package/vlt.json.example +0 -56
- package/wrangler.json +0 -65
- /package/{src → dist}/assets/public/images/bg.png +0 -0
- /package/{src → dist}/assets/public/images/clients/logo-bun.png +0 -0
- /package/{src → dist}/assets/public/images/clients/logo-deno.png +0 -0
- /package/{src → dist}/assets/public/images/clients/logo-npm.png +0 -0
- /package/{src → dist}/assets/public/images/clients/logo-pnpm.png +0 -0
- /package/{src → dist}/assets/public/images/clients/logo-vlt.png +0 -0
- /package/{src → dist}/assets/public/images/clients/logo-yarn.png +0 -0
- /package/{src → dist}/assets/public/images/favicon/apple-touch-icon.png +0 -0
- /package/{src → dist}/assets/public/images/favicon/favicon-96x96.png +0 -0
- /package/{src → dist}/assets/public/images/favicon/favicon.ico +0 -0
- /package/{src → dist}/assets/public/images/favicon/favicon.svg +0 -0
- /package/{src → dist}/assets/public/images/favicon/site.webmanifest +0 -0
- /package/{src → dist}/assets/public/images/favicon/web-app-manifest-192x192.png +0 -0
- /package/{src → dist}/assets/public/images/favicon/web-app-manifest-512x512.png +0 -0
- /package/{src → dist}/assets/public/styles/styles.css +0 -0
- /package/{src → dist}/bin/demo/package.json +0 -0
- /package/{src → dist}/bin/demo/vlt.json +0 -0
package/test/static.test.ts
DELETED
|
@@ -1,646 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { app } from '../src/index.ts'
|
|
3
|
-
|
|
4
|
-
// Mock environment for testing
|
|
5
|
-
const mockEnv = {
|
|
6
|
-
DB: {
|
|
7
|
-
// Minimal D1 interface to prevent database errors
|
|
8
|
-
prepare: () => ({
|
|
9
|
-
bind: () => ({
|
|
10
|
-
get: () => Promise.resolve(null),
|
|
11
|
-
all: () => Promise.resolve({ results: [] }),
|
|
12
|
-
run: () => Promise.resolve({ success: true }),
|
|
13
|
-
raw: () => Promise.resolve([]),
|
|
14
|
-
}),
|
|
15
|
-
get: () => Promise.resolve(null),
|
|
16
|
-
all: () => Promise.resolve({ results: [] }),
|
|
17
|
-
run: () => Promise.resolve({ success: true }),
|
|
18
|
-
raw: () => Promise.resolve([]),
|
|
19
|
-
}),
|
|
20
|
-
batch: () => Promise.resolve([]),
|
|
21
|
-
exec: () => Promise.resolve(),
|
|
22
|
-
},
|
|
23
|
-
BUCKET: {
|
|
24
|
-
get: () => Promise.resolve(null),
|
|
25
|
-
put: () => Promise.resolve(),
|
|
26
|
-
delete: () => Promise.resolve(),
|
|
27
|
-
},
|
|
28
|
-
KV: {
|
|
29
|
-
get: () => Promise.resolve(null),
|
|
30
|
-
put: () => Promise.resolve(),
|
|
31
|
-
delete: () => Promise.resolve(),
|
|
32
|
-
},
|
|
33
|
-
ASSETS: {
|
|
34
|
-
// Mock assets binding
|
|
35
|
-
fetch: () =>
|
|
36
|
-
Promise.resolve(new Response('mock asset', { status: 200 })),
|
|
37
|
-
},
|
|
38
|
-
DAEMON_ENABLED: false,
|
|
39
|
-
API_DOCS_ENABLED: false,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
describe('Static Asset Endpoints', () => {
|
|
43
|
-
describe('Public Assets', () => {
|
|
44
|
-
describe('GET /public/*', () => {
|
|
45
|
-
it('should serve static assets from public directory', async () => {
|
|
46
|
-
const res = await app.request(
|
|
47
|
-
'/public/styles/styles.css',
|
|
48
|
-
{},
|
|
49
|
-
mockEnv,
|
|
50
|
-
)
|
|
51
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('should serve JavaScript assets', async () => {
|
|
55
|
-
const res = await app.request(
|
|
56
|
-
'/public/js/app.js',
|
|
57
|
-
{},
|
|
58
|
-
mockEnv,
|
|
59
|
-
)
|
|
60
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('should serve image assets', async () => {
|
|
64
|
-
const res = await app.request(
|
|
65
|
-
'/public/images/logo.png',
|
|
66
|
-
{},
|
|
67
|
-
mockEnv,
|
|
68
|
-
)
|
|
69
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('should serve font assets', async () => {
|
|
73
|
-
const res = await app.request(
|
|
74
|
-
'/public/fonts/inter.woff2',
|
|
75
|
-
{},
|
|
76
|
-
mockEnv,
|
|
77
|
-
)
|
|
78
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('should handle nested public assets', async () => {
|
|
82
|
-
const res = await app.request(
|
|
83
|
-
'/public/assets/images/favicon/favicon.ico',
|
|
84
|
-
{},
|
|
85
|
-
mockEnv,
|
|
86
|
-
)
|
|
87
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
describe('Content-Type Headers', () => {
|
|
92
|
-
it('should set correct content-type for CSS files', async () => {
|
|
93
|
-
const res = await app.request(
|
|
94
|
-
'/public/styles/styles.css',
|
|
95
|
-
{},
|
|
96
|
-
mockEnv,
|
|
97
|
-
)
|
|
98
|
-
if (res.status === 200) {
|
|
99
|
-
expect(
|
|
100
|
-
res.headers.get('content-type')?.includes('text/css'),
|
|
101
|
-
).toBeTruthy()
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('should set correct content-type for JavaScript files', async () => {
|
|
106
|
-
const res = await app.request(
|
|
107
|
-
'/public/js/app.js',
|
|
108
|
-
{},
|
|
109
|
-
mockEnv,
|
|
110
|
-
)
|
|
111
|
-
if (res.status === 200) {
|
|
112
|
-
expect(
|
|
113
|
-
res.headers
|
|
114
|
-
.get('content-type')
|
|
115
|
-
?.includes('application/javascript'),
|
|
116
|
-
).toBeTruthy()
|
|
117
|
-
}
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('should set correct content-type for PNG images', async () => {
|
|
121
|
-
const res = await app.request(
|
|
122
|
-
'/public/images/logo.png',
|
|
123
|
-
{},
|
|
124
|
-
mockEnv,
|
|
125
|
-
)
|
|
126
|
-
if (res.status === 200) {
|
|
127
|
-
expect(
|
|
128
|
-
res.headers.get('content-type')?.includes('image/png'),
|
|
129
|
-
).toBeTruthy()
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('should set correct content-type for SVG images', async () => {
|
|
134
|
-
const res = await app.request(
|
|
135
|
-
'/public/images/icon.svg',
|
|
136
|
-
{},
|
|
137
|
-
mockEnv,
|
|
138
|
-
)
|
|
139
|
-
if (res.status === 200) {
|
|
140
|
-
expect(
|
|
141
|
-
res.headers
|
|
142
|
-
.get('content-type')
|
|
143
|
-
?.includes('image/svg+xml'),
|
|
144
|
-
).toBeTruthy()
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
describe('Cache Headers', () => {
|
|
150
|
-
it('should set appropriate cache headers for static assets', async () => {
|
|
151
|
-
const res = await app.request(
|
|
152
|
-
'/public/styles/styles.css',
|
|
153
|
-
{},
|
|
154
|
-
mockEnv,
|
|
155
|
-
)
|
|
156
|
-
if (res.status === 200) {
|
|
157
|
-
// Cache headers would be validated based on implementation
|
|
158
|
-
expect(res.status).toBe(200)
|
|
159
|
-
}
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('should set ETag headers for static assets', async () => {
|
|
163
|
-
const res = await app.request(
|
|
164
|
-
'/public/js/app.js',
|
|
165
|
-
{},
|
|
166
|
-
mockEnv,
|
|
167
|
-
)
|
|
168
|
-
if (res.status === 200) {
|
|
169
|
-
// ETag headers would be validated based on implementation
|
|
170
|
-
expect(res.status).toBe(200)
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
})
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
describe('Special Static Files', () => {
|
|
177
|
-
describe('GET /favicon.ico', () => {
|
|
178
|
-
it('should serve favicon.ico', async () => {
|
|
179
|
-
const res = await app.request('/favicon.ico', {}, mockEnv)
|
|
180
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('should set correct content-type for favicon', async () => {
|
|
184
|
-
const res = await app.request('/favicon.ico', {}, mockEnv)
|
|
185
|
-
if (res.status === 200) {
|
|
186
|
-
expect(
|
|
187
|
-
res.headers.get('content-type')?.includes('image/'),
|
|
188
|
-
).toBeTruthy()
|
|
189
|
-
}
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('should handle HEAD requests for favicon', async () => {
|
|
193
|
-
const res = await app.request(
|
|
194
|
-
'/favicon.ico',
|
|
195
|
-
{ method: 'HEAD' },
|
|
196
|
-
mockEnv,
|
|
197
|
-
)
|
|
198
|
-
expect([200, 404, 405].includes(res.status)).toBe(true)
|
|
199
|
-
})
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
describe('GET /robots.txt', () => {
|
|
203
|
-
it('should serve robots.txt', async () => {
|
|
204
|
-
const res = await app.request('/robots.txt', {}, mockEnv)
|
|
205
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
it('should set correct content-type for robots.txt', async () => {
|
|
209
|
-
const res = await app.request('/robots.txt', {}, mockEnv)
|
|
210
|
-
if (res.status === 200) {
|
|
211
|
-
expect(
|
|
212
|
-
res.headers.get('content-type')?.includes('text/plain'),
|
|
213
|
-
).toBeTruthy()
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
it('should contain valid robots.txt content', async () => {
|
|
218
|
-
const res = await app.request('/robots.txt', {}, mockEnv)
|
|
219
|
-
if (res.status === 200) {
|
|
220
|
-
const content = await res.text()
|
|
221
|
-
expect(content).toBeDefined()
|
|
222
|
-
// Would validate robots.txt format based on implementation
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
describe('GET /manifest.json', () => {
|
|
228
|
-
it('should serve PWA manifest.json', async () => {
|
|
229
|
-
const res = await app.request('/manifest.json', {}, mockEnv)
|
|
230
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
it('should set correct content-type for manifest.json', async () => {
|
|
234
|
-
const res = await app.request('/manifest.json', {}, mockEnv)
|
|
235
|
-
if (res.status === 200) {
|
|
236
|
-
expect(res.headers.get('content-type')).toContain(
|
|
237
|
-
'application/json',
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('should contain valid PWA manifest structure', async () => {
|
|
243
|
-
const res = await app.request('/manifest.json', {}, mockEnv)
|
|
244
|
-
if (res.status === 200) {
|
|
245
|
-
const manifest = (await res.json()) as any
|
|
246
|
-
expect(manifest).toBeDefined()
|
|
247
|
-
// Would validate PWA manifest structure based on implementation
|
|
248
|
-
}
|
|
249
|
-
})
|
|
250
|
-
})
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
describe('Catch-All Static Handler', () => {
|
|
254
|
-
describe('GET /*', () => {
|
|
255
|
-
it('should handle catch-all static asset requests', async () => {
|
|
256
|
-
const res = await app.request(
|
|
257
|
-
'/some-static-file.txt',
|
|
258
|
-
{},
|
|
259
|
-
mockEnv,
|
|
260
|
-
)
|
|
261
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
it('should handle nested static asset paths', async () => {
|
|
265
|
-
const res = await app.request(
|
|
266
|
-
'/assets/css/main.css',
|
|
267
|
-
{},
|
|
268
|
-
mockEnv,
|
|
269
|
-
)
|
|
270
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
it('should handle static assets with query parameters', async () => {
|
|
274
|
-
const res = await app.request(
|
|
275
|
-
'/assets/js/app.js?v=1.0.0',
|
|
276
|
-
{},
|
|
277
|
-
mockEnv,
|
|
278
|
-
)
|
|
279
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
it('should handle static assets with hash fragments', async () => {
|
|
283
|
-
const res = await app.request(
|
|
284
|
-
'/assets/app.js#main',
|
|
285
|
-
{},
|
|
286
|
-
mockEnv,
|
|
287
|
-
)
|
|
288
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
289
|
-
})
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
describe('Security Considerations', () => {
|
|
293
|
-
it('should prevent directory traversal attacks', async () => {
|
|
294
|
-
const res = await app.request(
|
|
295
|
-
'/../../etc/passwd',
|
|
296
|
-
{},
|
|
297
|
-
mockEnv,
|
|
298
|
-
)
|
|
299
|
-
expect([400, 404].includes(res.status)).toBe(true)
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
it('should handle encoded path traversal attempts', async () => {
|
|
303
|
-
const res = await app.request(
|
|
304
|
-
'/%2e%2e%2f%2e%2e%2fetc%2fpasswd',
|
|
305
|
-
{},
|
|
306
|
-
mockEnv,
|
|
307
|
-
)
|
|
308
|
-
expect([400, 404].includes(res.status)).toBe(true)
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
it('should handle null byte injection attempts', async () => {
|
|
312
|
-
const res = await app.request('/file.txt%00.exe', {}, mockEnv)
|
|
313
|
-
expect([400, 404].includes(res.status)).toBe(true)
|
|
314
|
-
})
|
|
315
|
-
})
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
describe('Error Handling', () => {
|
|
319
|
-
describe('Non-existent Assets', () => {
|
|
320
|
-
it('should return 404 for non-existent static assets', async () => {
|
|
321
|
-
const res = await app.request(
|
|
322
|
-
'/public/nonexistent-file.txt',
|
|
323
|
-
{},
|
|
324
|
-
mockEnv,
|
|
325
|
-
)
|
|
326
|
-
expect(res.status).toBe(404)
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
it('should return 404 for non-existent nested assets', async () => {
|
|
330
|
-
const res = await app.request(
|
|
331
|
-
'/public/deep/nested/nonexistent.js',
|
|
332
|
-
{},
|
|
333
|
-
mockEnv,
|
|
334
|
-
)
|
|
335
|
-
expect(res.status).toBe(404)
|
|
336
|
-
})
|
|
337
|
-
|
|
338
|
-
it('should handle malformed asset paths', async () => {
|
|
339
|
-
const res = await app.request(
|
|
340
|
-
'/public//double//slash.css',
|
|
341
|
-
{},
|
|
342
|
-
mockEnv,
|
|
343
|
-
)
|
|
344
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
345
|
-
})
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
describe('HTTP Method Validation', () => {
|
|
349
|
-
it('should handle POST requests to static assets', async () => {
|
|
350
|
-
const res = await app.request(
|
|
351
|
-
'/public/styles/styles.css',
|
|
352
|
-
{ method: 'POST' },
|
|
353
|
-
mockEnv,
|
|
354
|
-
)
|
|
355
|
-
expect([200, 404, 405].includes(res.status)).toBe(true)
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
it('should handle PUT requests to static assets', async () => {
|
|
359
|
-
const res = await app.request(
|
|
360
|
-
'/public/js/app.js',
|
|
361
|
-
{ method: 'PUT' },
|
|
362
|
-
mockEnv,
|
|
363
|
-
)
|
|
364
|
-
expect([200, 404, 405].includes(res.status)).toBe(true)
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
it('should handle DELETE requests to static assets', async () => {
|
|
368
|
-
const res = await app.request(
|
|
369
|
-
'/public/images/logo.png',
|
|
370
|
-
{ method: 'DELETE' },
|
|
371
|
-
mockEnv,
|
|
372
|
-
)
|
|
373
|
-
expect([200, 404, 405].includes(res.status)).toBe(true)
|
|
374
|
-
})
|
|
375
|
-
})
|
|
376
|
-
})
|
|
377
|
-
|
|
378
|
-
describe('Performance and Optimization', () => {
|
|
379
|
-
describe('Compression', () => {
|
|
380
|
-
it('should handle gzip compression for text assets', async () => {
|
|
381
|
-
const res = await app.request(
|
|
382
|
-
'/public/styles/styles.css',
|
|
383
|
-
{
|
|
384
|
-
headers: {
|
|
385
|
-
'Accept-Encoding': 'gzip, deflate, br',
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
mockEnv,
|
|
389
|
-
)
|
|
390
|
-
if (res.status === 200) {
|
|
391
|
-
// Compression headers would be validated based on implementation
|
|
392
|
-
expect(res.status).toBe(200)
|
|
393
|
-
}
|
|
394
|
-
})
|
|
395
|
-
|
|
396
|
-
it('should handle brotli compression for JavaScript assets', async () => {
|
|
397
|
-
const res = await app.request(
|
|
398
|
-
'/public/js/app.js',
|
|
399
|
-
{
|
|
400
|
-
headers: {
|
|
401
|
-
'Accept-Encoding': 'br, gzip, deflate',
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
mockEnv,
|
|
405
|
-
)
|
|
406
|
-
if (res.status === 200) {
|
|
407
|
-
// Compression headers would be validated based on implementation
|
|
408
|
-
expect(res.status).toBe(200)
|
|
409
|
-
}
|
|
410
|
-
})
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
describe('Range Requests', () => {
|
|
414
|
-
it('should handle range requests for large assets', async () => {
|
|
415
|
-
const res = await app.request(
|
|
416
|
-
'/public/videos/demo.mp4',
|
|
417
|
-
{
|
|
418
|
-
headers: {
|
|
419
|
-
Range: 'bytes=0-1023',
|
|
420
|
-
},
|
|
421
|
-
},
|
|
422
|
-
mockEnv,
|
|
423
|
-
)
|
|
424
|
-
expect([200, 206, 404, 416].includes(res.status)).toBe(true)
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
it('should handle invalid range requests', async () => {
|
|
428
|
-
const res = await app.request(
|
|
429
|
-
'/public/images/large-image.jpg',
|
|
430
|
-
{
|
|
431
|
-
headers: {
|
|
432
|
-
Range: 'bytes=invalid-range',
|
|
433
|
-
},
|
|
434
|
-
},
|
|
435
|
-
mockEnv,
|
|
436
|
-
)
|
|
437
|
-
expect([200, 400, 404, 416].includes(res.status)).toBe(true)
|
|
438
|
-
})
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
describe('Conditional Requests', () => {
|
|
442
|
-
it('should handle If-None-Match headers', async () => {
|
|
443
|
-
const res = await app.request(
|
|
444
|
-
'/public/styles/styles.css',
|
|
445
|
-
{
|
|
446
|
-
headers: {
|
|
447
|
-
'If-None-Match': '"some-etag-value"',
|
|
448
|
-
},
|
|
449
|
-
},
|
|
450
|
-
mockEnv,
|
|
451
|
-
)
|
|
452
|
-
expect([200, 304, 404].includes(res.status)).toBe(true)
|
|
453
|
-
})
|
|
454
|
-
|
|
455
|
-
it('should handle If-Modified-Since headers', async () => {
|
|
456
|
-
const res = await app.request(
|
|
457
|
-
'/public/js/app.js',
|
|
458
|
-
{
|
|
459
|
-
headers: {
|
|
460
|
-
'If-Modified-Since': 'Wed, 21 Oct 2015 07:28:00 GMT',
|
|
461
|
-
},
|
|
462
|
-
},
|
|
463
|
-
mockEnv,
|
|
464
|
-
)
|
|
465
|
-
expect([200, 304, 404].includes(res.status)).toBe(true)
|
|
466
|
-
})
|
|
467
|
-
})
|
|
468
|
-
})
|
|
469
|
-
|
|
470
|
-
describe('CORS and Security Headers', () => {
|
|
471
|
-
describe('CORS Headers', () => {
|
|
472
|
-
it('should handle CORS headers for static assets', async () => {
|
|
473
|
-
const res = await app.request(
|
|
474
|
-
'/public/styles/styles.css',
|
|
475
|
-
{
|
|
476
|
-
headers: {
|
|
477
|
-
Origin: 'https://example.com',
|
|
478
|
-
},
|
|
479
|
-
},
|
|
480
|
-
mockEnv,
|
|
481
|
-
)
|
|
482
|
-
if (res.status === 200) {
|
|
483
|
-
// CORS headers would be validated based on implementation
|
|
484
|
-
expect(res.status).toBe(200)
|
|
485
|
-
}
|
|
486
|
-
})
|
|
487
|
-
|
|
488
|
-
it('should handle preflight requests for static assets', async () => {
|
|
489
|
-
const res = await app.request(
|
|
490
|
-
'/public/js/app.js',
|
|
491
|
-
{
|
|
492
|
-
method: 'OPTIONS',
|
|
493
|
-
headers: {
|
|
494
|
-
Origin: 'https://example.com',
|
|
495
|
-
'Access-Control-Request-Method': 'GET',
|
|
496
|
-
},
|
|
497
|
-
},
|
|
498
|
-
mockEnv,
|
|
499
|
-
)
|
|
500
|
-
expect([200, 204, 404, 405].includes(res.status)).toBe(true)
|
|
501
|
-
})
|
|
502
|
-
})
|
|
503
|
-
|
|
504
|
-
describe('Security Headers', () => {
|
|
505
|
-
it('should include security headers for static assets', async () => {
|
|
506
|
-
const res = await app.request(
|
|
507
|
-
'/public/js/app.js',
|
|
508
|
-
{},
|
|
509
|
-
mockEnv,
|
|
510
|
-
)
|
|
511
|
-
if (res.status === 200) {
|
|
512
|
-
// Security headers would be validated based on implementation
|
|
513
|
-
expect(res.status).toBe(200)
|
|
514
|
-
}
|
|
515
|
-
})
|
|
516
|
-
|
|
517
|
-
it('should set X-Content-Type-Options header', async () => {
|
|
518
|
-
const res = await app.request(
|
|
519
|
-
'/public/styles/styles.css',
|
|
520
|
-
{},
|
|
521
|
-
mockEnv,
|
|
522
|
-
)
|
|
523
|
-
if (res.status === 200) {
|
|
524
|
-
// X-Content-Type-Options header would be validated
|
|
525
|
-
expect(res.status).toBe(200)
|
|
526
|
-
}
|
|
527
|
-
})
|
|
528
|
-
})
|
|
529
|
-
})
|
|
530
|
-
|
|
531
|
-
describe('Asset Types and Extensions', () => {
|
|
532
|
-
describe('Web Assets', () => {
|
|
533
|
-
it('should serve HTML files', async () => {
|
|
534
|
-
const res = await app.request(
|
|
535
|
-
'/public/index.html',
|
|
536
|
-
{},
|
|
537
|
-
mockEnv,
|
|
538
|
-
)
|
|
539
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
it('should serve XML files', async () => {
|
|
543
|
-
const res = await app.request(
|
|
544
|
-
'/public/sitemap.xml',
|
|
545
|
-
{},
|
|
546
|
-
mockEnv,
|
|
547
|
-
)
|
|
548
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
549
|
-
})
|
|
550
|
-
|
|
551
|
-
it('should serve JSON files', async () => {
|
|
552
|
-
const res = await app.request(
|
|
553
|
-
'/public/data.json',
|
|
554
|
-
{},
|
|
555
|
-
mockEnv,
|
|
556
|
-
)
|
|
557
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
558
|
-
})
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
describe('Media Assets', () => {
|
|
562
|
-
it('should serve JPEG images', async () => {
|
|
563
|
-
const res = await app.request(
|
|
564
|
-
'/public/images/photo.jpg',
|
|
565
|
-
{},
|
|
566
|
-
mockEnv,
|
|
567
|
-
)
|
|
568
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
569
|
-
})
|
|
570
|
-
|
|
571
|
-
it('should serve WebP images', async () => {
|
|
572
|
-
const res = await app.request(
|
|
573
|
-
'/public/images/modern.webp',
|
|
574
|
-
{},
|
|
575
|
-
mockEnv,
|
|
576
|
-
)
|
|
577
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
578
|
-
})
|
|
579
|
-
|
|
580
|
-
it('should serve AVIF images', async () => {
|
|
581
|
-
const res = await app.request(
|
|
582
|
-
'/public/images/next-gen.avif',
|
|
583
|
-
{},
|
|
584
|
-
mockEnv,
|
|
585
|
-
)
|
|
586
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
587
|
-
})
|
|
588
|
-
|
|
589
|
-
it('should serve video files', async () => {
|
|
590
|
-
const res = await app.request(
|
|
591
|
-
'/public/videos/demo.mp4',
|
|
592
|
-
{},
|
|
593
|
-
mockEnv,
|
|
594
|
-
)
|
|
595
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
596
|
-
})
|
|
597
|
-
|
|
598
|
-
it('should serve audio files', async () => {
|
|
599
|
-
const res = await app.request(
|
|
600
|
-
'/public/audio/sound.mp3',
|
|
601
|
-
{},
|
|
602
|
-
mockEnv,
|
|
603
|
-
)
|
|
604
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
605
|
-
})
|
|
606
|
-
})
|
|
607
|
-
|
|
608
|
-
describe('Font Assets', () => {
|
|
609
|
-
it('should serve WOFF fonts', async () => {
|
|
610
|
-
const res = await app.request(
|
|
611
|
-
'/public/fonts/font.woff',
|
|
612
|
-
{},
|
|
613
|
-
mockEnv,
|
|
614
|
-
)
|
|
615
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
616
|
-
})
|
|
617
|
-
|
|
618
|
-
it('should serve WOFF2 fonts', async () => {
|
|
619
|
-
const res = await app.request(
|
|
620
|
-
'/public/fonts/font.woff2',
|
|
621
|
-
{},
|
|
622
|
-
mockEnv,
|
|
623
|
-
)
|
|
624
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
625
|
-
})
|
|
626
|
-
|
|
627
|
-
it('should serve TTF fonts', async () => {
|
|
628
|
-
const res = await app.request(
|
|
629
|
-
'/public/fonts/font.ttf',
|
|
630
|
-
{},
|
|
631
|
-
mockEnv,
|
|
632
|
-
)
|
|
633
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
634
|
-
})
|
|
635
|
-
|
|
636
|
-
it('should serve OTF fonts', async () => {
|
|
637
|
-
const res = await app.request(
|
|
638
|
-
'/public/fonts/font.otf',
|
|
639
|
-
{},
|
|
640
|
-
mockEnv,
|
|
641
|
-
)
|
|
642
|
-
expect([200, 404].includes(res.status)).toBe(true)
|
|
643
|
-
})
|
|
644
|
-
})
|
|
645
|
-
})
|
|
646
|
-
})
|