From 7b0ab1ec6ae7b3188d8bbc378348b634e142619c Mon Sep 17 00:00:00 2001 From: "Sebastian \"Sebbie\" Silbermann" Date: Sun, 24 Nov 2024 14:16:34 +0100 Subject: [PATCH] Current behavior for fallbacks with async metadata and prefetching (#73106) --- .../app/metadata-await-promise/nested/page.js | 4 +- .../app/metadata-await-promise/page.js | 2 +- .../e2e/app-dir/navigation/navigation.test.ts | 66 ++++++++++++++----- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/test/e2e/app-dir/navigation/app/metadata-await-promise/nested/page.js b/test/e2e/app-dir/navigation/app/metadata-await-promise/nested/page.js index 431822fa1da45..0d933e4c61c18 100644 --- a/test/e2e/app-dir/navigation/app/metadata-await-promise/nested/page.js +++ b/test/e2e/app-dir/navigation/app/metadata-await-promise/nested/page.js @@ -3,13 +3,13 @@ import React from 'react' // ensure this page is dynamically rendered so we always trigger a loading state export const dynamic = 'force-dynamic' -export default function page() { +export default function Page() { return
Content
} async function getTitle() { return await new Promise((resolve) => - setTimeout(() => resolve('Async Title'), 1000) + setTimeout(() => resolve('Async Title'), 5000) ) } diff --git a/test/e2e/app-dir/navigation/app/metadata-await-promise/page.js b/test/e2e/app-dir/navigation/app/metadata-await-promise/page.js index 8481307e49730..1fb5f48153bf1 100644 --- a/test/e2e/app-dir/navigation/app/metadata-await-promise/page.js +++ b/test/e2e/app-dir/navigation/app/metadata-await-promise/page.js @@ -1,6 +1,6 @@ import Link from 'next/link' -export default function page() { +export default function Page() { return (
Link to nested diff --git a/test/e2e/app-dir/navigation/navigation.test.ts b/test/e2e/app-dir/navigation/navigation.test.ts index 8a626dd3789cf..a38a12a931d0a 100644 --- a/test/e2e/app-dir/navigation/navigation.test.ts +++ b/test/e2e/app-dir/navigation/navigation.test.ts @@ -881,29 +881,63 @@ describe('app dir - navigation', () => { }) describe('navigating to a page with async metadata', () => { - it('should render the final state of the page with correct metadata', async () => { + it('shows a fallback when prefetch was pending', async () => { + const resolveMetadataDuration = 5000 const browser = await next.browser('/metadata-await-promise') - // dev doesn't trigger the loading boundary as it's not prefetched - if (isNextDev) { - await browser - .elementByCss("[href='/metadata-await-promise/nested']") - .click() - } else { - const loadingText = await browser - .elementByCss("[href='/metadata-await-promise/nested']") - .click() - .waitForElementByCss('#loading') - .text() + // Hopefully this click happened before the prefetch was completed. + // TODO: Programmatically trigger prefetch e.g. by mounting the link later. + await browser + .elementByCss("[href='/metadata-await-promise/nested']") + .click() - expect(loadingText).toBe('Loading') + if (!isNextDev) { + // next-dev has no prefetch + expect( + await browser + .waitForElementByCss( + '#loading', + // Wait a bit longer than the prefetch duration since the click takes a while to register and the fallback render also takes time. + resolveMetadataDuration + 500 + ) + .text() + ).toEqual('Loading') + expect(await browser.elementByCss('title').text()).toBe('Async Title') } - await retry(async () => { - expect(await browser.elementById('page-content').text()).toBe('Content') + await waitFor(resolveMetadataDuration) + + expect(await browser.elementById('page-content').text()).toBe('Content') + }) + + it('shows a fallback when prefetch completed', async () => { + const resolveMetadataDuration = 5000 + const browser = await next.browser('/metadata-await-promise') + + if (!isNextDev) { + await waitFor(resolveMetadataDuration + 500) + } + await browser + .elementByCss("[href='/metadata-await-promise/nested']") + .click() + + if (!isNextDev) { + expect( + await browser + .waitForElementByCss( + '#loading', + // Give it some time to commit + 100 + ) + .text() + ).toEqual('Loading') expect(await browser.elementByCss('title').text()).toBe('Async Title') - }) + + await waitFor(resolveMetadataDuration + 500) + } + + expect(await browser.elementById('page-content').text()).toBe('Content') }) })