1- import type { Response } from "@cloudflare/workers-types" ;
21import ezSpawn from "@jsdevtools/ez-spawn" ;
32import { simulation } from "@simulacrum/github-api-simulator" ;
43import fs from "node:fs/promises" ;
@@ -171,9 +170,15 @@ describe.sequential.each([
171170 expect ( shaBlob . size ) . toBeGreaterThan ( 0 ) ;
172171
173172 // Test download with ref matches SHA content
174- const refResponse = await fetchWithRedirect (
173+ const refResponse = await worker . fetch (
175174 `/${ owner } /${ repo } /playground-a@${ ref } ` ,
176175 ) ;
176+ expect ( refResponse . status ) . toBe ( 200 ) ;
177+ expect ( refResponse . headers . get ( "x-pkg-name-key" ) ) . toBe ( "playground-a" ) ;
178+ expect ( refResponse . headers . get ( "x-commit-key" ) ) . toBe (
179+ `${ owner } :${ repo } :${ fullSha } ` ,
180+ ) ;
181+
177182 const refBlob = await refResponse . blob ( ) ;
178183 const shaBlobSize = await shaBlob . arrayBuffer ( ) ;
179184 const refBlobSize = await refBlob . arrayBuffer ( ) ;
@@ -197,6 +202,29 @@ describe.sequential.each([
197202 ) ;
198203 } , 20_000 ) ;
199204
205+ it ( `returns metadata for HEAD requests (${ mode } )` , async ( ) => {
206+ const [ owner , repo ] = payload . repository . full_name . split ( "/" ) ;
207+ const fullSha = pr ? payload . workflow_run . head_sha : gitRevParse ;
208+ const sha = fullSha . substring ( 0 , 7 ) ;
209+
210+ const headResponse = await worker . fetch (
211+ `/${ owner } /${ repo } /playground-a@${ sha } ` ,
212+ { method : "HEAD" } ,
213+ ) ;
214+
215+ expect ( headResponse . status ) . toBe ( 200 ) ;
216+ expect ( headResponse . headers . get ( "x-pkg-name-key" ) ) . toBe ( "playground-a" ) ;
217+ expect ( headResponse . headers . get ( "x-commit-key" ) ) . toBe (
218+ `${ owner } :${ repo } :${ sha } ` ,
219+ ) ;
220+ expect ( headResponse . headers . get ( "content-type" ) ) . toBe (
221+ "application/tar+gzip" ,
222+ ) ;
223+ expect ( headResponse . headers . get ( "etag" ) ) . toBeDefined ( ) ;
224+ const lastModified = headResponse . headers . get ( "last-modified" ) ;
225+ expect ( new Date ( lastModified ! ) . toString ( ) ) . not . toBe ( "Invalid Date" ) ;
226+ } ) ;
227+
200228 it ( `serves and installs playground-b for ${ mode } ` , async ( ) => {
201229 const [ owner , repo ] = payload . repository . full_name . split ( "/" ) ;
202230 const fullSha = pr ? payload . workflow_run . head_sha : gitRevParse ;
@@ -231,48 +259,57 @@ describe.sequential.each([
231259 } , 20_000 ) ;
232260} ) ;
233261
234- describe ( "URL redirects " , ( ) => {
262+ describe ( "URL resolution " , ( ) => {
235263 describe ( "standard packages" , ( ) => {
236- it ( "redirects full URLs correctly" , async ( ) => {
237- const response = await fetchWithRedirect ( "/tinylibs/tinybench@a832a55" ) ;
238- expect ( response . url ) . toContain ( "/tinylibs/tinybench/tinybench@a832a55" ) ;
264+ it . each ( [
265+ [ "full" , "/tinylibs/tinybench/tinybench@a832a55" ] ,
266+ [ "compact" , "/tinybench@a832a55" ] ,
267+ [ "with .tgz extension" , "/tinybench@a832a55.tgz" ] ,
268+ ] ) ( "resolves %s URLs" , async ( _ , url ) => {
269+ const response = await worker . fetch ( url ) ;
270+
271+ expect ( response . headers . get ( "x-commit-key" ) ) . toBe (
272+ "tinylibs:tinybench:a832a55" ,
273+ ) ;
274+ expect ( response . headers . get ( "x-pkg-name-key" ) ) . toBe ( "tinybench" ) ;
239275 } ) ;
240276
241- it ( "redirects compact URLs correctly" , async ( ) => {
242- const response = await fetchWithRedirect ( "/tinybench@a832a55" ) ;
243- expect ( response . url ) . toContain ( "/tinylibs/tinybench/tinybench@a832a55" ) ;
277+ it ( "resolves URL with full Git SHA" , async ( ) => {
278+ const response = await worker . fetch (
279+ "/tinylibs/tinybench/tinybench@a832a55e8f50c419ed8414024899e37e69b1f999" ,
280+ ) ;
281+
282+ expect ( response . headers . get ( "x-pkg-name-key" ) ) . toBe ( "tinybench" ) ;
283+ expect ( response . headers . get ( "x-commit-key" ) ) . toBe (
284+ "tinylibs:tinybench:a832a55e8f50c419ed8414024899e37e69b1f999" ,
285+ ) ;
244286 } ) ;
245287 } ) ;
246288
247289 describe ( "scoped packages" , ( ) => {
248- const expectedPath = `/stackblitz/sdk/${ encodeURIComponent ( "@stackblitz/sdk" ) } @a832a55` ;
290+ it . each ( [
291+ [ "full" , "/stackblitz/sdk/@stackblitz/sdk@a832a55" ] ,
292+ [ "encoded" , "/stackblitz/sdk/%40stackblitz%2Fsdk@a832a55" ] ,
293+ [ "compact" , "/@stackblitz/sdk@a832a55" ] ,
294+ [ "compact encoded" , "/%40stackblitz%2Fsdk@a832a55" ] ,
295+ ] ) ( "resolves %s URLs" , async ( _ , url ) => {
296+ const response = await worker . fetch ( url ) ;
249297
250- it ( "redirects full scoped package URLs correctly" , async ( ) => {
251- const response = await fetchWithRedirect (
252- "/ stackblitz/ sdk/@stackblitz/sdk@ a832a55" ,
298+ expect ( response . headers . get ( "x-pkg-name-key" ) ) . toBe ( "@stackblitz:sdk" ) ;
299+ expect ( response . headers . get ( "x-commit-key" ) ) . toBe (
300+ "stackblitz: sdk: a832a55" ,
253301 ) ;
254- expect ( response . url ) . toContain ( expectedPath ) ;
255302 } ) ;
256303
257- it ( "redirects compact scoped package URLs correctly" , async ( ) => {
258- const response = await fetchWithRedirect ( "/@stackblitz/sdk@a832a55" ) ;
259- expect ( response . url ) . toContain ( expectedPath ) ;
304+ it ( "resolves URL with full Git SHA" , async ( ) => {
305+ const response = await worker . fetch (
306+ "/stackblitz/sdk/@stackblitz/sdk@a832a55e8f50c419ed8414024899e37e69b1f999" ,
307+ ) ;
308+
309+ expect ( response . headers . get ( "x-pkg-name-key" ) ) . toBe ( "@stackblitz:sdk" ) ;
310+ expect ( response . headers . get ( "x-commit-key" ) ) . toBe (
311+ "stackblitz:sdk:a832a55e8f50c419ed8414024899e37e69b1f999" ,
312+ ) ;
260313 } ) ;
261314 } ) ;
262315} ) ;
263-
264- async function fetchWithRedirect (
265- url : string ,
266- maxRedirects = 999 ,
267- ) : Promise < Response > {
268- const response = await worker . fetch ( url , { redirect : "manual" } ) ;
269-
270- if ( response . status >= 300 && response . status < 400 && maxRedirects > 0 ) {
271- const location = response . headers . get ( "location" ) ;
272- if ( location ) {
273- return fetchWithRedirect ( location , maxRedirects - 1 ) ;
274- }
275- }
276-
277- return response as unknown as Response ;
278- }
0 commit comments