Repository: vercel/next.js
Pull request #79066: test: split error recovery HMR test into multiple files
Author: login: devjiwonchoi
Labels: name: created-by: Next.js team
description: PRs by the Next.js team.
name: locked
name: tests
Created: 2025-05-12T00:33:03Z | Merged: 2025-05-12T22:04:58Z

Split long-running error recovery hmr test to parallelize and reduce CI time.

Port of https://github.com/vercel/next.js/pull/73617, confirmed and synced changes https://github.com/vercel/next.js/pull/78198, https://github.com/vercel/next.js/pull/77892, https://github.com/vercel/next.js/pull/76299, https://github.com/vercel/next.js/pull/76290, and https://github.com/vercel/next.js/pull/75882.

x-ref: https://github.com/vercel/next.js/commits/canary/test/development/basic/hmr/error-recovery.test.ts


Diff:
diff --git a/test/development/basic/hmr/error-recovery-no-base-path-no-asset-prefix.test.ts b/test/development/basic/hmr/error-recovery-no-base-path-no-asset-prefix.test.ts
new file mode 100644
index 000000000000..337634c2cbe5
--- /dev/null
+++ b/test/development/basic/hmr/error-recovery-no-base-path-no-asset-prefix.test.ts
@@ -0,0 +1,7 @@
+import { runErrorRecoveryHmrTest } from './run-error-recovery-hmr-test.util'
+
+const nextConfig = { basePath: '', assetPrefix: '' }
+
+describe(`HMR - Error Recovery, nextConfig: ${JSON.stringify(nextConfig)}`, () => {
+  runErrorRecoveryHmrTest(nextConfig)
+})
diff --git a/test/development/basic/hmr/error-recovery-no-base-path-yes-asset-prefix.test.ts b/test/development/basic/hmr/error-recovery-no-base-path-yes-asset-prefix.test.ts
new file mode 100644
index 000000000000..f0ba03b132f4
--- /dev/null
+++ b/test/development/basic/hmr/error-recovery-no-base-path-yes-asset-prefix.test.ts
@@ -0,0 +1,7 @@
+import { runErrorRecoveryHmrTest } from './run-error-recovery-hmr-test.util'
+
+const nextConfig = { basePath: '', assetPrefix: '/asset-prefix' }
+
+describe(`HMR - Error Recovery, nextConfig: ${JSON.stringify(nextConfig)}`, () => {
+  runErrorRecoveryHmrTest(nextConfig)
+})
diff --git a/test/development/basic/hmr/error-recovery-yes-base-path-no-asset-prefix.test.ts b/test/development/basic/hmr/error-recovery-yes-base-path-no-asset-prefix.test.ts
new file mode 100644
index 000000000000..2a566068e84b
--- /dev/null
+++ b/test/development/basic/hmr/error-recovery-yes-base-path-no-asset-prefix.test.ts
@@ -0,0 +1,7 @@
+import { runErrorRecoveryHmrTest } from './run-error-recovery-hmr-test.util'
+
+const nextConfig = { basePath: '/docs', assetPrefix: '' }
+
+describe(`HMR - Error Recovery, nextConfig: ${JSON.stringify(nextConfig)}`, () => {
+  runErrorRecoveryHmrTest(nextConfig)
+})
diff --git a/test/development/basic/hmr/error-recovery-yes-base-path-yes-asset-prefix.test.ts b/test/development/basic/hmr/error-recovery-yes-base-path-yes-asset-prefix.test.ts
new file mode 100644
index 000000000000..a5d6ea966b0a
--- /dev/null
+++ b/test/development/basic/hmr/error-recovery-yes-base-path-yes-asset-prefix.test.ts
@@ -0,0 +1,7 @@
+import { runErrorRecoveryHmrTest } from './run-error-recovery-hmr-test.util'
+
+const nextConfig = { basePath: '/docs', assetPrefix: '/asset-prefix' }
+
+describe(`HMR - Error Recovery, nextConfig: ${JSON.stringify(nextConfig)}`, () => {
+  runErrorRecoveryHmrTest(nextConfig)
+})
diff --git a/test/development/basic/hmr/error-recovery.test.ts b/test/development/basic/hmr/error-recovery.test.ts
deleted file mode 100644
index 60262d46a7f7..000000000000
--- a/test/development/basic/hmr/error-recovery.test.ts
+++ /dev/null
@@ -1,842 +0,0 @@
-import type { NextConfig } from 'next'
-import { join } from 'path'
-import {
-  assertHasRedbox,
-  assertNoRedbox,
-  getBrowserBodyText,
-  getRedboxHeader,
-  getRedboxDescription,
-  getRedboxSource,
-  renderViaHTTP,
-  retry,
-  waitFor,
-  trimEndMultiline,
-} from 'next-test-utils'
-import { nextTestSetup } from 'e2e-utils'
-import { outdent } from 'outdent'
-
-describe.each([
-  { basePath: '', assetPrefix: '' },
-  { basePath: '', assetPrefix: '/asset-prefix' },
-  { basePath: '/docs', assetPrefix: '' },
-  { basePath: '/docs', assetPrefix: '/asset-prefix' },
-])(
-  'HMR - Error Recovery, nextConfig: %o',
-  (nextConfig: Partial<NextConfig>) => {
-    const { next } = nextTestSetup({
-      files: __dirname,
-      nextConfig,
-      patchFileDelay: 500,
-    })
-    const { basePath } = nextConfig
-
-    it('should recover from 404 after a page has been added', async () => {
-      const newPage = join('pages', 'hmr', 'new-page.js')
-
-      try {
-        const browser = await next.browser(basePath + '/hmr/new-page')
-
-        expect(await browser.elementByCss('body').text()).toMatch(
-          /This page could not be found/
-        )
-
-        // Add the page
-        await next.patchFile(
-          newPage,
-          'export default () => (<div id="new-page">the-new-page</div>)'
-        )
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(/the-new-page/)
-        })
-
-        await next.deleteFile(newPage)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This page could not be found/
-          )
-        })
-
-        expect(next.cliOutput).toContain('Compiled /_error')
-      } catch (err) {
-        await next.deleteFile(newPage)
-        throw err
-      }
-    })
-
-    it('should recover from 404 after a page has been added with dynamic segments', async () => {
-      const newPage = join('pages', 'hmr', '[foo]', 'page.js')
-
-      try {
-        const browser = await next.browser(basePath + '/hmr/foo/page')
-
-        expect(await browser.elementByCss('body').text()).toMatch(
-          /This page could not be found/
-        )
-
-        // Add the page
-        await next.patchFile(
-          newPage,
-          'export default () => (<div id="new-page">the-new-page</div>)'
-        )
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(/the-new-page/)
-        })
-
-        await next.deleteFile(newPage)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This page could not be found/
-          )
-        })
-
-        expect(next.cliOutput).toContain('Compiled /_error')
-      } catch (err) {
-        await next.deleteFile(newPage)
-        throw err
-      }
-    })
-    ;(process.env.IS_TURBOPACK_TEST ? it.skip : it)(
-      // this test fails frequently with turbopack
-      'should not continously poll a custom error page',
-      async () => {
-        const errorPage = join('pages', '_error.js')
-
-        await next.patchFile(
-          errorPage,
-          outdent`
-          function Error({ statusCode, message, count }) {
-            return (
-              <div>
-                Error Message: {message}
-              </div>
-            )
-          }
-
-          Error.getInitialProps = async ({ res, err }) => {
-            const statusCode = res ? res.statusCode : err ? err.statusCode : 404
-            console.log('getInitialProps called');
-            return {
-              statusCode,
-              message: err ? err.message : 'Oops...',
-            }
-          }
-
-          export default Error
-        `
-        )
-
-        try {
-          // navigate to a 404 page
-          await next.browser(basePath + '/does-not-exist')
-
-          await retry(() => {
-            // eslint-disable-next-line jest/no-standalone-expect
-            expect(next.cliOutput).toMatch(/getInitialProps called/)
-          })
-
-          const outputIndex = next.cliOutput.length
-
-          // wait a few seconds to ensure polling didn't happen
-          await waitFor(3000)
-
-          const logOccurrences =
-            next.cliOutput.slice(outputIndex).split('getInitialProps called')
-              .length - 1
-          // eslint-disable-next-line jest/no-standalone-expect
-          expect(logOccurrences).toBe(0)
-        } finally {
-          await next.deleteFile(errorPage)
-        }
-      }
-    )
-
-    it('should detect syntax errors and recover', async () => {
-      const browser = await next.browser(basePath + '/hmr/about2')
-      const aboutPage = join('pages', 'hmr', 'about2.js')
-      const aboutContent = await next.readFile(aboutPage)
-      await retry(async () => {
-        expect(await getBrowserBodyText(browser)).toMatch(
-          /This is the about page/
-        )
-      })
-
-      await next.patchFile(aboutPage, aboutContent.replace('</div>', 'div'))
-
-      await assertHasRedbox(browser)
-      const source = next.normalizeTestDirContent(
-        await getRedboxSource(browser)
-      )
-
-      if (basePath === '' && process.env.IS_TURBOPACK_TEST) {
-        expect(source).toMatchInlineSnapshot(`
-         "./pages/hmr/about2.js (7:1)
-         Parsing ecmascript source code failed
-           5 |     div
-           6 |   )
-         > 7 | }
-             | ^
-           8 |
-
-         Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?"
-        `)
-      } else if (basePath === '' && process.env.NEXT_RSPACK) {
-        expect(trimEndMultiline(source)).toMatchInlineSnapshot(`
-         "./pages/hmr/about2.js
-           × Module build failed:
-           ├─▶   ×
-           │     │   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
-           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:1]
-           │     │  4 |       <p>This is the about page.</p>
-           │     │  5 |     div
-           │     │  6 |   )
-           │     │  7 | }
-           │     │    : ^
-           │     │    \`----
-           │     │
-           │     │   x Unexpected eof
-           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:3]
-           │     │  5 |     div
-           │     │  6 |   )
-           │     │  7 | }
-           │     │    \`----
-           │     │
-           │
-           ╰─▶ Syntax Error
-
-         Import trace for requested module:
-         ./pages/hmr/about2.js"
-        `)
-      } else if (basePath === '') {
-        expect(source).toMatchInlineSnapshot(`
-          "./pages/hmr/about2.js
-          Error:   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
-             ,-[7:1]
-           4 |       <p>This is the about page.</p>
-           5 |     div
-           6 |   )
-           7 | }
-             : ^
-             \`----
-            x Unexpected eof
-             ,-[7:3]
-           5 |     div
-           6 |   )
-           7 | }
-             \`----
-
-          Caused by:
-              Syntax Error
-
-          Import trace for requested module:
-          ./pages/hmr/about2.js"
-        `)
-      } else if (basePath === '/docs' && process.env.IS_TURBOPACK_TEST) {
-        expect(source).toMatchInlineSnapshot(`
-            "./pages/hmr/about2.js (7:1)
-            Parsing ecmascript source code failed
-              5 |     div
-              6 |   )
-            > 7 | }
-                | ^
-              8 |
-
-            Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?"
-          `)
-      } else if (basePath === '/docs' && process.env.NEXT_RSPACK) {
-        expect(trimEndMultiline(source)).toMatchInlineSnapshot(`
-         "./pages/hmr/about2.js
-           × Module build failed:
-           ├─▶   ×
-           │     │   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
-           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:1]
-           │     │  4 |       <p>This is the about page.</p>
-           │     │  5 |     div
-           │     │  6 |   )
-           │     │  7 | }
-           │     │    : ^
-           │     │    \`----
-           │     │
-           │     │   x Unexpected eof
-           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:3]
-           │     │  5 |     div
-           │     │  6 |   )
-           │     │  7 | }
-           │     │    \`----
-           │     │
-           │
-           ╰─▶ Syntax Error
-
-         Import trace for requested module:
-         ./pages/hmr/about2.js"
-        `)
-      } else if (basePath === '/docs') {
-        expect(source).toMatchInlineSnapshot(`
-          "./pages/hmr/about2.js
-          Error:   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
-             ,-[7:1]
-           4 |       <p>This is the about page.</p>
-           5 |     div
-           6 |   )
-           7 | }
-             : ^
-             \`----
-            x Unexpected eof
-             ,-[7:3]
-           5 |     div
-           6 |   )
-           7 | }
-             \`----
-
-          Caused by:
-              Syntax Error
-
-          Import trace for requested module:
-          ./pages/hmr/about2.js"
-        `)
-      }
-
-      await next.patchFile(aboutPage, aboutContent)
-
-      await retry(async () => {
-        expect(await getBrowserBodyText(browser)).toMatch(
-          /This is the about page/
-        )
-      })
-    })
-
-    if (!process.env.IS_TURBOPACK_TEST) {
-      // Turbopack doesn't have this restriction
-      it('should show the error on all pages', async () => {
-        const aboutPage = join('pages', 'hmr', 'about2.js')
-        const aboutContent = await next.readFile(aboutPage)
-        const browser = await next.browser(basePath + '/hmr/contact')
-        try {
-          await renderViaHTTP(next.url, basePath + '/hmr/about2')
-
-          await next.patchFile(aboutPage, aboutContent.replace('</div>', 'div'))
-
-          // Ensure dev server has time to break:
-          await new Promise((resolve) => setTimeout(resolve, 2000))
-
-          await assertHasRedbox(browser)
-          expect(await getRedboxSource(browser)).toMatch(/Unexpected eof/)
-
-          await next.patchFile(aboutPage, aboutContent)
-
-          await retry(async () => {
-            expect(await getBrowserBodyText(browser)).toMatch(
-              /This is the contact page/
-            )
-          })
-        } catch (err) {
-          await next.patchFile(aboutPage, aboutContent)
-          if (browser) {
-            await retry(async () => {
-              expect(await getBrowserBodyText(browser)).toMatch(
-                /This is the contact page/
-              )
-            })
-          }
-
-          throw err
-        }
-      })
-    }
-
-    it('should detect runtime errors on the module scope', async () => {
-      const browser = await next.browser(basePath + '/hmr/about3')
-      const aboutPage = join('pages', 'hmr', 'about3.js')
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace('export', 'aa=20;\nexport')
-        )
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxHeader(browser)).toMatch(/aa is not defined/)
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-      } finally {
-        await next.patchFile(aboutPage, aboutContent)
-      }
-    })
-
-    it('should recover from errors in the render function', async () => {
-      const browser = await next.browser(basePath + '/hmr/about4')
-      const aboutPage = join('pages', 'hmr', 'about4.js')
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace(
-            'return',
-            'throw new Error("an-expected-error");\nreturn'
-          )
-        )
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxSource(browser)).toMatch(/an-expected-error/)
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-      } catch (err) {
-        await next.patchFile(aboutPage, aboutContent)
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        throw err
-      }
-    })
-
-    it('should recover after exporting an invalid page', async () => {
-      const browser = await next.browser(basePath + '/hmr/about5')
-      const aboutPage = join('pages', 'hmr', 'about5.js')
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace(
-            'export default',
-            'export default {};\nexport const fn ='
-          )
-        )
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
-          `"The default export is not a React Component in page: "/hmr/about5""`
-        )
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-      } catch (err) {
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        throw err
-      }
-    })
-
-    it('should recover after a bad return from the render function', async () => {
-      const browser = await next.browser(basePath + '/hmr/about6')
-      const aboutPage = join('pages', 'hmr', 'about6.js')
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace(
-            'export default',
-            'export default () => /search/;\nexport const fn ='
-          )
-        )
-
-        await assertHasRedbox(browser)
-        // TODO: Replace this when webpack 5 is the default
-        expect(await getRedboxHeader(browser)).toMatch(
-          `Objects are not valid as a React child (found: [object RegExp]). If you meant to render a collection of children, use an array instead.`
-        )
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-      } catch (err) {
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        throw err
-      }
-    })
-
-    it('should recover after undefined exported as default', async () => {
-      const browser = await next.browser(basePath + '/hmr/about7')
-      const aboutPage = join('pages', 'hmr', 'about7.js')
-
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace(
-            'export default',
-            'export default undefined;\nexport const fn ='
-          )
-        )
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
-          `"The default export is not a React Component in page: "/hmr/about7""`
-        )
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-        await assertNoRedbox(browser)
-      } catch (err) {
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        throw err
-      }
-    })
-
-    it('should recover after webpack parse error in an imported file', async () => {
-      const browser = await next.browser(basePath + '/hmr/about8')
-      const aboutPage = join('pages', 'hmr', 'about8.js')
-
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace(
-            'export default',
-            'import "../../components/parse-error.xyz"\nexport default'
-          )
-        )
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxHeader(browser)).toMatch('Build Error')
-
-        if (process.env.IS_TURBOPACK_TEST) {
-          expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
-              "./components/parse-error.xyz
-              Unknown module type
-              This module doesn't have an associated type. Use a known file extension, or register a loader for it.
-
-              Read more: https://nextjs.org/docs/app/api-reference/next-config-js/turbo#webpack-loaders"
-            `)
-        } else if (process.env.NEXT_RSPACK) {
-          expect(trimEndMultiline(await getRedboxSource(browser)))
-            .toMatchInlineSnapshot(`
-           "./components/parse-error.xyz
-             × Module parse failed:
-             ╰─▶   × JavaScript parsing error: Expression expected
-                    ╭─[3:0]
-                  1 │ This
-                  2 │ is
-                  3 │ }}}
-                    · ─
-                  4 │ invalid
-                  5 │ js
-                    ╰────
-
-             help:
-                   You may need an appropriate loader to handle this file type.
-
-           Import trace for requested module:
-           ./components/parse-error.xyz
-           ./pages/hmr/about8.js"
-          `)
-        } else {
-          expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
-                      "./components/parse-error.xyz
-                      Module parse failed: Unexpected token (3:0)
-                      You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
-                      | This
-                      | is
-                      > }}}
-                      | invalid
-                      | js
-
-                      Import trace for requested module:
-                      ./components/parse-error.xyz
-                      ./pages/hmr/about8.js"
-                  `)
-        }
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-        await assertNoRedbox(browser)
-      } catch (err) {
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        throw err
-      }
-    })
-
-    it('should recover after loader parse error in an imported file', async () => {
-      const browser = await next.browser(basePath + '/hmr/about9')
-      const aboutPage = join('pages', 'hmr', 'about9.js')
-
-      const aboutContent = await next.readFile(aboutPage)
-      try {
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-
-        await next.patchFile(
-          aboutPage,
-          aboutContent.replace(
-            'export default',
-            'import "../../components/parse-error.js"\nexport default'
-          )
-        )
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxHeader(browser)).toMatch('Build Error')
-        let redboxSource = await getRedboxSource(browser)
-
-        redboxSource = redboxSource.replace(`${next.testDir}`, '.')
-        if (process.env.IS_TURBOPACK_TEST) {
-          expect(next.normalizeTestDirContent(redboxSource))
-            .toMatchInlineSnapshot(`
-           "./components/parse-error.js (3:1)
-           Parsing ecmascript source code failed
-             1 | This
-             2 | is
-           > 3 | }}}
-               | ^
-             4 | invalid
-             5 | js
-
-           Expression expected"
-          `)
-        } else if (process.env.NEXT_RSPACK) {
-          expect(trimEndMultiline(next.normalizeTestDirContent(redboxSource)))
-            .toMatchInlineSnapshot(`
-           "./components/parse-error.js
-             × Module build failed:
-             ├─▶   ×
-             │     │   x Expression expected
-             │     │    ,-[./components/parse-error.js:3:1]
-             │     │  1 | This
-             │     │  2 | is
-             │     │  3 | }}}
-             │     │    : ^
-             │     │  4 | invalid
-             │     │  5 | js
-             │     │    \`----
-             │     │
-             │
-             ╰─▶ Syntax Error
-
-           Import trace for requested module:
-           ./components/parse-error.js
-           ./pages/hmr/about9.js"
-          `)
-        } else {
-          redboxSource = redboxSource.substring(
-            0,
-            redboxSource.indexOf('`----')
-          )
-
-          expect(next.normalizeTestDirContent(redboxSource))
-            .toMatchInlineSnapshot(`
-            "./components/parse-error.js
-            Error:   x Expression expected
-               ,-[3:1]
-             1 | This
-             2 | is
-             3 | }}}
-               : ^
-             4 | invalid
-             5 | js
-               "
-          `)
-        }
-
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-        await assertNoRedbox(browser)
-      } catch (err) {
-        await next.patchFile(aboutPage, aboutContent)
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(
-            /This is the about page/
-          )
-        })
-      }
-    })
-
-    it('should recover from errors in getInitialProps in client', async () => {
-      const browser = await next.browser(basePath + '/hmr')
-      const erroredPage = join('pages', 'hmr', 'error-in-gip.js')
-      const errorContent = await next.readFile(erroredPage)
-      try {
-        await browser.elementByCss('#error-in-gip-link').click()
-
-        await assertHasRedbox(browser)
-        expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
-          `"an-expected-error-in-gip"`
-        )
-
-        await next.patchFile(
-          erroredPage,
-          errorContent.replace('throw error', 'return {}')
-        )
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(/Hello/)
-        })
-
-        await next.patchFile(erroredPage, errorContent)
-
-        await retry(async () => {
-          await browser.refresh()
-          await waitFor(2000)
-          const text = await getBrowserBodyText(browser)
-          if (text.includes('Hello')) {
-            throw new Error('waiting')
-          }
-          return expect(await getRedboxSource(browser)).toMatch(
-            /an-expected-error-in-gip/
-          )
-        })
-      } catch (err) {
-        await next.patchFile(erroredPage, errorContent)
-
-        throw err
-      }
-    })
-
-    it('should recover after an error reported via SSR', async () => {
-      const browser = await next.browser(basePath + '/hmr/error-in-gip')
-      const erroredPage = join('pages', 'hmr', 'error-in-gip.js')
-      const errorContent = await next.readFile(erroredPage)
-      try {
-        await assertHasRedbox(browser)
-        expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
-          `"an-expected-error-in-gip"`
-        )
-
-        const erroredPage = join('pages', 'hmr', 'error-in-gip.js')
-
-        await next.patchFile(
-          erroredPage,
-          errorContent.replace('throw error', 'return {}')
-        )
-
-        await retry(async () => {
-          expect(await getBrowserBodyText(browser)).toMatch(/Hello/)
-        })
-
-        await next.patchFile(erroredPage, errorContent)
-
-        await retry(async () => {
-          await browser.refresh()
-          await waitFor(2000)
-          const text = await getBrowserBodyText(browser)
-          if (text.includes('Hello')) {
-            throw new Error('waiting')
-          }
-          return expect(await getRedboxSource(browser)).toMatch(
-            /an-expected-error-in-gip/
-          )
-        })
-      } catch (err) {
-        await next.patchFile(erroredPage, errorContent)
-
-        throw err
-      }
-    })
-
-    if (!process.env.IS_TURBOPACK_TEST) {
-      it('should have client HMR events in trace file', async () => {
-        const traceData = await next.readFile('.next/trace')
-        expect(traceData).toContain('client-hmr-latency')
-        expect(traceData).toContain('client-error')
-        expect(traceData).toContain('client-success')
-        expect(traceData).toContain('client-full-reload')
-      })
-    }
-  }
-)
diff --git a/test/development/basic/hmr/run-error-recovery-hmr-test.util.ts b/test/development/basic/hmr/run-error-recovery-hmr-test.util.ts
new file mode 100644
index 000000000000..5498f9ba7315
--- /dev/null
+++ b/test/development/basic/hmr/run-error-recovery-hmr-test.util.ts
@@ -0,0 +1,831 @@
+import { join } from 'path'
+import {
+  assertHasRedbox,
+  assertNoRedbox,
+  getBrowserBodyText,
+  getRedboxHeader,
+  getRedboxDescription,
+  getRedboxSource,
+  renderViaHTTP,
+  retry,
+  waitFor,
+  trimEndMultiline,
+} from 'next-test-utils'
+import { nextTestSetup } from 'e2e-utils'
+import { outdent } from 'outdent'
+
+export function runErrorRecoveryHmrTest(nextConfig: {
+  basePath: string
+  assetPrefix: string
+}) {
+  const { next } = nextTestSetup({
+    files: __dirname,
+    nextConfig,
+    patchFileDelay: 500,
+  })
+  const { basePath } = nextConfig
+
+  it('should recover from 404 after a page has been added', async () => {
+    const newPage = join('pages', 'hmr', 'new-page.js')
+
+    try {
+      const browser = await next.browser(basePath + '/hmr/new-page')
+
+      expect(await browser.elementByCss('body').text()).toMatch(
+        /This page could not be found/
+      )
+
+      // Add the page
+      await next.patchFile(
+        newPage,
+        'export default () => (<div id="new-page">the-new-page</div>)'
+      )
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(/the-new-page/)
+      })
+
+      await next.deleteFile(newPage)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This page could not be found/
+        )
+      })
+
+      expect(next.cliOutput).toContain('Compiled /_error')
+    } catch (err) {
+      await next.deleteFile(newPage)
+      throw err
+    }
+  })
+
+  it('should recover from 404 after a page has been added with dynamic segments', async () => {
+    const newPage = join('pages', 'hmr', '[foo]', 'page.js')
+
+    try {
+      const browser = await next.browser(basePath + '/hmr/foo/page')
+
+      expect(await browser.elementByCss('body').text()).toMatch(
+        /This page could not be found/
+      )
+
+      // Add the page
+      await next.patchFile(
+        newPage,
+        'export default () => (<div id="new-page">the-new-page</div>)'
+      )
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(/the-new-page/)
+      })
+
+      await next.deleteFile(newPage)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This page could not be found/
+        )
+      })
+
+      expect(next.cliOutput).toContain('Compiled /_error')
+    } catch (err) {
+      await next.deleteFile(newPage)
+      throw err
+    }
+  })
+  ;(process.env.IS_TURBOPACK_TEST ? it.skip : it)(
+    // this test fails frequently with turbopack
+    'should not continously poll a custom error page',
+    async () => {
+      const errorPage = join('pages', '_error.js')
+
+      await next.patchFile(
+        errorPage,
+        outdent`
+          function Error({ statusCode, message, count }) {
+            return (
+              <div>
+                Error Message: {message}
+              </div>
+            )
+          }
+
+          Error.getInitialProps = async ({ res, err }) => {
+            const statusCode = res ? res.statusCode : err ? err.statusCode : 404
+            console.log('getInitialProps called');
+            return {
+              statusCode,
+              message: err ? err.message : 'Oops...',
+            }
+          }
+
+          export default Error
+        `
+      )
+
+      try {
+        // navigate to a 404 page
+        await next.browser(basePath + '/does-not-exist')
+
+        await retry(() => {
+          // eslint-disable-next-line jest/no-standalone-expect
+          expect(next.cliOutput).toMatch(/getInitialProps called/)
+        })
+
+        const outputIndex = next.cliOutput.length
+
+        // wait a few seconds to ensure polling didn't happen
+        await waitFor(3000)
+
+        const logOccurrences =
+          next.cliOutput.slice(outputIndex).split('getInitialProps called')
+            .length - 1
+        // eslint-disable-next-line jest/no-standalone-expect
+        expect(logOccurrences).toBe(0)
+      } finally {
+        await next.deleteFile(errorPage)
+      }
+    }
+  )
+
+  it('should detect syntax errors and recover', async () => {
+    const browser = await next.browser(basePath + '/hmr/about2')
+    const aboutPage = join('pages', 'hmr', 'about2.js')
+    const aboutContent = await next.readFile(aboutPage)
+    await retry(async () => {
+      expect(await getBrowserBodyText(browser)).toMatch(
+        /This is the about page/
+      )
+    })
+
+    await next.patchFile(aboutPage, aboutContent.replace('</div>', 'div'))
+
+    await assertHasRedbox(browser)
+    const source = next.normalizeTestDirContent(await getRedboxSource(browser))
+
+    if (basePath === '' && process.env.IS_TURBOPACK_TEST) {
+      expect(source).toMatchInlineSnapshot(`
+         "./pages/hmr/about2.js (7:1)
+         Parsing ecmascript source code failed
+           5 |     div
+           6 |   )
+         > 7 | }
+             | ^
+           8 |
+
+         Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?"
+        `)
+    } else if (basePath === '' && process.env.NEXT_RSPACK) {
+      expect(trimEndMultiline(source)).toMatchInlineSnapshot(`
+         "./pages/hmr/about2.js
+           × Module build failed:
+           ├─▶   ×
+           │     │   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
+           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:1]
+           │     │  4 |       <p>This is the about page.</p>
+           │     │  5 |     div
+           │     │  6 |   )
+           │     │  7 | }
+           │     │    : ^
+           │     │    \`----
+           │     │
+           │     │   x Unexpected eof
+           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:3]
+           │     │  5 |     div
+           │     │  6 |   )
+           │     │  7 | }
+           │     │    \`----
+           │     │
+           │
+           ╰─▶ Syntax Error
+
+         Import trace for requested module:
+         ./pages/hmr/about2.js"
+        `)
+    } else if (basePath === '') {
+      expect(source).toMatchInlineSnapshot(`
+          "./pages/hmr/about2.js
+          Error:   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
+             ,-[7:1]
+           4 |       <p>This is the about page.</p>
+           5 |     div
+           6 |   )
+           7 | }
+             : ^
+             \`----
+            x Unexpected eof
+             ,-[7:3]
+           5 |     div
+           6 |   )
+           7 | }
+             \`----
+
+          Caused by:
+              Syntax Error
+
+          Import trace for requested module:
+          ./pages/hmr/about2.js"
+        `)
+    } else if (basePath === '/docs' && process.env.IS_TURBOPACK_TEST) {
+      expect(source).toMatchInlineSnapshot(`
+            "./pages/hmr/about2.js (7:1)
+            Parsing ecmascript source code failed
+              5 |     div
+              6 |   )
+            > 7 | }
+                | ^
+              8 |
+
+            Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?"
+          `)
+    } else if (basePath === '/docs' && process.env.NEXT_RSPACK) {
+      expect(trimEndMultiline(source)).toMatchInlineSnapshot(`
+         "./pages/hmr/about2.js
+           × Module build failed:
+           ├─▶   ×
+           │     │   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
+           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:1]
+           │     │  4 |       <p>This is the about page.</p>
+           │     │  5 |     div
+           │     │  6 |   )
+           │     │  7 | }
+           │     │    : ^
+           │     │    \`----
+           │     │
+           │     │   x Unexpected eof
+           │     │    ,-[TEST_DIR/pages/hmr/about2.js:7:3]
+           │     │  5 |     div
+           │     │  6 |   )
+           │     │  7 | }
+           │     │    \`----
+           │     │
+           │
+           ╰─▶ Syntax Error
+
+         Import trace for requested module:
+         ./pages/hmr/about2.js"
+        `)
+    } else if (basePath === '/docs') {
+      expect(source).toMatchInlineSnapshot(`
+          "./pages/hmr/about2.js
+          Error:   x Unexpected token. Did you mean \`{'}'}\` or \`&rbrace;\`?
+             ,-[7:1]
+           4 |       <p>This is the about page.</p>
+           5 |     div
+           6 |   )
+           7 | }
+             : ^
+             \`----
+            x Unexpected eof
+             ,-[7:3]
+           5 |     div
+           6 |   )
+           7 | }
+             \`----
+
+          Caused by:
+              Syntax Error
+
+          Import trace for requested module:
+          ./pages/hmr/about2.js"
+        `)
+    }
+
+    await next.patchFile(aboutPage, aboutContent)
+
+    await retry(async () => {
+      expect(await getBrowserBodyText(browser)).toMatch(
+        /This is the about page/
+      )
+    })
+  })
+
+  if (!process.env.IS_TURBOPACK_TEST) {
+    // Turbopack doesn't have this restriction
+    it('should show the error on all pages', async () => {
+      const aboutPage = join('pages', 'hmr', 'about2.js')
+      const aboutContent = await next.readFile(aboutPage)
+      const browser = await next.browser(basePath + '/hmr/contact')
+      try {
+        await renderViaHTTP(next.url, basePath + '/hmr/about2')
+
+        await next.patchFile(aboutPage, aboutContent.replace('</div>', 'div'))
+
+        // Ensure dev server has time to break:
+        await new Promise((resolve) => setTimeout(resolve, 2000))
+
+        await assertHasRedbox(browser)
+        expect(await getRedboxSource(browser)).toMatch(/Unexpected eof/)
+
+        await next.patchFile(aboutPage, aboutContent)
+
+        await retry(async () => {
+          expect(await getBrowserBodyText(browser)).toMatch(
+            /This is the contact page/
+          )
+        })
+      } catch (err) {
+        await next.patchFile(aboutPage, aboutContent)
+        if (browser) {
+          await retry(async () => {
+            expect(await getBrowserBodyText(browser)).toMatch(
+              /This is the contact page/
+            )
+          })
+        }
+
+        throw err
+      }
+    })
+  }
+
+  it('should detect runtime errors on the module scope', async () => {
+    const browser = await next.browser(basePath + '/hmr/about3')
+    const aboutPage = join('pages', 'hmr', 'about3.js')
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace('export', 'aa=20;\nexport')
+      )
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxHeader(browser)).toMatch(/aa is not defined/)
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+    } finally {
+      await next.patchFile(aboutPage, aboutContent)
+    }
+  })
+
+  it('should recover from errors in the render function', async () => {
+    const browser = await next.browser(basePath + '/hmr/about4')
+    const aboutPage = join('pages', 'hmr', 'about4.js')
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace(
+          'return',
+          'throw new Error("an-expected-error");\nreturn'
+        )
+      )
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxSource(browser)).toMatch(/an-expected-error/)
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+    } catch (err) {
+      await next.patchFile(aboutPage, aboutContent)
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      throw err
+    }
+  })
+
+  it('should recover after exporting an invalid page', async () => {
+    const browser = await next.browser(basePath + '/hmr/about5')
+    const aboutPage = join('pages', 'hmr', 'about5.js')
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace(
+          'export default',
+          'export default {};\nexport const fn ='
+        )
+      )
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
+        `"The default export is not a React Component in page: "/hmr/about5""`
+      )
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+    } catch (err) {
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      throw err
+    }
+  })
+
+  it('should recover after a bad return from the render function', async () => {
+    const browser = await next.browser(basePath + '/hmr/about6')
+    const aboutPage = join('pages', 'hmr', 'about6.js')
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace(
+          'export default',
+          'export default () => /search/;\nexport const fn ='
+        )
+      )
+
+      await assertHasRedbox(browser)
+      // TODO: Replace this when webpack 5 is the default
+      expect(await getRedboxHeader(browser)).toMatch(
+        `Objects are not valid as a React child (found: [object RegExp]). If you meant to render a collection of children, use an array instead.`
+      )
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+    } catch (err) {
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      throw err
+    }
+  })
+
+  it('should recover after undefined exported as default', async () => {
+    const browser = await next.browser(basePath + '/hmr/about7')
+    const aboutPage = join('pages', 'hmr', 'about7.js')
+
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace(
+          'export default',
+          'export default undefined;\nexport const fn ='
+        )
+      )
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
+        `"The default export is not a React Component in page: "/hmr/about7""`
+      )
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+      await assertNoRedbox(browser)
+    } catch (err) {
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      throw err
+    }
+  })
+
+  it('should recover after webpack parse error in an imported file', async () => {
+    const browser = await next.browser(basePath + '/hmr/about8')
+    const aboutPage = join('pages', 'hmr', 'about8.js')
+
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace(
+          'export default',
+          'import "../../components/parse-error.xyz"\nexport default'
+        )
+      )
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxHeader(browser)).toMatch('Build Error')
+
+      if (process.env.IS_TURBOPACK_TEST) {
+        expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
+              "./components/parse-error.xyz
+              Unknown module type
+              This module doesn't have an associated type. Use a known file extension, or register a loader for it.
+
+              Read more: https://nextjs.org/docs/app/api-reference/next-config-js/turbo#webpack-loaders"
+            `)
+      } else if (process.env.NEXT_RSPACK) {
+        expect(trimEndMultiline(await getRedboxSource(browser)))
+          .toMatchInlineSnapshot(`
+           "./components/parse-error.xyz
+             × Module parse failed:
+             ╰─▶   × JavaScript parsing error: Expression expected
+                    ╭─[3:0]
+                  1 │ This
+                  2 │ is
+                  3 │ }}}
+                    · ─
+                  4 │ invalid
+                  5 │ js
+                    ╰────
+
+             help:
+                   You may need an appropriate loader to handle this file type.
+
+           Import trace for requested module:
+           ./components/parse-error.xyz
+           ./pages/hmr/about8.js"
+          `)
+      } else {
+        expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
+                      "./components/parse-error.xyz
+                      Module parse failed: Unexpected token (3:0)
+                      You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
+                      | This
+                      | is
+                      > }}}
+                      | invalid
+                      | js
+
+                      Import trace for requested module:
+                      ./components/parse-error.xyz
+                      ./pages/hmr/about8.js"
+                  `)
+      }
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+      await assertNoRedbox(browser)
+    } catch (err) {
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      throw err
+    }
+  })
+
+  it('should recover after loader parse error in an imported file', async () => {
+    const browser = await next.browser(basePath + '/hmr/about9')
+    const aboutPage = join('pages', 'hmr', 'about9.js')
+
+    const aboutContent = await next.readFile(aboutPage)
+    try {
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+
+      await next.patchFile(
+        aboutPage,
+        aboutContent.replace(
+          'export default',
+          'import "../../components/parse-error.js"\nexport default'
+        )
+      )
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxHeader(browser)).toMatch('Build Error')
+      let redboxSource = await getRedboxSource(browser)
+
+      redboxSource = redboxSource.replace(`${next.testDir}`, '.')
+      if (process.env.IS_TURBOPACK_TEST) {
+        expect(next.normalizeTestDirContent(redboxSource))
+          .toMatchInlineSnapshot(`
+           "./components/parse-error.js (3:1)
+           Parsing ecmascript source code failed
+             1 | This
+             2 | is
+           > 3 | }}}
+               | ^
+             4 | invalid
+             5 | js
+
+           Expression expected"
+          `)
+      } else if (process.env.NEXT_RSPACK) {
+        expect(trimEndMultiline(next.normalizeTestDirContent(redboxSource)))
+          .toMatchInlineSnapshot(`
+           "./components/parse-error.js
+             × Module build failed:
+             ├─▶   ×
+             │     │   x Expression expected
+             │     │    ,-[./components/parse-error.js:3:1]
+             │     │  1 | This
+             │     │  2 | is
+             │     │  3 | }}}
+             │     │    : ^
+             │     │  4 | invalid
+             │     │  5 | js
+             │     │    \`----
+             │     │
+             │
+             ╰─▶ Syntax Error
+
+           Import trace for requested module:
+           ./components/parse-error.js
+           ./pages/hmr/about9.js"
+          `)
+      } else {
+        redboxSource = redboxSource.substring(0, redboxSource.indexOf('`----'))
+
+        expect(next.normalizeTestDirContent(redboxSource))
+          .toMatchInlineSnapshot(`
+            "./components/parse-error.js
+            Error:   x Expression expected
+               ,-[3:1]
+             1 | This
+             2 | is
+             3 | }}}
+               : ^
+             4 | invalid
+             5 | js
+               "
+          `)
+      }
+
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+      await assertNoRedbox(browser)
+    } catch (err) {
+      await next.patchFile(aboutPage, aboutContent)
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(
+          /This is the about page/
+        )
+      })
+    }
+  })
+
+  it('should recover from errors in getInitialProps in client', async () => {
+    const browser = await next.browser(basePath + '/hmr')
+    const erroredPage = join('pages', 'hmr', 'error-in-gip.js')
+    const errorContent = await next.readFile(erroredPage)
+    try {
+      await browser.elementByCss('#error-in-gip-link').click()
+
+      await assertHasRedbox(browser)
+      expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
+        `"an-expected-error-in-gip"`
+      )
+
+      await next.patchFile(
+        erroredPage,
+        errorContent.replace('throw error', 'return {}')
+      )
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(/Hello/)
+      })
+
+      await next.patchFile(erroredPage, errorContent)
+
+      await retry(async () => {
+        await browser.refresh()
+        await waitFor(2000)
+        const text = await getBrowserBodyText(browser)
+        if (text.includes('Hello')) {
+          throw new Error('waiting')
+        }
+        return expect(await getRedboxSource(browser)).toMatch(
+          /an-expected-error-in-gip/
+        )
+      })
+    } catch (err) {
+      await next.patchFile(erroredPage, errorContent)
+
+      throw err
+    }
+  })
+
+  it('should recover after an error reported via SSR', async () => {
+    const browser = await next.browser(basePath + '/hmr/error-in-gip')
+    const erroredPage = join('pages', 'hmr', 'error-in-gip.js')
+    const errorContent = await next.readFile(erroredPage)
+    try {
+      await assertHasRedbox(browser)
+      expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
+        `"an-expected-error-in-gip"`
+      )
+
+      const erroredPage = join('pages', 'hmr', 'error-in-gip.js')
+
+      await next.patchFile(
+        erroredPage,
+        errorContent.replace('throw error', 'return {}')
+      )
+
+      await retry(async () => {
+        expect(await getBrowserBodyText(browser)).toMatch(/Hello/)
+      })
+
+      await next.patchFile(erroredPage, errorContent)
+
+      await retry(async () => {
+        await browser.refresh()
+        await waitFor(2000)
+        const text = await getBrowserBodyText(browser)
+        if (text.includes('Hello')) {
+          throw new Error('waiting')
+        }
+        return expect(await getRedboxSource(browser)).toMatch(
+          /an-expected-error-in-gip/
+        )
+      })
+    } catch (err) {
+      await next.patchFile(erroredPage, errorContent)
+
+      throw err
+    }
+  })
+
+  if (!process.env.IS_TURBOPACK_TEST) {
+    it('should have client HMR events in trace file', async () => {
+      const traceData = await next.readFile('.next/trace')
+      expect(traceData).toContain('client-hmr-latency')
+      expect(traceData).toContain('client-error')
+      expect(traceData).toContain('client-success')
+      expect(traceData).toContain('client-full-reload')
+    })
+  }
+}


