-
Notifications
You must be signed in to change notification settings - Fork 26.9k
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
Loading UI Interferes with Puppeteer navigation #52265
Comments
A workaround for this with Puppeteer and Next.js would be to use the await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
page.click('a[href="/page"]'),
]);
await page.waitForSelector('h1:has-text("page")'); |
Adding onto what was said above from @ProchaLu you could set a timeout and maybe do a try catch so if selector is there do x if not then do y.
|
Another workaround would be to add a export default function RootLoading() {
return <h1 data-test-id="loading">Loading</h1>;
} This await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
clickElement.click(),
]);
await page.waitForFunction(() => {
const loadingElement = document.querySelector('[data-test-id="loading"]');
return !loadingElement;
}); This change ensures that the test moves on only when the loading part is no longer there. This should address the problem of the loading component staying visible when we don't want it to. |
I investigated the loading states in Next.js and found that loading state behavior differs in 3 ways in earlier versions (I tested 13.4.9 because the reproduction repos were already at this version) vs In some cases, with previous Next.js versions before
To test the different behaviors, I created two reproduction projects (Next.js 13.4.9 reproduction, Next.js 13.4.20-canary.24 reproduction) using different Next.js versions with a loading state and a reproduction project without a loading state. I wrote a small Puppeteer test that goes to every page, checks if the loading state is visible, and waits for the network to be idle to see if this can cause an issue when the test runner thinks the page is already loaded. The reproduction projects contain:
Differences in loading state behavior in Next.js versions Behavior 1: Loading state not rendered when the network is pending
Behavior 2: Loading state is rendered when the network is idle
Behavior 3: Loading state behavior when visiting a page with server-side timeout
No loading state in Next.jsNetwork requests are consistently completed before the page changes Behavior 1: Loading state not rendered when the network is pendingNext.js
|
Solutions to the loading state issue with Next.js and PuppeteerThe loading state issue with Next.js and Puppeteer can be fixed by using a more robust way for a route change like OrKoN described in this comment. If you want to get into more detail, you can read my comment above. Solution 1:Use a more robust way for a route change, such as: function clickAndWaitForNavigation(page) {
await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
page.click('a[href="/login"]'),
]);
await page.waitForSelector('text/Welcome back, please login to your account');
} Solution 2:Use a export default function RootLoading() {
return <div data-test-id="loading">...Loading...</div>;
} Then, wait for the loading element to disappear in your test: await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
clickElement.click(),
]);
await page.waitForFunction(() => {
const loadingElement = document.querySelector('[data-test-id="loading"]');
return !loadingElement;
}); Solutions without using a loading stateWhen using no loading state in Next.js, you can use the Puppeteer function described in the docs. const [response] = await Promise.all([
page.waitForNavigation(waitOptions),
page.click(selector, clickOptions),
]); |
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Verify canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 22.1.0: Sun Oct 9 20:14:30 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T8103 Binaries: Node: 18.16.0 npm: 9.5.1 Yarn: 1.22.19 pnpm: 8.6.0 Relevant Packages: next: 13.4.9-canary.2 eslint-config-next: N/A react: 18.2.0 react-dom: 18.2.0 typescript: 5.1.3 Next.js Config: output: N/A
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true), Routing (next/router, next/navigation, next/link)
Link to the code that reproduces this issue or a replay of the bug
https://github.com/ProchaLu/next-route-puppeteer
To Reproduce
Describe the Bug
I have encountered an issue where the Next.js Loading component interferes with Puppeteer and the actual page loading process. Currently, Puppeteer considers the page as "done" when the Loading component is visible, causing a problem because Puppeteer waits for the network to become idle before proceeding.
To illustrate the problem, I have created a small Next.js app directory project with a Next.js Loading component that is visible for a short amount of time. The small project repository is deployed with vercel. Additionally, here is the Puppeteer test repository.
The problem seems to be that Next.js uses same-document navigation, causing the browser navigation to be resolved much earlier than the app-level navigation. Consequently, Puppeteer waits for the network to become idle, assuming the page has finished loading, while the actual app-level navigation and content loading are still in progress. This discrepancy causes issues between Puppeteer and the Next.js Loading component.
This issue is related to the problem described in the Puppeteer issue:
waitForNavigation()
not waiting for full page visibility in Next.js app puppeteer/puppeteer#10447Expected Behavior
The expected behavior is for Puppeteer to accurately determine the readiness of the page, ensuring that it waits until the actual content is fully loaded before proceeding with the test. Ideally, there should be a seamless synchronization between Puppeteer's network idle state and the completion of the app-level navigation in Next.js. This improvement would prevent Puppeteer from misinterpreting the page readiness when the Next.js Loading component is displayed, resulting in consistent and reliable test execution.
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
Vercel
The text was updated successfully, but these errors were encountered: