next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Remove async/await from navigate-reducer

Open acdlite opened this issue 2 weeks ago • 2 comments

This is part of a series of refactors to remove all the promise-based code from the router's internal state machine.

Promises, and async/await, can still be used when performing I/O, but it shouldn't be used in any of the state machine or queueing paths. We should always be able to compute the next state for a given navigation.

Even in cases where the router doesn't have enough information to render the next navigation, we should still be able to produce a router state object that represents this suspended state. React needs to suspend on something to prevent the route from committing to the UI, but we don't need to turn the entire state object into a promise.

This PR removes async/await from navigate-reducer, and introduces the basic mechanism that will be used to convert the remaining reducers, like server-action-reducer.

acdlite avatar Dec 10 '25 01:12 acdlite

Failing test suites

Commit: 01a7d61f95a554637263c0f60929b7f6e760a393 | About building and testing Next.js

pnpm test-start test/e2e/app-dir/concurrent-navigations/mismatching-prefetch.test.ts (job)

  • mismatching prefetch > recovers when a navigation redirects to a different route than the one that was prefetched (DD)
Expand output

● mismatching prefetch › recovers when a navigation redirects to a different route than the one that was prefetched

Expected sequence of responses does not match:

- Expected
+ Received

  Array [
    "Dynamic page b",
-   "Dynamic page b",
  ]

NOTE: Assertions are checked in order, so if an expectation is missing, it may have actually appeared earlier in the sequence than expected. Make sure the order is correct.

  39 |       // When we click the link to navigate, the navigation will redirect to
  40 |       // a different route than the one that was prefetched.
> 41 |       await act(
     |             ^
  42 |         async () => {
  43 |           const link = await browser.elementByCss(
  44 |             'a[href="/mismatching-prefetch/dynamic-page/a?mismatch-redirect=./b"]'

  at Object.act (e2e/app-dir/concurrent-navigations/mismatching-prefetch.test.ts:41:13)

pnpm test-start-turbo test/e2e/app-dir/actions-revalidate-remount/actions-revalidate-remount.test.ts (turbopack) (job)

  • mismatching prefetch > recovers when a navigation redirects to a different route than the one that was prefetched (DD)
Expand output

● mismatching prefetch › recovers when a navigation redirects to a different route than the one that was prefetched

Expected sequence of responses does not match:

- Expected
+ Received

  Array [
    "Dynamic page b",
-   "Dynamic page b",
  ]

NOTE: Assertions are checked in order, so if an expectation is missing, it may have actually appeared earlier in the sequence than expected. Make sure the order is correct.

  39 |       // When we click the link to navigate, the navigation will redirect to
  40 |       // a different route than the one that was prefetched.
> 41 |       await act(
     |             ^
  42 |         async () => {
  43 |           const link = await browser.elementByCss(
  44 |             'a[href="/mismatching-prefetch/dynamic-page/a?mismatch-redirect=./b"]'

  at Object.act (e2e/app-dir/concurrent-navigations/mismatching-prefetch.test.ts:41:13)

pnpm test-dev test/development/app-dir/use-cache-errors/use-cache-errors.test.ts (job)

  • navigation between pages and app dir > It should be able to navigate app -> pages and go back and forward (DD)
Expand output

● navigation between pages and app dir › It should be able to navigate app -> pages and go back and forward

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#app-page') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Object.<anonymous> (e2e/app-dir/interoperability-with-pages/navigation.test.ts:64:7)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:632:17)
  at Proxy.startChain (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/interoperability-with-pages/navigation.test.ts:64:28)

pnpm test-dev test/e2e/app-dir/refresh/refresh.test.ts (job)

  • app-dir refresh > should refresh client cache when refresh() is called in a server action (DD)
Expand output

● app-dir refresh › should refresh client cache when refresh() is called in a server action

expect(received).not.toBe(expected) // Object.is equality

Expected: not "6718.306089997292"

  28 |         .elementById('server-timestamp')
  29 |         .text()
> 30 |       expect(newServerTimestamp).not.toBe(initialServerTimestamp)
     |                                      ^
  31 |       expect(Number(newServerTimestamp)).toBeGreaterThan(
  32 |         Number(initialServerTimestamp)
  33 |       )

  at toBe (e2e/app-dir/refresh/refresh.test.ts:30:38)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/refresh/refresh.test.ts:26:5)

pnpm test-start-turbo test/e2e/app-dir/app-middleware/app-middleware.test.ts (turbopack) (job)

  • app-dir action useActionState > should support submitting form state with JS (DD)
Expand output

● app-dir action useActionState › should support submitting form state with JS

TIMED OUT: initial-state:test

initial-state

undefined

  724 |   }
  725 |   console.error('TIMED OUT CHECK: ', { regex, content, lastErr })
> 726 |   throw new Error('TIMED OUT: ' + regex + '\n\n' + content + '\n\n' + lastErr)
      |         ^
  727 | }
  728 |
  729 | export class File {

  at check (lib/next-test-utils.ts:726:9)
  at Object.<anonymous> (e2e/app-dir/actions/app-action-form-state.test.ts:23:5)

pnpm test-start test/e2e/app-dir/app-middleware-proxy/app-middleware-proxy.test.ts (job)

  • app-dir with proxy > should respect cookie options of merged proxy cookies (DD)
  • app-dir with proxy > should be possible to read cookies that are set during the proxy handling of a server action (DD)
Expand output

● app-dir with proxy › should respect cookie options of merged proxy cookies

expect(received).toMatch(expected)

Expected pattern: /Action Result: \d+\.\d+/
Received string:  "Action Result:"

  189 |
  190 |     await retry(async () => {
> 191 |       expect(await browser.elementById('action-result').text()).toMatch(
      |                                                                 ^
  192 |         /Action Result: \d+\.\d+/
  193 |       )
  194 |     })

  at toMatch (e2e/app-dir/app-middleware-proxy/app-middleware-proxy.test.ts:191:65)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/app-middleware-proxy/app-middleware-proxy.test.ts:190:5)

● app-dir with proxy › should be possible to read cookies that are set during the proxy handling of a server action

expect(received).toBe(expected) // Object.is equality

Expected: "Total Cookie Length: 2"
Received: "Total Cookie Length: 3"

  236 |     expect(initialRandom1).toMatch(/Cookie 1: \d+\.\d+/)
  237 |     expect(initialRandom2).toMatch(/Cookie 2: \d+\.\d+/)
> 238 |     expect(totalCookies).toBe('Total Cookie Length: 2')
      |                          ^
  239 |
  240 |     expect(await browser.eval('document.cookie')).toBeTruthy()
  241 |

  at Object.toBe (e2e/app-dir/app-middleware-proxy/app-middleware-proxy.test.ts:238:26)

pnpm test-start-turbo test/e2e/app-dir/cache-components/cache-components.server-action.test.ts (turbopack) (job)

  • app-dir action size limit invalid config > should respect the size set in serverActions.bodySizeLimit for multipart fetch actions > should error for requests that exceed the size limit (DD)
Expand output

● app-dir action size limit invalid config › should respect the size set in serverActions.bodySizeLimit for multipart fetch actions › should error for requests that exceed the size limit

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('#error') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at Object.elementByCss (e2e/app-dir/actions/app-action-size-limit-invalid.test.ts:234:28)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:433:17)
  at Object.text (e2e/app-dir/actions/app-action-size-limit-invalid.test.ts:234:51)

pnpm test-dev test/e2e/app-dir/error-boundary-navigation/index.test.ts (job)

  • app-dir refresh > should refresh client cache when refresh() is called in a server action (DD)
Expand output

● app-dir refresh › should refresh client cache when refresh() is called in a server action

expect(received).not.toBe(expected) // Object.is equality

Expected: not "4861.249560952187"

  28 |         .elementById('server-timestamp')
  29 |         .text()
> 30 |       expect(newServerTimestamp).not.toBe(initialServerTimestamp)
     |                                      ^
  31 |       expect(Number(newServerTimestamp)).toBeGreaterThan(
  32 |         Number(initialServerTimestamp)
  33 |       )

  at toBe (e2e/app-dir/refresh/refresh.test.ts:30:38)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/refresh/refresh.test.ts:26:5)

pnpm test-start test/e2e/app-dir/actions-unrecognized/actions-unrecognized.test.ts (job)

  • temporary-references > should return the same object that was sent to the action (edge) (DD)
  • temporary-references > should return the same object that was sent to the action (node) (DD)
Expand output

● temporary-references › should return the same object that was sent to the action (edge)

expect(received).toBe(expected) // Object.is equality

Expected: "identical"
Received: "initial"

  16 |
  17 |       await retry(async () => {
> 18 |         expect(await browser.elementByCss('p').text()).toBe('identical')
     |                                                        ^
  19 |       })
  20 |     }
  21 |   )

  at toBe (e2e/app-dir/temporary-references/temporary-references.test.ts:18:56)
  at retry (lib/next-test-utils.ts:797:14)
  at e2e/app-dir/temporary-references/temporary-references.test.ts:17:7

● temporary-references › should return the same object that was sent to the action (node)

expect(received).toBe(expected) // Object.is equality

Expected: "identical"
Received: "initial"

  16 |
  17 |       await retry(async () => {
> 18 |         expect(await browser.elementByCss('p').text()).toBe('identical')
     |                                                        ^
  19 |       })
  20 |     }
  21 |   )

  at toBe (e2e/app-dir/temporary-references/temporary-references.test.ts:18:56)
  at retry (lib/next-test-utils.ts:797:14)
  at e2e/app-dir/temporary-references/temporary-references.test.ts:17:7

pnpm test-start-turbo test/e2e/app-dir/interoperability-with-pages/navigation.test.ts (turbopack) (job)

  • parallel-routes-revalidation > should submit the action and revalidate the page data (DD)
  • parallel-routes-revalidation > should refresh the correct page when a server action triggers a redirect (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: false > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: false > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: true > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: true > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: false > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: false > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: true > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: true > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > server action revalidation > handles refreshing when multiple parallel slots are active (DD)
Expand output

● parallel-routes-revalidation › should submit the action and revalidate the page data

expect(received).toBe(expected) // Object.is equality

Expected: 1
Received: 0

  26 |       // we created an entry and called revalidate, so we should have 1 entry
  27 |       await retry(async () => {
> 28 |         expect((await browser.elementsByCss('#entries li')).length).toBe(1)
     |                                                                     ^
  29 |       })
  30 |
  31 |       await browser.elementById('create-entry').click()

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:28:69)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:27:7)