Reviews:
user: login: ijjk
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-12T15:38:58Z
user: login: devjiwonchoi
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-12T18:16:11Z
user: login: ijjk
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-12T18:17:56Z

Review comments:
diff_hunk: @@ -0,0 +1,830 @@
+import { join } from 'path'
+import {
+  assertHasRedbox,
+  assertNoRedbox,
+  getBrowserBodyText,
+  getRedboxHeader,
+  getRedboxDescription,
+  getRedboxSource,
+  renderViaHTTP,
+  retry,
+  waitFor,
+  trimEndMultiline,
+} from 'next-test-utils'
+import { nextTestSetup } from 'e2e-utils'
+import { outdent } from 'outdent'
+
+const nextConfig = { basePath: '', assetPrefix: '' }
path: test/development/basic/hmr/error-recovery-no-base-path-no-asset-prefix.test.ts
user: login: ijjk
body: Same as https://github.com/vercel/next.js/pull/79067/files#r2084959470
created_at: 2025-05-12T15:38:57Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,830 @@
+import { join } from 'path'
+import {
+  assertHasRedbox,
+  assertNoRedbox,
+  getBrowserBodyText,
+  getRedboxHeader,
+  getRedboxDescription,
+  getRedboxSource,
+  renderViaHTTP,
+  retry,
+  waitFor,
+  trimEndMultiline,
+} from 'next-test-utils'
+import { nextTestSetup } from 'e2e-utils'
+import { outdent } from 'outdent'
+
+const nextConfig = { basePath: '', assetPrefix: '' }
path: test/development/basic/hmr/error-recovery-no-base-path-no-asset-prefix.test.ts
user: login: devjiwonchoi
body: Changed to `runTest` util
created_at: 2025-05-12T18:16:11Z
author_association: MEMBER

