diff --git a/e2e-tests/development-runtime/cypress/integration/navigation/redirect.js b/e2e-tests/development-runtime/cypress/integration/navigation/redirect.js index 293930eda4c16..d3621d61cfaa8 100644 --- a/e2e-tests/development-runtime/cypress/integration/navigation/redirect.js +++ b/e2e-tests/development-runtime/cypress/integration/navigation/redirect.js @@ -5,34 +5,38 @@ Cypress.on(`window:before:load`, win => { const runTests = () => { it(`should redirect page to index page when there is no such page`, () => { - cy.visit(`/redirect-without-page`).waitForRouteChange() + cy.visit(`/redirect-without-page`, { + failOnStatusCode: false, + }).waitForRouteChange() cy.location(`pathname`).should(`equal`, `/`) cy.then(() => { const calls = spy.getCalls() - const callsAboutRedirectMatchingPage = calls.filter(call => { - return call.args[0].includes( - "matches both a page and a redirect; this is probably not intentional." + const callsAboutRedirectMatchingPage = calls.filter(call => + call.args[0].includes( + `matches both a page and a redirect; this is probably not intentional.` ) - }) + ) expect(callsAboutRedirectMatchingPage.length).to.equal(0) }) }) it(`should redirect page to index page even there is a such page`, () => { - cy.visit(`/redirect`).waitForRouteChange() + cy.visit(`/redirect`, { + failOnStatusCode: false, + }).waitForRouteChange() cy.location(`pathname`).should(`equal`, `/`) cy.then(() => { const calls = spy.getCalls() - const callsAboutRedirectMatchingPage = calls.filter(call => { - return call.args[0].includes( - "matches both a page and a redirect; this is probably not intentional." + const callsAboutRedirectMatchingPage = calls.filter(call => + call.args[0].includes( + `matches both a page and a redirect; this is probably not intentional.` ) - }) + ) expect(callsAboutRedirectMatchingPage.length).not.to.equal(0) expect(spy).to.be.calledWith( @@ -42,7 +46,9 @@ const runTests = () => { }) it(`should redirect to a dynamically-created replacement page`, () => { - cy.visit(`/redirect-me/`).waitForRouteChange() + cy.visit(`/redirect-me/`, { + failOnStatusCode: false, + }).waitForRouteChange() cy.location(`pathname`).should(`equal`, `/pt/redirect-me/`) cy.then(() => { @@ -50,7 +56,7 @@ const runTests = () => { `The route "/redirect" matches both a page and a redirect; this is probably not intentional.` ) - cy.findByText("This should be at /pt/redirect-me/", { + cy.findByText(`This should be at /pt/redirect-me/`, { exact: false, }).should(`exist`) }) @@ -58,27 +64,29 @@ const runTests = () => { } describe(`redirect`, () => { - describe("404 is present", () => { + describe(`404 is present`, () => { before(() => { cy.task(`restoreAllBlockedResources`) }) // this is sanity check for this group it(`make sure 404 is present`, () => { - cy.visit(`/______not_existing_page`).waitForRouteChange() - cy.findByText("Preview custom 404 page").click() - cy.findByText("A custom 404 page wasn't detected", { + cy.visit(`/______not_existing_page`, { + failOnStatusCode: false, + }).waitForRouteChange() + cy.findByText(`Preview custom 404 page`).click() + cy.findByText(`A custom 404 page wasn't detected`, { exact: false, }).should(`not.exist`) cy.findByText( - "You just hit a route that does not exist... the sadness." + `You just hit a route that does not exist... the sadness.` ).should(`exist`) }) runTests() }) - describe("no 404", () => { + describe(`no 404`, () => { before(() => { cy.task(`restoreAllBlockedResources`) @@ -100,13 +108,15 @@ describe(`redirect`, () => { }) it(`make sure 404 is NOT present`, () => { - cy.visit(`/______not_existing_page`).waitForRouteChange() - cy.findByText("Preview custom 404 page").click() - cy.findByText("A custom 404 page wasn't detected", { + cy.visit(`/______not_existing_page`, { + failOnStatusCode: false, + }).waitForRouteChange() + cy.findByText(`Preview custom 404 page`).click() + cy.findByText(`A custom 404 page wasn't detected`, { exact: false, }).should(`exist`) cy.findByText( - "You just hit a route that does not exist... the sadness.", + `You just hit a route that does not exist... the sadness.`, { exact: false } ).should(`not.exist`) }) diff --git a/e2e-tests/development-runtime/cypress/integration/page-not-found/404.js b/e2e-tests/development-runtime/cypress/integration/page-not-found/404.js index 400e7c13a27e1..28e6bba1cca4e 100644 --- a/e2e-tests/development-runtime/cypress/integration/page-not-found/404.js +++ b/e2e-tests/development-runtime/cypress/integration/page-not-found/404.js @@ -1,6 +1,8 @@ describe(`page not found`, () => { beforeEach(() => { - cy.visit(`/__404__`) + cy.visit(`/__404__`, { + failOnStatusCode: false, + }) }) it(`should display message `, () => { cy.get(`h1`).invoke(`text`).should(`eq`, `Gatsby.js development 404 page`) diff --git a/integration-tests/ssr/__tests__/__snapshots__/ssr.js.snap b/integration-tests/ssr/__tests__/__snapshots__/ssr.js.snap index 1de25d640ab7c..57990a718a79c 100644 --- a/integration-tests/ssr/__tests__/__snapshots__/ssr.js.snap +++ b/integration-tests/ssr/__tests__/__snapshots__/ssr.js.snap @@ -3,134 +3,15 @@ exports[`SSR is run for a page when it is requested 1`] = `"

Hello world

"`; exports[`SSR it generates an error page correctly 1`] = ` -" - Develop SSR Error - - -

Error

-

The page didn't server render (SSR) correctly

-

- React components in Gatsby must render successfully in the browser and in a - node.js environment. When we tried to render your page component in - node.js, it errored. -

- -

error

- window is not defined -
  2 |
-  3 | const Component = () => {
-> 4 |   const a = window.width
-    |             ^
-  5 |
-  6 |   return <div>hi</div>
-  7 | }
-

For help debugging SSR errors, see this docs page: https://www.gatsbyjs.com/docs/debugging-html-builds/

-

Skip SSR

-

- If you don't wish to fix the SSR error at the moment, press the - button below to reload the page without attempting SSR

-

- Note: this error will show up in when you build your site so must be fixed before then.

-

- Caveat: SSR errors in module scope i.e. outside of your components can't be skipped so will need fixed before you can continue

- - - " +"
" `; diff --git a/integration-tests/ssr/__tests__/ssr.js b/integration-tests/ssr/__tests__/ssr.js index d82b19c1dc9b2..0395743a970dd 100644 --- a/integration-tests/ssr/__tests__/ssr.js +++ b/integration-tests/ssr/__tests__/ssr.js @@ -38,7 +38,7 @@ describe(`SSR`, () => { const pageUrl = `http://localhost:8000/bad-page/` // Poll until the new page is bundled (so starts returning a non-404 status). const rawDevHtml = await fetchUntil(pageUrl, res => { - return res.status === 500 + return res }).then(res => res.text()) expect(rawDevHtml).toMatchSnapshot() await fs.remove(dest) diff --git a/integration-tests/ssr/jest.config.js b/integration-tests/ssr/jest.config.js index 57d3e1a6afb2b..881e96b65584b 100644 --- a/integration-tests/ssr/jest.config.js +++ b/integration-tests/ssr/jest.config.js @@ -1,4 +1,5 @@ module.exports = { + snapshotSerializers: [`jest-serializer-path`], testPathIgnorePatterns: [ `/node_modules/`, `__tests__/fixtures`, diff --git a/integration-tests/ssr/package.json b/integration-tests/ssr/package.json index 24a7d7323e54b..e221a38cc7d18 100644 --- a/integration-tests/ssr/package.json +++ b/integration-tests/ssr/package.json @@ -18,6 +18,7 @@ "fs-extra": "^9.0.0", "jest": "^24.0.0", "jest-diff": "^24.0.0", + "jest-serializer-path": "^0.1.15", "npm-run-all": "4.1.5", "start-server-and-test": "^1.11.3" }, @@ -30,7 +31,7 @@ "scripts": { "build": "gatsby build", "clean": "gatsby clean", - "develop": "cross-env GATSBY_EXPERIMENTAL_DEV_SSR=true gatsby develop", + "develop": "cross-env GATSBY_EXPERIMENTAL_DEV_SSR=true CI=1 FORCE_COLOR=0 gatsby develop", "serve": "gatsby serve", "start-dev-server": "start-server-and-test develop http://localhost:8000 test:jest", "test": "cross-env GATSBY_EXPERIMENTAL_DEV_SSR=true npm-run-all -s build start-dev-server", diff --git a/packages/gatsby-cli/src/structured-errors/error-map.ts b/packages/gatsby-cli/src/structured-errors/error-map.ts index 8460f93c84ff3..7f05bd9c9fc30 100644 --- a/packages/gatsby-cli/src/structured-errors/error-map.ts +++ b/packages/gatsby-cli/src/structured-errors/error-map.ts @@ -549,18 +549,29 @@ const errors = { docsUrl: `https://www.gatsbyjs.com/docs/reference/gatsby-cli#new`, }, "11614": { - text: ({ - path, - filePath, - line, - column, - }): string => `The path "${path}" errored during SSR. - - Edit its component ${filePath}${ - line ? `:${line}:${column}` : `` - } to resolve the error.`, + text: (context): string => + stripIndent(` + The path "${context.path}" errored during SSR. + Edit its component ${context.filePath}${ + context.line ? `:${context.line}:${context.column}` : `` + } to resolve the error.`), level: Level.WARNING, - docsUrl: `https://gatsby.dev/debug-html`, + }, + "11615": { + text: (context): string => + stripIndent(` + There was an error while trying to load dev-404-page: + ${context.sourceMessage}`), + level: Level.ERROR, + category: ErrorCategory.SYSTEM, + }, + "11616": { + text: (context): string => + stripIndent(` + There was an error while trying to create the client-only shell for displaying SSR errors: + ${context.sourceMessage}`), + level: Level.ERROR, + category: ErrorCategory.SYSTEM, }, // Watchdog "11701": { diff --git a/packages/gatsby/cache-dir/__tests__/static-entry.js b/packages/gatsby/cache-dir/__tests__/static-entry.js index 638dc0d6f32ac..eba0a4c5c3a86 100644 --- a/packages/gatsby/cache-dir/__tests__/static-entry.js +++ b/packages/gatsby/cache-dir/__tests__/static-entry.js @@ -195,7 +195,7 @@ describe(`develop-static-entry`, () => { test(`SSR: onPreRenderHTML can be used to replace headComponents`, done => { global.plugins = [fakeStylesPlugin, reverseHeadersPlugin] - ssrDevelopStaticEntry(`/about/`, false, publicDir, (_, html) => { + ssrDevelopStaticEntry(`/about/`, false, publicDir, undefined, (_, html) => { expect(html).toMatchSnapshot() done() }) @@ -207,7 +207,7 @@ describe(`develop-static-entry`, () => { reverseBodyComponentsPluginFactory(`Post`), ] - ssrDevelopStaticEntry(`/about/`, false, publicDir, (_, html) => { + ssrDevelopStaticEntry(`/about/`, false, publicDir, undefined, (_, html) => { expect(html).toMatchSnapshot() done() }) @@ -219,14 +219,14 @@ describe(`develop-static-entry`, () => { reverseBodyComponentsPluginFactory(`Pre`), ] - ssrDevelopStaticEntry(`/about/`, false, publicDir, (_, html) => { + ssrDevelopStaticEntry(`/about/`, false, publicDir, undefined, (_, html) => { expect(html).toMatchSnapshot() done() }) }) test(`SSR: onPreRenderHTML adds metatag note for development environment`, done => { - ssrDevelopStaticEntry(`/about/`, false, publicDir, (_, html) => { + ssrDevelopStaticEntry(`/about/`, false, publicDir, undefined, (_, html) => { expect(html).toContain( `` ) @@ -237,7 +237,7 @@ describe(`develop-static-entry`, () => { test(`SSR: onPreRenderHTML adds metatag note for development environment after replaceHeadComponents`, done => { global.plugins = [reverseHeadersPlugin] - ssrDevelopStaticEntry(`/about/`, false, publicDir, (_, html) => { + ssrDevelopStaticEntry(`/about/`, false, publicDir, undefined, (_, html) => { expect(html).toContain( `` ) diff --git a/packages/gatsby/cache-dir/fast-refresh-overlay/components/dev-ssr-error.js b/packages/gatsby/cache-dir/fast-refresh-overlay/components/dev-ssr-error.js new file mode 100644 index 0000000000000..fd0776451b3a1 --- /dev/null +++ b/packages/gatsby/cache-dir/fast-refresh-overlay/components/dev-ssr-error.js @@ -0,0 +1,66 @@ +import * as React from "react" +import { Overlay, Header, Body, Footer, HeaderOpenClose } from "./overlay" +import { CodeFrame } from "./code-frame" +import { prettifyStack, openInEditor, skipSSR, reloadPage } from "../utils" + +export function DevSsrError({ error }) { + const { codeFrame, source, line } = error + const decoded = prettifyStack(codeFrame) + + return ( + +
+
+

Failed to server render (SSR)

+ {source} +
+ openInEditor(source, line)} + dismiss={false} + /> +
+ +

+ React Components in Gatsby must render both successfully in the + browser and in a Node.js environment. When we tried to render your + page component in Node.js, it errored. +

+

Source

+ +
+ See our docs page for more info on SSR errors:{` `} + + Debugging HTML Builds + +
+

+ If you fixed the error, saved your file, and want to retry server + rendering this page, please reload the page. +

+ +

Skip Server Render

+

+ If you don't wish to fix the SSR error at the moment, press the button + below to reload the page without attempting to do SSR. +

+ + + +
+ ) +} diff --git a/packages/gatsby/cache-dir/fast-refresh-overlay/components/overlay.js b/packages/gatsby/cache-dir/fast-refresh-overlay/components/overlay.js index 78b936e5788db..9360e391f2af1 100644 --- a/packages/gatsby/cache-dir/fast-refresh-overlay/components/overlay.js +++ b/packages/gatsby/cache-dir/fast-refresh-overlay/components/overlay.js @@ -73,7 +73,7 @@ export function Overlay({ children }) { export function CloseButton({ dismiss }) { return ( -