Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(gatsby-plugin-image): fix image flickers #35226

Merged
merged 20 commits into from May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,6 +1,4 @@
// TODO: In https://github.com/gatsbyjs/gatsby/pull/35226 the skip needs to be removed

describe.skip(`Production build tests`, () => {
describe(`Production build tests`, () => {
it(`should remount when navigating to different template`, () => {
cy.visit(`/`).waitForRouteChange()

Expand Down
6 changes: 0 additions & 6 deletions packages/gatsby-plugin-image/gatsby-browser.js

This file was deleted.

7 changes: 3 additions & 4 deletions packages/gatsby-plugin-image/package.json
Expand Up @@ -6,9 +6,9 @@
"build:gatsby-node": "tsc --jsx react --downlevelIteration true --skipLibCheck true --esModuleInterop true --outDir dist/ src/gatsby-node.ts src/babel-plugin-parse-static-images.ts src/resolver-utils.ts src/types.d.ts -d --declarationDir dist/src",
"build:gatsby-ssr": "microbundle -i src/gatsby-ssr.tsx -f cjs -o ./[name].js --no-pkg-main --jsx React.createElement --no-compress --external=common-tags,react --no-sourcemap",
"build:server": "microbundle -f cjs,es --jsx React.createElement --define SERVER=true",
"build:browser": "microbundle -i src/index.browser.ts -f cjs,modern,es --jsx React.createElement -o dist/gatsby-image.browser --define SERVER=false",
"build:browser": "microbundle -i src/index.browser.ts -f cjs,modern --jsx React.createElement -o dist/gatsby-image.browser --define SERVER=false",
"prepare": "yarn build",
"watch": "run-p watch:*",
"watch": "npm-run-all -s clean -p watch:*",
"watch:gatsby-node": "yarn build:gatsby-node --watch",
"watch:gatsby-ssr": "yarn build:gatsby-ssr watch",
"watch:server": "yarn build:server --no-compress watch",
Expand All @@ -27,8 +27,7 @@
"esmodule": "dist/gatsby-image.modern.js",
"browser": {
"./dist/gatsby-image.js": "./dist/gatsby-image.browser.js",
"./dist/gatsby-image.module.js": "./dist/gatsby-image.browser.module.js",
"./dist/gatsby-image.modern.js": "./dist/gatsby-image.browser.modern.js"
"./dist/gatsby-image.module.js": "./dist/gatsby-image.browser.modern.js"
},
"files": [
"dist/*",
Expand Down
@@ -1,7 +1,6 @@
/**
* @jest-environment jsdom
*/

import React from "react"
import { render, waitFor } from "@testing-library/react"
import * as hooks from "../hooks"
Expand All @@ -15,7 +14,20 @@ jest.mock(
strs.join(``)
)

// test
let count = 0
function generateImage(): IGatsbyImageData {
return {
width: 100,
height: 100,
layout: `fullWidth`,
images: {
fallback: { src: `some-src-fallback-${count++}.jpg`, sizes: `192x192` },
},
placeholder: { sources: [] },

backgroundColor: `red`,
}
}

describe(`GatsbyImage browser`, () => {
let beforeHydrationContent: HTMLDivElement
Expand All @@ -27,18 +39,9 @@ describe(`GatsbyImage browser`, () => {
console.error = jest.fn()
global.SERVER = true
global.GATSBY___IMAGE = true
global.HAS_REACT_18 = false

GatsbyImage = require(`../gatsby-image.browser`).GatsbyImage
image = {
width: 100,
height: 100,
layout: `fullWidth`,
images: { fallback: { src: `some-src-fallback.jpg`, sizes: `192x192` } },
placeholder: { sources: [] },

backgroundColor: `red`,
}
image = generateImage()

beforeHydrationContent = document.createElement(`div`)
beforeHydrationContent.innerHTML = `
Expand Down Expand Up @@ -81,7 +84,6 @@ describe(`GatsbyImage browser`, () => {
jest.clearAllMocks()
global.SERVER = undefined
global.GATSBY___IMAGE = undefined
global.HAS_REACT_18 = undefined
process.env.NODE_ENV = `test`
})

Expand Down Expand Up @@ -141,13 +143,18 @@ describe(`GatsbyImage browser`, () => {
{ container: beforeHydrationContent, hydrate: true }
)

const placeholder = await waitFor(() =>
container.querySelector(`[data-placeholder-image=""]`)
const placeholder = await waitFor(
() =>
container.querySelector(`[data-placeholder-image=""]`) as HTMLElement
)
const mainImage = container.querySelector(`[data-main-image=""]`)
const mainImage = container.querySelector(
`[data-main-image=""]`
) as HTMLElement

expect(placeholder).toBeDefined()
expect(mainImage).toBeDefined()
expect(placeholder.style.opacity).toBe(`1`)
expect(mainImage.style.opacity).toBe(`0`)
})

it(`relies on native lazy loading when the SSR element exists and that the browser supports native lazy loading`, async () => {
Expand All @@ -157,11 +164,10 @@ describe(`GatsbyImage browser`, () => {
// In this scenario,
// hasSSRHtml is true and resolved through "beforeHydrationContent" and hydrate: true
;(hooks as any).hasNativeLazyLoadSupport = (): boolean => true
;(hooks as any).storeImageloaded = jest.fn()

const { container } = render(
<GatsbyImage
image={image}
image={generateImage()}
alt="Alt content"
onStartLoad={onStartLoadSpy}
onLoad={onLoadSpy}
Expand All @@ -175,53 +181,7 @@ describe(`GatsbyImage browser`, () => {

img?.dispatchEvent(new Event(`load`))

expect(onStartLoadSpy).toBeCalledWith({ wasCached: false })
expect(onStartLoadSpy).toBeCalledWith({ wasCached: true })
expect(onLoadSpy).toBeCalled()
expect(hooks.storeImageloaded).toBeCalledWith(
`{"fallback":{"src":"some-src-fallback.jpg","sizes":"192x192"}}`
)
})

it(`relies on intersection observer when the SSR element is not resolved`, async () => {
;(hooks as any).hasNativeLazyLoadSupport = (): boolean => true
const onStartLoadSpy = jest.fn()
let GatsbyImage
jest.isolateModules(() => {
GatsbyImage = require(`../gatsby-image.browser`).GatsbyImage
})

const { container } = render(
<GatsbyImage
image={image}
alt="Alt content"
onStartLoad={onStartLoadSpy}
/>
)

await waitFor(() => container.querySelector(`[data-main-image=""]`))

expect(onStartLoadSpy).toBeCalledWith({ wasCached: false })
})

it(`relies on intersection observer when browser does not support lazy loading`, async () => {
;(hooks as any).hasNativeLazyLoadSupport = (): boolean => false
const onStartLoadSpy = jest.fn()
let GatsbyImage
jest.isolateModules(() => {
GatsbyImage = require(`../gatsby-image.browser`).GatsbyImage
})

const { container } = render(
<GatsbyImage
image={image}
alt="Alt content"
onStartLoad={onStartLoadSpy}
/>,
{ container: beforeHydrationContent, hydrate: true }
)

await waitFor(() => container.querySelector(`[data-main-image=""]`))

expect(onStartLoadSpy).toBeCalledWith({ wasCached: false })
})
})