PR comments:
user: login: devjiwonchoi
created_at: 2025-05-12T00:33:16Z
body: * **#73624** <a href="https://app.graphite.dev/github/pr/vercel/next.js/73624?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#73625** <a href="https://app.graphite.dev/github/pr/vercel/next.js/73625?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#79067** <a href="https://app.graphite.dev/github/pr/vercel/next.js/79067?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#79066** <a href="https://app.graphite.dev/github/pr/vercel/next.js/79066?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a> 👈 <a href="https://app.graphite.dev/github/pr/vercel/next.js/79066?utm_source=stack-comment-view-in-graphite" target="_blank">(View in Graphite)</a>
* **#79065** <a href="https://app.graphite.dev/github/pr/vercel/next.js/79065?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#79064** <a href="https://app.graphite.dev/github/pr/vercel/next.js/79064?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* `canary`


<h2></h2>

This stack of pull requests is managed by <a href="https://graphite.dev?utm-source=stack-comment"><b>Graphite</b></a>. Learn more about <a href="https://stacking.dev/?utm_source=stack-comment">stacking</a>.
<!-- Current dependencies on/for this PR: -->
author_association: MEMBER
user: login: ijjk
created_at: 2025-05-12T00:44:09Z
body: # Stats from current PR

<details open>
<summary><strong>Default Build</strong> (Increase detected ⚠️)</summary>

