-
Notifications
You must be signed in to change notification settings - Fork 29.3k
[test] Enable scroll related tests in experimental tests #83245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: canary
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,16 @@ | ||
import { Suspense } from 'react' | ||
|
||
export default function Layout({ children }: any) { | ||
return ( | ||
<html | ||
style={{ | ||
overflowY: 'scroll', | ||
}} | ||
> | ||
<head /> | ||
<body style={{ margin: 0 }}>{children}</body> | ||
</html> | ||
<Suspense> | ||
<html | ||
style={{ | ||
overflowY: 'scroll', | ||
}} | ||
> | ||
<head /> | ||
<body style={{ margin: 0 }}>{children}</body> | ||
</html> | ||
</Suspense> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,20 @@ | ||
export const dynamic = 'force-dynamic' | ||
import { connection } from 'next/server' | ||
import { Suspense } from 'react' | ||
|
||
async function ForceDynamic({ children }) { | ||
await connection() | ||
return children | ||
} | ||
|
||
export default function Layout({ children }) { | ||
return ( | ||
<html> | ||
<head></head> | ||
<body>{children}</body> | ||
</html> | ||
<Suspense> | ||
<ForceDynamic> | ||
<html> | ||
<head></head> | ||
<body>{children}</body> | ||
</html> | ||
</ForceDynamic> | ||
</Suspense> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import { redirect } from 'next/navigation' | ||
import { connection } from 'next/server' | ||
|
||
export const dynamic = 'force-dynamic' | ||
|
||
export default function Page() { | ||
export default async function Page() { | ||
await connection() | ||
return redirect('/?a=b;c') | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -261,16 +261,21 @@ describe('app dir - navigation', () => { | |
await checkLink(50, 730) | ||
await checkLink(160, 2270) | ||
|
||
// FIXME: navigation is dropped on slower machines e.g. cpuThrottleRate: 4 | ||
// Need another attempt until that bug is fixed | ||
// Navigate to other | ||
await browser.elementByCss('#to-other-page').click() | ||
// Navigate to other | ||
await browser.elementByCss('#to-other-page').click() | ||
// Wait for other to load | ||
await browser.elementByCss('#link-to-home') | ||
|
||
// Navigate back to hash-link-back-to-same-page | ||
await browser | ||
.elementByCss('#to-other-page') | ||
// Navigate to other | ||
.click() | ||
// Wait for other ot load | ||
.waitForElementByCss('#link-to-home') | ||
// Navigate back to hash-link-back-to-same-page | ||
.elementByCss('#link-to-home') | ||
.click() | ||
// Wait for hash-link-back-to-same-page to load | ||
.waitForElementByCss('#to-other-page') | ||
.elementByCss('#to-other-page') | ||
|
||
await retry(() => | ||
expect(browser.eval('window.pageYOffset')).resolves.toEqual(0) | ||
|
@@ -407,21 +412,6 @@ describe('app dir - navigation', () => { | |
}) | ||
}) | ||
|
||
describe('bots', () => { | ||
if (!isNextDeploy) { | ||
it('should block rendering for bots and return 404 status', async () => { | ||
const res = await next.fetch('/not-found/servercomponent', { | ||
headers: { | ||
'User-Agent': 'Googlebot', | ||
}, | ||
}) | ||
|
||
expect(res.status).toBe(404) | ||
expect(await res.text()).toInclude('"noindex"') | ||
}) | ||
} | ||
}) | ||
|
||
Comment on lines
-410
to
-424
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved to |
||
describe('redirect', () => { | ||
describe('components', () => { | ||
it('should redirect in a server component', async () => { | ||
|
@@ -520,7 +510,9 @@ describe('app dir - navigation', () => { | |
|
||
// If the timestamp has changed, throw immediately. | ||
if (currentTimestamp !== initialTimestamp) { | ||
throw new Error('Timestamp has changed') | ||
throw new Error( | ||
`Timestamp has changed from the initial '${initialTimestamp}' to '${currentTimestamp}'` | ||
) | ||
} | ||
|
||
// If we've reached the last attempt without the timestamp changing, force a retry failure to keep going. | ||
|
@@ -582,27 +574,6 @@ describe('app dir - navigation', () => { | |
expect(await browser.url()).toBe(next.url + '/redirect-dest') | ||
}) | ||
}) | ||
|
||
describe('status code', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already tested in |
||
it('should respond with 307 status code in server component', async () => { | ||
const res = await next.fetch('/redirect/servercomponent', { | ||
redirect: 'manual', | ||
}) | ||
expect(res.status).toBe(307) | ||
}) | ||
it('should respond with 307 status code in client component', async () => { | ||
const res = await next.fetch('/redirect/clientcomponent', { | ||
redirect: 'manual', | ||
}) | ||
expect(res.status).toBe(307) | ||
}) | ||
it('should respond with 308 status code if permanent flag is set', async () => { | ||
const res = await next.fetch('/redirect/servercomponent-2', { | ||
redirect: 'manual', | ||
}) | ||
expect(res.status).toBe(308) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('external push', () => { | ||
|
@@ -994,15 +965,18 @@ describe('app dir - navigation', () => { | |
describe('locale warnings', () => { | ||
it('should warn about using the `locale` prop with `next/link` in app router', async () => { | ||
const browser = await next.browser('/locale-app') | ||
const logs = await browser.log() | ||
expect(logs).toContainEqual( | ||
expect.objectContaining({ | ||
message: expect.stringContaining( | ||
'The `locale` prop is not supported in `next/link` while using the `app` router.' | ||
), | ||
source: 'warning', | ||
}) | ||
) | ||
|
||
await retry(async () => { | ||
const logs = await browser.log() | ||
expect(logs).toContainEqual( | ||
expect.objectContaining({ | ||
message: expect.stringContaining( | ||
'The `locale` prop is not supported in `next/link` while using the `app` router.' | ||
), | ||
source: 'warning', | ||
}) | ||
) | ||
}) | ||
}) | ||
|
||
it('should have no warnings in pages router', async () => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { notFound } from 'next/navigation' | ||
|
||
export default function ShellPage() { | ||
notFound() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
'use client' | ||
|
||
import Link from 'next/link' | ||
import React, { useEffect } from 'react' | ||
import React, { Suspense, useEffect } from 'react' | ||
import { useRouter } from 'next/navigation' | ||
|
||
export default function Layout({ children }: { children: React.ReactNode }) { | ||
|
@@ -16,24 +16,26 @@ export default function Layout({ children }: { children: React.ReactNode }) { | |
}, [router]) | ||
|
||
return ( | ||
<html> | ||
<head></head> | ||
<body | ||
style={{ | ||
margin: 0, | ||
}} | ||
> | ||
<div | ||
<Suspense> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The View Details📝 Patch Detailsdiff --git a/test/e2e/app-dir/router-autoscroll/app/layout.tsx b/test/e2e/app-dir/router-autoscroll/app/layout.tsx
index aa60f7cc54..68bfa0a3c8 100644
--- a/test/e2e/app-dir/router-autoscroll/app/layout.tsx
+++ b/test/e2e/app-dir/router-autoscroll/app/layout.tsx
@@ -16,14 +16,14 @@ export default function Layout({ children }: { children: React.ReactNode }) {
}, [router])
return (
- <Suspense>
- <html>
- <head></head>
- <body
- style={{
- margin: 0,
- }}
- >
+ <html>
+ <head></head>
+ <body
+ style={{
+ margin: 0,
+ }}
+ >
+ <Suspense>
<div
style={{
position: 'fixed',
@@ -34,8 +34,8 @@ export default function Layout({ children }: { children: React.ReactNode }) {
<Link id="to-vertical-page" href="1" />
</div>
{children}
- </body>
- </html>
- </Suspense>
+ </Suspense>
+ </body>
+ </html>
)
}
AnalysisSame issue as the previous file - the root layout component is wrapping the In Next.js App Router, the The fix is to move the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suspense around html is fine nowadays. |
||
<html> | ||
<head></head> | ||
<body | ||
style={{ | ||
position: 'fixed', | ||
top: 0, | ||
left: 0, | ||
margin: 0, | ||
}} | ||
> | ||
<Link id="to-vertical-page" href="1" /> | ||
</div> | ||
{children} | ||
</body> | ||
</html> | ||
<div | ||
style={{ | ||
position: 'fixed', | ||
top: 0, | ||
left: 0, | ||
}} | ||
> | ||
<Link id="to-vertical-page" href="1" /> | ||
</div> | ||
{children} | ||
</body> | ||
</html> | ||
</Suspense> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
import Link from 'next/link' | ||
|
||
export const dynamic = 'force-dynamic' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't that implied by accessing search params? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. When the page was added, there was no search params access: |
||
|
||
export default async function Page(props: PageProps<'/loading-scroll'>) { | ||
const search = await props.searchParams | ||
const skipSleep = !!search.skipSleep | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,6 @@ | ||
module.exports = {} | ||
/** | ||
* @type {import('next').NextConfig} | ||
*/ | ||
const config = {} | ||
|
||
module.exports = config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
<html>
element cannot be wrapped in a<Suspense>
boundary in Next.js root layouts, which will cause React to throw an error.View Details
📝 Patch Details
Analysis
This layout component has the same structural issue as the others - it's wrapping the
<html>
element in<Suspense>
, which is invalid in React and Next.js root layouts. The<html>
element must be the root element returned from a layout component.Additionally, the
ForceDynamic
component is being used to replace theexport const dynamic = 'force-dynamic'
configuration, which is a valid approach, but it should not wrap the HTML structure in Suspense.The fix is to restructure this so that the
<html>
element is the root return value, and any Suspense or dynamic behavior is handled within the<body>
element or around specific child components.