next.js/test/unit/next-image-get-img-props.test.ts
next-image-get-img-props.test.ts1104 lines34.0 KB
/* eslint-env jest */
import { getImageProps } from 'next/image'

let deploymentId: string | undefined
let assetToken: string | undefined
jest.mock('next/dist/shared/lib/deployment-id.js', () => {
  return {
    __esModule: true,
    getDeploymentId() {
      return deploymentId
    },
    getDeploymentIdQuery(ampersand = false): string {
      let id = deploymentId
      if (id) {
        return `${ampersand ? '&' : '?'}dpl=${id}`
      }
      return ''
    },
    getAssetToken() {
      return assetToken
    },
    getAssetTokenQuery(ampersand = false) {
      let token = assetToken
      if (token) {
        return `${ampersand ? '&' : '?'}at=${token}`
      }
      return ''
    },
  }
})

describe('getImageProps()', () => {
  let warningMessages: string[]
  const originalConsoleWarn = console.warn
  beforeEach(() => {
    warningMessages = []
    console.warn = (m: string) => {
      warningMessages.push(m)
    }
    deploymentId = undefined
  })

  afterEach(() => {
    console.warn = originalConsoleWarn
  })
  it('should return props in correct order', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
    })
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })

  it('should have correct type for props', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
    })

    expect(props.alt).toBeString()
    expect(props.id).toBeString()
    expect(props.loading).toBeString()

    expect(props.width).toBeNumber()
    expect(props.height).toBeNumber()

    expect(props.decoding).toBeString()
    expect(props.style).toBeObject()
    expect(props.style.color).toBeString()
    expect(props.src).toBeString()
    expect(props.srcSet).toBeString()
  })

  it('should handle preload', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      preload: true,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })

  it('should error when both priority and preload are used', async () => {
    expect(() =>
      getImageProps({
        alt: 'a nice desc',
        id: 'my-image',
        src: '/test.png',
        width: 100,
        height: 200,
        preload: true,
        priority: true,
      })
    ).toThrow(
      'Image with src "/test.png" has both "preload" and "priority" properties. Only "preload" should be used.'
    )
  })

  it('should handle priority', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      priority: true,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle fetchPriority', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      fetchPriority: 'high',
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['fetchPriority', 'high'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle quality coercion from 50 to 75', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      quality: 50,
    })
    expect(warningMessages).toStrictEqual([
      'Image with src "/test.png" is using quality "50" which is not configured in images.qualities [75]. Please update your config to [50, 75].\nRead more: https://nextjs.org/docs/messages/next-image-unconfigured-qualities',
    ])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle quality exact match config and not warn', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      quality: 75,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle quality as a string and not warn', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      quality: '75',
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle loading eager', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      loading: 'eager',
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'eager'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle 16px image', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 16,
      height: 16,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 16],
      ['height', 16],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      ['srcSet', '/_next/image?url=%2Ftest.png&w=32&q=75 1x'],
      ['src', '/_next/image?url=%2Ftest.png&w=32&q=75'],
    ])
  })
  it('should handle 32px image', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 32,
      height: 32,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 32],
      ['height', 32],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=32&q=75 1x, /_next/image?url=%2Ftest.png&w=64&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=64&q=75'],
    ])
  })
  it('should handle 256px image', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 256,
      height: 256,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 256],
      ['height', 256],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=256&q=75 1x, /_next/image?url=%2Ftest.png&w=640&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=640&q=75'],
    ])
  })
  it('should handle 512px image', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 512,
      height: 512,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 512],
      ['height', 512],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=640&q=75 1x, /_next/image?url=%2Ftest.png&w=1080&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=1080&q=75'],
    ])
  })
  it('should handle 3072px image', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 3072,
      height: 3072,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 3072],
      ['height', 3072],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      ['srcSet', '/_next/image?url=%2Ftest.png&w=3840&q=75 1x'],
      ['src', '/_next/image?url=%2Ftest.png&w=3840&q=75'],
    ])
  })
  it('should handle sizes', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      sizes: '100vw',
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      ['sizes', '100vw'],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=640&q=75 640w, /_next/image?url=%2Ftest.png&w=750&q=75 750w, /_next/image?url=%2Ftest.png&w=828&q=75 828w, /_next/image?url=%2Ftest.png&w=1080&q=75 1080w, /_next/image?url=%2Ftest.png&w=1200&q=75 1200w, /_next/image?url=%2Ftest.png&w=1920&q=75 1920w, /_next/image?url=%2Ftest.png&w=2048&q=75 2048w, /_next/image?url=%2Ftest.png&w=3840&q=75 3840w',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=3840&q=75'],
    ])
  })
  it('should handle fill', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      fill: true,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['decoding', 'async'],
      [
        'style',
        {
          bottom: 0,
          color: 'transparent',
          height: '100%',
          left: 0,
          objectFit: undefined,
          objectPosition: undefined,
          position: 'absolute',
          right: 0,
          top: 0,
          width: '100%',
        },
      ],
      ['sizes', '100vw'],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=640&q=75 640w, /_next/image?url=%2Ftest.png&w=750&q=75 750w, /_next/image?url=%2Ftest.png&w=828&q=75 828w, /_next/image?url=%2Ftest.png&w=1080&q=75 1080w, /_next/image?url=%2Ftest.png&w=1200&q=75 1200w, /_next/image?url=%2Ftest.png&w=1920&q=75 1920w, /_next/image?url=%2Ftest.png&w=2048&q=75 2048w, /_next/image?url=%2Ftest.png&w=3840&q=75 3840w',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=3840&q=75'],
    ])
  })
  it('should handle style', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      style: { maxWidth: '100%', height: 'auto' },
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent', maxWidth: '100%', height: 'auto' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should handle loader', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      id: 'my-image',
      src: '/test.png',
      width: 100,
      height: 200,
      loader: ({ src, width, quality }) =>
        `https://example.com${src}?w=${width}&q=${quality || 75}`,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['id', 'my-image'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        'https://example.com/test.png?w=128&q=75 1x, https://example.com/test.png?w=256&q=75 2x',
      ],
      ['src', 'https://example.com/test.png?w=256&q=75'],
    ])
  })
  it('should handle arbitrary props', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      src: '/test.png',
      width: 100,
      height: 200,
      // @ts-ignore - testing arbitrary props
      foo: true,
      bar: 42,
      baz: 'str',
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['foo', true],
      ['bar', 42],
      ['baz', 'str'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should override src', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      src: '/test.png',
      overrideSrc: '/override.png',
      width: 100,
      height: 200,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/override.png'],
    ])
  })
  it('should handle decoding=sync', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      src: '/test.png',
      decoding: 'sync',
      width: 100,
      height: 200,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'sync'],
      ['style', { color: 'transparent' }],
      [
        'srcSet',
        '/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
      ],
      ['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
    ])
  })
  it('should auto unoptimized for relative svg', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      src: '/test.svg',
      width: 100,
      height: 200,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      ['src', '/test.svg'],
    ])
  })
  it('should auto unoptimized for absolute svg', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      src: 'https://example.com/test.svg',
      width: 100,
      height: 200,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      ['src', 'https://example.com/test.svg'],
    ])
  })
  it('should auto unoptimized for absolute svg with query', async () => {
    const { props } = getImageProps({
      alt: 'a nice desc',
      src: 'https://example.com/test.svg?v=1',
      width: 100,
      height: 200,
    })
    expect(warningMessages).toStrictEqual([])
    expect(Object.entries(props)).toStrictEqual([
      ['alt', 'a nice desc'],
      ['loading', 'lazy'],
      ['width', 100],
      ['height', 200],
      ['decoding', 'async'],
      ['style', { color: 'transparent' }],
      ['src', 'https://example.com/test.svg?v=1'],
    ])
  })
  it('should add query string for imported local image when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/_next/static/media/test.abc123.png',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=128&q=75&dpl=dpl_123 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_123 2x',
        ],
        [
          'src',
          '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_123',
        ],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string for imported local immutable image when assetToken is set', async () => {
    try {
      deploymentId = 'dpl_123'
      assetToken = 'dpl_789'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/_next/static/immutable/media/test.abc123.png',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2F_next%2Fstatic%2Fimmutable%2Fmedia%2Ftest.abc123.png&w=128&q=75&dpl=dpl_123 1x, /_next/image?url=%2F_next%2Fstatic%2Fimmutable%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_123 2x',
        ],
        [
          'src',
          '/_next/image?url=%2F_next%2Fstatic%2Fimmutable%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_123',
        ],
      ])
    } finally {
      assetToken = undefined
      deploymentId = undefined
    }
  })
  it('should not add query string for imported local immutable image when assetToken is empty', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/_next/static/immutable/media/test.abc123.png',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2F_next%2Fstatic%2Fimmutable%2Fmedia%2Ftest.abc123.png&w=128&q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fimmutable%2Fmedia%2Ftest.abc123.png&w=256&q=75 2x',
        ],
        [
          'src',
          '/_next/image?url=%2F_next%2Fstatic%2Fimmutable%2Fmedia%2Ftest.abc123.png&w=256&q=75',
        ],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should respect query string for imported local image when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/_next/static/media/test.abc123.png?dpl=dpl_existing',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=128&q=75&dpl=dpl_existing 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_existing 2x',
        ],
        [
          'src',
          '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_existing',
        ],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string for imported local image from microfrontend when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/microfrontend/_next/static/media/test.abc123.png', // simulating microfrontend path
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2Fmicrofrontend%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=128&q=75&dpl=dpl_123 1x, /_next/image?url=%2Fmicrofrontend%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_123 2x',
        ],
        [
          'src',
          '/_next/image?url=%2Fmicrofrontend%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_123',
        ],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should respect existing query string for imported local image from microfrontend when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/microfrontend/_next/static/media/test.abc123.png?dpl=dpl_existing', // simulating microfrontend path
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2Fmicrofrontend%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=128&q=75&dpl=dpl_existing 1x, /_next/image?url=%2Fmicrofrontend%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_existing 2x',
        ],
        [
          'src',
          '/_next/image?url=%2Fmicrofrontend%2F_next%2Fstatic%2Fmedia%2Ftest.abc123.png&w=256&q=75&dpl=dpl_existing',
        ],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string for imported local image with unicode when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const src = '/_next/static/media/äöüščří.3f1a293b.png'
      const srcEncoded = encodeURIComponent(src)
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: src,
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          `/_next/image?url=${srcEncoded}&w=128&q=75&dpl=dpl_123 1x, /_next/image?url=${srcEncoded}&w=256&q=75&dpl=dpl_123 2x`,
        ],
        ['src', `/_next/image?url=${srcEncoded}&w=256&q=75&dpl=dpl_123`],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should respect query string for imported local image with unicode when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const src = '/_next/static/media/äöüščří.3f1a293b.png'
      const srcEncoded = encodeURIComponent(src)
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: `${src}?dpl=dpl_existing`,
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          `/_next/image?url=${srcEncoded}&w=128&q=75&dpl=dpl_existing 1x, /_next/image?url=${srcEncoded}&w=256&q=75&dpl=dpl_existing 2x`,
        ],
        ['src', `/_next/image?url=${srcEncoded}&w=256&q=75&dpl=dpl_existing`],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string for relative local image when deployment id defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/test.png',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=%2Ftest.png&w=128&q=75&dpl=dpl_123 1x, /_next/image?url=%2Ftest.png&w=256&q=75&dpl=dpl_123 2x',
        ],
        ['src', '/_next/image?url=%2Ftest.png&w=256&q=75&dpl=dpl_123'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should not add query string for absolute remote image when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: 'http://example.com/test.png',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        [
          'srcSet',
          '/_next/image?url=http%3A%2F%2Fexample.com%2Ftest.png&w=128&q=75 1x, /_next/image?url=http%3A%2F%2Fexample.com%2Ftest.png&w=256&q=75 2x',
        ],
        [
          'src',
          '/_next/image?url=http%3A%2F%2Fexample.com%2Ftest.png&w=256&q=75',
        ],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string with question mark for unoptimized relative svg when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/test.svg',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', '/test.svg?dpl=dpl_123'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string with question mark for unoptimized relative svg with unicode when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/äöüščří.svg',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', '/äöüščří.svg?dpl=dpl_123'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should add query string with ampersand for unoptimized relative svg when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/test.svg?v=1',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', '/test.svg?v=1&dpl=dpl_123'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should not add query string for unoptimized absolute remote svg when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: 'http://example.com/test.svg',
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', 'http://example.com/test.svg'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should not add query string for unoptimized with no protocol when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '//example.com/test.png',
        unoptimized: true,
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', '//example.com/test.png'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should respect existing query string for unoptimized relative image when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: '/_next/static/media/test.abc123.png?dpl=dpl_existing',
        unoptimized: true,
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', '/_next/static/media/test.abc123.png?dpl=dpl_existing'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
  it('should respect existing query string for unoptimized relative image with unicode when deployment id is defined', async () => {
    try {
      deploymentId = 'dpl_123'
      const { props } = getImageProps({
        alt: 'a nice desc',
        src: `/_next/static/media/äöüščří.3f1a293b.png?dpl=dpl_existing`,
        unoptimized: true,
        width: 100,
        height: 200,
      })
      expect(warningMessages).toStrictEqual([])
      expect(Object.entries(props)).toStrictEqual([
        ['alt', 'a nice desc'],
        ['loading', 'lazy'],
        ['width', 100],
        ['height', 200],
        ['decoding', 'async'],
        ['style', { color: 'transparent' }],
        ['src', '/_next/static/media/äöüščří.3f1a293b.png?dpl=dpl_existing'],
      ])
    } finally {
      deploymentId = undefined
    }
  })
})
Quest for Codev2.0.0
/
SIGN IN