<br/>

<details>
<summary><strong>General</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| buildDuration | 17.5s | 15.3s | N/A |
| buildDurationCached | 14.6s | 12.3s | N/A |
| nodeModulesSize | 418 MB | 418 MB | ✓ |
| nextStartRea..uration (ms) | 432ms | 425ms | N/A |

</details>

<details>
<summary><strong>Client Bundles (main, webpack)</strong> Overall increase ⚠️</summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| 1733-HASH.js gzip | 44.5 kB | 45 kB | ⚠️ +473 B |
| 194b18f3-HASH.js gzip | 53.8 kB | 53.8 kB | N/A |
| 2192.HASH.js gzip | 169 B | 169 B | ✓ |
| 4719-HASH.js gzip | 5.47 kB | 5.44 kB | N/A |
| framework-HASH.js gzip | 57.4 kB | 57.4 kB | ✓ |
| main-app-HASH.js gzip | 253 B | 256 B | N/A |
| main-HASH.js gzip | 33.5 kB | 33.6 kB | N/A |
| webpack-HASH.js gzip | 1.71 kB | 1.71 kB | N/A |
| Overall change | 102 kB | 103 kB | ⚠️ +473 B |

</details>

<details>
<summary><strong>Legacy Client Bundles (polyfills)</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| polyfills-HASH.js gzip | 39.4 kB | 39.4 kB | ✓ |
| Overall change | 39.4 kB | 39.4 kB | ✓ |

</details>

<details>
<summary><strong>Client Pages</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| _app-HASH.js gzip | 193 B | 193 B | ✓ |
| _error-HASH.js gzip | 192 B | 192 B | ✓ |
| amp-HASH.js gzip | 510 B | 510 B | ✓ |
| css-HASH.js gzip | 344 B | 342 B | N/A |
| dynamic-HASH.js gzip | 1.84 kB | 1.83 kB | N/A |
| edge-ssr-HASH.js gzip | 265 B | 265 B | ✓ |
| head-HASH.js gzip | 363 B | 364 B | N/A |
| hooks-HASH.js gzip | 392 B | 391 B | N/A |
| image-HASH.js gzip | 4.69 kB | 4.67 kB | N/A |
| index-HASH.js gzip | 267 B | 267 B | ✓ |
| link-HASH.js gzip | 2.53 kB | 2.53 kB | N/A |
| routerDirect..HASH.js gzip | 328 B | 325 B | N/A |
| script-HASH.js gzip | 396 B | 396 B | ✓ |
| withRouter-HASH.js gzip | 325 B | 325 B | ✓ |
| 1afbb74e6ecf..834.css gzip | 106 B | 106 B | ✓ |
| Overall change | 2.25 kB | 2.25 kB | ✓ |

</details>

<details>
<summary><strong>Client Build Manifests</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| _buildManifest.js gzip | 751 B | 750 B | N/A |
| Overall change | 0 B | 0 B | ✓ |

</details>

<details>
<summary><strong>Rendered Page Sizes</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| index.html gzip | 524 B | 523 B | N/A |
| link.html gzip | 538 B | 537 B | N/A |
| withRouter.html gzip | 520 B | 520 B | ✓ |
| Overall change | 520 B | 520 B | ✓ |

</details>

<details>
<summary><strong>Edge SSR bundle Size</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| edge-ssr.js gzip | 137 kB | 137 kB | N/A |
| page.js gzip | 219 kB | 214 kB | N/A |
| Overall change | 0 B | 0 B | ✓ |

</details>

<details>
<summary><strong>Middleware size</strong> Overall increase ⚠️</summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| middleware-b..fest.js gzip | 675 B | 675 B | ✓ |
| middleware-r..fest.js gzip | 155 B | 157 B | N/A |
| middleware.js gzip | 32.3 kB | 32.5 kB | ⚠️ +220 B |
| edge-runtime..pack.js gzip | 853 B | 853 B | ✓ |
| Overall change | 33.8 kB | 34 kB | ⚠️ +220 B |

</details>

<details>
<summary><strong>Next Runtimes</strong></summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| app-page-exp...dev.js gzip | 312 kB | 312 kB | ✓ |
| app-page-exp..prod.js gzip | 144 kB | 144 kB | ✓ |
| app-page-tur...dev.js gzip | 312 kB | 312 kB | ✓ |
| app-page-tur..prod.js gzip | 144 kB | 144 kB | ✓ |
| app-page-tur...dev.js gzip | 303 kB | 303 kB | ✓ |
| app-page-tur..prod.js gzip | 139 kB | 139 kB | ✓ |
| app-page.run...dev.js gzip | 303 kB | 303 kB | ✓ |
| app-page.run..prod.js gzip | 139 kB | 139 kB | ✓ |
| app-route-ex...dev.js gzip | 40.7 kB | 40.7 kB | ✓ |
| app-route-ex..prod.js gzip | 26.4 kB | 26.4 kB | ✓ |
| app-route-tu...dev.js gzip | 40.7 kB | 40.7 kB | ✓ |
| app-route-tu..prod.js gzip | 26.4 kB | 26.4 kB | ✓ |
| app-route-tu...dev.js gzip | 40.1 kB | 40.1 kB | ✓ |
| app-route-tu..prod.js gzip | 26.1 kB | 26.1 kB | ✓ |
| app-route.ru...dev.js gzip | 40.1 kB | 40.1 kB | ✓ |
| app-route.ru..prod.js gzip | 26.1 kB | 26.1 kB | ✓ |
| dist_client_...dev.js gzip | 332 B | 332 B | ✓ |
| dist_client_...dev.js gzip | 334 B | 334 B | ✓ |
| dist_client_...dev.js gzip | 326 B | 326 B | ✓ |
| dist_client_...dev.js gzip | 324 B | 324 B | ✓ |
| pages-api-tu...dev.js gzip | 11.6 kB | 11.6 kB | ✓ |
| pages-api-tu..prod.js gzip | 9.65 kB | 9.65 kB | ✓ |
| pages-api.ru...dev.js gzip | 11.6 kB | 11.6 kB | ✓ |
| pages-api.ru..prod.js gzip | 9.64 kB | 9.64 kB | ✓ |
| pages-turbo....dev.js gzip | 31 kB | 31 kB | ✓ |
| pages-turbo...prod.js gzip | 21.9 kB | 21.9 kB | ✓ |
| pages.runtim...dev.js gzip | 31.2 kB | 31.2 kB | ✓ |
| pages.runtim..prod.js gzip | 22 kB | 22 kB | ✓ |
| server.runti..prod.js gzip | 62.2 kB | 62.2 kB | ✓ |
| Overall change | 2.27 MB | 2.27 MB | ✓ |

</details>

<details>
<summary><strong>build cache</strong> Overall increase ⚠️</summary>

|  | vercel/next.js canary  | vercel/next.js jiwon/05-12-test_split_error_recovery_hmr_test_into_multiple_files | Change |
| - | - | - | - |
| 0.pack gzip | 2.19 MB | 2.19 MB | ⚠️ +3.59 kB |
| index.pack gzip | 77.7 kB | 77.4 kB | N/A |
| Overall change | 2.19 MB | 2.19 MB | ⚠️ +3.59 kB |

</details>

<details>
<summary><strong>Diff details</strong></summary>

<details>
<summary>Diff for <strong>page.js</strong></summary>

Diff too large to display
</details>
<details>
<summary>Diff for <strong>middleware.js</strong></summary>

Diff too large to display
</details>
<details>
<summary>Diff for <strong>edge-ssr.js</strong></summary>

```diff
failed to diff
```
</details>
<details>
<summary>Diff for <strong>css-HASH.js</strong></summary>

```diff
@@ -1,7 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9813],
   {
-    /***/ 1586: /***/ (
+    /***/ 2628: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/css",
         function () {
-          return __webpack_require__(4362);
+          return __webpack_require__(8707);
         },
       ]);
       if (false) {
@@ -18,14 +18,7 @@
       /***/
     },
 
-    /***/ 4350: /***/ (module) => {
-      // extracted by mini-css-extract-plugin
-      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
-
-      /***/
-    },
-
-    /***/ 4362: /***/ (
+    /***/ 8707: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -39,7 +32,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(5640);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(4350);
+        __webpack_require__(9080);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           _css_module_css__WEBPACK_IMPORTED_MODULE_1__
@@ -58,13 +51,20 @@
 
       /***/
     },
+
+    /***/ 9080: /***/ (module) => {
+      // extracted by mini-css-extract-plugin
+      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(1586)
+      __webpack_exec__(2628)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>dynamic-HASH.js</strong></summary>

```diff
@@ -1,17 +1,117 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2291],
   {
-    /***/ 283: /***/ (
+    /***/ 2001: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
+      __webpack_require__
+    ) => {
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
+        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
+        /* harmony export */
+      });
+      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
+        __webpack_require__(5640);
+      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
+        __webpack_require__(9553);
+      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
+        /*#__PURE__*/ __webpack_require__.n(
+          next_dynamic__WEBPACK_IMPORTED_MODULE_1__
+        );
+
+      const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
+        () =>
+          __webpack_require__
+            .e(/* import() */ 8042)
+            .then(__webpack_require__.bind(__webpack_require__, 8042))
+            .then((mod) => mod.Hello),
+        {
+          loadableGenerated: {
+            webpack: () => [/*require.resolve*/ 8042],
+          },
+        }
+      );
+      const Page = () =>
+        /*#__PURE__*/ (0, react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(
+          react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment,
+          {
+            children: [
+              /*#__PURE__*/ (0,
+              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("p", {
+                children: "testing next/dynamic size",
+              }),
+              /*#__PURE__*/ (0,
+              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
+                DynamicHello,
+                {}
+              ),
+            ],
+          }
+        );
+      var __N_SSP = true;
+      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = Page;
+
+      /***/
+    },
+
+    /***/ 2976: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/dynamic",
+        function () {
+          return __webpack_require__(2001);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 7807: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      "use strict";
+      /* __next_internal_client_entry_do_not_use__  cjs */
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "LoadableContext", {
+        enumerable: true,
+        get: function () {
+          return LoadableContext;
+        },
+      });
+      const _interop_require_default = __webpack_require__(1532);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(148)
+      );
+      const LoadableContext = _react.default.createContext(null);
+      if (false) {
+      } //# sourceMappingURL=loadable-context.shared-runtime.js.map
+
+      /***/
+    },
+
+    /***/ 9553: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(6990);
+      module.exports = __webpack_require__(9986);
 
       /***/
     },
 
-    /***/ 505: /***/ (
+    /***/ 9829: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -53,7 +153,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       const _react = /*#__PURE__*/ _interop_require_default._(
         __webpack_require__(148)
       );
-      const _loadablecontextsharedruntime = __webpack_require__(6179);
+      const _loadablecontextsharedruntime = __webpack_require__(7807);
       function resolve(obj) {
         return obj && obj.default ? obj.default : obj;
       }
@@ -288,90 +388,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /***/
     },
 