● parallel-routes-revalidation › should refresh the correct page when a server action triggers a redirect

expect(received).toBe(expected) // Object.is equality

Expected: 0
Received: 1

  203 |       await retry(async () => {
  204 |         // confirm there aren't any entries yet
> 205 |         expect((await browser.elementsByCss('#entries li')).length).toBe(0)
      |                                                                     ^
  206 |       })
  207 |
  208 |       await browser.elementById('create-entry').click()

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:205:69)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:203:7)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: false › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.7283806507603909"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: false › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.7973738268903123"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: true › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.5806118907006306"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: true › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.7642922424790684"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: false › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.04947632006576619"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: false › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.3661309073335346"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: true › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.25073048580271506"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: true › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.11630659176153402"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › server action revalidation › handles refreshing when multiple parallel slots are active

expect(received).not.toEqual(expected) // deep equality

Expected: not "1765480728548"

  415 |
  416 |         // And the drawer should have a new time
> 417 |         expect(await browser.elementById('drawer-now').text()).not.toEqual(
      |                                                                    ^
  418 |           currentDrawerTime
  419 |         )
  420 |

  at toEqual (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:417:68)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:409:7)

pnpm test-dev test/e2e/app-dir/actions/app-action-form-state-node-middleware.test.ts (job)

  • app dir - not found navigation > should allow navigating to a non-existent page (DD)
  • app dir - not found navigation - with overridden node env > should allow navigating to a non-existent page (DD)
Expand output

● app dir - not found navigation › should allow navigating to a non-existent page

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#homepage') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Object.<anonymous> (e2e/app-dir/error-boundary-navigation/index.test.ts:94:5)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:632:17)
  at Proxy.startChain (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/error-boundary-navigation/index.test.ts:94:26)

● app dir - not found navigation - with overridden node env › should allow navigating to a non-existent page

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#homepage') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Object.<anonymous> (e2e/app-dir/error-boundary-navigation/index.test.ts:94:5)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:632:17)
  at Proxy.startChain (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/error-boundary-navigation/index.test.ts:94:26)

pnpm test-start test/e2e/app-dir/use-cache-with-server-function-props/use-cache-with-server-function-props.test.ts (job)

  • use-cache-with-server-function-props > should be able to use inline server actions as props (DD)
  • use-cache-with-server-function-props > should be able to use nested cache functions as props (DD)
Expand output

● use-cache-with-server-function-props › should be able to use inline server actions as props

expect(received).toMatch(expected)

Expected substring: "Hi, World!"
Received string:    "loading..."

  15 |     await browser.elementById('submit-button-hi').click()
  16 |     await retry(async () => {
> 17 |       expect(await browser.elementById('hi').text()).toMatch('Hi, World!')
     |                                                      ^
  18 |     })
  19 |
  20 |     await browser.elementById('submit-button-hello').click()

  at toMatch (e2e/app-dir/use-cache-with-server-function-props/use-cache-with-server-function-props.test.ts:17:54)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache-with-server-function-props/use-cache-with-server-function-props.test.ts:16:5)

● use-cache-with-server-function-props › should be able to use nested cache functions as props

expect(received).toMatch(expected)

Expected pattern: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
Received string:  "loading..."

  29 |     await browser.elementById('submit-button-date').click()
  30 |     await retry(async () => {
> 31 |       expect(await browser.elementById('date').text()).toMatch(isoDateRegExp)
     |                                                        ^
  32 |     })
  33 |
  34 |     await browser.elementById('submit-button-random').click()

  at toMatch (e2e/app-dir/use-cache-with-server-function-props/use-cache-with-server-function-props.test.ts:31:56)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache-with-server-function-props/use-cache-with-server-function-props.test.ts:30:5)

pnpm test-dev-turbo test/development/app-dir/cache-components-dev-cache-scope/cache-components-dev-cache-scope.test.ts (turbopack) (job)

  • app dir - not found navigation > should allow navigating to a non-existent page (DD)
  • app dir - not found navigation - with overridden node env > should allow navigating to a non-existent page (DD)
Expand output

● app dir - not found navigation › should allow navigating to a non-existent page

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#homepage') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Object.<anonymous> (e2e/app-dir/error-boundary-navigation/index.test.ts:94:5)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:632:17)
  at Proxy.startChain (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/error-boundary-navigation/index.test.ts:94:26)

● app dir - not found navigation - with overridden node env › should allow navigating to a non-existent page

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#homepage') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Object.<anonymous> (e2e/app-dir/error-boundary-navigation/index.test.ts:94:5)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:632:17)
  at Proxy.startChain (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/error-boundary-navigation/index.test.ts:94:26)

pnpm test-start test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts (job)

  • parallel-routes-revalidation > should submit the action and revalidate the page data (DD)
  • parallel-routes-revalidation > should refresh the correct page when a server action triggers a redirect (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: false > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: false > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: true > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (dynamic) - searchParams: true > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: false > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: false > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: true > should correctly refresh data for the intercepted route and previously active page slot (DD)
  • parallel-routes-revalidation > router.refresh (regular) - searchParams: true > should correctly refresh data for previously intercepted modal and active page slot (DD)
  • parallel-routes-revalidation > server action revalidation > handles refreshing when multiple parallel slots are active (DD)
Expand output

● parallel-routes-revalidation › should submit the action and revalidate the page data

expect(received).toBe(expected) // Object.is equality

Expected: 1
Received: 0

  26 |       // we created an entry and called revalidate, so we should have 1 entry
  27 |       await retry(async () => {
> 28 |         expect((await browser.elementsByCss('#entries li')).length).toBe(1)
     |                                                                     ^
  29 |       })
  30 |
  31 |       await browser.elementById('create-entry').click()

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:28:69)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:27:7)

● parallel-routes-revalidation › should refresh the correct page when a server action triggers a redirect

expect(received).toBe(expected) // Object.is equality

Expected: 0
Received: 1

  203 |       await retry(async () => {
  204 |         // confirm there aren't any entries yet
> 205 |         expect((await browser.elementsByCss('#entries li')).length).toBe(0)
      |                                                                     ^
  206 |       })
  207 |
  208 |       await browser.elementById('create-entry').click()

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:205:69)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:203:7)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: false › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.3767647597107058"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: false › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.4948174822229554"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: true › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.23899570584845242"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (regular) - searchParams: true › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.38638576178443396"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: false › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.6487662605834867"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: false › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.09761941012754916"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: true › should correctly refresh data for the intercepted route and previously active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.1557062886202616"

  285 |             .elementById('modal-random')
  286 |             .text()
> 287 |           expect(initialRandomNumber).not.toBe(newRandomNumber)
      |                                           ^
  288 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
  289 |
  290 |           if (withSearchParams) {

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:287:43)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:280:9)

● parallel-routes-revalidation › router.refresh (dynamic) - searchParams: true › should correctly refresh data for previously intercepted modal and active page slot

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.201542147856564"

  371 |             .elementById('other-page-random')
  372 |             .text()
> 373 |           expect(initialModalRandomNumber).not.toBe(newModalRandomNumber)
      |                                                ^
  374 |           expect(initialOtherPageRandomNumber).not.toBe(
  375 |             newOtherPageRandomNumber
  376 |           )

  at toBe (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:373:48)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:365:9)

● parallel-routes-revalidation › server action revalidation › handles refreshing when multiple parallel slots are active

expect(received).not.toEqual(expected) // deep equality

Expected: not "1765480781639"

  415 |
  416 |         // And the drawer should have a new time
> 417 |         expect(await browser.elementById('drawer-now').text()).not.toEqual(
      |                                                                    ^
  418 |           currentDrawerTime
  419 |         )
  420 |

  at toEqual (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:417:68)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts:409:7)

pnpm test-start test/e2e/app-dir/use-cache/use-cache.test.ts (job)

  • use-cache > should cache results for cached functions imported from client components (DD)
  • use-cache > should cache results for cached functions passed to client components (DD)
  • use-cache > should update after revalidateTag correctly (DD)
  • use-cache > should revalidate caches nested in unstable_cache (DD)
  • use-cache > should revalidate caches during on-demand revalidation (DD)
  • use-cache > should not use stale caches in server actions that have revalidated (DD)
  • use-cache > can reference server actions in "use cache" functions (DD)
  • use-cache > should be able to revalidate a page using revalidateTag (DD)
  • use-cache > works with useActionState if previousState parameter is not used in "use cache" function (DD)
  • use-cache > works with useActionState if previousState parameter is not used in "use cache" function (separate export) (DD)
  • use-cache > works with "use cache" in method props (DD)
  • use-cache > works with "use cache" in static class methods (DD)
  • use-cache > should not read nor write cached data when draft mode is enabled > js enabled, with cookies (DD)
  • use-cache > should not read nor write cached data when draft mode is enabled > js enabled, without cookies (DD)
Expand output

● use-cache › should cache results for cached functions imported from client components

expect(received).toMatch(expected)

Expected pattern: /\d\.\d+ \d\.\d+/
Received string:  "0 0 0"

  185 |     await retry(async () => {
  186 |       threeRandomValues = await browser.elementByCss('p').text()
> 187 |       expect(threeRandomValues).toMatch(/\d\.\d+ \d\.\d+/)
      |                                 ^
  188 |     })
  189 |
  190 |     await browser.elementById('reset-button').click()

  at toMatch (e2e/app-dir/use-cache/use-cache.test.ts:187:33)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:185:5)

● use-cache › should cache results for cached functions passed to client components

expect(received).toMatch(expected)

