@@ -196,6 +196,72 @@ export function runTests(ctx) {
196196 expect ( res . status ) . toBe ( 200 )
197197 } )
198198
199+ it ( 'should maintain icns' , async ( ) => {
200+ const query = { w : ctx . w , q : 90 , url : '/test.icns' }
201+ const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , { } )
202+ expect ( res . status ) . toBe ( 200 )
203+ expect ( res . headers . get ( 'Content-Type' ) ) . toContain ( 'image/x-icns' )
204+ expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
205+ `public, max-age=0, must-revalidate`
206+ )
207+ expect ( res . headers . get ( 'Vary' ) ) . toBe ( 'Accept' )
208+ expect ( res . headers . get ( 'etag' ) ) . toBeTruthy ( )
209+ expect ( res . headers . get ( 'Content-Disposition' ) ) . toBe (
210+ `${ contentDispositionType } ; filename="test.icns"`
211+ )
212+ await expectWidth ( res , 256 )
213+ } )
214+
215+ it ( 'should maintain jxl' , async ( ) => {
216+ const query = { w : ctx . w , q : 90 , url : '/test.jxl' }
217+ const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , { } )
218+ expect ( res . status ) . toBe ( 200 )
219+ expect ( res . headers . get ( 'Content-Type' ) ) . toContain ( 'image/jxl' )
220+ expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
221+ `public, max-age=0, must-revalidate`
222+ )
223+ expect ( res . headers . get ( 'Vary' ) ) . toBe ( 'Accept' )
224+ expect ( res . headers . get ( 'etag' ) ) . toBeTruthy ( )
225+ expect ( res . headers . get ( 'Content-Disposition' ) ) . toBe (
226+ `${ contentDispositionType } ; filename="test.jxl"`
227+ )
228+ // JXL is a bypass type, served as-is without processing
229+ // [email protected] doesn't support JXL, so skip width check 230+ } )
231+
232+ it ( 'should maintain heic' , async ( ) => {
233+ const query = { w : ctx . w , q : 90 , url : '/test.heic' }
234+ const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , { } )
235+ expect ( res . status ) . toBe ( 200 )
236+ expect ( res . headers . get ( 'Content-Type' ) ) . toContain ( 'image/heic' )
237+ expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
238+ `public, max-age=0, must-revalidate`
239+ )
240+ expect ( res . headers . get ( 'Vary' ) ) . toBe ( 'Accept' )
241+ expect ( res . headers . get ( 'etag' ) ) . toBeTruthy ( )
242+ expect ( res . headers . get ( 'Content-Disposition' ) ) . toBe (
243+ `${ contentDispositionType } ; filename="test.heic"`
244+ )
245+ // HEIC is a bypass type, served as-is without processing
246+ // [email protected] doesn't support HEIC, so skip width check 247+ } )
248+
249+ it ( 'should maintain jp2' , async ( ) => {
250+ const query = { w : ctx . w , q : 90 , url : '/test.jp2' }
251+ const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , { } )
252+ expect ( res . status ) . toBe ( 200 )
253+ expect ( res . headers . get ( 'Content-Type' ) ) . toContain ( 'image/jp2' )
254+ expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
255+ `public, max-age=${ isDev ? 0 : minimumCacheTTL } , must-revalidate`
256+ )
257+ expect ( res . headers . get ( 'Vary' ) ) . toBe ( 'Accept' )
258+ expect ( res . headers . get ( 'etag' ) ) . toBeTruthy ( )
259+ expect ( res . headers . get ( 'Content-Disposition' ) ) . toBe (
260+ `${ contentDispositionType } ; filename="test.jp2"`
261+ )
262+ await expectWidth ( res , 1 )
263+ } )
264+
199265 it ( 'should maintain animated gif' , async ( ) => {
200266 const query = { w : ctx . w , q : 90 , url : '/animated.gif' }
201267 const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , { } )
@@ -295,7 +361,6 @@ export function runTests(ctx) {
295361 'utf8'
296362 )
297363 expect ( actual ) . toMatch ( expected )
298- expect ( ctx . nextOutput ) . not . toContain ( 'The requested resource' )
299364 } )
300365 } else {
301366 it ( 'should not allow vector svg' , async ( ) => {
@@ -312,7 +377,7 @@ export function runTests(ctx) {
312377 const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
313378 expect ( res . status ) . toBe ( 400 )
314379 expect ( await res . text ( ) ) . toContain (
315- "The requested resource isn't a valid image"
380+ '"url" parameter is valid but image type is not allowed'
316381 )
317382 } )
318383
@@ -322,7 +387,7 @@ export function runTests(ctx) {
322387 const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
323388 expect ( res . status ) . toBe ( 400 )
324389 expect ( await res . text ( ) ) . toContain (
325- "The requested resource isn't a valid image"
390+ '"url" parameter is valid but image type is not allowed'
326391 )
327392 } )
328393
@@ -337,14 +402,24 @@ export function runTests(ctx) {
337402 } )
338403 }
339404
405+ it ( 'should not allow pdf format' , async ( ) => {
406+ const query = { w : ctx . w , q : 90 , url : '/test.pdf' }
407+ const opts = { headers : { accept : 'image/webp' } }
408+ const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
409+ expect ( res . status ) . toBe ( 400 )
410+ expect ( await res . text ( ) ) . toContain (
411+ "The requested resource isn't a valid image"
412+ )
413+ } )
414+
340415 it ( 'should maintain ico format' , async ( ) => {
341416 const query = { w : ctx . w , q : 90 , url : `/test.ico` }
342417 const opts = { headers : { accept : 'image/webp' } }
343418 const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
344419 expect ( res . status ) . toBe ( 200 )
345420 expect ( res . headers . get ( 'Content-Type' ) ) . toContain ( 'image/x-icon' )
346421 expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
347- `public, max-age=${ isDev ? 0 : minimumCacheTTL } , must-revalidate`
422+ `public, max-age=0 , must-revalidate`
348423 )
349424 expect ( res . headers . get ( 'Vary' ) ) . toMatch ( / ^ A c c e p t ( , | $ ) / )
350425 expect ( res . headers . get ( 'etag' ) ) . toBeTruthy ( )
@@ -940,8 +1015,8 @@ export function runTests(ctx) {
9401015 const opts = { headers : { accept : 'image/webp' } }
9411016 const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
9421017 expect ( res . status ) . toBe ( 400 )
943- expect ( await res . text ( ) ) . toBe (
944- `Unable to optimize image and unable to fallback to upstream image`
1018+ expect ( await res . text ( ) ) . toContain (
1019+ "The requested resource isn't a valid image"
9451020 )
9461021 } )
9471022
@@ -1186,7 +1261,7 @@ export function runTests(ctx) {
11861261 expect ( res . status ) . toBe ( 200 )
11871262 expect ( res . headers . get ( 'Content-Type' ) ) . toBe ( 'image/bmp' )
11881263 expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
1189- `public, max-age=${ isDev ? 0 : minimumCacheTTL } , must-revalidate`
1264+ `public, max-age=0 , must-revalidate`
11901265 )
11911266 // bmp is compressible so will have accept-encoding set from
11921267 // compression
0 commit comments