-    /***/ 5703: /***/ (
-      __unused_webpack_module,
-      __webpack_exports__,
-      __webpack_require__
-    ) => {
-      "use strict";
-      __webpack_require__.r(__webpack_exports__);
-      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
-        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
-        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
-        /* harmony export */
-      });
-      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
-        __webpack_require__(5640);
-      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(283);
-      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
-        /*#__PURE__*/ __webpack_require__.n(
-          next_dynamic__WEBPACK_IMPORTED_MODULE_1__
-        );
-
-      const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
-        () =>
-          __webpack_require__
-            .e(/* import() */ 2192)
-            .then(__webpack_require__.bind(__webpack_require__, 2192))
-            .then((mod) => mod.Hello),
-        {
-          loadableGenerated: {
-            webpack: () => [/*require.resolve*/ 2192],
-          },
-        }
-      );
-      const Page = () =>
-        /*#__PURE__*/ (0, react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(
-          react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment,
-          {
-            children: [
-              /*#__PURE__*/ (0,
-              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("p", {
-                children: "testing next/dynamic size",
-              }),
-              /*#__PURE__*/ (0,
-              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
-                DynamicHello,
-                {}
-              ),
-            ],
-          }
-        );
-      var __N_SSP = true;
-      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = Page;
-
-      /***/
-    },
-
-    /***/ 6179: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      "use strict";
-      /* __next_internal_client_entry_do_not_use__  cjs */
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "LoadableContext", {
-        enumerable: true,
-        get: function () {
-          return LoadableContext;
-        },
-      });
-      const _interop_require_default = __webpack_require__(1532);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(148)
-      );
-      const LoadableContext = _react.default.createContext(null);
-      if (false) {
-      } //# sourceMappingURL=loadable-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 6990: /***/ (module, exports, __webpack_require__) => {
+    /***/ 9986: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -404,7 +421,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
         __webpack_require__(148)
       );
       const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(505)
+        __webpack_require__(9829)
       );
       const isServerSide = "object" === "undefined";
       // Normalize loader to return the module as form { default: Component } for `React.lazy`.
@@ -504,30 +521,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
 
       /***/
     },
-
-    /***/ 9254: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/dynamic",
-        function () {
-          return __webpack_require__(5703);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9254)
+      __webpack_exec__(2976)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>hooks-HASH.js</strong></summary>

```diff
@@ -1,24 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9804],
   {
-    /***/ 1664: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/hooks",
-        function () {
-          return __webpack_require__(6130);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 6130: /***/ (
+    /***/ 4756: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -76,13 +59,30 @@
 
       /***/
     },
+
+    /***/ 5426: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/hooks",
+        function () {
+          return __webpack_require__(4756);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(1664)
+      __webpack_exec__(5426)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>image-HASH.js</strong></summary>

```diff
@@ -1,7 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2983],
   {
-    /***/ 2198: /***/ (
+    /***/ 264: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/image",
         function () {
-          return __webpack_require__(3444);
+          return __webpack_require__(3594);
         },
       ]);
       if (false) {
@@ -18,7 +18,190 @@
       /***/
     },
 
-    /***/ 2514: /***/ (
+    /***/ 1206: /***/ (__unused_webpack_module, exports) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "default", {
+        enumerable: true,
+        get: function () {
+          return _default;
+        },
+      });
+      const DEFAULT_Q = 75;
+      function defaultLoader(param) {
+        let { config, src, width, quality } = param;
+        var _config_qualities;
+        if (false) {
+        }
+        const q =
+          quality ||
+          ((_config_qualities = config.qualities) == null
+            ? void 0
+            : _config_qualities.reduce((prev, cur) =>
+                Math.abs(cur - DEFAULT_Q) < Math.abs(prev - DEFAULT_Q)
+                  ? cur
+                  : prev
+              )) ||
+          DEFAULT_Q;
+        return (
+          config.path +
+          "?url=" +
+          encodeURIComponent(src) +
+          "&w=" +
+          width +
+          "&q=" +
+          q +
+          (src.startsWith("/_next/static/media/") && false ? 0 : "")
+        );
+      }
+      // We use this to determine if the import is the default loader
+      // or a custom loader defined by the user in next.config.js
+      defaultLoader.__next_img_default = true;
+      const _default = defaultLoader; //# sourceMappingURL=image-loader.js.map
+
+      /***/
+    },
+
+    /***/ 1765: /***/ (module, exports, __webpack_require__) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "useMergedRef", {
+        enumerable: true,
+        get: function () {
+          return useMergedRef;
+        },
+      });
+      const _react = __webpack_require__(148);
+      function useMergedRef(refA, refB) {
+        const cleanupA = (0, _react.useRef)(null);
+        const cleanupB = (0, _react.useRef)(null);
+        // NOTE: In theory, we could skip the wrapping if only one of the refs is non-null.
+        // (this happens often if the user doesn't pass a ref to Link/Form/Image)
+        // But this can cause us to leak a cleanup-ref into user code (e.g. via `<Link legacyBehavior>`),
+        // and the user might pass that ref into ref-merging library that doesn't support cleanup refs
+        // (because it hasn't been updated for React 19)
+        // which can then cause things to blow up, because a cleanup-returning ref gets called with `null`.
+        // So in practice, it's safer to be defensive and always wrap the ref, even on React 19.
+        return (0, _react.useCallback)(
+          (current) => {
+            if (current === null) {
+              const cleanupFnA = cleanupA.current;
+              if (cleanupFnA) {
+                cleanupA.current = null;
+                cleanupFnA();
+              }
+              const cleanupFnB = cleanupB.current;
+              if (cleanupFnB) {
+                cleanupB.current = null;
+                cleanupFnB();
+              }
+            } else {
+              if (refA) {
+                cleanupA.current = applyRef(refA, current);
+              }
+              if (refB) {
+                cleanupB.current = applyRef(refB, current);
+              }
+            }
+          },
+          [refA, refB]
+        );
+      }
+      function applyRef(refA, current) {
+        if (typeof refA === "function") {
+          const cleanup = refA(current);
+          if (typeof cleanup === "function") {
+            return cleanup;
+          } else {
+            return () => refA(null);
+          }
+        } else {
+          refA.current = current;
+          return () => {
+            refA.current = null;
+          };
+        }
+      }
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
+        });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=use-merged-ref.js.map
+
+      /***/
+    },
+
+    /***/ 3353: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(5526);
+
+      /***/
+    },
+
+    /***/ 3594: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
+      __webpack_require__
+    ) => {
+      "use strict";
+      // ESM COMPAT FLAG
+      __webpack_require__.r(__webpack_exports__);
+
+      // EXPORTS
+      __webpack_require__.d(__webpack_exports__, {
+        __N_SSP: () => /* binding */ __N_SSP,
+        default: () => /* binding */ pages_image,
+      });
+
+      // EXTERNAL MODULE: ./node_modules/.pnpm/react@19.1.0/node_modules/react/jsx-runtime.js
+      var jsx_runtime = __webpack_require__(5640);
+      // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+diff-repo+packages+next+next-packed.tgz_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/image.js
+      var next_image = __webpack_require__(3353);
+      var image_default = /*#__PURE__*/ __webpack_require__.n(next_image); // ./pages/nextjs.png
+      /* harmony default export */ const nextjs = {
+        src: "/_next/static/media/nextjs.cae0b805.png",
+        height: 1347,
+        width: 1626,
+        blurDataURL:
+          "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAHCAMAAAACh/xsAAAAD1BMVEX////x8fH6+vrb29vo6Oh8o70bAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAH0lEQVR4nGNgwARMjIyMjCAGCzMzMwsTRISJCcRABwAEcAAkLCQfgAAAAABJRU5ErkJggg==",
+        blurWidth: 8,
+        blurHeight: 7,
+      }; // ./pages/image.js
+      function ImagePage(props) {
+        return /*#__PURE__*/ (0, jsx_runtime.jsxs)(jsx_runtime.Fragment, {
+          children: [
+            /*#__PURE__*/ (0, jsx_runtime.jsx)("h1", {
+              children: "next/image example",
+            }),
+            /*#__PURE__*/ (0, jsx_runtime.jsx)(image_default(), {
+              src: nextjs,
+              placeholder: "blur",
+            }),
+          ],
+        });
+      }
+      var __N_SSP = true;
+      /* harmony default export */ const pages_image = ImagePage;
+
+      /***/
+    },
+
+    /***/ 3854: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -34,9 +217,9 @@
           return getImgProps;
         },
       });
-      const _warnonce = __webpack_require__(5127);
-      const _imageblursvg = __webpack_require__(4287);
-      const _imageconfig = __webpack_require__(2795);
+      const _warnonce = __webpack_require__(3603);
+      const _imageblursvg = __webpack_require__(7835);
+      const _imageconfig = __webpack_require__(6799);
       const VALID_LOADING_VALUES =
         /* unused pure expression or super */ null && [
           "lazy",
@@ -463,55 +646,69 @@
       /***/
     },
 