Expected pattern: /100\.\d+ 100\.\d+ 100\.\d+/
Received string:  "0 0 0"

  207 |     await retry(async () => {
  208 |       threeRandomValues = await browser.elementByCss('p').text()
> 209 |       expect(threeRandomValues).toMatch(/100\.\d+ 100\.\d+ 100\.\d+/)
      |                                 ^
  210 |     })
  211 |
  212 |     await browser.elementById('reset-button').click()

  at toMatch (e2e/app-dir/use-cache/use-cache.test.ts:209:33)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:207:5)

● use-cache › should update after revalidateTag correctly

expect(received).not.toBe(expected) // Object.is equality

Expected: not "[a, c] 0.5115329957333192 0.9556648660007647"

  229 |       await browser.elementByCss('#revalidate-path').click()
  230 |       await retry(async () => {
> 231 |         expect(await browser.elementByCss('#a').text()).not.toBe(initial)
      |                                                             ^
  232 |       })
  233 |     }
  234 |

  at toBe (e2e/app-dir/use-cache/use-cache.test.ts:231:61)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:230:7)

● use-cache › should revalidate caches nested in unstable_cache

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.9992642939211993"

  357 |
  358 |       await retry(async () => {
> 359 |         expect(await browser.elementByCss('p').text()).not.toBe(initial)
      |                                                            ^
  360 |       })
  361 |     }
  362 |

  at toBe (e2e/app-dir/use-cache/use-cache.test.ts:359:60)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:358:7)

● use-cache › should revalidate caches during on-demand revalidation

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.026712185996271565"

  383 |
  384 |       await retry(async () => {
> 385 |         expect(await browser.elementById('value').text()).not.toBe(initial)
      |                                                               ^
  386 |       })
  387 |     }
  388 |

  at toBe (e2e/app-dir/use-cache/use-cache.test.ts:385:63)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:384:7)

● use-cache › should not use stale caches in server actions that have revalidated

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#revalidate-tag:enabled') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/use-cache/use-cache.test.ts:409:19)

● use-cache › can reference server actions in "use cache" functions

expect(received).toBe(expected) // Object.is equality

Expected: "result"
Received: "initial"

  605 |
  606 |     await retry(async () => {
> 607 |       expect(await browser.elementByCss('p').text()).toBe('result')
      |                                                      ^
  608 |     })
  609 |   })
  610 |

  at toBe (e2e/app-dir/use-cache/use-cache.test.ts:607:54)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:606:5)

● use-cache › should be able to revalidate a page using revalidateTag

expect(received).not.toBe(expected) // Object.is equality

Expected: not "2025-12-11T19:19:26.301Z"

  623 |     await retry(async () => {
  624 |       const time3 = await browser.waitForElementByCss('#t').text()
> 625 |       expect(time3).not.toBe(time2)
      |                         ^
  626 |     })
  627 |
  628 |     // Reloading again should ideally be the same value but because the Action seeds

  at toBe (e2e/app-dir/use-cache/use-cache.test.ts:625:25)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:623:5)

● use-cache › works with useActionState if previousState parameter is not used in "use cache" function

expect(received).toMatch(expected)

Expected pattern: /\d\.\d+/
Received string:  "loading..."

  701 |     await retry(async () => {
  702 |       value = await browser.elementByCss('p').text()
> 703 |       expect(value).toMatch(/\d\.\d+/)
      |                     ^
  704 |     })
  705 |
  706 |     await browser.elementByCss('button').click()

  at toMatch (e2e/app-dir/use-cache/use-cache.test.ts:703:21)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:701:5)

● use-cache › works with useActionState if previousState parameter is not used in "use cache" function (separate export)

expect(received).toMatch(expected)

Expected pattern: /\d\.\d+/
Received string:  "loading..."

  721 |     await retry(async () => {
  722 |       value = await browser.elementByCss('p').text()
> 723 |       expect(value).toMatch(/\d\.\d+/)
      |                     ^
  724 |     })
  725 |
  726 |     await browser.elementByCss('button').click()

  at toMatch (e2e/app-dir/use-cache/use-cache.test.ts:723:21)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:721:5)

● use-cache › works with "use cache" in method props

expect(received).toMatch(expected)

Expected pattern: /1\.\d+/
Received string:  "loading..."

  746 |     await retry(async () => {
  747 |       value1 = await browser.elementByCss('#form-1 p').text()
> 748 |       expect(value1).toMatch(/1\.\d+/)
      |                      ^
  749 |     })
  750 |
  751 |     await browser.elementByCss('#form-2 button').click()

  at toMatch (e2e/app-dir/use-cache/use-cache.test.ts:748:22)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:746:5)

● use-cache › works with "use cache" in static class methods

expect(received).toMatch(expected)

Expected pattern: /\d\.\d+/
Received string:  "loading..."

  780 |     await retry(async () => {
  781 |       value = await browser.elementByCss('p').text()
> 782 |       expect(value).toMatch(/\d\.\d+/)
      |                     ^
  783 |     })
  784 |
  785 |     await browser.elementByCss('button').click()

  at toMatch (e2e/app-dir/use-cache/use-cache.test.ts:782:21)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/use-cache/use-cache.test.ts:780:5)

● use-cache › should not read nor write cached data when draft mode is enabled › js enabled, with cookies

expect(received).toMatchObject(expected)

Expected: ArrayContaining [{"message": "An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.", "source": "error"}]
Received: [{"message": "Next.js page already hydrated", "source": "log"}]

  890 |               : GENERIC_RSC_ERROR
  891 |
> 892 |           expect(logs).toMatchObject(
      |                        ^
  893 |             expect.arrayContaining([
  894 |               { source: 'error', message: expectedErrorMessage },
  895 |             ])

  at toMatchObject (e2e/app-dir/use-cache/use-cache.test.ts:892:24)
  at retry (lib/next-test-utils.ts:797:14)

● use-cache › should not read nor write cached data when draft mode is enabled › js enabled, without cookies

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('button#toggle:enabled') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at waitForElementByCss (e2e/app-dir/use-cache/use-cache.test.ts:900:21)

pnpm test-dev test/e2e/app-dir/actions/app-action-form-state.test.ts (job)

  • after() in edge runtime > does not allow modifying cookies in a callback (DD)
  • after() in nodejs runtime > does not allow modifying cookies in a callback (DD)
Expand output

● after() in nodejs runtime › does not allow modifying cookies in a callback

expect(received).toEqual(expected) // deep equality

Expected: "Cookie: \"action\""
Received: "Cookie: null"

  320 |       await retry(async () => {
  321 |         const cookie1 = await browser.elementById('cookie').text()
> 322 |         expect(cookie1).toEqual('Cookie: "action"')
      |                         ^
  323 |         const newLogs = next.cliOutput.slice(cliOutputIndex)
  324 |         // // after() from action
  325 |         expect(newLogs).toMatch(EXPECTED_ERROR)

  at toEqual (e2e/app-dir/next-after-app/index.test.ts:322:25)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/next-after-app/index.test.ts:320:7)

● after() in edge runtime › does not allow modifying cookies in a callback

expect(received).toEqual(expected) // deep equality

Expected: "Cookie: \"action\""
Received: "Cookie: null"

  320 |       await retry(async () => {
  321 |         const cookie1 = await browser.elementById('cookie').text()
> 322 |         expect(cookie1).toEqual('Cookie: "action"')
      |                         ^
  323 |         const newLogs = next.cliOutput.slice(cliOutputIndex)
  324 |         // // after() from action
  325 |         expect(newLogs).toMatch(EXPECTED_ERROR)

  at toEqual (e2e/app-dir/next-after-app/index.test.ts:322:25)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/next-after-app/index.test.ts:320:7)

pnpm test-start test/e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts (job)

  • runtime prefetching > in a page > includes cookies, but not dynamic content (DD)
  • runtime prefetching > in a private cache > includes cookies, but not dynamic content (DD)
  • runtime prefetching > passed to a public cache > includes cookies, but not dynamic content (DD)
Expand output

● runtime prefetching › in a page › includes cookies, but not dynamic content

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('a[href="/in-page/cookies"]') to be visible
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-page/cookies">/in-page/cookies (auto)</a>

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at elementByCss (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:483:27)
  at scope (lib/router-act.ts:296:33)
  at e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:481:9
  at act (lib/router-act.ts:296:27)
  at Object.<anonymous> (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:480:7)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:471:17)
  at click (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:483:72)
  at scope (lib/router-act.ts:296:33)
  at e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:481:9
  at act (lib/router-act.ts:296:27)
  at Object.<anonymous> (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:480:7)

● runtime prefetching › in a private cache › includes cookies, but not dynamic content

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('a[href="/in-private-cache/cookies"]') to be visible
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/in-private-cache/cookies">/in-private-cache/cookies (auto)</a>

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at elementByCss (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:483:27)
  at scope (lib/router-act.ts:296:33)
  at e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:481:9
  at act (lib/router-act.ts:296:27)
  at Object.<anonymous> (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:480:7)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:471:17)
  at click (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:483:72)
  at scope (lib/router-act.ts:296:33)
  at e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:481:9
  at act (lib/router-act.ts:296:27)
  at Object.<anonymous> (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:480:7)

● runtime prefetching › passed to a public cache › includes cookies, but not dynamic content

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('a[href="/passed-to-public-cache/cookies"]') to be visible
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>
  -   locator resolved to hidden <a href="/passed-to-public-cache/cookies">/passed-to-public-cache/cookies (auto)</a>

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at elementByCss (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:483:27)
  at scope (lib/router-act.ts:296:33)
  at e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:481:9
  at act (lib/router-act.ts:296:27)
  at Object.<anonymous> (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:480:7)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:471:17)
  at click (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:483:72)
  at scope (lib/router-act.ts:296:33)
  at e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:481:9
  at act (lib/router-act.ts:296:27)
  at Object.<anonymous> (e2e/app-dir/segment-cache/prefetch-runtime/prefetch-runtime.test.ts:480:7)

pnpm test-start-turbo test/e2e/app-dir/actions-navigation/index.test.ts (turbopack) (job)

  • app-dir action handling > should propagate errors from a text/plain response to an error boundary (DD)
  • app-dir action handling > should trigger an error boundary for action responses with an invalid content-type (DD)
  • app-dir action handling > should support notFound (DD)
  • app-dir action handling > should support importing the same action module instance in both server and action layers (DD)
  • app-dir action handling > should handle actions executed in quick succession (DD)
  • app-dir action handling > should reset the form state when the action redirects to a page that contains the same form (DD)
  • app-dir action handling > should work with interception routes (DD)
  • app-dir action handling > Edge SSR > should handle calls to redirect() with external URLs (DD)
  • app-dir action handling > encryption > should be able to resolve other server actions and client components (DD)
  • app-dir action handling > fetch actions > should handle calls to redirect() with external URLs (DD)
  • app-dir action handling > fetch actions > should handle revalidatePath (DD)
  • app-dir action handling > fetch actions > should handle revalidateTag (DD)
  • app-dir action handling > fetch actions > should store revalidation data in the prefetch cache (DD)
  • app-dir action handling > fetch actions > should revalidate when cookies.set is called (DD)
  • app-dir action handling > fetch actions > should invalidate client cache on other routes when cookies.set is called (DD)
  • app-dir action handling > fetch actions > should revalidate when cookies.set is called in a client action (DD)
  • app-dir action handling > fetch actions > should invalidate client cache when tag is revalidated (DD)
  • app-dir action handling > fetch actions > should invalidate client cache when path is revalidated (DD)
  • app-dir action handling > request body decoding > should correctly decode multi-byte characters in the request body (node) (DD)
  • app-dir action handling > request body decoding > should correctly decode multi-byte characters in the request body (edge) (DD)
  • app-dir action handling > server actions render client components > server component imported action > should support importing client components from actions (DD)
Expand output

● app-dir action handling › should propagate errors from a text/plain response to an error boundary

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#error-text') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/actions/app-action.test.ts:165:33)

● app-dir action handling › should trigger an error boundary for action responses with an invalid content-type

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#error-text') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/actions/app-action.test.ts:189:33)

● app-dir action handling › should support notFound

expect(received).toBe(expected) // Object.is equality

Expected: "my-not-found"
Received: "0"

  408 |     // Until not-found page is resolved
  409 |     await retry(async () => {
> 410 |       expect(await browser.elementByCss('h1').text()).toBe('my-not-found')
      |                                                       ^
  411 |     })
  412 |
  413 |     // Should have default noindex meta tag

  at toBe (e2e/app-dir/actions/app-action.test.ts:410:55)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:409:5)

● app-dir action handling › should support importing the same action module instance in both server and action layers

expect(received).toBe(expected) // Object.is equality

Expected: "Value = 1"
Received: "Value = 0"

  511 |     await browser.elementByCss('#server-inc').click()
  512 |     await retry(async () => {
> 513 |       expect(await browser.elementByCss('#value').text()).toBe('Value = 1')
      |                                                           ^
  514 |     })
  515 |
  516 |     await browser.elementByCss('#client-inc').click()

  at toBe (e2e/app-dir/actions/app-action.test.ts:513:59)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:512:5)

● app-dir action handling › should handle actions executed in quick succession

expect(received).toBe(expected) // Object.is equality

Expected: "Transition is: idle"
Received: "Transition is: pending"

  700 |     await retry(
  701 |       async () => {
> 702 |         expect(await browser.elementByCss('h1').text()).toBe(
      |                                                         ^
  703 |           'Transition is: idle'
  704 |         )
  705 |         expect(requestCount).toBe(6)

  at toBe (e2e/app-dir/actions/app-action.test.ts:702:57)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:700:5)

● app-dir action handling › should reset the form state when the action redirects to a page that contains the same form

expect(received).toBe(expected) // Object.is equality

Expected: true
Received: false

  723 |     // verify that the error state is displayed
  724 |     await retry(async () => {
> 725 |       expect(await browser.hasElementByCssSelector('#error')).toBe(true)
      |                                                               ^
  726 |       expect(await browser.elementByCss('#error').text()).toBe(
  727 |         "Only 'justputit' is accepted."
  728 |       )

  at toBe (e2e/app-dir/actions/app-action.test.ts:725:63)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:724:5)

● app-dir action handling › Edge SSR › should handle calls to redirect() with external URLs

expect(received).toBe(expected) // Object.is equality

Expected: "https://next-data-api-endpoint.vercel.app/api/random?page"
Received: "http://localhost:43879/api/random?page"

  1178 |
  1179 |       await retry(async () => {
> 1180 |         expect(await browser.url()).toBe(
       |                                     ^
  1181 |           'https://next-data-api-endpoint.vercel.app/api/random?page'
  1182 |         )
  1183 |       })

  at toBe (e2e/app-dir/actions/app-action.test.ts:1180:37)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1179:7)

● app-dir action handling › fetch actions › should handle calls to redirect() with external URLs

expect(received).toBe(expected) // Object.is equality

Expected: "https://next-data-api-endpoint.vercel.app/api/random?page"
Received: "http://localhost:43879/api/random?page"

  1291 |
  1292 |       await retry(async () => {
> 1293 |         expect(await browser.url()).toBe(
       |                                     ^
  1294 |           'https://next-data-api-endpoint.vercel.app/api/random?page'
  1295 |         )
  1296 |       })

  at toBe (e2e/app-dir/actions/app-action.test.ts:1293:37)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1292:7)

● app-dir action handling › fetch actions › should handle revalidatePath

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.17308999056061092"

  1335 |           .text()
  1336 |
> 1337 |         expect(newRandomNumber).not.toBe(randomNumber)
       |                                     ^
  1338 |         expect(newJustPutIt).not.toBe(justPutIt)
  1339 |         expect(newThankYouNext).not.toBe(thankYouNext)
  1340 |       })

  at toBe (e2e/app-dir/actions/app-action.test.ts:1337:37)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1328:7)

● app-dir action handling › fetch actions › should handle revalidateTag

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.12411309538737791"

  1358 |           .text()
  1359 |
> 1360 |         expect(newRandomNumber).not.toBe(randomNumber)
       |                                     ^
  1361 |         expect(newJustPutIt).not.toBe(justPutIt)
  1362 |         expect(newThankYouNext).toBe(thankYouNext)
  1363 |       })

  at toBe (e2e/app-dir/actions/app-action.test.ts:1360:37)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1351:7)

● app-dir action handling › fetch actions › should store revalidation data in the prefetch cache

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.5083703587549255"

  1395 |       await retry(async () => {
  1396 |         const newJustPutIt = await browser.elementByCss('#justputit').text()
> 1397 |         expect(newJustPutIt).not.toBe(justPutIt)
       |                                  ^
  1398 |       })
  1399 |
  1400 |       const newJustPutIt = await browser.elementByCss('#justputit').text()

  at toBe (e2e/app-dir/actions/app-action.test.ts:1397:34)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1395:7)

● app-dir action handling › fetch actions › should revalidate when cookies.set is called

expect(received).not.toBe(expected) // Object.is equality

Expected: not "{}"

  1427 |           .text()
  1428 |
> 1429 |         expect(newRandomNumber).not.toBe(randomNumber)
       |                                     ^
  1430 |       })
  1431 |     })
  1432 |

  at toBe (e2e/app-dir/actions/app-action.test.ts:1429:37)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1424:7)

● app-dir action handling › fetch actions › should invalidate client cache on other routes when cookies.set is called

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('#value') to be visible
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>
  -   locator resolved to hidden <p id="value"></p>

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at elementByCss (e2e/app-dir/actions/app-action.test.ts:1439:32)
  at fn (lib/next-test-utils.ts:797:20)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1438:7)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:433:17)
  at text (e2e/app-dir/actions/app-action.test.ts:1439:55)
  at fn (lib/next-test-utils.ts:797:20)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1438:7)

● app-dir action handling › fetch actions › should revalidate when cookies.set is called in a client action

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.0715034529388372"

  1499 |           await browser.elementByCss('#random-cookie').text()
  1500 |         ).cookie.value
> 1501 |         expect(revalidatedRandomCookie).not.toBe(randomCookie)
       |                                             ^
  1502 |       })
  1503 |
  1504 |       await browser.elementByCss('#another').click()

  at toBe (e2e/app-dir/actions/app-action.test.ts:1501:45)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1497:7)

● app-dir action handling › fetch actions › should invalidate client cache when tag is revalidated

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.18184670671159475"

  1553 |         await retry(async () => {
  1554 |           revalidated = await browser.elementByCss('#thankyounext').text()
> 1555 |           expect(revalidated).not.toBe(original)
       |                                   ^
  1556 |         })
  1557 |
  1558 |         await browser.elementByCss('#another').click()

  at toBe (e2e/app-dir/actions/app-action.test.ts:1555:35)
  at retry (lib/next-test-utils.ts:797:14)
  at e2e/app-dir/actions/app-action.test.ts:1553:9

● app-dir action handling › fetch actions › should invalidate client cache when path is revalidated

expect(received).not.toBe(expected) // Object.is equality

Expected: not "0.6433367192869555"

  1553 |         await retry(async () => {
  1554 |           revalidated = await browser.elementByCss('#thankyounext').text()
> 1555 |           expect(revalidated).not.toBe(original)
       |                                   ^
  1556 |         })
  1557 |
  1558 |         await browser.elementByCss('#another').click()

  at toBe (e2e/app-dir/actions/app-action.test.ts:1555:35)
  at retry (lib/next-test-utils.ts:797:14)
  at e2e/app-dir/actions/app-action.test.ts:1553:9

● app-dir action handling › should work with interception routes

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#submit-intercept-action-response') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/actions/app-action.test.ts:1596:41)

● app-dir action handling › encryption › should be able to resolve other server actions and client components

expect(received).toBe(expected) // Object.is equality

Expected: "hello from client"
Received: "initial"

  1636 |
  1637 |       await retry(async () => {
> 1638 |         expect(await browser.elementByCss('p').text()).toBe('hello from client')
       |                                                        ^
  1639 |       })
  1640 |     })
  1641 |   })

  at toBe (e2e/app-dir/actions/app-action.test.ts:1638:56)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1637:7)

● app-dir action handling › server actions render client components › server component imported action › should support importing client components from actions

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#client-component') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1820:11)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:632:17)
  at Proxy.startChain (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/actions/app-action.test.ts:1823:14)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:433:17)
  at Object.text (e2e/app-dir/actions/app-action.test.ts:1824:14)

