@@ -56,11 +56,12 @@ function cachePathFor(iconUrl: string): string {
5656 return nodePath . join ( CACHE_ROOT , ...iconUrl . split ( '/' ) ) ;
5757}
5858
59- function makeFetchResponse ( body : ArrayBuffer | string , status = 200 , statusText = 'OK' ) : Response {
59+ function makeFetchResponse ( body : ArrayBuffer | string , status = 200 , statusText = 'OK' , contentType = 'image/webp' ) : Response {
6060 return {
6161 ok : status >= 200 && status < 300 ,
6262 status,
6363 statusText,
64+ headers : { get : ( name : string ) => ( name . toLowerCase ( ) === 'content-type' ? contentType : null ) } ,
6465 async arrayBuffer ( ) { return typeof body === 'string' ? new TextEncoder ( ) . encode ( body ) . buffer : body ; } ,
6566 } as unknown as Response ;
6667}
@@ -132,6 +133,14 @@ describe('GameImageProviderImpl', () => {
132133 expect ( mockFetch ) . toHaveBeenCalledTimes ( 1 ) ;
133134 } ) ;
134135
136+ test ( 'treats a 200 HTML SPA-fallback response as unreachable and falls through to CDN' , async ( ) => {
137+ await GameImageProviderImplementation . init ( ) ;
138+ mockFetch . mockResolvedValueOnce ( makeFetchResponse ( '<!doctype html>' , 200 , 'OK' , 'text/html' ) ) ;
139+
140+ const result = await GameImageProviderImplementation . resolve ( 'spa-game/spa-game-cover-360x480.webp' ) ;
141+ expect ( result . startsWith ( 'data:image/webp;base64,' ) ) . toBe ( true ) ;
142+ } ) ;
143+
135144 test ( 'returns disk-cached data URL when bundled is unreachable but cache exists' , async ( ) => {
136145 await GameImageProviderImplementation . init ( ) ;
137146 // Pre-seed cache.
@@ -148,20 +157,6 @@ describe('GameImageProviderImpl', () => {
148157 expect ( mockFetch ) . toHaveBeenCalledTimes ( 1 ) ;
149158 } ) ;
150159
151- test ( 'fetches from CDN, caches, and returns data URL on first cache miss' , async ( ) => {
152- await GameImageProviderImplementation . init ( ) ;
153- const cdnBody = new Uint8Array ( [ 0x52 , 0x49 , 0x46 , 0x46 ] ) . buffer ; // "RIFF"
154- mockFetch . mockResolvedValueOnce ( makeFetchResponse ( '' , 404 ) ) ; // bundled miss
155- mockFetch . mockResolvedValueOnce ( makeFetchResponse ( cdnBody , 200 ) ) ; // CDN hit
156-
157- const iconUrl = 'fresh-game/fresh-game-cover-360x480.webp' ;
158- const result = await GameImageProviderImplementation . resolve ( iconUrl ) ;
159-
160- expect ( result . startsWith ( 'data:image/webp;base64,' ) ) . toBe ( true ) ;
161- // Should now exist in cache.
162- expect ( await FsProvider . instance . exists ( cachePathFor ( 'fresh-game/fresh-game-cover-360x480.webp' ) ) ) . toBe ( true ) ;
163- } ) ;
164-
165160 test ( 'CDN 404 returns placeholder and does NOT increment failure counter' , async ( ) => {
166161 await GameImageProviderImplementation . init ( ) ;
167162 mockFetch . mockResolvedValueOnce ( makeFetchResponse ( '' , 404 ) ) ; // bundled miss
0 commit comments