@@ -196,6 +196,72 @@ export function runTests(ctx) {
196
196
expect ( res . status ) . toBe ( 200 )
197
197
} )
198
198
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
+
199
265
it ( 'should maintain animated gif' , async ( ) => {
200
266
const query = { w : ctx . w , q : 90 , url : '/animated.gif' }
201
267
const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , { } )
@@ -295,7 +361,6 @@ export function runTests(ctx) {
295
361
'utf8'
296
362
)
297
363
expect ( actual ) . toMatch ( expected )
298
- expect ( ctx . nextOutput ) . not . toContain ( 'The requested resource' )
299
364
} )
300
365
} else {
301
366
it ( 'should not allow vector svg' , async ( ) => {
@@ -312,7 +377,7 @@ export function runTests(ctx) {
312
377
const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
313
378
expect ( res . status ) . toBe ( 400 )
314
379
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'
316
381
)
317
382
} )
318
383
@@ -322,7 +387,7 @@ export function runTests(ctx) {
322
387
const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
323
388
expect ( res . status ) . toBe ( 400 )
324
389
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'
326
391
)
327
392
} )
328
393
@@ -337,14 +402,24 @@ export function runTests(ctx) {
337
402
} )
338
403
}
339
404
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
+
340
415
it ( 'should maintain ico format' , async ( ) => {
341
416
const query = { w : ctx . w , q : 90 , url : `/test.ico` }
342
417
const opts = { headers : { accept : 'image/webp' } }
343
418
const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
344
419
expect ( res . status ) . toBe ( 200 )
345
420
expect ( res . headers . get ( 'Content-Type' ) ) . toContain ( 'image/x-icon' )
346
421
expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
347
- `public, max-age=${ isDev ? 0 : minimumCacheTTL } , must-revalidate`
422
+ `public, max-age=0 , must-revalidate`
348
423
)
349
424
expect ( res . headers . get ( 'Vary' ) ) . toMatch ( / ^ A c c e p t ( , | $ ) / )
350
425
expect ( res . headers . get ( 'etag' ) ) . toBeTruthy ( )
@@ -940,8 +1015,8 @@ export function runTests(ctx) {
940
1015
const opts = { headers : { accept : 'image/webp' } }
941
1016
const res = await fetchViaHTTP ( ctx . appPort , '/_next/image' , query , opts )
942
1017
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"
945
1020
)
946
1021
} )
947
1022
@@ -1186,7 +1261,7 @@ export function runTests(ctx) {
1186
1261
expect ( res . status ) . toBe ( 200 )
1187
1262
expect ( res . headers . get ( 'Content-Type' ) ) . toBe ( 'image/bmp' )
1188
1263
expect ( res . headers . get ( 'Cache-Control' ) ) . toBe (
1189
- `public, max-age=${ isDev ? 0 : minimumCacheTTL } , must-revalidate`
1264
+ `public, max-age=0 , must-revalidate`
1190
1265
)
1191
1266
// bmp is compressible so will have accept-encoding set from
1192
1267
// compression
0 commit comments