● app-dir action handling › request body decoding › should correctly decode multi-byte characters in the request body (node)

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('p') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at elementByCss (e2e/app-dir/actions/app-action.test.ts:1919:38)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:433:17)
  at text (e2e/app-dir/actions/app-action.test.ts:1919:56)

● app-dir action handling › request body decoding › should correctly decode multi-byte characters in the request body (edge)

page.waitForSelector: Timeout 5000ms exceeded.
Call log:
  - waiting for locator('p') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Playwright.waitForElementByCss [as elementByCss] (lib/browsers/playwright.ts:405:17)
  at elementByCss (e2e/app-dir/actions/app-action.test.ts:1919:38)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:433:17)
  at text (e2e/app-dir/actions/app-action.test.ts:1919:56)

pnpm test-start test/e2e/app-dir/actions/app-action-size-limit-invalid-node-middleware.test.ts (job)

  • app dir - navigation > browser back to a revalidated page > should load the page (DD)
  • app dir - navigation > external push > should push external url without affecting hooks (DD)
  • app dir - navigation > redirect > components > should redirect to external url, initiating only once (DD)
Expand output

● app dir - navigation › redirect › components › should redirect to external url, initiating only once

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('h1') to be visible

  519 |
  520 |     return this.startChain(async () => {
> 521 |       const el = await page.waitForSelector(selector, {
      |                             ^
  522 |         timeout,
  523 |         state,
  524 |       })

  at waitForSelector (lib/browsers/playwright.ts:521:29)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:632:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:520:17)
  at Object.waitForElementByCss (e2e/app-dir/navigation/navigation.test.ts:466:30)
  at Proxy._chain (lib/browsers/playwright.ts:651:23)
  at Proxy._chain (lib/browsers/playwright.ts:627:17)
  at Proxy.continueChain (lib/browsers/playwright.ts:433:17)
  at Object.text (e2e/app-dir/navigation/navigation.test.ts:466:56)

● app dir - navigation › external push › should push external url without affecting hooks

page.waitForFunction: Timeout 60000ms exceeded.

  539 |   waitForCondition(snippet: string, timeout?: number) {
  540 |     return this.startOrPreserveChain(async () => {
> 541 |       await page.waitForFunction(snippet, { timeout })
      |                  ^
  542 |     })
  543 |   }
  544 |

  at waitForFunction (lib/browsers/playwright.ts:541:18)
  at nextCall (lib/browsers/playwright.ts:638:13)
  at Playwright._chain (lib/browsers/playwright.ts:651:23)
  at Playwright._chain [as startOrPreserveChain] (lib/browsers/playwright.ts:637:17)
  at Playwright.startOrPreserveChain [as waitForCondition] (lib/browsers/playwright.ts:540:17)
  at Object.waitForCondition (e2e/app-dir/navigation/navigation.test.ts:613:21)

● app dir - navigation › browser back to a revalidated page › should load the page

expect(received).toContain(expected) // indexOf

Expected substring: "Form Submitted."
Received string:    "Form
Push this button to submit the form"

  966 |
  967 |       await retry(async () => {
> 968 |         expect(await browser.elementByCss('body').text()).toContain(
      |                                                           ^
  969 |           'Form Submitted.'
  970 |         )
  971 |       })

  at toContain (e2e/app-dir/navigation/navigation.test.ts:968:59)
  at retry (lib/next-test-utils.ts:797:14)
  at Object.<anonymous> (e2e/app-dir/navigation/navigation.test.ts:967:7)

nextjs-bot avatar Dec 10 '25 02:12 nextjs-bot

Stats from current PR

Default Build (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
buildDuration 16.8s 15.1s N/A
buildDurationCached 13.6s 11s N/A
nodeModulesSize 456 MB 457 MB ⚠️ +566 kB
nextStartRea..uration (ms) 711ms 718ms N/A
Client Bundles (main, webpack) Overall increase ⚠️
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
4951-HASH.js gzip 5.37 kB 5.38 kB N/A
68680909-HASH.js gzip 62.3 kB 62.3 kB N/A
8034-HASH.js gzip 52.8 kB 54 kB ⚠️ +1.24 kB
9564.HASH.js gzip 170 B 168 B N/A
9565-HASH.js gzip 4.46 kB 4.48 kB N/A
framework-HASH.js gzip 59.7 kB 59.7 kB N/A
main-app-HASH.js gzip 255 B 252 B N/A
main-HASH.js gzip 38.6 kB 38.5 kB N/A
webpack-HASH.js gzip 1.69 kB 1.69 kB N/A
Overall change 52.8 kB 54 kB ⚠️ +1.24 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Overall change 39.4 kB 39.4 kB
Client Pages
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
_app-HASH.js gzip 192 B 194 B N/A
_error-HASH.js gzip 183 B 182 B N/A
css-HASH.js gzip 334 B 333 B N/A
dynamic-HASH.js gzip 1.79 kB 1.81 kB N/A
edge-ssr-HASH.js gzip 254 B 255 B N/A
head-HASH.js gzip 352 B 349 B N/A
hooks-HASH.js gzip 383 B 378 B N/A
image-HASH.js gzip 580 B 581 B N/A
index-HASH.js gzip 259 B 258 B N/A
link-HASH.js gzip 2.51 kB 2.5 kB N/A
routerDirect..HASH.js gzip 317 B 319 B N/A
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 314 B 312 B N/A
1afbb74e6ecf..834.css gzip 106 B 106 B
Overall change 492 B 492 B
Client Build Manifests
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
_buildManifest.js gzip 735 B 738 B N/A
Overall change 0 B 0 B
Rendered Page Sizes
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
index.html gzip 521 B 522 B N/A
link.html gzip 538 B 538 B
withRouter.html gzip 520 B 519 B N/A
Overall change 538 B 538 B
Edge SSR bundle Size Overall increase ⚠️
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
edge-ssr.js gzip 124 kB 124 kB N/A
page.js gzip 236 kB 237 kB ⚠️ +1.09 kB
Overall change 236 kB 237 kB ⚠️ +1.09 kB
Middleware size
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
middleware-b..fest.js gzip 652 B 653 B N/A
middleware-r..fest.js gzip 156 B 156 B
middleware.js gzip 32.8 kB 32.9 kB N/A
edge-runtime..pack.js gzip 846 B 846 B
Overall change 1 kB 1 kB
Next Runtimes Overall increase ⚠️
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
app-page-exp...dev.js gzip 301 kB 302 kB ⚠️ +1 kB
app-page-exp..prod.js gzip 155 kB 155 kB N/A
app-page-tur...dev.js gzip 301 kB 302 kB ⚠️ +1 kB
app-page-tur..prod.js gzip 155 kB 155 kB N/A
app-page-tur...dev.js gzip 297 kB 298 kB ⚠️ +1.02 kB
app-page-tur..prod.js gzip 153 kB 153 kB N/A
app-page.run...dev.js gzip 297 kB 298 kB ⚠️ +1.02 kB
app-page.run..prod.js gzip 153 kB 153 kB N/A
app-route-ex...dev.js gzip 68.6 kB 68.6 kB
app-route-ex..prod.js gzip 47.5 kB 47.5 kB
app-route-tu...dev.js gzip 68.7 kB 68.7 kB
app-route-tu..prod.js gzip 47.5 kB 47.5 kB
app-route-tu...dev.js gzip 68.3 kB 68.3 kB
app-route-tu..prod.js gzip 47.2 kB 47.2 kB
app-route.ru...dev.js gzip 68.2 kB 68.2 kB
app-route.ru..prod.js gzip 47.2 kB 47.2 kB
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 328 B 328 B
dist_client_...dev.js gzip 320 B 320 B
dist_client_...dev.js gzip 318 B 318 B
pages-api-tu...dev.js gzip 41 kB 41 kB
pages-api-tu..prod.js gzip 31.1 kB 31.1 kB
pages-api.ru...dev.js gzip 41 kB 41 kB
pages-api.ru..prod.js gzip 31.1 kB 31.1 kB
pages-turbo....dev.js gzip 50.5 kB 50.5 kB
pages-turbo...prod.js gzip 38 kB 38 kB
pages.runtim...dev.js gzip 50.5 kB 50.5 kB
pages.runtim..prod.js gzip 38 kB 38 kB
server.runti..prod.js gzip 59.8 kB 59.8 kB
Overall change 2.04 MB 2.05 MB ⚠️ +4.05 kB
build cache Overall increase ⚠️
vercel/next.js canary acdlite/next.js remove-async-await-from-navigate-reducer Change
0.pack gzip 3.1 MB 3.84 MB ⚠️ +734 kB
index.pack gzip 93.8 kB 110 kB ⚠️ +15.8 kB
Overall change 3.2 MB 3.94 MB ⚠️ +750 kB
Diff details
Diff for page.js

Diff too large to display

Diff for middleware.js

Diff too large to display

Diff for edge-ssr.js

Diff too large to display

Diff for _buildManifest.js
@@ -611,35 +611,35 @@ self.__BUILD_MANIFEST = (function (a, b, c) {
       numHashes: NaN,
       bitArray: [],
     },
-    "/": ["static\u002Fchunks\u002Fpages\u002Findex-b087a17851e05d6f.js"],
+    "/": ["static\u002Fchunks\u002Fpages\u002Findex-3361ed053e34d664.js"],
     "/_error": [
-      "static\u002Fchunks\u002Fpages\u002F_error-0d6cadd1684bf608.js",
+      "static\u002Fchunks\u002Fpages\u002F_error-c7ffde23a6d1e061.js",
     ],
     "/css": [
       "static\u002Fcss\u002Fded6b86ab9cc0a1f.css",
-      "static\u002Fchunks\u002Fpages\u002Fcss-d018beb4ee617700.js",
+      "static\u002Fchunks\u002Fpages\u002Fcss-0b6177a056485c89.js",
     ],
     "/dynamic": [
-      "static\u002Fchunks\u002Fpages\u002Fdynamic-22fa1f98925287e3.js",
+      "static\u002Fchunks\u002Fpages\u002Fdynamic-8e7954693aad6744.js",
     ],
     "/edge-ssr": [
-      "static\u002Fchunks\u002Fpages\u002Fedge-ssr-79392016bf448b0e.js",
+      "static\u002Fchunks\u002Fpages\u002Fedge-ssr-7515805a0793fb50.js",
     ],
-    "/head": ["static\u002Fchunks\u002Fpages\u002Fhead-7c5bbe7e16e0461c.js"],
-    "/hooks": ["static\u002Fchunks\u002Fpages\u002Fhooks-9fbae4ac20575871.js"],
+    "/head": ["static\u002Fchunks\u002Fpages\u002Fhead-18530459356f6f47.js"],
+    "/hooks": ["static\u002Fchunks\u002Fpages\u002Fhooks-221843a8082c5fe0.js"],
     "/image": [
-      "static\u002Fchunks\u002F9565-2e0c4004742fb14a.js",
-      "static\u002Fchunks\u002Fpages\u002Fimage-811425894781cf7d.js",
+      "static\u002Fchunks\u002F5467-5440e689c12d4e40.js",
+      "static\u002Fchunks\u002Fpages\u002Fimage-fe20cdcfe67a7d4d.js",
     ],
-    "/link": ["static\u002Fchunks\u002Fpages\u002Flink-14068c948da9dc39.js"],
+    "/link": ["static\u002Fchunks\u002Fpages\u002Flink-814c1a2b0c6775c5.js"],
     "/routerDirect": [
-      "static\u002Fchunks\u002Fpages\u002FrouterDirect-6d3e9dcd1348423d.js",
+      "static\u002Fchunks\u002Fpages\u002FrouterDirect-a0028e2a28aa8c85.js",
     ],
     "/script": [
-      "static\u002Fchunks\u002Fpages\u002Fscript-eda35f71f7a910ba.js",
+      "static\u002Fchunks\u002Fpages\u002Fscript-5b734e02315dd67a.js",
     ],
     "/withRouter": [
-      "static\u002Fchunks\u002Fpages\u002FwithRouter-4a6d5ec263e28451.js",
+      "static\u002Fchunks\u002Fpages\u002FwithRouter-db2aefa859481ae2.js",
     ],
     sortedPages: [
       "\u002F",
Diff for css-HASH.js
@@ -1,14 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9813],
   {
-    /***/ 1361: /***/ (module) => {
-      // extracted by mini-css-extract-plugin
-      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
-
-      /***/
-    },
-
-    /***/ 1651: /***/ (
+    /***/ 942: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -16,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/css",
         function () {
-          return __webpack_require__(3321);
+          return __webpack_require__(3023);
         },
       ]);
       if (false) {
@@ -25,7 +18,7 @@
       /***/
     },
 
-    /***/ 3321: /***/ (
+    /***/ 3023: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -39,7 +32,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7002);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(1361);
+        __webpack_require__(3264);
       /* 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 @@
 
       /***/
     },
+
+    /***/ 3264: /***/ (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__(1651)
+      __webpack_exec__(942)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for dynamic-HASH.js
@@ -1,177 +1,17 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2291],
   {
-    /***/ 617: /***/ (
-      __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__(6466)
-      );
-      const LoadableContext = _react.default.createContext(null);
-      if (false) {
-      } //# sourceMappingURL=loadable-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 620: /***/ (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, {
-        /**
-         * This function lets you dynamically import a component.
-         * It uses [React.lazy()](https://react.dev/reference/react/lazy) with [Suspense](https://react.dev/reference/react/Suspense) under the hood.
-         *
-         * Read more: [Next.js Docs: `next/dynamic`](https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading#nextdynamic)
-         */ default: function () {
-          return dynamic;
-        },
-        noSSR: function () {
-          return noSSR;
-        },
-      });
-      const _interop_require_default = __webpack_require__(1532);
-      const _jsxruntime = __webpack_require__(7002);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(6466)
-      );
-      const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(3147)
-      );
-      const isServerSide = "object" === "undefined";
-      // Normalize loader to return the module as form { default: Component } for `React.lazy`.
-      // Also for backward compatible since next/dynamic allows to resolve a component directly with loader
-      // Client component reference proxy need to be converted to a module.
-      function convertModule(mod) {
-        return {
-          default: mod?.default || mod,
-        };
-      }
-      function noSSR(LoadableInitializer, loadableOptions) {
-        // Removing webpack and modules means react-loadable won't try preloading
-        delete loadableOptions.webpack;
-        delete loadableOptions.modules;
-        // This check is necessary to prevent react-loadable from initializing on the server
-        if (!isServerSide) {
-          return LoadableInitializer(loadableOptions);
-        }
-        const Loading = loadableOptions.loading;
-        // This will only be rendered on the server side
-        return () =>
-          /*#__PURE__*/ (0, _jsxruntime.jsx)(Loading, {
-            error: null,
-            isLoading: true,
-            pastDelay: false,
-            timedOut: false,
-          });
-      }
-      function dynamic(dynamicOptions, options) {
-        let loadableFn = _loadablesharedruntime.default;
-        let loadableOptions = {
-          // A loading component is not required, so we default it
-          loading: ({ error, isLoading, pastDelay }) => {
-            if (!pastDelay) return null;
-            if (false) {
-            }
-            return null;
-          },
-        };
-        // Support for direct import(), eg: dynamic(import('../hello-world'))
-        // Note that this is only kept for the edge case where someone is passing in a promise as first argument
-        // The react-loadable babel plugin will turn dynamic(import('../hello-world')) into dynamic(() => import('../hello-world'))
-        // To make sure we don't execute the import without rendering first
-        if (dynamicOptions instanceof Promise) {
-          loadableOptions.loader = () => dynamicOptions;
-          // Support for having import as a function, eg: dynamic(() => import('../hello-world'))
-        } else if (typeof dynamicOptions === "function") {
-          loadableOptions.loader = dynamicOptions;
-          // Support for having first argument being options, eg: dynamic({loader: import('../hello-world')})
-        } else if (typeof dynamicOptions === "object") {
-          loadableOptions = {
-            ...loadableOptions,
-            ...dynamicOptions,
-          };
-        }
-        // Support for passing options, eg: dynamic(import('../hello-world'), {loading: () => <p>Loading something</p>})
-        loadableOptions = {
-          ...loadableOptions,
-          ...options,
-        };
-        const loaderFn = loadableOptions.loader;
-        const loader = () =>
-          loaderFn != null
-            ? loaderFn().then(convertModule)
-            : Promise.resolve(convertModule(() => null));
-        // coming from build/babel/plugins/react-loadable-plugin.js
-        if (loadableOptions.loadableGenerated) {
-          loadableOptions = {
-            ...loadableOptions,
-            ...loadableOptions.loadableGenerated,
-          };
-          delete loadableOptions.loadableGenerated;
-        }
-        // support for disabling server side rendering, eg: dynamic(() => import('../hello-world'), {ssr: false}).
-        if (typeof loadableOptions.ssr === "boolean" && !loadableOptions.ssr) {
-          delete loadableOptions.webpack;
-          delete loadableOptions.modules;
-          return noSSR(loadableFn, loadableOptions);
-        }
-        return loadableFn({
-          ...loadableOptions,
-          loader: loader,
-        });
-      }
-      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=dynamic.js.map
-
-      /***/
-    },
-
-    /***/ 1173: /***/ (
+    /***/ 1151: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(620);
+      module.exports = __webpack_require__(7368);
 
       /***/
     },
 
