@vltpkg/vsr 0.0.0-26 → 0.0.0-28
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/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/images/bg.png +0 -0
- package/dist/assets/public/images/clients/logo-bun.png +0 -0
- package/dist/assets/public/images/clients/logo-deno.png +0 -0
- package/dist/assets/public/images/clients/logo-npm.png +0 -0
- package/dist/assets/public/images/clients/logo-pnpm.png +0 -0
- package/dist/assets/public/images/clients/logo-vlt.png +0 -0
- package/dist/assets/public/images/clients/logo-yarn.png +0 -0
- package/dist/assets/public/images/favicon/apple-touch-icon.png +0 -0
- package/dist/assets/public/images/favicon/favicon-96x96.png +0 -0
- package/dist/assets/public/images/favicon/favicon.ico +0 -0
- package/dist/assets/public/images/favicon/favicon.svg +3 -0
- package/dist/assets/public/images/favicon/site.webmanifest +21 -0
- package/dist/assets/public/images/favicon/web-app-manifest-192x192.png +0 -0
- package/dist/assets/public/images/favicon/web-app-manifest-512x512.png +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/assets/public/styles/styles.css +231 -0
- package/dist/bin/demo/package.json +6 -0
- package/dist/bin/demo/vlt.json +1 -0
- package/dist/bin/vsr.js +773 -0
- package/dist/index.js +28280 -0
- package/dist/index.js.map +8 -0
- package/package.json +6 -6
- package/scripts/build-bin.js +1 -0
- package/src/bin/vsr.ts +15 -3
- package/scripts/prepack.js +0 -27
- 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/test/dashboard.test.ts
DELETED
|
@@ -1,693 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { env } from 'cloudflare:test'
|
|
3
|
-
import { app } from '../src/index.ts'
|
|
4
|
-
|
|
5
|
-
describe('Dashboard Endpoints', () => {
|
|
6
|
-
describe('Dashboard Data Endpoint', () => {
|
|
7
|
-
describe('GET /dashboard.json', () => {
|
|
8
|
-
it('should return dashboard data when daemon is enabled', async () => {
|
|
9
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
10
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
11
|
-
|
|
12
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
13
|
-
if (res.status === 500) return
|
|
14
|
-
// Dashboard endpoints may return 500 with text/plain when external services are unavailable
|
|
15
|
-
if (res.status === 200) {
|
|
16
|
-
expect(res.headers.get('content-type')).toContain(
|
|
17
|
-
'application/json',
|
|
18
|
-
)
|
|
19
|
-
} else if (res.status === 500) {
|
|
20
|
-
expect(res.headers.get('content-type')).toContain(
|
|
21
|
-
'text/plain',
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('should return dashboard data in standalone mode when daemon is disabled', async () => {
|
|
27
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
28
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
29
|
-
// Dashboard endpoints now provide standalone data when daemon is disabled
|
|
30
|
-
if (res.status === 200) {
|
|
31
|
-
expect(res.headers.get('content-type')).toContain(
|
|
32
|
-
'application/json',
|
|
33
|
-
)
|
|
34
|
-
const data = await res.json()
|
|
35
|
-
expect(data.registry).toBeDefined()
|
|
36
|
-
expect(data.features).toBeDefined()
|
|
37
|
-
} else if (res.status === 500) {
|
|
38
|
-
expect(res.headers.get('content-type')).toContain(
|
|
39
|
-
'text/plain',
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('should return proper dashboard configuration structure', async () => {
|
|
45
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
46
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
47
|
-
|
|
48
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
49
|
-
if (res.status === 500) return
|
|
50
|
-
if (res.status === 200) {
|
|
51
|
-
const data = (await res.json()) as any
|
|
52
|
-
expect(data).toBeDefined()
|
|
53
|
-
expect(data.registry).toBeDefined()
|
|
54
|
-
expect(data.features).toBeDefined()
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('should include registry information in response', async () => {
|
|
59
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
60
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
61
|
-
|
|
62
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
63
|
-
if (res.status === 500) return
|
|
64
|
-
const data = (await res.json()) as any
|
|
65
|
-
expect(data.registry).toBeDefined()
|
|
66
|
-
expect(data.registry.url).toBeDefined()
|
|
67
|
-
expect(data.registry.name).toBeDefined()
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it('should include feature flags in response', async () => {
|
|
71
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
72
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
73
|
-
|
|
74
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
75
|
-
if (res.status === 500) return
|
|
76
|
-
const data = (await res.json()) as any
|
|
77
|
-
expect(data.features).toBeDefined()
|
|
78
|
-
expect(typeof data.features.search).toBe('boolean')
|
|
79
|
-
expect(typeof data.features.publish).toBe('boolean')
|
|
80
|
-
expect(typeof data.features.access).toBe('boolean')
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('should handle HEAD requests', async () => {
|
|
84
|
-
const res = await app.request(
|
|
85
|
-
'/dashboard.json',
|
|
86
|
-
{ method: 'HEAD' },
|
|
87
|
-
env,
|
|
88
|
-
)
|
|
89
|
-
expect(
|
|
90
|
-
[200, 401, 404, 405, 500, 501].includes(res.status),
|
|
91
|
-
).toBe(true)
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
describe('Dashboard Data Validation', () => {
|
|
96
|
-
it('should return valid JSON structure', async () => {
|
|
97
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
98
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
99
|
-
|
|
100
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
101
|
-
if (res.status === 500) return
|
|
102
|
-
|
|
103
|
-
const data = (await res.json()) as any
|
|
104
|
-
expect(data).toBeDefined()
|
|
105
|
-
expect(typeof data).toBe('object')
|
|
106
|
-
expect(data).not.toBeNull()
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('should include all required registry fields', async () => {
|
|
110
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
111
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
112
|
-
|
|
113
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
114
|
-
if (res.status === 500) return
|
|
115
|
-
|
|
116
|
-
const data = (await res.json()) as any
|
|
117
|
-
expect(data.registry).toBeDefined()
|
|
118
|
-
expect(typeof data.registry.url).toBe('string')
|
|
119
|
-
expect(typeof data.registry.name).toBe('string')
|
|
120
|
-
expect(data.registry.url.length).toBeGreaterThan(0)
|
|
121
|
-
expect(data.registry.name.length).toBeGreaterThan(0)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('should include all required feature fields', async () => {
|
|
125
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
126
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
127
|
-
|
|
128
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
129
|
-
if (res.status === 500) return
|
|
130
|
-
|
|
131
|
-
const data = (await res.json()) as any
|
|
132
|
-
expect(data.features).toBeDefined()
|
|
133
|
-
expect('search' in data.features).toBe(true)
|
|
134
|
-
expect('publish' in data.features).toBe(true)
|
|
135
|
-
expect('access' in data.features).toBe(true)
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
describe('App Data Endpoint', () => {
|
|
141
|
-
describe('GET /app-data.json', () => {
|
|
142
|
-
it('should return app data when daemon is enabled', async () => {
|
|
143
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
144
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
145
|
-
|
|
146
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
147
|
-
if (res.status === 500) return
|
|
148
|
-
// Dashboard endpoints may return 500 with text/plain when external services are unavailable
|
|
149
|
-
if (res.status === 200) {
|
|
150
|
-
expect(res.headers.get('content-type')).toContain(
|
|
151
|
-
'application/json',
|
|
152
|
-
)
|
|
153
|
-
} else if (res.status === 500) {
|
|
154
|
-
expect(res.headers.get('content-type')).toContain(
|
|
155
|
-
'text/plain',
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it('should return app data in standalone mode when daemon is disabled', async () => {
|
|
161
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
162
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
163
|
-
// Dashboard endpoints now provide standalone data when daemon is disabled
|
|
164
|
-
if (res.status === 200) {
|
|
165
|
-
expect(res.headers.get('content-type')).toContain(
|
|
166
|
-
'application/json',
|
|
167
|
-
)
|
|
168
|
-
const data = await res.json()
|
|
169
|
-
expect(data.packages).toBeDefined()
|
|
170
|
-
expect(data.stats).toBeDefined()
|
|
171
|
-
} else if (res.status === 500) {
|
|
172
|
-
expect(res.headers.get('content-type')).toContain(
|
|
173
|
-
'text/plain',
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
it('should return proper app data structure', async () => {
|
|
179
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
180
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
181
|
-
|
|
182
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
183
|
-
if (res.status === 500) return
|
|
184
|
-
const data = (await res.json()) as any
|
|
185
|
-
expect(data).toBeDefined()
|
|
186
|
-
expect(data.packages).toBeDefined()
|
|
187
|
-
expect(data.stats).toBeDefined()
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
it('should include packages array in response', async () => {
|
|
191
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
192
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
193
|
-
|
|
194
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
195
|
-
if (res.status === 500) return
|
|
196
|
-
const data = (await res.json()) as any
|
|
197
|
-
expect(Array.isArray(data.packages)).toBe(true)
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
it('should include statistics in response', async () => {
|
|
201
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
202
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
203
|
-
|
|
204
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
205
|
-
if (res.status === 500) return
|
|
206
|
-
const data = (await res.json()) as any
|
|
207
|
-
expect(data.stats).toBeDefined()
|
|
208
|
-
expect(typeof data.stats.totalPackages).toBe('number')
|
|
209
|
-
expect(typeof data.stats.totalDownloads).toBe('number')
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
it('should handle HEAD requests', async () => {
|
|
213
|
-
const res = await app.request(
|
|
214
|
-
'/app-data.json',
|
|
215
|
-
{ method: 'HEAD' },
|
|
216
|
-
env,
|
|
217
|
-
)
|
|
218
|
-
expect(
|
|
219
|
-
[200, 401, 404, 405, 500, 501].includes(res.status),
|
|
220
|
-
).toBe(true)
|
|
221
|
-
})
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
describe('App Data Package Information', () => {
|
|
225
|
-
it('should return packages with proper structure', async () => {
|
|
226
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
227
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
228
|
-
|
|
229
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
230
|
-
if (res.status === 500) return
|
|
231
|
-
|
|
232
|
-
const data = (await res.json()) as any
|
|
233
|
-
expect(Array.isArray(data.packages)).toBe(true)
|
|
234
|
-
|
|
235
|
-
// If packages exist, validate their structure
|
|
236
|
-
if (data.packages.length > 0) {
|
|
237
|
-
const pkg = data.packages[0]
|
|
238
|
-
expect(typeof pkg.name).toBe('string')
|
|
239
|
-
expect(typeof pkg.version).toBe('string')
|
|
240
|
-
// description is optional
|
|
241
|
-
if (pkg.description !== undefined) {
|
|
242
|
-
expect(typeof pkg.description).toBe('string')
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
it('should handle empty packages array', async () => {
|
|
248
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
249
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
250
|
-
|
|
251
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
252
|
-
if (res.status === 500) return
|
|
253
|
-
|
|
254
|
-
const data = (await res.json()) as any
|
|
255
|
-
expect(Array.isArray(data.packages)).toBe(true)
|
|
256
|
-
// Empty array is valid
|
|
257
|
-
expect(data.packages.length).toBeGreaterThanOrEqual(0)
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
it('should include valid package names', async () => {
|
|
261
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
262
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
263
|
-
|
|
264
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
265
|
-
if (res.status === 500) return
|
|
266
|
-
|
|
267
|
-
const data = (await res.json()) as any
|
|
268
|
-
data.packages.forEach((pkg: any) => {
|
|
269
|
-
expect(typeof pkg.name).toBe('string')
|
|
270
|
-
expect(pkg.name.length).toBeGreaterThan(0)
|
|
271
|
-
// Package names should follow npm naming conventions
|
|
272
|
-
expect(pkg.name).toMatch(
|
|
273
|
-
/^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$|^@[a-z0-9-]+\/[a-z0-9]([a-z0-9._-]*[a-z0-9])?$/,
|
|
274
|
-
)
|
|
275
|
-
})
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
it('should include valid semver versions', async () => {
|
|
279
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
280
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
281
|
-
|
|
282
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
283
|
-
if (res.status === 500) return
|
|
284
|
-
|
|
285
|
-
const data = (await res.json()) as any
|
|
286
|
-
data.packages.forEach((pkg: any) => {
|
|
287
|
-
expect(typeof pkg.version).toBe('string')
|
|
288
|
-
expect(pkg.version.length).toBeGreaterThan(0)
|
|
289
|
-
// Basic semver validation
|
|
290
|
-
expect(pkg.version).toMatch(/^\d+\.\d+\.\d+/)
|
|
291
|
-
})
|
|
292
|
-
})
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
describe('App Data Statistics', () => {
|
|
296
|
-
it('should return non-negative statistics', async () => {
|
|
297
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
298
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
299
|
-
|
|
300
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
301
|
-
if (res.status === 500) return
|
|
302
|
-
|
|
303
|
-
const data = (await res.json()) as any
|
|
304
|
-
expect(data.stats.totalPackages).toBeGreaterThanOrEqual(0)
|
|
305
|
-
expect(data.stats.totalDownloads).toBeGreaterThanOrEqual(0)
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
it('should return integer statistics', async () => {
|
|
309
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
310
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
311
|
-
|
|
312
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
313
|
-
if (res.status === 500) return
|
|
314
|
-
|
|
315
|
-
const data = (await res.json()) as any
|
|
316
|
-
expect(Number.isInteger(data.stats.totalPackages)).toBe(true)
|
|
317
|
-
expect(Number.isInteger(data.stats.totalDownloads)).toBe(true)
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
it('should have consistent package count', async () => {
|
|
321
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
322
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
323
|
-
|
|
324
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
325
|
-
if (res.status === 500) return
|
|
326
|
-
|
|
327
|
-
const data = (await res.json()) as any
|
|
328
|
-
// Total packages should match or be close to packages array length
|
|
329
|
-
// (might differ due to filtering, pagination, etc.)
|
|
330
|
-
expect(data.stats.totalPackages).toBeGreaterThanOrEqual(0)
|
|
331
|
-
expect(data.packages.length).toBeGreaterThanOrEqual(0)
|
|
332
|
-
})
|
|
333
|
-
})
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
describe('Dashboard Error Handling', () => {
|
|
337
|
-
describe('Daemon Disabled Responses', () => {
|
|
338
|
-
it('should return consistent data format in standalone mode', async () => {
|
|
339
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
340
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
341
|
-
|
|
342
|
-
if (res.status === 200) {
|
|
343
|
-
const data = (await res.json()) as any
|
|
344
|
-
expect(data).toBeDefined()
|
|
345
|
-
expect(data.registry).toBeDefined()
|
|
346
|
-
expect(data.features).toBeDefined()
|
|
347
|
-
} else if (res.status === 404) {
|
|
348
|
-
try {
|
|
349
|
-
const data = (await res.json()) as any
|
|
350
|
-
expect(data).toBeDefined()
|
|
351
|
-
expect(data.error).toBeDefined()
|
|
352
|
-
} catch {
|
|
353
|
-
// 500 responses may return text/plain instead of JSON
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
it('should return consistent data format for app-data in standalone mode', async () => {
|
|
359
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
360
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
361
|
-
|
|
362
|
-
if (res.status === 200) {
|
|
363
|
-
const data = (await res.json()) as any
|
|
364
|
-
expect(data).toBeDefined()
|
|
365
|
-
expect(data.packages).toBeDefined()
|
|
366
|
-
expect(data.stats).toBeDefined()
|
|
367
|
-
} else if (res.status === 404) {
|
|
368
|
-
try {
|
|
369
|
-
const data = (await res.json()) as any
|
|
370
|
-
expect(data).toBeDefined()
|
|
371
|
-
expect(data.error).toBeDefined()
|
|
372
|
-
} catch {
|
|
373
|
-
// 500 responses may return text/plain instead of JSON
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
})
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
describe('HTTP Method Validation', () => {
|
|
380
|
-
it('should handle POST requests to dashboard endpoints', async () => {
|
|
381
|
-
const res = await app.request(
|
|
382
|
-
'/dashboard.json',
|
|
383
|
-
{ method: 'POST' },
|
|
384
|
-
env,
|
|
385
|
-
)
|
|
386
|
-
expect(
|
|
387
|
-
[200, 401, 404, 405, 500, 501].includes(res.status),
|
|
388
|
-
).toBe(true)
|
|
389
|
-
})
|
|
390
|
-
|
|
391
|
-
it('should handle PUT requests to dashboard endpoints', async () => {
|
|
392
|
-
const res = await app.request(
|
|
393
|
-
'/app-data.json',
|
|
394
|
-
{ method: 'PUT' },
|
|
395
|
-
env,
|
|
396
|
-
)
|
|
397
|
-
expect(
|
|
398
|
-
[200, 401, 404, 405, 500, 501].includes(res.status),
|
|
399
|
-
).toBe(true)
|
|
400
|
-
})
|
|
401
|
-
|
|
402
|
-
it('should handle DELETE requests to dashboard endpoints', async () => {
|
|
403
|
-
const res = await app.request(
|
|
404
|
-
'/dashboard.json',
|
|
405
|
-
{ method: 'DELETE' },
|
|
406
|
-
env,
|
|
407
|
-
)
|
|
408
|
-
expect(
|
|
409
|
-
[200, 401, 404, 405, 500, 501].includes(res.status),
|
|
410
|
-
).toBe(true)
|
|
411
|
-
})
|
|
412
|
-
})
|
|
413
|
-
|
|
414
|
-
// Database error handling is now tested through real bindings in integration tests
|
|
415
|
-
})
|
|
416
|
-
|
|
417
|
-
describe('Dashboard Response Headers', () => {
|
|
418
|
-
describe('Content-Type Headers', () => {
|
|
419
|
-
it('should set correct content-type for dashboard.json', async () => {
|
|
420
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
421
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
422
|
-
|
|
423
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
424
|
-
if (res.status === 500) return
|
|
425
|
-
// Dashboard endpoints may return 500 with text/plain when external services are unavailable
|
|
426
|
-
if (res.status === 200) {
|
|
427
|
-
expect(res.headers.get('content-type')).toContain(
|
|
428
|
-
'application/json',
|
|
429
|
-
)
|
|
430
|
-
} else if (res.status === 500) {
|
|
431
|
-
expect(res.headers.get('content-type')).toContain(
|
|
432
|
-
'text/plain',
|
|
433
|
-
)
|
|
434
|
-
}
|
|
435
|
-
})
|
|
436
|
-
|
|
437
|
-
it('should set correct content-type for app-data.json', async () => {
|
|
438
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
439
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
440
|
-
|
|
441
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
442
|
-
if (res.status === 500) return
|
|
443
|
-
// Dashboard endpoints may return 500 with text/plain when external services are unavailable
|
|
444
|
-
if (res.status === 200) {
|
|
445
|
-
expect(res.headers.get('content-type')).toContain(
|
|
446
|
-
'application/json',
|
|
447
|
-
)
|
|
448
|
-
} else if (res.status === 500) {
|
|
449
|
-
expect(res.headers.get('content-type')).toContain(
|
|
450
|
-
'text/plain',
|
|
451
|
-
)
|
|
452
|
-
}
|
|
453
|
-
})
|
|
454
|
-
|
|
455
|
-
it('should set correct content-type for responses', async () => {
|
|
456
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
457
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
458
|
-
// Dashboard endpoints now return data in standalone mode or errors
|
|
459
|
-
if (res.status === 200) {
|
|
460
|
-
expect(res.headers.get('content-type')).toContain(
|
|
461
|
-
'application/json',
|
|
462
|
-
)
|
|
463
|
-
} else if (res.status === 404) {
|
|
464
|
-
expect(res.headers.get('content-type')).toContain(
|
|
465
|
-
'application/json',
|
|
466
|
-
)
|
|
467
|
-
} else if (res.status === 500) {
|
|
468
|
-
expect(res.headers.get('content-type')).toContain(
|
|
469
|
-
'text/plain',
|
|
470
|
-
)
|
|
471
|
-
}
|
|
472
|
-
})
|
|
473
|
-
})
|
|
474
|
-
|
|
475
|
-
describe('Cache Control Headers', () => {
|
|
476
|
-
it('should set appropriate cache headers for dashboard data', async () => {
|
|
477
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
478
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
479
|
-
|
|
480
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
481
|
-
if (res.status === 500) return
|
|
482
|
-
// Cache headers would be validated based on implementation
|
|
483
|
-
// Dashboard data might be cached for short periods
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
it('should set appropriate cache headers for app data', async () => {
|
|
487
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
488
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
489
|
-
|
|
490
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
491
|
-
if (res.status === 500) return
|
|
492
|
-
// App data might have different caching strategy than dashboard config
|
|
493
|
-
})
|
|
494
|
-
})
|
|
495
|
-
|
|
496
|
-
describe('Security Headers', () => {
|
|
497
|
-
it('should include security headers in dashboard responses', async () => {
|
|
498
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
499
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
500
|
-
|
|
501
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
502
|
-
if (res.status === 500) return
|
|
503
|
-
// Security headers would be validated based on implementation
|
|
504
|
-
})
|
|
505
|
-
|
|
506
|
-
it('should include CORS headers for dashboard endpoints', async () => {
|
|
507
|
-
const res = await app.request(
|
|
508
|
-
'/app-data.json',
|
|
509
|
-
{
|
|
510
|
-
headers: {
|
|
511
|
-
Origin: 'https://example.com',
|
|
512
|
-
},
|
|
513
|
-
},
|
|
514
|
-
env,
|
|
515
|
-
)
|
|
516
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
517
|
-
|
|
518
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
519
|
-
if (res.status === 500) return
|
|
520
|
-
// CORS headers would be validated based on implementation
|
|
521
|
-
})
|
|
522
|
-
})
|
|
523
|
-
})
|
|
524
|
-
|
|
525
|
-
describe('Dashboard Performance', () => {
|
|
526
|
-
describe('Response Time', () => {
|
|
527
|
-
const factor = env.REAL_PLATFORM === 'win32' ? 10 : 1
|
|
528
|
-
it(`should respond quickly for dashboard data`, async () => {
|
|
529
|
-
const startTime = Date.now()
|
|
530
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
531
|
-
const endTime = Date.now()
|
|
532
|
-
|
|
533
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
534
|
-
|
|
535
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
536
|
-
if (res.status === 500) return
|
|
537
|
-
expect(endTime - startTime).toBeLessThan(factor * 1000) // 1 second
|
|
538
|
-
})
|
|
539
|
-
|
|
540
|
-
it(`should respond quickly for app data`, async () => {
|
|
541
|
-
const startTime = Date.now()
|
|
542
|
-
const res = await app.request('/app-data.json', {}, env)
|
|
543
|
-
const endTime = Date.now()
|
|
544
|
-
|
|
545
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
546
|
-
|
|
547
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
548
|
-
if (res.status === 500) return
|
|
549
|
-
expect(endTime - startTime).toBeLessThan(factor * 2000) // 2 seconds (might query database)
|
|
550
|
-
})
|
|
551
|
-
})
|
|
552
|
-
|
|
553
|
-
describe('Concurrent Requests', () => {
|
|
554
|
-
it('should handle concurrent dashboard requests', async () => {
|
|
555
|
-
const promises = [
|
|
556
|
-
app.request('/dashboard.json', {}, env),
|
|
557
|
-
app.request('/dashboard.json', {}, env),
|
|
558
|
-
app.request('/dashboard.json', {}, env),
|
|
559
|
-
]
|
|
560
|
-
|
|
561
|
-
const results = await Promise.all(promises)
|
|
562
|
-
results.forEach(res => {
|
|
563
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
564
|
-
|
|
565
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
566
|
-
if (res.status === 500) return
|
|
567
|
-
})
|
|
568
|
-
})
|
|
569
|
-
|
|
570
|
-
it('should handle concurrent app data requests', async () => {
|
|
571
|
-
const promises = [
|
|
572
|
-
app.request('/app-data.json', {}, env),
|
|
573
|
-
app.request('/app-data.json', {}, env),
|
|
574
|
-
app.request('/app-data.json', {}, env),
|
|
575
|
-
]
|
|
576
|
-
|
|
577
|
-
const results = await Promise.all(promises)
|
|
578
|
-
results.forEach(res => {
|
|
579
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
580
|
-
|
|
581
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
582
|
-
if (res.status === 500) return
|
|
583
|
-
})
|
|
584
|
-
})
|
|
585
|
-
|
|
586
|
-
it('should handle mixed dashboard endpoint requests', async () => {
|
|
587
|
-
const promises = [
|
|
588
|
-
app.request('/dashboard.json', {}, env),
|
|
589
|
-
app.request('/app-data.json', {}, env),
|
|
590
|
-
app.request('/dashboard.json', {}, env),
|
|
591
|
-
app.request('/app-data.json', {}, env),
|
|
592
|
-
]
|
|
593
|
-
|
|
594
|
-
const results = await Promise.all(promises)
|
|
595
|
-
results.forEach(res => {
|
|
596
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
597
|
-
|
|
598
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
599
|
-
if (res.status === 500) return
|
|
600
|
-
})
|
|
601
|
-
})
|
|
602
|
-
})
|
|
603
|
-
})
|
|
604
|
-
|
|
605
|
-
describe('Dashboard Integration', () => {
|
|
606
|
-
describe('Data Consistency', () => {
|
|
607
|
-
it('should return consistent data across multiple requests', async () => {
|
|
608
|
-
const res1 = await app.request('/dashboard.json', {}, env)
|
|
609
|
-
const res2 = await app.request('/dashboard.json', {}, env)
|
|
610
|
-
|
|
611
|
-
expect([200, 500].includes(res1.status)).toBe(true)
|
|
612
|
-
expect([200, 500].includes(res2.status)).toBe(true)
|
|
613
|
-
|
|
614
|
-
if (res1.status === 200 && res2.status === 200) {
|
|
615
|
-
const data1 = await res1.json()
|
|
616
|
-
const data2 = await res2.json()
|
|
617
|
-
|
|
618
|
-
// Configuration should be consistent
|
|
619
|
-
expect(data1.registry.name).toBe(data2.registry.name)
|
|
620
|
-
expect(data1.registry.url).toBe(data2.registry.url)
|
|
621
|
-
}
|
|
622
|
-
})
|
|
623
|
-
|
|
624
|
-
it('should return app data that matches dashboard configuration', async () => {
|
|
625
|
-
const dashboardRes = await app.request(
|
|
626
|
-
'/dashboard.json',
|
|
627
|
-
{},
|
|
628
|
-
env,
|
|
629
|
-
)
|
|
630
|
-
const appDataRes = await app.request(
|
|
631
|
-
'/app-data.json',
|
|
632
|
-
{},
|
|
633
|
-
env,
|
|
634
|
-
)
|
|
635
|
-
|
|
636
|
-
expect([200, 404, 500].includes(dashboardRes.status)).toBe(
|
|
637
|
-
true,
|
|
638
|
-
)
|
|
639
|
-
expect([200, 404, 500].includes(appDataRes.status)).toBe(true)
|
|
640
|
-
|
|
641
|
-
if (
|
|
642
|
-
dashboardRes.status === 200 &&
|
|
643
|
-
appDataRes.status === 200
|
|
644
|
-
) {
|
|
645
|
-
const dashboard = await dashboardRes.json()
|
|
646
|
-
const appData = await appDataRes.json()
|
|
647
|
-
|
|
648
|
-
// Both should be valid JSON objects
|
|
649
|
-
expect(typeof dashboard).toBe('object')
|
|
650
|
-
expect(typeof appData).toBe('object')
|
|
651
|
-
}
|
|
652
|
-
})
|
|
653
|
-
})
|
|
654
|
-
|
|
655
|
-
describe('Feature Flag Integration', () => {
|
|
656
|
-
it('should reflect search feature availability in dashboard', async () => {
|
|
657
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
658
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
659
|
-
|
|
660
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
661
|
-
if (res.status === 500) return
|
|
662
|
-
|
|
663
|
-
const data = (await res.json()) as any
|
|
664
|
-
expect(typeof data.features.search).toBe('boolean')
|
|
665
|
-
// Search feature flag should be consistent with actual search endpoint availability
|
|
666
|
-
})
|
|
667
|
-
|
|
668
|
-
it('should reflect publish feature availability in dashboard', async () => {
|
|
669
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
670
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
671
|
-
|
|
672
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
673
|
-
if (res.status === 500) return
|
|
674
|
-
|
|
675
|
-
const data = (await res.json()) as any
|
|
676
|
-
expect(typeof data.features.publish).toBe('boolean')
|
|
677
|
-
// Publish feature flag should be consistent with actual publish endpoint availability
|
|
678
|
-
})
|
|
679
|
-
|
|
680
|
-
it('should reflect access control feature availability in dashboard', async () => {
|
|
681
|
-
const res = await app.request('/dashboard.json', {}, env)
|
|
682
|
-
expect([200, 404, 500].includes(res.status)).toBe(true)
|
|
683
|
-
|
|
684
|
-
// Skip JSON parsing tests if endpoint returns 500 (external service unavailable)
|
|
685
|
-
if (res.status === 500) return
|
|
686
|
-
|
|
687
|
-
const data = (await res.json()) as any
|
|
688
|
-
expect(typeof data.features.access).toBe('boolean')
|
|
689
|
-
// Access feature flag should be consistent with actual access control endpoints
|
|
690
|
-
})
|
|
691
|
-
})
|
|
692
|
-
})
|
|
693
|
-
})
|