-    /***/ 3444: /***/ (
+    /***/ 5526: /***/ (
       __unused_webpack_module,
-      __webpack_exports__,
+      exports,
       __webpack_require__
     ) => {
       "use strict";
-      // ESM COMPAT FLAG
-      __webpack_require__.r(__webpack_exports__);
 
-      // EXPORTS
-      __webpack_require__.d(__webpack_exports__, {
-        __N_SSP: () => /* binding */ __N_SSP,
-        default: () => /* binding */ pages_image,
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
       });
-
-      // EXTERNAL MODULE: ./node_modules/.pnpm/react@19.1.0/node_modules/react/jsx-runtime.js
-      var jsx_runtime = __webpack_require__(5640);
-      // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+main-repo+packages+next+next-packed.tgz_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/image.js
-      var next_image = __webpack_require__(6359);
-      var image_default = /*#__PURE__*/ __webpack_require__.n(next_image); // ./pages/nextjs.png
-      /* harmony default export */ const nextjs = {
-        src: "/_next/static/media/nextjs.cae0b805.png",
-        height: 1347,
-        width: 1626,
-        blurDataURL:
-          "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAHCAMAAAACh/xsAAAAD1BMVEX////x8fH6+vrb29vo6Oh8o70bAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAH0lEQVR4nGNgwARMjIyMjCAGCzMzMwsTRISJCcRABwAEcAAkLCQfgAAAAABJRU5ErkJggg==",
-        blurWidth: 8,
-        blurHeight: 7,
-      }; // ./pages/image.js
-      function ImagePage(props) {
-        return /*#__PURE__*/ (0, jsx_runtime.jsxs)(jsx_runtime.Fragment, {
-          children: [
-            /*#__PURE__*/ (0, jsx_runtime.jsx)("h1", {
-              children: "next/image example",
-            }),
-            /*#__PURE__*/ (0, jsx_runtime.jsx)(image_default(), {
-              src: nextjs,
-              placeholder: "blur",
-            }),
-          ],
+      0 && 0;
+      function _export(target, all) {
+        for (var name in all)
+          Object.defineProperty(target, name, {
+            enumerable: true,
+            get: all[name],
+          });
+      }
+      _export(exports, {
+        default: function () {
+          return _default;
+        },
+        getImageProps: function () {
+          return getImageProps;
+        },
+      });
+      const _interop_require_default = __webpack_require__(1532);
+      const _getimgprops = __webpack_require__(3854);
+      const _imagecomponent = __webpack_require__(8350);
+      const _imageloader = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(1206)
+      );
+      function getImageProps(imgProps) {
+        const { props } = (0, _getimgprops.getImgProps)(imgProps, {
+          defaultLoader: _imageloader.default,
+          // This is replaced by webpack define plugin
+          imgConf: {
+            deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
+            imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
+            path: "/_next/image",
+            loader: "default",
+            dangerouslyAllowSVG: false,
+            unoptimized: false,
+          },
         });
+        // Normally we don't care about undefined props because we pass to JSX,
+        // but this exported function could be used by the end user for anything
+        // so we delete undefined props to clean it up a little.
+        for (const [key, value] of Object.entries(props)) {
+          if (value === undefined) {
+            delete props[key];
+          }
+        }
+        return {
+          props,
+        };
       }
-      var __N_SSP = true;
-      /* harmony default export */ const pages_image = ImagePage;
+      const _default = _imagecomponent.Image; //# sourceMappingURL=image-external.js.map
 
       /***/
     },
 
-    /***/ 4287: /***/ (__unused_webpack_module, exports) => {
+    /***/ 7835: /***/ (__unused_webpack_module, exports) => {
       "use strict";
       /**
        * A shared function, used on both client and server, to generate a SVG blur placeholder.
@@ -566,85 +763,7 @@
       /***/
     },
 
-    /***/ 4985: /***/ (module, exports, __webpack_require__) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "useMergedRef", {
-        enumerable: true,
-        get: function () {
-          return useMergedRef;
-        },
-      });
-      const _react = __webpack_require__(148);
-      function useMergedRef(refA, refB) {
-        const cleanupA = (0, _react.useRef)(null);
-        const cleanupB = (0, _react.useRef)(null);
-        // NOTE: In theory, we could skip the wrapping if only one of the refs is non-null.
-        // (this happens often if the user doesn't pass a ref to Link/Form/Image)
-        // But this can cause us to leak a cleanup-ref into user code (e.g. via `<Link legacyBehavior>`),
-        // and the user might pass that ref into ref-merging library that doesn't support cleanup refs
-        // (because it hasn't been updated for React 19)
-        // which can then cause things to blow up, because a cleanup-returning ref gets called with `null`.
-        // So in practice, it's safer to be defensive and always wrap the ref, even on React 19.
-        return (0, _react.useCallback)(
-          (current) => {
-            if (current === null) {
-              const cleanupFnA = cleanupA.current;
-              if (cleanupFnA) {
-                cleanupA.current = null;
-                cleanupFnA();
-              }
-              const cleanupFnB = cleanupB.current;
-              if (cleanupFnB) {
-                cleanupB.current = null;
-                cleanupFnB();
-              }
-            } else {
-              if (refA) {
-                cleanupA.current = applyRef(refA, current);
-              }
-              if (refB) {
-                cleanupB.current = applyRef(refB, current);
-              }
-            }
-          },
-          [refA, refB]
-        );
-      }
-      function applyRef(refA, current) {
-        if (typeof refA === "function") {
-          const cleanup = refA(current);
-          if (typeof cleanup === "function") {
-            return cleanup;
-          } else {
-            return () => refA(null);
-          }
-        } else {
-          refA.current = current;
-          return () => {
-            refA.current = null;
-          };
-        }
-      }
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=use-merged-ref.js.map
-
-      /***/
-    },
-
-    /***/ 5898: /***/ (module, exports, __webpack_require__) => {
+    /***/ 8350: /***/ (module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -666,17 +785,17 @@
         __webpack_require__(7897)
       );
       const _head = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(5207)
+        __webpack_require__(8843)
       );
-      const _getimgprops = __webpack_require__(2514);
-      const _imageconfig = __webpack_require__(2795);
-      const _imageconfigcontextsharedruntime = __webpack_require__(2349);
-      const _warnonce = __webpack_require__(5127);
-      const _routercontextsharedruntime = __webpack_require__(3556);
+      const _getimgprops = __webpack_require__(3854);
+      const _imageconfig = __webpack_require__(6799);
+      const _imageconfigcontextsharedruntime = __webpack_require__(3905);
+      const _warnonce = __webpack_require__(3603);
+      const _routercontextsharedruntime = __webpack_require__(6712);
       const _imageloader = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(5970)
+        __webpack_require__(1206)
       );
-      const _usemergedref = __webpack_require__(4985);
+      const _usemergedref = __webpack_require__(1765);
       // This is replaced by webpack define plugin
       const configEnv = {
         deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
@@ -1002,132 +1121,13 @@
 
       /***/
     },
-
-    /***/ 5970: /***/ (__unused_webpack_module, exports) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "default", {
-        enumerable: true,
-        get: function () {
-          return _default;
-        },
-      });
-      const DEFAULT_Q = 75;
-      function defaultLoader(param) {
-        let { config, src, width, quality } = param;
-        var _config_qualities;
-        if (false) {
-        }
-        const q =
-          quality ||
-          ((_config_qualities = config.qualities) == null
-            ? void 0
-            : _config_qualities.reduce((prev, cur) =>
-                Math.abs(cur - DEFAULT_Q) < Math.abs(prev - DEFAULT_Q)
-                  ? cur
-                  : prev
-              )) ||
-          DEFAULT_Q;
-        return (
-          config.path +
-          "?url=" +
-          encodeURIComponent(src) +
-          "&w=" +
-          width +
-          "&q=" +
-          q +
-          (src.startsWith("/_next/static/media/") && false ? 0 : "")
-        );
-      }
-      // We use this to determine if the import is the default loader
-      // or a custom loader defined by the user in next.config.js
-      defaultLoader.__next_img_default = true;
-      const _default = defaultLoader; //# sourceMappingURL=image-loader.js.map
-
-      /***/
-    },
-
-    /***/ 6359: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(8986);
-
-      /***/
-    },
-
-    /***/ 8986: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      0 && 0;
-      function _export(target, all) {
-        for (var name in all)
-          Object.defineProperty(target, name, {
-            enumerable: true,
-            get: all[name],
-          });
-      }
-      _export(exports, {
-        default: function () {
-          return _default;
-        },
-        getImageProps: function () {
-          return getImageProps;
-        },
-      });
-      const _interop_require_default = __webpack_require__(1532);
-      const _getimgprops = __webpack_require__(2514);
-      const _imagecomponent = __webpack_require__(5898);
-      const _imageloader = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(5970)
-      );
-      function getImageProps(imgProps) {
-        const { props } = (0, _getimgprops.getImgProps)(imgProps, {
-          defaultLoader: _imageloader.default,
-          // This is replaced by webpack define plugin
-          imgConf: {
-            deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
-            imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
-            path: "/_next/image",
-            loader: "default",
-            dangerouslyAllowSVG: false,
-            unoptimized: false,
-          },
-        });
-        // Normally we don't care about undefined props because we pass to JSX,
-        // but this exported function could be used by the end user for anything
-        // so we delete undefined props to clean it up a little.
-        for (const [key, value] of Object.entries(props)) {
-          if (value === undefined) {
-            delete props[key];
-          }
-        }
-        return {
-          props,
-        };
-      }
-      const _default = _imagecomponent.Image; //# sourceMappingURL=image-external.js.map
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(2198)
+      __webpack_exec__(264)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>index-HASH.js</strong></summary>

```diff
@@ -1,7 +1,24 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [3332],
   {
-    /***/ 9418: /***/ (
+    /***/ 8230: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/",
+        function () {
+          return __webpack_require__(8696);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 8696: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -19,30 +36,13 @@
 
       /***/
     },
-
-    /***/ 9532: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/",
-        function () {
-          return __webpack_require__(9418);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9532)
+      __webpack_exec__(8230)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>link-HASH.js</strong></summary>

```diff
@@ -1,125 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [4672],
   {
-    /***/ 1854: /***/ (
-      __unused_webpack_module,
-      __webpack_exports__,
-      __webpack_require__
-    ) => {
-      "use strict";
-      __webpack_require__.r(__webpack_exports__);
-      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
-        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
-        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
-        /* harmony export */
-      });
-      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
-        __webpack_require__(5640);
-      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(8770);
-      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
-        /*#__PURE__*/ __webpack_require__.n(
-          next_link__WEBPACK_IMPORTED_MODULE_1__
-        );
-
-      function aLink(props) {
-        return /*#__PURE__*/ (0,
-        react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", {
-          children: [
-            /*#__PURE__*/ (0,
-            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("h3", {
-              children: "A Link page!",
-            }),
-            /*#__PURE__*/ (0,
-            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
-              next_link__WEBPACK_IMPORTED_MODULE_1___default(),
-              {
-                href: "/",
-                children: "Go to /",
-              }
-            ),
-          ],
-        });
-      }
-      var __N_SSP = true;
-      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = aLink;
-
-      /***/
-    },
-
-    /***/ 3199: /***/ (__unused_webpack_module, exports) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "errorOnce", {
-        enumerable: true,
-        get: function () {
-          return errorOnce;
-        },
-      });
-      let errorOnce = (_) => {};
-      if (false) {
-      } //# sourceMappingURL=error-once.js.map
-
-      /***/
-    },
-
-    /***/ 3568: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/link",
-        function () {
-          return __webpack_require__(1854);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 3857: /***/ (module, exports, __webpack_require__) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "getDomainLocale", {
-        enumerable: true,
-        get: function () {
-          return getDomainLocale;
-        },
-      });
-      const _normalizetrailingslash = __webpack_require__(4869);
-      const basePath =
-        /* unused pure expression or super */ null && (false || "");
-      function getDomainLocale(path, locale, locales, domainLocales) {
-        if (false) {
-        } else {
-          return false;
-        }
-      }
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=get-domain-locale.js.map
-
-      /***/
-    },
-
-    /***/ 3947: /***/ (module, exports, __webpack_require__) => {
+    /***/ 591: /***/ (module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -146,17 +28,17 @@
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
         __webpack_require__(148)
       );
-      const _resolvehref = __webpack_require__(3161);
-      const _islocalurl = __webpack_require__(2309);
-      const _formaturl = __webpack_require__(3768);
-      const _utils = __webpack_require__(5554);
-      const _addlocale = __webpack_require__(7591);
-      const _routercontextsharedruntime = __webpack_require__(3556);
-      const _useintersection = __webpack_require__(5624);
-      const _getdomainlocale = __webpack_require__(3857);
-      const _addbasepath = __webpack_require__(4356);
-      const _usemergedref = __webpack_require__(4985);
-      const _erroronce = __webpack_require__(3199);
+      const _resolvehref = __webpack_require__(5837);
+      const _islocalurl = __webpack_require__(5953);
+      const _formaturl = __webpack_require__(6212);
+      const _utils = __webpack_require__(6950);
+      const _addlocale = __webpack_require__(6467);
+      const _routercontextsharedruntime = __webpack_require__(6712);
+      const _useintersection = __webpack_require__(9692);
+      const _getdomainlocale = __webpack_require__(6850);
+      const _addbasepath = __webpack_require__(4928);
+      const _usemergedref = __webpack_require__(1765);
+      const _erroronce = __webpack_require__(8659);
       const prefetched = new Set();
       function prefetch(router, href, as, options) {
         if (false) {
@@ -545,7 +427,17 @@
       /***/
     },
 
-    /***/ 4985: /***/ (module, exports, __webpack_require__) => {
+    /***/ 1148: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(591);
+
+      /***/
+    },
+
+    /***/ 1765: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -623,7 +515,125 @@
       /***/
     },
 
-    /***/ 5624: /***/ (module, exports, __webpack_require__) => {
+    /***/ 5436: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
+      __webpack_require__
+    ) => {
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
+        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
+        /* harmony export */
+      });
+      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
+        __webpack_require__(5640);
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
+        __webpack_require__(1148);
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
+        /*#__PURE__*/ __webpack_require__.n(
+          next_link__WEBPACK_IMPORTED_MODULE_1__
+        );
+
+      function aLink(props) {
+        return /*#__PURE__*/ (0,
+        react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", {
+          children: [
+            /*#__PURE__*/ (0,
+            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("h3", {
+              children: "A Link page!",
+            }),
+            /*#__PURE__*/ (0,
+            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
+              next_link__WEBPACK_IMPORTED_MODULE_1___default(),
+              {
+                href: "/",
+                children: "Go to /",
+              }
+            ),
+          ],
+        });
+      }
+      var __N_SSP = true;
+      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = aLink;
+
+      /***/
+    },
+
+    /***/ 6850: /***/ (module, exports, __webpack_require__) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "getDomainLocale", {
+        enumerable: true,
+        get: function () {
+          return getDomainLocale;
+        },
+      });
+      const _normalizetrailingslash = __webpack_require__(6457);
+      const basePath =
+        /* unused pure expression or super */ null && (false || "");
+      function getDomainLocale(path, locale, locales, domainLocales) {
+        if (false) {
+        } else {
+          return false;
+        }
+      }
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
+        });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=get-domain-locale.js.map
+
+      /***/
+    },
+
+    /***/ 8659: /***/ (__unused_webpack_module, exports) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "errorOnce", {
+        enumerable: true,
+        get: function () {
+          return errorOnce;
+        },
+      });
+      let errorOnce = (_) => {};
+      if (false) {
+      } //# sourceMappingURL=error-once.js.map
+
+      /***/
+    },
+
+    /***/ 9666: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/link",
+        function () {
+          return __webpack_require__(5436);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 9692: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -636,7 +646,7 @@
         },
       });
       const _react = __webpack_require__(148);
