Skip to content

Commit

Permalink
feat(gatsby-plugin-sharp): create image sizes helper (#27554)
Browse files Browse the repository at this point in the history
* wip tests and tweaks to utility

* more wip tests

* remove file reading from helper

* fixing fluid calculations and adding more tests

* tweak a little more

* remove extraneous export

* check that user specified dimensions are positive

* remove unnecessary code from review suggestions

* add warning, simplify case of no fluid dimensions

* add files to warnings and clean up logic

* Split into two functions and remove 3x default

* Rename warn function and use reporter

Co-authored-by: Matt Kane <matt@gatsbyjs.com>
  • Loading branch information
gillkyle and ascorbic committed Oct 20, 2020
1 parent 48ffac8 commit 99d5c77
Show file tree
Hide file tree
Showing 2 changed files with 378 additions and 63 deletions.
238 changes: 238 additions & 0 deletions packages/gatsby-plugin-sharp/src/__tests__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ jest.mock(`gatsby-cli/lib/reporter`)
jest.mock(`progress`)
const {
createGatsbyProgressOrFallbackToExternalProgressBar,
calculateImageSizes,
} = require(`../utils`)
const reporter = require(`gatsby-cli/lib/reporter`)
const progress = require(`progress`)
Expand Down Expand Up @@ -39,3 +40,240 @@ describe(`createGatsbyProgressOrFallbackToExternalProgressBar`, () => {
expect(bar).toHaveProperty(`total`)
})
})

const file = {
absolutePath: `~/Usr/gatsby-sites/src/img/photo.png`,
}
const imgDimensions = {
width: 1200,
height: 800,
}

describe(`calculateImageSizes (fixed)`, () => {
it(`should throw if width is less than 1`, () => {
const args = {
layout: `fixed`,
width: 0,
file,
imgDimensions,
}
const getSizes = () => calculateImageSizes(args)
expect(getSizes).toThrow()
})

it(`should throw if height is less than 1`, () => {
const args = {
layout: `fixed`,
height: -50,
file,
imgDimensions,
}
const getSizes = () => calculateImageSizes(args)
expect(getSizes).toThrow()
})

it(`should warn if ignored maxWidth or maxHeight are passed in`, () => {
jest.spyOn(global.console, `warn`)
const args = {
layout: `fixed`,
height: 240,
maxWidth: 1000,
maxHeight: 1000,
file,
imgDimensions,
}
calculateImageSizes(args)
expect(console.warn).toBeCalled()
})

it(`should return the original width of the image when only width is provided`, () => {
const args = {
layout: `fixed`,
width: 600,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toContain(600)
})

it(`should return the original width of the image when only height is provided`, () => {
const args = {
layout: `fixed`,
height: 500,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toContain(500 * (imgDimensions.width / imgDimensions.height))
})

it(`should create images of different sizes based on pixel densities with a given width`, () => {
const args = {
layout: `fixed`,
width: 120,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([120, 240]))
})

it(`should create images of different sizes based on pixel densities with a given height`, () => {
const args = {
layout: `fixed`,
height: 80,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([120, 240]))
})
})

describe(`calculateImageSizes (fluid & constrained)`, () => {
it(`should throw if maxWidth is less than 1`, () => {
const args = {
layout: `fluid`,
maxWidth: 0,
file,
imgDimensions,
}
const getSizes = () => calculateImageSizes(args)
expect(getSizes).toThrow()
})

it(`should throw if maxHeight is less than 1`, () => {
const args = {
layout: `fluid`,
maxHeight: -50,
file,
imgDimensions,
}
const getSizes = () => calculateImageSizes(args)
expect(getSizes).toThrow()
})

it(`should warn if ignored width or height are passed in`, () => {
jest.spyOn(global.console, `warn`)
const args = {
layout: `fluid`,
maxWidth: 240,
height: 1000,
width: 1000,
file,
imgDimensions,
}
calculateImageSizes(args)
expect(console.warn).toBeCalled()
})

it(`should include the original size of the image when maxWidth is passed`, () => {
const args = {
layout: `fluid`,
maxWidth: 400,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toContain(400)
})

it(`should include the original size of the image when maxWidth is passed for a constrained image`, () => {
const args = {
layout: `constrained`,
maxWidth: 400,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toContain(400)
})

it(`should include the original size of the image when maxHeight is passed`, () => {
const args = {
layout: `fluid`,
maxHeight: 300,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toContain(450)
})

it(`should create images of different sizes (0.25x, 0.5x, 1x, 2x) from a maxWidth`, () => {
const args = {
layout: `fluid`,
maxWidth: 320,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([80, 160, 320, 640]))
})

it(`should create images of different sizes (0.25x, 0.5x, 1x) without any defined size provided`, () => {
const args = {
layout: `fluid`,
file,
imgDimensions,
}
const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([200, 400, 800]))
})

it(`should return sizes of provided srcSetBreakpoints`, () => {
const srcSetBreakpoints = [50, 70, 150, 250, 300]
const maxWidth = 500
const args = {
layout: `fluid`,
maxWidth,
srcSetBreakpoints,
file,
imgDimensions,
}

const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([50, 70, 150, 250, 300, 500]))
})

it(`should reject any srcSetBreakpoints larger than the original width`, () => {
const srcSetBreakpoints = [
50,
70,
150,
250,
1250, // shouldn't be included, larger than original width
]
const maxWidth = 1500 // also shouldn't be included
const args = {
layout: `fluid`,
maxWidth,
srcSetBreakpoints,
file,
imgDimensions,
}

const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([50, 70, 150, 250]))
expect(sizes).toEqual(expect.not.arrayContaining([1250, 1500]))
})

it(`should only uses sizes from srcSetBreakpoints when outputPixelDensities are also passed in`, () => {
jest.spyOn(global.console, `warn`)
const srcSetBreakpoints = [400, 800] // should find these
const maxWidth = 500
const args = {
layout: `fluid`,
maxWidth,
outputPixelDensities: [2, 4], // and ignore these, ie [1000, 2000]
srcSetBreakpoints,
file,
imgDimensions,
}

const sizes = calculateImageSizes(args)
expect(sizes).toEqual(expect.arrayContaining([400, 500, 800]))
expect(console.warn).toBeCalled()
})
})
Loading

0 comments on commit 99d5c77

Please sign in to comment.