-    /***/ 2907: /***/ (
+    /***/ 4773: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -186,7 +26,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7002);
       /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(1173);
+        __webpack_require__(1151);
       /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_dynamic__WEBPACK_IMPORTED_MODULE_1__
@@ -195,12 +35,12 @@
       const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
         () =>
           __webpack_require__
-            .e(/* import() */ 9564)
-            .then(__webpack_require__.bind(__webpack_require__, 9564))
+            .e(/* import() */ 6022)
+            .then(__webpack_require__.bind(__webpack_require__, 6022))
             .then((mod) => mod.Hello),
         {
           loadableGenerated: {
-            webpack: () => [/*require.resolve*/ 9564],
+            webpack: () => [/*require.resolve*/ 6022],
           },
         }
       );
@@ -227,7 +67,7 @@
       /***/
     },
 
-    /***/ 3147: /***/ (
+    /***/ 5631: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -269,7 +109,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       const _react = /*#__PURE__*/ _interop_require_default._(
         __webpack_require__(6466)
       );
-      const _loadablecontextsharedruntime = __webpack_require__(617);
+      const _loadablecontextsharedruntime = __webpack_require__(6861);
       function resolve(obj) {
         return obj && obj.default ? obj.default : obj;
       }
@@ -502,7 +342,167 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /***/
     },
 
