Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,42 +85,50 @@ function startObservingForPortal() {

// Set up MutationObserver to watch for the portal element
const observer = new MutationObserver((mutations) => {
if (mutations.length === 0 || mutations[0].addedNodes.length === 0) {
if (mutations.length === 0) {
return
}

// Check if mutation is script[data-nextjs-dev-overlay] tag, which is the
// parent of the nextjs-portal element
const mutationNode = mutations[0].addedNodes[0]
let portalNode = null
if (
// app router: body > script[data-nextjs-dev-overlay] > nextjs-portal
mutationNode.tagName === 'SCRIPT' &&
mutationNode.getAttribute('data-nextjs-dev-overlay')
) {
portalNode = mutationNode.firstChild
} else if (
// pages router: body > nextjs-portal
mutationNode.tagName === 'NEXTJS-PORTAL'
) {
portalNode = mutationNode
}
if (!portalNode) {
return
}

// Wait until shadow root is available
const checkShadowRoot = () => {
if (getShadowRoot()) {
flushCachedElements()
observer.disconnect()
cache.isObserving = false
} else {
// Try again after a short delay
setTimeout(checkShadowRoot, 20)
// Check all mutations and all added nodes
for (const mutation of mutations) {
if (mutation.addedNodes.length === 0) continue

for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeType !== Node.ELEMENT_NODE) continue

const mutationNode = addedNode

let portalNode = null
if (
// app router: body > script[data-nextjs-dev-overlay] > nextjs-portal
mutationNode.tagName === 'SCRIPT' &&
mutationNode.getAttribute('data-nextjs-dev-overlay')
) {
portalNode = mutationNode.firstChild
} else if (
// pages router: body > nextjs-portal
mutationNode.tagName === 'NEXTJS-PORTAL'
) {
portalNode = mutationNode
}

if (portalNode) {
// Wait until shadow root is available
const checkShadowRoot = () => {
if (getShadowRoot()) {
flushCachedElements()
observer.disconnect()
cache.isObserving = false
} else {
// Try again after a short delay
setTimeout(checkShadowRoot, 20)
}
}
checkShadowRoot()
return // Exit early once we find a portal
}
}
}
checkShadowRoot()
})

observer.observe(document.body, {
Expand Down
24 changes: 24 additions & 0 deletions test/development/error-overlay/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,28 @@ describe('DevErrorOverlay', () => {
expect(request.status).toBe(200)
}
})

it('should load dev overlay styles successfully', async () => {
const browser = await next.browser('/hydration-error')

await assertHasRedbox(browser)
const redbox = browser.locateRedbox()

// check the data-nextjs-dialog-header="true" DOM element styles under redbox is applied
const dialogHeader = redbox.locator('[data-nextjs-dialog-header="true"]')
expect(await dialogHeader.isVisible()).toBe(true)
// get computed styles
const computedStyles = await dialogHeader.evaluate((element) => {
return window.getComputedStyle(element)
})
const styles = {
backgroundColor: computedStyles.backgroundColor,
color: computedStyles.color,
}

expect(styles).toEqual({
backgroundColor: 'rgba(0, 0, 0, 0)',
color: 'rgb(117, 117, 117)',
})
})
})
5 changes: 5 additions & 0 deletions test/development/error-overlay/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { AppProps } from 'next/app'

export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
13 changes: 13 additions & 0 deletions test/development/error-overlay/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
5 changes: 5 additions & 0 deletions test/development/error-overlay/pages/hydration-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function Home() {
return (
<div>{typeof window === 'undefined' ? <p>Server</p> : <p>Client</p>}</div>
)
}
Loading