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 flaky onLoad() test for next/image/future #37993

Merged
merged 3 commits into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/api-reference/next/future/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ The callback function will be called with one argument, an object with the follo
- [`naturalWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth)
- [`naturalHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight)

### onLoad

A callback function that is invoked when the image is loaded.

Note that the load event might occur before client-side hydration completes, so this callback might not be invoked in that case.

Instead, use [`onLoadingComplete`](#onloadingcomplete).

### onError

A callback function that is invoked if the image fails to load.
Expand Down
44 changes: 15 additions & 29 deletions test/integration/image-future/default/pages/on-load.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,70 @@ import { useState } from 'react'
import Image from 'next/future/image'

const Page = () => {
// Hoisted state to count each image load callback
const [idToCount, setIdToCount] = useState({})
const [clicked, setClicked] = useState(false)

const red =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO8ysv7HwAEngHwC+JqOgAAAABJRU5ErkJggg=='

return (
<div>
<h1>Test onLoad</h1>
<p>
This is the native onLoad which doesn't work as many places as
onLoadingComplete
</p>
<button id="toggle" onClick={() => setClicked(!clicked)}>
Toggle
</button>

<ImageWithMessage
id="1"
src="/test.jpg"
src={clicked ? '/test.jpg' : red}
width="128"
height="128"
idToCount={idToCount}
setIdToCount={setIdToCount}
/>

<ImageWithMessage
id="2"
src={require('../public/test.png')}
placeholder="blur"
idToCount={idToCount}
setIdToCount={setIdToCount}
src={clicked ? require('../public/test.png') : red}
placeholder={clicked ? 'blur' : 'empty'}
/>

<ImageWithMessage
id="3"
src="/test.svg"
src={clicked ? '/test.svg' : red}
width="1200"
height="1200"
idToCount={idToCount}
setIdToCount={setIdToCount}
/>

<ImageWithMessage
id="4"
src="/test.ico"
src={clicked ? '/test.ico' : red}
width={200}
height={200}
idToCount={idToCount}
setIdToCount={setIdToCount}
/>

<ImageWithMessage
id="5"
src={clicked ? '/foo/test-rect.jpg' : '/wide.png'}
src={clicked ? '/wide.png' : red}
width="500"
height="500"
idToCount={idToCount}
setIdToCount={setIdToCount}
/>

<button id="toggle" onClick={() => setClicked(!clicked)}>
Toggle
</button>
<div id="footer" />
</div>
)
}

function ImageWithMessage({ id, idToCount, setIdToCount, ...props }) {
function ImageWithMessage({ id, ...props }) {
const [msg, setMsg] = useState('[LOADING]')
return (
<>
<div className="wrap">
<Image
id={`img${id}`}
onLoad={(e) => {
let count = idToCount[id] || 0
count++
idToCount[id] = count
setIdToCount(idToCount)
const msg = `loaded ${count} ${e.target.id} with native onLoad`
setMsg(msg)
console.log(msg)
setMsg(`loaded ${e.target.id} with native onLoad`)
}}
{...props}
/>
Expand Down
58 changes: 21 additions & 37 deletions test/integration/image-future/default/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,48 +313,31 @@ function runTests(mode) {
it('should callback native onLoad in most cases', async () => {
let browser = await webdriver(appPort, '/on-load')

for (let i = 1; i < 6; i++) {
await browser.eval(
`document.getElementById("img${i}").scrollIntoView({behavior: "smooth"})`
)
await waitFor(100)
}
await browser.eval('document.getElementById("toggle").click()')

await check(
() => browser.eval(`document.getElementById("img1").currentSrc`),
/test(.*)jpg/
)
await check(
() => browser.eval(`document.getElementById("img2").currentSrc`),
/test(.*).png/
)
await check(
() => browser.eval(`document.getElementById("img3").currentSrc`),
/test\.svg/
)
await check(
() => browser.eval(`document.getElementById("img4").currentSrc`),
/test(.*)ico/
await browser.eval(
`document.getElementById("footer").scrollIntoView({behavior: "smooth"})`
)

await check(
() => browser.eval(`document.getElementById("msg1").textContent`),
'loaded 1 img1 with native onLoad'
'loaded img1 with native onLoad'
)
await check(
() => browser.eval(`document.getElementById("msg2").textContent`),
'loaded 1 img2 with native onLoad'
'loaded img2 with native onLoad'
)
await check(
() => browser.eval(`document.getElementById("msg3").textContent`),
'loaded 1 img3 with native onLoad'
'loaded img3 with native onLoad'
)
await check(
() => browser.eval(`document.getElementById("msg4").textContent`),
'loaded 1 img4 with native onLoad'
'loaded img4 with native onLoad'
)
await check(
() => browser.eval(`document.getElementById("msg5").textContent`),
'loaded 1 img5 with native onLoad'
'loaded img5 with native onLoad'
)
await check(
() =>
Expand All @@ -363,25 +346,26 @@ function runTests(mode) {
),
'future'
)

await check(
() => browser.eval(`document.getElementById("img5").currentSrc`),
/wide.png/
() => browser.eval(`document.getElementById("img1").currentSrc`),
/test(.*)jpg/
)
await browser.eval('document.getElementById("toggle").click()')
await check(
() => browser.eval(`document.getElementById("msg5").textContent`),
'loaded 2 img5 with native onLoad'
() => browser.eval(`document.getElementById("img2").currentSrc`),
/test(.*).png/
)
await check(
() =>
browser.eval(
`document.getElementById("img5").getAttribute("data-nimg")`
),
'future'
() => browser.eval(`document.getElementById("img3").currentSrc`),
/test\.svg/
)
await check(
() => browser.eval(`document.getElementById("img4").currentSrc`),
/test(.*)ico/
)
await check(
() => browser.eval(`document.getElementById("img5").currentSrc`),
/test-rect.jpg/
/wide.png/
)
})

Expand Down