From 2334de2bde105534f82086d1da14875dbf1045a2 Mon Sep 17 00:00:00 2001 From: devjiwonchoi Date: Thu, 16 Jan 2025 01:21:42 +0900 Subject: [PATCH] [DevOverlay] Enable new UI when PPR testing is enabled --- .github/workflows/build_and_test.yml | 6 +- .../webpack/plugins/define-env-plugin.ts | 6 +- .../_experimental/app/error-boundary.tsx | 28 +- .../_experimental/app/react-dev-overlay.tsx | 55 ++-- .../components/code-frame/code-frame.tsx | 4 +- .../dev-tools-indicator.tsx | 7 +- .../internal/next-logo.tsx | 3 +- .../internal/components/terminal/terminal.tsx | 4 +- .../_experimental/pages/error-boundary.tsx | 10 +- .../_experimental/pages/react-dev-overlay.tsx | 63 ++-- .../internal/container/RuntimeError/index.tsx | 2 +- .../acceptance-app/ReactRefreshLogBox.test.ts | 36 ++- .../acceptance/ReactRefreshLogBox.test.ts | 24 +- .../capture-console-error-owner-stack.test.ts | 272 +++++++++--------- .../capture-console-error.test.ts | 262 +++++++++-------- .../app-dir/dynamic-error-trace/index.test.ts | 5 +- .../error-ignored-frames.test.ts | 270 ++++++++--------- .../invalid-element-type.test.ts | 24 +- .../owner-stack-invalid-element-type.test.ts | 36 ++- ...owner-stack-react-missing-key-prop.test.ts | 24 +- .../react-missing-key-prop.test.ts | 16 +- .../app-dir/owner-stack/owner-stack.test.ts | 199 ++++++++----- .../prerender-indicator.test.ts | 54 ++-- ...r-component-next-dynamic-ssr-false.test.ts | 48 +++- .../app-dir/ssr-in-rsc/ssr-in-rsc.test.ts | 32 ++- .../error-on-next-codemod-comment.test.ts | 47 ++- .../non-root-project-monorepo.test.ts | 22 +- .../use-cache-unknown-cache-kind.test.ts | 43 ++- .../use-cache-without-dynamic-io.test.ts | 95 ++++-- test/lib/next-test-utils.ts | 91 +++++- 30 files changed, 1134 insertions(+), 654 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index f750f6c673c65..0936964a0749f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -578,7 +578,7 @@ jobs: uses: ./.github/workflows/build_reusable.yml with: nodeVersion: 18.18.2 - afterBuild: __NEXT_EXPERIMENTAL_PPR=true NEXT_EXTERNAL_TESTS_FILTERS="test/ppr-tests-manifest.json" node run-tests.js --timings -c ${TEST_CONCURRENCY} --type integration + afterBuild: __NEXT_EXPERIMENTAL_PPR=true __NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY=true NEXT_EXTERNAL_TESTS_FILTERS="test/ppr-tests-manifest.json" node run-tests.js --timings -c ${TEST_CONCURRENCY} --type integration stepName: 'test-ppr-integration' secrets: inherit @@ -593,7 +593,7 @@ jobs: group: [1/6, 2/6, 3/6, 4/6, 5/6, 6/6] uses: ./.github/workflows/build_reusable.yml with: - afterBuild: __NEXT_EXPERIMENTAL_PPR=true NEXT_EXTERNAL_TESTS_FILTERS="test/ppr-tests-manifest.json" NEXT_TEST_MODE=dev node run-tests.js --timings -g ${{ matrix.group }} -c ${TEST_CONCURRENCY} --type development + afterBuild: __NEXT_EXPERIMENTAL_PPR=true __NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY=true NEXT_EXTERNAL_TESTS_FILTERS="test/ppr-tests-manifest.json" NEXT_TEST_MODE=dev node run-tests.js --timings -g ${{ matrix.group }} -c ${TEST_CONCURRENCY} --type development stepName: 'test-ppr-dev-${{ matrix.group }}' secrets: inherit @@ -608,7 +608,7 @@ jobs: group: [1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 7/7] uses: ./.github/workflows/build_reusable.yml with: - afterBuild: __NEXT_EXPERIMENTAL_PPR=true NEXT_EXTERNAL_TESTS_FILTERS="test/ppr-tests-manifest.json" NEXT_TEST_MODE=start node run-tests.js --timings -g ${{ matrix.group }} -c ${TEST_CONCURRENCY} --type production + afterBuild: __NEXT_EXPERIMENTAL_PPR=true __NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY=true NEXT_EXTERNAL_TESTS_FILTERS="test/ppr-tests-manifest.json" NEXT_TEST_MODE=start node run-tests.js --timings -g ${{ matrix.group }} -c ${TEST_CONCURRENCY} --type production stepName: 'test-ppr-prod-${{ matrix.group }}' secrets: inherit diff --git a/packages/next/src/build/webpack/plugins/define-env-plugin.ts b/packages/next/src/build/webpack/plugins/define-env-plugin.ts index 417df966c57a0..f15fb1c4b0c83 100644 --- a/packages/next/src/build/webpack/plugins/define-env-plugin.ts +++ b/packages/next/src/build/webpack/plugins/define-env-plugin.ts @@ -286,7 +286,11 @@ export function getDefineEnv({ } : undefined), 'process.env.__NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY': - config.experimental.newDevOverlay ?? false, + // When `__NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY` is set on CI, + // we need to pass it here so it can be enabled. + process.env.__NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY === 'true' || + config.experimental.newDevOverlay || + false, } const userDefines = config.compiler?.define ?? {} diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/app/error-boundary.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/app/error-boundary.tsx index 804918cda20ab..799d73a03892a 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/app/error-boundary.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/app/error-boundary.tsx @@ -3,13 +3,14 @@ import type { GlobalErrorComponent } from '../../../error-boundary' import { PureComponent } from 'react' import { RuntimeErrorHandler } from '../../../errors/runtime-error-handler' -type DevToolsErrorBoundaryProps = { +type DevOverlayErrorBoundaryProps = { children: React.ReactNode - onError: (value: boolean) => void + devOverlay: React.ReactNode globalError: [GlobalErrorComponent, React.ReactNode] + onError: (value: boolean) => void } -type DevToolsErrorBoundaryState = { +type DevOverlayErrorBoundaryState = { isReactError: boolean reactError: unknown } @@ -37,9 +38,9 @@ function ErroredHtml({ ) } -export class DevToolsErrorBoundary extends PureComponent< - DevToolsErrorBoundaryProps, - DevToolsErrorBoundaryState +export class DevOverlayErrorBoundary extends PureComponent< + DevOverlayErrorBoundaryProps, + DevOverlayErrorBoundaryState > { state = { isReactError: false, reactError: null } @@ -61,13 +62,18 @@ export class DevToolsErrorBoundary extends PureComponent< } render() { + const { children, globalError, devOverlay } = this.props + const { isReactError, reactError } = this.state + const fallback = ( - + ) - return this.state.isReactError ? fallback : this.props.children + return ( + <> + {isReactError ? fallback : children} + {devOverlay} + + ) } } diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/app/react-dev-overlay.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/app/react-dev-overlay.tsx index 589d0a56a157b..fbcac3085401d 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/app/react-dev-overlay.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/app/react-dev-overlay.tsx @@ -2,7 +2,7 @@ import type { OverlayState } from '../../shared' import type { GlobalErrorComponent } from '../../../error-boundary' import { useState } from 'react' -import { DevToolsErrorBoundary } from './error-boundary' +import { DevOverlayErrorBoundary } from './error-boundary' import { ShadowPortal } from '../internal/components/shadow-portal' import { Base } from '../internal/styles/base' import { ComponentStyles } from '../internal/styles/component-styles' @@ -24,34 +24,35 @@ export default function ReactDevOverlay({ const [isErrorOverlayOpen, setIsErrorOverlayOpen] = useState(false) const { readyErrors } = useErrorHook({ errors: state.errors, isAppDir: true }) - return ( - <> - - {children} - + const devOverlay = ( + + + + + - - - - - + - + + + ) - - - + return ( + + {children} + ) } diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/code-frame/code-frame.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/code-frame/code-frame.tsx index ee870c4b0bc4f..e26a42e109526 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/code-frame/code-frame.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/code-frame/code-frame.tsx @@ -36,9 +36,7 @@ export function CodeFrame({ stackFrame, codeFrame }: CodeFrameProps) { .map((line, a) => ~(a = line.indexOf('|')) ? line.substring(0, a) + - line - .substring(a + 1) - .replace(`^\\ {${miniLeadingSpacesLength}}`, '') + line.substring(a).replace(`^\\ {${miniLeadingSpacesLength}}`, '') : line ) .join('\n') diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/dev-tools-indicator.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/dev-tools-indicator.tsx index e238741f80d85..a281ee3f099f9 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/dev-tools-indicator.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/dev-tools-indicator.tsx @@ -126,6 +126,7 @@ const DevToolsPopover = ({ return ( @@ -205,14 +207,15 @@ const IndicatorRow = ({ label, value, onClick, + ...props }: { label: string value: React.ReactNode onClick?: () => void -}) => { +} & React.HTMLAttributes) => { const Wrapper = onClick ? 'button' : 'div' return ( - + {label} {value} diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/internal/next-logo.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/internal/next-logo.tsx index d669d16b5b237..125168b061061 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/internal/next-logo.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/dev-tools-indicator/internal/next-logo.tsx @@ -301,7 +301,8 @@ export const NextLogo = ({ aria-label="Open issues overlay" onClick={onIssuesClick} > - {issueCount} {issueCount === 1 ? 'Issue' : 'Issues'} + {issueCount}{' '} + {issueCount === 1 ? 'Issue' : 'Issues'}