-    /***/ 4236: /***/ (
+    /***/ 6861: /***/ (
+      __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__(6466)
+      );
+      const LoadableContext = _react.default.createContext(null);
+      if (false) {
+      } //# sourceMappingURL=loadable-context.shared-runtime.js.map
+
+      /***/
+    },
+
+    /***/ 7368: /***/ (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, {
+        /**
+         * This function lets you dynamically import a component.
+         * It uses [React.lazy()](https://react.dev/reference/react/lazy) with [Suspense](https://react.dev/reference/react/Suspense) under the hood.
+         *
+         * Read more: [Next.js Docs: `next/dynamic`](https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading#nextdynamic)
+         */ default: function () {
+          return dynamic;
+        },
+        noSSR: function () {
+          return noSSR;
+        },
+      });
+      const _interop_require_default = __webpack_require__(1532);
+      const _jsxruntime = __webpack_require__(7002);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(6466)
+      );
+      const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(5631)
+      );
+      const isServerSide = "object" === "undefined";
+      // Normalize loader to return the module as form { default: Component } for `React.lazy`.
+      // Also for backward compatible since next/dynamic allows to resolve a component directly with loader
+      // Client component reference proxy need to be converted to a module.
+      function convertModule(mod) {
+        return {
+          default: mod?.default || mod,
+        };
+      }
+      function noSSR(LoadableInitializer, loadableOptions) {
+        // Removing webpack and modules means react-loadable won't try preloading
+        delete loadableOptions.webpack;
+        delete loadableOptions.modules;
+        // This check is necessary to prevent react-loadable from initializing on the server
+        if (!isServerSide) {
+          return LoadableInitializer(loadableOptions);
+        }
+        const Loading = loadableOptions.loading;
+        // This will only be rendered on the server side
+        return () =>
+          /*#__PURE__*/ (0, _jsxruntime.jsx)(Loading, {
+            error: null,
+            isLoading: true,
+            pastDelay: false,
+            timedOut: false,
+          });
+      }
+      function dynamic(dynamicOptions, options) {
+        let loadableFn = _loadablesharedruntime.default;
+        let loadableOptions = {
+          // A loading component is not required, so we default it
+          loading: ({ error, isLoading, pastDelay }) => {
+            if (!pastDelay) return null;
+            if (false) {
+            }
+            return null;
+          },
+        };
+        // Support for direct import(), eg: dynamic(import('../hello-world'))
+        // Note that this is only kept for the edge case where someone is passing in a promise as first argument
+        // The react-loadable babel plugin will turn dynamic(import('../hello-world')) into dynamic(() => import('../hello-world'))
+        // To make sure we don't execute the import without rendering first
+        if (dynamicOptions instanceof Promise) {
+          loadableOptions.loader = () => dynamicOptions;
+          // Support for having import as a function, eg: dynamic(() => import('../hello-world'))
+        } else if (typeof dynamicOptions === "function") {
+          loadableOptions.loader = dynamicOptions;
+          // Support for having first argument being options, eg: dynamic({loader: import('../hello-world')})
+        } else if (typeof dynamicOptions === "object") {
+          loadableOptions = {
+            ...loadableOptions,
+            ...dynamicOptions,
+          };
+        }
+        // Support for passing options, eg: dynamic(import('../hello-world'), {loading: () => <p>Loading something</p>})
+        loadableOptions = {
+          ...loadableOptions,
+          ...options,
+        };
+        const loaderFn = loadableOptions.loader;
+        const loader = () =>
+          loaderFn != null
+            ? loaderFn().then(convertModule)
+            : Promise.resolve(convertModule(() => null));
+        // coming from build/babel/plugins/react-loadable-plugin.js
+        if (loadableOptions.loadableGenerated) {
+          loadableOptions = {
+            ...loadableOptions,
+            ...loadableOptions.loadableGenerated,
+          };
+          delete loadableOptions.loadableGenerated;
+        }
+        // support for disabling server side rendering, eg: dynamic(() => import('../hello-world'), {ssr: false}).
+        if (typeof loadableOptions.ssr === "boolean" && !loadableOptions.ssr) {
+          delete loadableOptions.webpack;
+          delete loadableOptions.modules;
+          return noSSR(loadableFn, loadableOptions);
+        }
+        return loadableFn({
+          ...loadableOptions,
+          loader: loader,
+        });
+      }
+      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=dynamic.js.map
+
+      /***/
+    },
+
+    /***/ 8258: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -510,7 +510,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/dynamic",
         function () {
-          return __webpack_require__(2907);
+          return __webpack_require__(4773);
         },
       ]);
       if (false) {
@@ -524,7 +524,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(4236)
+      __webpack_exec__(8258)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for head-HASH.js
@@ -1,24 +1,13 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [5350],
   {
-    /***/ 2366: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/head",
-        function () {
-          return __webpack_require__(8140);
-        },
-      ]);
-      if (false) {
-      }
+    /***/ 48: /***/ (module, __unused_webpack_exports, __webpack_require__) => {
+      module.exports = __webpack_require__(8141);
 
       /***/
     },
 
-    /***/ 8140: /***/ (
+    /***/ 2682: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -33,7 +22,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7002);
       /* harmony import */ var next_head__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(9386);
+        __webpack_require__(48);
       /* harmony import */ var next_head__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_head__WEBPACK_IMPORTED_MODULE_1__
@@ -67,12 +56,19 @@
       /***/
     },
 
-    /***/ 9386: /***/ (
-      module,
+    /***/ 2956: /***/ (
+      __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(1649);
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/head",
+        function () {
+          return __webpack_require__(2682);
+        },
+      ]);
+      if (false) {
+      }
 
       /***/
     },