-      const _requestidlecallback = __webpack_require__(3543);
+      const _requestidlecallback = __webpack_require__(315);
       const hasIntersectionObserver =
         typeof IntersectionObserver === "function";
       const observers = new Map();
@@ -748,23 +758,13 @@
 
       /***/
     },
-
-    /***/ 8770: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(3947);
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(3568)
+      __webpack_exec__(9666)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>routerDirect-HASH.js</strong></summary>

```diff
@@ -1,7 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [188],
   {
-    /***/ 3618: /***/ (
+    /***/ 76: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -16,7 +16,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(5640);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(4631);
+        __webpack_require__(9413);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -36,17 +36,7 @@
       /***/
     },
 
-    /***/ 4631: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(7086);
-
-      /***/
-    },
-
-    /***/ 7824: /***/ (
+    /***/ 1810: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -54,7 +44,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/routerDirect",
         function () {
-          return __webpack_require__(3618);
+          return __webpack_require__(76);
         },
       ]);
       if (false) {
@@ -62,13 +52,23 @@
 
       /***/
     },
+
+    /***/ 9413: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(5282);
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(7824)
+      __webpack_exec__(1810)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>script-HASH.js</strong></summary>

```diff
@@ -1,24 +1,17 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [1209],
   {
-    /***/ 1984: /***/ (
-      __unused_webpack_module,
+    /***/ 2227: /***/ (
+      module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/script",
-        function () {
-          return __webpack_require__(5769);
-        },
-      ]);
-      if (false) {
-      }
+      module.exports = __webpack_require__(5984);
 
       /***/
     },
 
-    /***/ 5769: /***/ (
+    /***/ 3043: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -33,7 +26,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(5640);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(8293);
+        __webpack_require__(2227);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_script__WEBPACK_IMPORTED_MODULE_1__
@@ -66,12 +59,19 @@
       /***/
     },
 
-    /***/ 8293: /***/ (
-      module,
+    /***/ 3642: /***/ (
+      __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(900);
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/script",
+        function () {
+          return __webpack_require__(3043);
+        },
+      ]);
+      if (false) {
+      }
 
       /***/
     },
@@ -81,7 +81,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(1984)
+      __webpack_exec__(3642)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>withRouter-HASH.js</strong></summary>

```diff
@@ -1,34 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [3263],
   {
-    /***/ 4631: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(7086);
-
-      /***/
-    },
-
-    /***/ 9216: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/withRouter",
-        function () {
-          return __webpack_require__(9803);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 9803: /***/ (
+    /***/ 1089: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -43,7 +16,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(5640);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(4631);
+        __webpack_require__(9413);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -61,13 +34,40 @@
 
       /***/
     },
+
+    /***/ 3962: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/withRouter",
+        function () {
+          return __webpack_require__(1089);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 9413: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(5282);
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9216)
+      __webpack_exec__(3962)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
```
</details>
<details>
<summary>Diff for <strong>1733-HASH.js</strong></summary>

Diff too large to display
</details>
<details>
<summary>Diff for <strong>4719-HASH.js</strong></summary>

Diff too large to display
</details>
<details>
<summary>Diff for <strong>main-HASH.js</strong></summary>

Diff too large to display
</details>

</details>

</details>
Commit: 4a701f23a327e4b8b758e60a036400ec4d3e7007
author_association: MEMBER
user: login: ijjk
created_at: 2025-05-12T21:45:01Z
body: ## Failing test suites <!--38461343023-->
Commit: 4a701f23a327e4b8b758e60a036400ec4d3e7007

`pnpm test-start test/e2e/app-dir/back-forward-cache/back-forward-cache.test.ts`
- back/forward cache > React state is preserved when navigating with back/forward buttons
- back/forward cache > React state is preserved when navigating back/forward with links
- back/forward cache > React state is preserved when navigating back to a page with different search params than before 
- back/forward cache > bfcache only preserves up to N entries
- back/forward cache > navigate back and forth repeatedly between the same pages without evicting

<details>
<summary>Expand output</summary>

  ● back/forward cache › React state is preserved when navigating with back/forward buttons

    page.waitForSelector: Timeout 5000ms exceeded.
    Call log:
      - waiting for locator('#increment-button-1')

      454 |   waitForElementByCss(selector: string, timeout = 10_000) {
      455 |     return this.startChain(async () => {
    > 456 |       const el = await page.waitForSelector(selector, {
          |                             ^
      457 |         timeout,
      458 |         state: 'attached',
      459 |       })

      at waitForSelector (lib/browsers/playwright.ts:456:29)
      at Playwright._chain (lib/browsers/playwright.ts:568:23)
      at Playwright._chain [as startChain] (lib/browsers/playwright.ts:549:17)
      at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:455:17)
      at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:375:17)
      at Playwright.elementByCss [as elementById] (lib/browsers/playwright.ts:379:17)
      at elementById (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:16:21)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:13:5)
      at Proxy._chain (lib/browsers/playwright.ts:568:23)
      at Proxy._chain (lib/browsers/playwright.ts:544:17)
      at Proxy.continueChain (lib/browsers/playwright.ts:425:17)
      at click (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:16:55)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:13:5)

  ● back/forward cache › React state is preserved when navigating back/forward with links

    page.waitForSelector: Timeout 5000ms exceeded.
    Call log:
      - waiting for locator('#increment-button-1')

      454 |   waitForElementByCss(selector: string, timeout = 10_000) {
      455 |     return this.startChain(async () => {
    > 456 |       const el = await page.waitForSelector(selector, {
          |                             ^
      457 |         timeout,
      458 |         state: 'attached',
      459 |       })

      at waitForSelector (lib/browsers/playwright.ts:456:29)
      at Playwright._chain (lib/browsers/playwright.ts:568:23)
      at Playwright._chain [as startChain] (lib/browsers/playwright.ts:549:17)
      at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:455:17)
      at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:375:17)
      at Playwright.elementByCss [as elementById] (lib/browsers/playwright.ts:379:17)
      at elementById (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:63:21)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:60:5)
      at Proxy._chain (lib/browsers/playwright.ts:568:23)
      at Proxy._chain (lib/browsers/playwright.ts:544:17)
      at Proxy.continueChain (lib/browsers/playwright.ts:425:17)
      at click (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:63:55)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:60:5)

  ● back/forward cache › React state is preserved when navigating back to a page with different search params than before 

    page.waitForSelector: Timeout 5000ms exceeded.
    Call log:
      - waiting for locator('#increment-button-1')

      454 |   waitForElementByCss(selector: string, timeout = 10_000) {
      455 |     return this.startChain(async () => {
    > 456 |       const el = await page.waitForSelector(selector, {
          |                             ^
      457 |         timeout,
      458 |         state: 'attached',
      459 |       })

      at waitForSelector (lib/browsers/playwright.ts:456:29)
      at Playwright._chain (lib/browsers/playwright.ts:568:23)
      at Playwright._chain [as startChain] (lib/browsers/playwright.ts:549:17)
      at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:455:17)
      at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:375:17)
      at Playwright.elementByCss [as elementById] (lib/browsers/playwright.ts:379:17)
      at elementById (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:110:21)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:107:5)
      at Proxy._chain (lib/browsers/playwright.ts:568:23)
      at Proxy._chain (lib/browsers/playwright.ts:544:17)
      at Proxy.continueChain (lib/browsers/playwright.ts:425:17)
      at click (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:110:55)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:107:5)

  ● back/forward cache › bfcache only preserves up to N entries

    page.waitForSelector: Timeout 5000ms exceeded.
    Call log:
      - waiting for locator('#increment-button-1')

      454 |   waitForElementByCss(selector: string, timeout = 10_000) {
      455 |     return this.startChain(async () => {
    > 456 |       const el = await page.waitForSelector(selector, {
          |                             ^
      457 |         timeout,
      458 |         state: 'attached',
      459 |       })

      at waitForSelector (lib/browsers/playwright.ts:456:29)
      at Playwright._chain (lib/browsers/playwright.ts:568:23)
      at Playwright._chain [as startChain] (lib/browsers/playwright.ts:549:17)
      at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:455:17)
      at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:375:17)
      at Playwright.elementByCss [as elementById] (lib/browsers/playwright.ts:379:17)
      at elementById (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:147:21)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:144:5)
      at Proxy._chain (lib/browsers/playwright.ts:568:23)
      at Proxy._chain (lib/browsers/playwright.ts:544:17)
      at Proxy.continueChain (lib/browsers/playwright.ts:425:17)
      at click (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:147:55)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:144:5)

  ● back/forward cache › navigate back and forth repeatedly between the same pages without evicting

    page.waitForSelector: Timeout 5000ms exceeded.
    Call log:
      - waiting for locator('#increment-button-1')

      454 |   waitForElementByCss(selector: string, timeout = 10_000) {
      455 |     return this.startChain(async () => {
    > 456 |       const el = await page.waitForSelector(selector, {
          |                             ^
      457 |         timeout,
      458 |         state: 'attached',
      459 |       })

      at waitForSelector (lib/browsers/playwright.ts:456:29)
      at Playwright._chain (lib/browsers/playwright.ts:568:23)
      at Playwright._chain [as startChain] (lib/browsers/playwright.ts:549:17)
      at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:455:17)
      at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:375:17)
      at Playwright.elementByCss [as elementById] (lib/browsers/playwright.ts:379:17)
      at elementById (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:208:21)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:205:5)
      at Proxy._chain (lib/browsers/playwright.ts:568:23)
      at Proxy._chain (lib/browsers/playwright.ts:544:17)
      at Proxy.continueChain (lib/browsers/playwright.ts:425:17)
      at click (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:208:55)
      at fn (lib/next-test-utils.ts:811:20)
      at Object.<anonymous> (e2e/app-dir/back-forward-cache/back-forward-cache.test.ts:205:5)

</details>


Read more about building and testing Next.js in [contributing.md](https://github.com/vercel/next.js/blob/canary/contributing.md).

author_association: MEMBER