@@ -82,7 +78,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(2366)
+      __webpack_exec__(2956)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for image-HASH.js
@@ -1,7 +1,24 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2983],
   {
-    /***/ 497: /***/ (
+    /***/ 8114: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/image",
+        function () {
+          return __webpack_require__(9180);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 9180: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -18,8 +35,8 @@
 
       // EXTERNAL MODULE: ./node_modules/.pnpm/[email protected]/node_modules/react/jsx-runtime.js
       var jsx_runtime = __webpack_require__(7002);
-      // EXTERNAL MODULE: ./node_modules/.pnpm/next@[email protected][email protected][email protected]/node_modules/next/image.js
-      var next_image = __webpack_require__(9565);
+      // EXTERNAL MODULE: ./node_modules/.pnpm/next@[email protected][email protected][email protected]/node_modules/next/image.js
+      var next_image = __webpack_require__(5467);
       var image_default = /*#__PURE__*/ __webpack_require__.n(next_image); // ./pages/nextjs.png
       /* harmony default export */ const nextjs = {
         src: "/_next/static/media/nextjs.cae0b805.png",
@@ -48,30 +65,13 @@
 
       /***/
     },
-
-    /***/ 5748: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/image",
-        function () {
-          return __webpack_require__(497);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
-    /******/ __webpack_require__.O(0, [9565, 636, 6593, 8792], () =>
-      __webpack_exec__(5748)
+    /******/ __webpack_require__.O(0, [5467, 636, 6593, 8792], () =>
+      __webpack_exec__(8114)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for link-HASH.js
@@ -1,7 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [4672],
   {
-    /***/ 1182: /***/ (
+    /***/ 2156: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/link",
         function () {
-          return __webpack_require__(4610);
+          return __webpack_require__(8272);
         },
       ]);
       if (false) {
@@ -18,7 +18,220 @@
       /***/
     },
 
-    /***/ 1557: /***/ (module, exports, __webpack_require__) => {
+    /***/ 4581: /***/ (module, exports, __webpack_require__) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "useIntersection", {
+        enumerable: true,
+        get: function () {
+          return useIntersection;
+        },
+      });
+      const _react = __webpack_require__(6466);
+      const _requestidlecallback = __webpack_require__(7441);
+      const hasIntersectionObserver =
+        typeof IntersectionObserver === "function";
+      const observers = new Map();
+      const idList = [];
+      function createObserver(options) {
+        const id = {
+          root: options.root || null,
+          margin: options.rootMargin || "",
+        };
+        const existing = idList.find(
+          (obj) => obj.root === id.root && obj.margin === id.margin
+        );
+        let instance;
+        if (existing) {
+          instance = observers.get(existing);
+          if (instance) {
+            return instance;
+          }
+        }
+        const elements = new Map();
+        const observer = new IntersectionObserver((entries) => {
+          entries.forEach((entry) => {
+            const callback = elements.get(entry.target);
+            const isVisible =
+              entry.isIntersecting || entry.intersectionRatio > 0;
+            if (callback && isVisible) {
+              callback(isVisible);
+            }
+          });
+        }, options);
+        instance = {
+          id,
+          observer,
+          elements,
+        };
+        idList.push(id);
+        observers.set(id, instance);
+        return instance;
+      }
+      function observe(element, callback, options) {
+        const { id, observer, elements } = createObserver(options);
+        elements.set(element, callback);
+        observer.observe(element);
+        return function unobserve() {
+          elements.delete(element);
+          observer.unobserve(element);
+          // Destroy observer when there's nothing left to watch:
+          if (elements.size === 0) {
+            observer.disconnect();
+            observers.delete(id);
+            const index = idList.findIndex(
+              (obj) => obj.root === id.root && obj.margin === id.margin
+            );
+            if (index > -1) {
+              idList.splice(index, 1);
+            }
+          }
+        };
+      }
+      function useIntersection({ rootRef, rootMargin, disabled }) {
+        const isDisabled = disabled || !hasIntersectionObserver;
+        const [visible, setVisible] = (0, _react.useState)(false);
+        const elementRef = (0, _react.useRef)(null);
+        const setElement = (0, _react.useCallback)((element) => {
+          elementRef.current = element;
+        }, []);
+        (0, _react.useEffect)(() => {
+          if (hasIntersectionObserver) {
+            if (isDisabled || visible) return;
+            const element = elementRef.current;
+            if (element && element.tagName) {
+              const unobserve = observe(
+                element,
+                (isVisible) => isVisible && setVisible(isVisible),
+                {
+                  root: rootRef?.current,
+                  rootMargin,
+                }
+              );
+              return unobserve;
+            }
+          } else {
+            if (!visible) {
+              const idleCallback = (0,
+              _requestidlecallback.requestIdleCallback)(() => setVisible(true));
+              return () =>
+                (0, _requestidlecallback.cancelIdleCallback)(idleCallback);
+            }
+          }
+          // eslint-disable-next-line react-hooks/exhaustive-deps
+        }, [isDisabled, rootMargin, rootRef, visible, elementRef.current]);
+        const resetVisible = (0, _react.useCallback)(() => {
+          setVisible(false);
+        }, []);
+        return [setElement, visible, resetVisible];
+      }
+      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-intersection.js.map
+
+      /***/
+    },
+
+    /***/ 6155: /***/ (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__(6466);
+      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 (previously 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
+
+      /***/
+    },
+
+    /***/ 7046: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(8113);
+
+      /***/
+    },
+
+    /***/ 8113: /***/ (module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -45,17 +258,17 @@
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
         __webpack_require__(6466)
       );
-      const _resolvehref = __webpack_require__(5475);
-      const _islocalurl = __webpack_require__(6475);
-      const _formaturl = __webpack_require__(9998);
-      const _utils = __webpack_require__(3084);
-      const _addlocale = __webpack_require__(3921);
-      const _routercontextsharedruntime = __webpack_require__(7726);
-      const _useintersection = __webpack_require__(4806);
-      const _getdomainlocale = __webpack_require__(3219);
-      const _addbasepath = __webpack_require__(5498);
-      const _usemergedref = __webpack_require__(3255);
-      const _erroronce = __webpack_require__(1685);
+      const _resolvehref = __webpack_require__(2399);
+      const _islocalurl = __webpack_require__(6687);
+      const _formaturl = __webpack_require__(4802);
+      const _utils = __webpack_require__(9208);
+      const _addlocale = __webpack_require__(9845);
+      const _routercontextsharedruntime = __webpack_require__(3466);
+      const _useintersection = __webpack_require__(4581);
+      const _getdomainlocale = __webpack_require__(8319);
+      const _addbasepath = __webpack_require__(4126);
+      const _usemergedref = __webpack_require__(6155);
+      const _erroronce = __webpack_require__(8305);
       const prefetched = new Set();
       function prefetch(router, href, as, options) {
         if (false) {
@@ -434,140 +647,7 @@
       /***/
     },
 
-    /***/ 1685: /***/ (__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
-
-      /***/
-    },
-
-    /***/ 3219: /***/ (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__(1059);
-      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
-
-      /***/
-    },
-
-    /***/ 3255: /***/ (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__(6466);
-      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 (previously 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
-
-      /***/
-    },
-
-    /***/ 4610: /***/ (
+    /***/ 8272: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -582,7 +662,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7002);
       /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(9056);
+        __webpack_require__(7046);
       /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_link__WEBPACK_IMPORTED_MODULE_1__
@@ -613,115 +693,45 @@
       /***/
     },
 
-    /***/ 4806: /***/ (module, exports, __webpack_require__) => {
+    /***/ 8305: /***/ (__unused_webpack_module, exports) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
-      Object.defineProperty(exports, "useIntersection", {
+      Object.defineProperty(exports, "errorOnce", {
         enumerable: true,
         get: function () {
-          return useIntersection;
+          return errorOnce;
         },
       });
-      const _react = __webpack_require__(6466);
-      const _requestidlecallback = __webpack_require__(805);
-      const hasIntersectionObserver =
-        typeof IntersectionObserver === "function";
-      const observers = new Map();
-      const idList = [];
-      function createObserver(options) {
-        const id = {
-          root: options.root || null,
-          margin: options.rootMargin || "",
-        };
-        const existing = idList.find(
-          (obj) => obj.root === id.root && obj.margin === id.margin
-        );
-        let instance;
-        if (existing) {
-          instance = observers.get(existing);
-          if (instance) {
-            return instance;
-          }
+      let errorOnce = (_) => {};
+      if (false) {
+      } //# sourceMappingURL=error-once.js.map
+
+      /***/
+    },
+
+    /***/ 8319: /***/ (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__(6063);
+      const basePath =
+        /* unused pure expression or super */ null && (false || "");
+      function getDomainLocale(path, locale, locales, domainLocales) {
+        if (false) {
+        } else {
+          return false;
         }
-        const elements = new Map();
-        const observer = new IntersectionObserver((entries) => {
-          entries.forEach((entry) => {
-            const callback = elements.get(entry.target);
-            const isVisible =
-              entry.isIntersecting || entry.intersectionRatio > 0;
-            if (callback && isVisible) {
-              callback(isVisible);
-            }
-          });
-        }, options);
-        instance = {
-          id,
-          observer,
-          elements,
-        };
-        idList.push(id);
-        observers.set(id, instance);
-        return instance;
-      }
-      function observe(element, callback, options) {
-        const { id, observer, elements } = createObserver(options);
-        elements.set(element, callback);
-        observer.observe(element);
-        return function unobserve() {
-          elements.delete(element);
-          observer.unobserve(element);
-          // Destroy observer when there's nothing left to watch:
-          if (elements.size === 0) {
-            observer.disconnect();
-            observers.delete(id);
-            const index = idList.findIndex(
-              (obj) => obj.root === id.root && obj.margin === id.margin
-            );
-            if (index > -1) {
-              idList.splice(index, 1);
-            }
-          }
-        };
-      }
-      function useIntersection({ rootRef, rootMargin, disabled }) {
-        const isDisabled = disabled || !hasIntersectionObserver;
-        const [visible, setVisible] = (0, _react.useState)(false);
-        const elementRef = (0, _react.useRef)(null);
-        const setElement = (0, _react.useCallback)((element) => {
-          elementRef.current = element;
-        }, []);
-        (0, _react.useEffect)(() => {
-          if (hasIntersectionObserver) {
-            if (isDisabled || visible) return;
-            const element = elementRef.current;
-            if (element && element.tagName) {
-              const unobserve = observe(
-                element,
-                (isVisible) => isVisible && setVisible(isVisible),
-                {
-                  root: rootRef?.current,
-                  rootMargin,
-                }
-              );
-              return unobserve;
-            }
-          } else {
-            if (!visible) {
-              const idleCallback = (0,
-              _requestidlecallback.requestIdleCallback)(() => setVisible(true));
-              return () =>
-                (0, _requestidlecallback.cancelIdleCallback)(idleCallback);
-            }
-          }
-          // eslint-disable-next-line react-hooks/exhaustive-deps
-        }, [isDisabled, rootMargin, rootRef, visible, elementRef.current]);
-        const resetVisible = (0, _react.useCallback)(() => {
-          setVisible(false);
-        }, []);
-        return [setElement, visible, resetVisible];
       }
       if (
         (typeof exports.default === "function" ||
@@ -733,17 +743,7 @@
         });
         Object.assign(exports.default, exports);
         module.exports = exports.default;
-      } //# sourceMappingURL=use-intersection.js.map
-
-      /***/
-    },
-
-    /***/ 9056: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(1557);
+      } //# sourceMappingURL=get-domain-locale.js.map
 
       /***/
     },
@@ -753,7 +753,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(1182)
+      __webpack_exec__(2156)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for script-HASH.js
@@ -1,13 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [1209],
   {
-    /***/ 15: /***/ (module, __unused_webpack_exports, __webpack_require__) => {
-      module.exports = __webpack_require__(5258);
-
-      /***/
-    },
-
-    /***/ 6853: /***/ (
+    /***/ 2895: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -22,7 +16,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7002);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(15);
+        __webpack_require__(3489);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_script__WEBPACK_IMPORTED_MODULE_1__
@@ -55,7 +49,17 @@
       /***/
     },
 
-    /***/ 9264: /***/ (
+    /***/ 3489: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(3102);
+
+      /***/
+    },
+
+    /***/ 9884: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -63,7 +67,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/script",
         function () {
-          return __webpack_require__(6853);
+          return __webpack_require__(2895);
         },
       ]);
       if (false) {
@@ -77,7 +81,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9264)
+      __webpack_exec__(9884)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for withRouter-HASH.js
@@ -1,34 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [3263],
   {
-    /***/ 1593: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(372);
-
-      /***/
-    },
-
-    /***/ 4550: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/withRouter",
-        function () {
-          return __webpack_require__(8527);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 8527: /***/ (
+    /***/ 69: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -43,7 +16,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7002);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(1593);
+        __webpack_require__(2027);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -61,13 +34,40 @@
 
       /***/
     },
+
+    /***/ 2027: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(1536);
+
+      /***/
+    },
+
+    /***/ 2268: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/withRouter",
+        function () {
+          return __webpack_require__(69);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(4550)
+      __webpack_exec__(2268)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for 4951-HASH.js

Diff too large to display

Diff for 8034-HASH.js
failed to diff
Diff for 9565-HASH.js

Diff too large to display

Diff for main-HASH.js

Diff too large to display

Diff for main-app-HASH.js
@@ -1,64 +1,64 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [4977],
   {
-    /***/ 3233: /***/ (
+    /***/ 905: /***/ () => {
+      /* (ignored) */
+      /***/
+    },
+
+    /***/ 9069: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 5065, 23)
+        __webpack_require__.t.bind(__webpack_require__, 2467, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 8974, 23)
+        __webpack_require__.t.bind(__webpack_require__, 8296, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 6506, 23)
+        __webpack_require__.t.bind(__webpack_require__, 488, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 1, 23)
+        __webpack_require__.t.bind(__webpack_require__, 6887, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 8239, 23)
+        __webpack_require__.t.bind(__webpack_require__, 1753, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 1187, 23)
+        __webpack_require__.t.bind(__webpack_require__, 3265, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 7790, 23)
+        __webpack_require__.t.bind(__webpack_require__, 1848, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 6543, 23)
+        __webpack_require__.t.bind(__webpack_require__, 565, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 5802, 23)
+        __webpack_require__.t.bind(__webpack_require__, 6732, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 2809, 23)
+        __webpack_require__.t.bind(__webpack_require__, 6439, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 5738, 23)
+        __webpack_require__.t.bind(__webpack_require__, 228, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.bind(__webpack_require__, 5455)
+        __webpack_require__.bind(__webpack_require__, 3013)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 4731, 23)
+        __webpack_require__.t.bind(__webpack_require__, 8253, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 3753, 23)
+        __webpack_require__.t.bind(__webpack_require__, 3772, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 2816, 23)
+        __webpack_require__.t.bind(__webpack_require__, 5846, 23)
       );
 
       /***/
     },
-
-    /***/ 3643: /***/ () => {
-      /* (ignored) */
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
@@ -66,8 +66,8 @@
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(
       0,
-      [119, 8034],
-      () => (__webpack_exec__(5111), __webpack_exec__(3233))
+      [4246, 2914],
+      () => (__webpack_exec__(1429), __webpack_exec__(9069))
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for app-page-exp..ntime.dev.js
failed to diff
Diff for app-page-exp..time.prod.js

Diff too large to display

Diff for app-page-tur..ntime.dev.js
failed to diff
Diff for app-page-tur..time.prod.js

Diff too large to display

Diff for app-page-tur..ntime.dev.js
failed to diff
Diff for app-page-tur..time.prod.js

Diff too large to display

Diff for app-page.runtime.dev.js
failed to diff
Diff for app-page.runtime.prod.js

Diff too large to display

Commit: 01a7d61f95a554637263c0f60929b7f6e760a393

nextjs-bot avatar Dec 10 '25 02:12 nextjs-bot

Going to go with a slightly different approach

acdlite avatar Dec 11 '25 21:12 acdlite