Skip to content

Commit 66c6400

Browse files
committed
re-add pieh e2e tests
1 parent 395b0b5 commit 66c6400

14 files changed

+403
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"selector": "page-query",
3+
"hasError": false
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"selector": "static-query",
3+
"hasError": false
4+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
before(() => {
2+
cy.exec(
3+
`npm run update -- --file src/pages/error-handling/compile-error.js --restore`
4+
)
5+
})
6+
7+
after(() => {
8+
cy.exec(
9+
`npm run update -- --file src/pages/error-handling/compile-error.js --restore`
10+
)
11+
})
12+
13+
const errorPlaceholder = `// compile-error`
14+
const errorReplacement = `a b`
15+
16+
describe(`testing error overlay and ability to automatically recover from webpack compile errors`, () => {
17+
it(`displays content initially (no errors yet)`, () => {
18+
cy.visit(`/error-handling/compile-error/`).waitForRouteChange()
19+
cy.findByTestId(`hot`).should(`contain.text`, `Working`)
20+
})
21+
22+
it(`displays error with overlay on compilation errors`, () => {
23+
cy.exec(
24+
`npm run update -- --file src/pages/error-handling/compile-error.js --replacements "${errorPlaceholder}:${errorReplacement}" --exact`
25+
)
26+
27+
cy.getOverlayIframe().contains(`Failed to compile`)
28+
cy.getOverlayIframe().contains(`Unexpected token, expected ";"`)
29+
cy.screenshot()
30+
})
31+
32+
it(`can recover without need to refresh manually`, () => {
33+
cy.exec(
34+
`npm run update -- --file src/pages/error-handling/compile-error.js --replacements "Working:Updated" --replacements "${errorReplacement}:${errorPlaceholder}" --exact`
35+
)
36+
37+
cy.findByTestId(`hot`).should(`contain.text`, `Updated`)
38+
cy.assertNoOverlayIframe()
39+
cy.screenshot()
40+
})
41+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
Cypress.on("uncaught:exception", (err, runnable) => {
2+
// returning false here prevents Cypress from
3+
// failing the test
4+
return false
5+
})
6+
7+
before(() => {
8+
cy.exec(
9+
`npm run update -- --file content/error-recovery/page-query.json --restore`
10+
)
11+
cy.exec(
12+
`npm run update -- --file src/pages/error-handling/page-query-result-runtime-error.js --restore`
13+
)
14+
})
15+
16+
after(() => {
17+
cy.exec(
18+
`npm run update -- --file content/error-recovery/page-query.json --restore`
19+
)
20+
cy.exec(
21+
`npm run update -- --file src/pages/error-handling/page-query-result-runtime-error.js --restore`
22+
)
23+
})
24+
25+
const errorPlaceholder = `false`
26+
const errorReplacement = `true`
27+
28+
describe(`testing error overlay and ability to automatically recover runtime errors cause by content changes (page queries variant)`, () => {
29+
it(`displays content initially (no errors yet)`, () => {
30+
cy.visit(
31+
`/error-handling/page-query-result-runtime-error/`
32+
).waitForRouteChange()
33+
cy.findByTestId(`hot`).should(`contain.text`, `Working`)
34+
cy.findByTestId(`results`)
35+
.should(`contain.text`, `"hasError": false`)
36+
})
37+
38+
it(`displays error with overlay on runtime errors`, () => {
39+
cy.exec(
40+
`npm run update -- --file content/error-recovery/page-query.json --replacements "${errorPlaceholder}:${errorReplacement}" --exact`
41+
)
42+
43+
// that's the exact error we throw and we expect to see that
44+
cy.getOverlayIframe().contains(`Page query results caused runtime error`)
45+
// contains details
46+
cy.getOverlayIframe().contains(
47+
`src/pages/error-handling/page-query-result-runtime-error.js`
48+
)
49+
cy.screenshot()
50+
})
51+
52+
it(`can recover without need to refresh manually`, () => {
53+
cy.exec(
54+
`npm run update -- --file content/error-recovery/page-query.json --replacements "${errorReplacement}:${errorPlaceholder}" --exact`
55+
)
56+
cy.exec(
57+
`npm run update -- --file src/pages/error-handling/page-query-result-runtime-error.js --replacements "Working:Updated" --exact`
58+
)
59+
60+
cy.findByTestId(`hot`).should(`contain.text`, `Updated`)
61+
cy.findByTestId(`results`)
62+
.should(`contain.text`, `"hasError": false`)
63+
64+
cy.assertNoOverlayIframe()
65+
cy.screenshot()
66+
})
67+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
before(() => {
2+
cy.exec(
3+
`npm run update -- --file src/pages/error-handling/query-validation-error.js --restore`
4+
)
5+
})
6+
7+
after(() => {
8+
cy.exec(
9+
`npm run update -- --file src/pages/error-handling/query-validation-error.js --restore`
10+
)
11+
})
12+
13+
const errorPlaceholder = `# query-validation-error`
14+
const errorReplacement = `fieldThatDoesNotExistOnSiteMapType`
15+
16+
describe(`testing error overlay and ability to automatically recover from query extraction validation errors`, () => {
17+
it(`displays content initially (no errors yet)`, () => {
18+
cy.visit(`/error-handling/query-validation-error/`).waitForRouteChange()
19+
cy.findByTestId(`hot`).should(`contain.text`, `Working`)
20+
})
21+
22+
it(`displays error with overlay on compilation errors`, () => {
23+
cy.exec(
24+
`npm run update -- --file src/pages/error-handling/query-validation-error.js --replacements "${errorPlaceholder}:${errorReplacement}" --exact`
25+
)
26+
27+
cy.getOverlayIframe().contains(`Failed to compile`)
28+
cy.getOverlayIframe().contains(`There was an error in your GraphQL query`)
29+
// make sure we mark location
30+
cy.getOverlayIframe().contains(
31+
`src/pages/error-handling/query-validation-error.js`
32+
)
33+
cy.screenshot()
34+
})
35+
36+
it(`can recover without need to refresh manually`, () => {
37+
cy.exec(
38+
`npm run update -- --file src/pages/error-handling/query-validation-error.js --replacements "Working:Updated" --replacements "${errorReplacement}:${errorPlaceholder}" --exact`
39+
)
40+
41+
cy.findByTestId(`hot`).should(`contain.text`, `Updated`)
42+
cy.assertNoOverlayIframe()
43+
cy.screenshot()
44+
})
45+
})
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Cypress.on("uncaught:exception", (err, runnable) => {
2+
// returning false here prevents Cypress from
3+
// failing the test
4+
return false
5+
})
6+
7+
before(() => {
8+
cy.exec(
9+
`npm run update -- --file src/pages/error-handling/runtime-error.js --restore`
10+
)
11+
})
12+
13+
after(() => {
14+
cy.exec(
15+
`npm run update -- --file src/pages/error-handling/runtime-error.js --restore`
16+
)
17+
})
18+
19+
const errorPlaceholder = `// runtime-error`
20+
const errorReplacement = `window.a.b.c.d.e.f.g()`
21+
22+
describe(`testing error overlay and ability to automatically recover from runtime errors`, () => {
23+
it(`displays content initially (no errors yet)`, () => {
24+
cy.visit(`/error-handling/runtime-error/`).waitForRouteChange()
25+
cy.findByTestId(`hot`).should(`contain.text`, `Working`)
26+
})
27+
28+
it(`displays error with overlay on runtime errors`, () => {
29+
cy.exec(
30+
`npm run update -- --file src/pages/error-handling/runtime-error.js --replacements "${errorPlaceholder}:${errorReplacement}" --exact`
31+
)
32+
33+
cy.getOverlayIframe().contains(`Cannot read property`)
34+
// contains details
35+
cy.getOverlayIframe().contains(`src/pages/error-handling/runtime-error.js`)
36+
cy.screenshot()
37+
})
38+
39+
it(`can recover without need to refresh manually`, () => {
40+
cy.exec(
41+
`npm run update -- --file src/pages/error-handling/runtime-error.js --replacements "Working:Updated" --replacements "${errorReplacement}:${errorPlaceholder}" --exact`
42+
)
43+
44+
cy.findByTestId(`hot`).should(`contain.text`, `Updated`)
45+
cy.assertNoOverlayIframe()
46+
cy.screenshot()
47+
})
48+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
Cypress.on("uncaught:exception", (err, runnable) => {
2+
// returning false here prevents Cypress from
3+
// failing the test
4+
return false
5+
})
6+
7+
before(() => {
8+
cy.exec(
9+
`npm run update -- --file content/error-recovery/static-query.json --restore`
10+
)
11+
cy.exec(
12+
`npm run update -- --file src/pages/error-handling/static-query-result-runtime-error.js --restore`
13+
)
14+
})
15+
16+
after(() => {
17+
cy.exec(
18+
`npm run update -- --file content/error-recovery/static-query.json --restore`
19+
)
20+
cy.exec(
21+
`npm run update -- --file src/pages/error-handling/static-query-result-runtime-error.js --restore`
22+
)
23+
})
24+
25+
const errorPlaceholder = `false`
26+
const errorReplacement = `true`
27+
28+
describe(`testing error overlay and ability to automatically recover from runtime errors (static queries variant)`, () => {
29+
it(`displays content initially (no errors yet)`, () => {
30+
cy.visit(
31+
`/error-handling/static-query-result-runtime-error/`
32+
).waitForRouteChange()
33+
cy.findByTestId(`hot`).should(`contain.text`, `Working`)
34+
cy.findByTestId(`results`)
35+
.should(`contain.text`, `"hasError": false`)
36+
})
37+
38+
it(`displays error with overlay on runtime errors`, () => {
39+
cy.exec(
40+
`npm run update -- --file content/error-recovery/static-query.json --replacements "${errorPlaceholder}:${errorReplacement}" --exact`
41+
)
42+
43+
// that's the exact error we throw and we expect to see that
44+
cy.getOverlayIframe().contains(`Static query results caused runtime error`)
45+
// contains details
46+
cy.getOverlayIframe().contains(
47+
`src/pages/error-handling/static-query-result-runtime-error.js`
48+
)
49+
cy.screenshot()
50+
})
51+
52+
it(`can recover without need to refresh manually`, () => {
53+
cy.exec(
54+
`npm run update -- --file content/error-recovery/static-query.json --replacements "${errorReplacement}:${errorPlaceholder}" --exact`
55+
)
56+
cy.exec(
57+
`npm run update -- --file src/pages/error-handling/static-query-result-runtime-error.js --replacements "Working:Updated" --exact`
58+
)
59+
60+
cy.findByTestId(`hot`).should(`contain.text`, `Updated`)
61+
cy.findByTestId(`results`)
62+
.should(`contain.text`, `"hasError": false`)
63+
64+
cy.assertNoOverlayIframe()
65+
cy.screenshot()
66+
})
67+
})

e2e-tests/development-runtime/cypress/support/commands.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Cypress.Commands.add(`lifecycleCallOrder`, expectedActionCallOrder =>
2424
if (expectedActionCallOrderLength > actionsLength) {
2525
return false
2626
}
27-
27+
2828
let prevActionIndex = -1
2929
for (let i = 0; i < actionsLength; i += 1) {
3030
const nextActionIndex = prevActionIndex + 1
@@ -84,3 +84,26 @@ Cypress.Commands.add(
8484
Cypress.Commands.add(`assertRoute`, (route) => {
8585
cy.url().should(`equal`, `${window.location.origin}${route}`)
8686
})
87+
88+
// react-error-overlay is iframe, so this is just convenience helper
89+
// https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/#custom-command
90+
Cypress.Commands.add(`getOverlayIframe`, () => {
91+
// get the iframe > document > body
92+
// and retry until the body element is not empty
93+
return (
94+
cy
95+
.get(`iframe`, { log: true, timeout: 150000 })
96+
.its(`0.contentDocument.body`)
97+
.should(`not.be.empty`)
98+
// wraps "body" DOM element to allow
99+
// chaining more Cypress commands, like ".find(...)"
100+
// https://on.cypress.io/wrap
101+
.then(cy.wrap, { log: true })
102+
)
103+
})
104+
105+
Cypress.Commands.add(`assertNoOverlayIframe`, () => {
106+
// get the iframe > document > body
107+
// and retry until the body element is not empty
108+
return cy.get(`iframe`, { log: true, timeout: 15000 }).should(`not.exist`)
109+
})

e2e-tests/development-runtime/scripts/update.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ const args = yargs
2121
default: JSON.stringify(
2222
`
2323
import * as React from 'react';
24-
24+
2525
import Layout from '../components/layout';
26-
26+
2727
export default function SomeComponent() {
2828
return (
2929
<Layout>
@@ -34,13 +34,29 @@ const args = yargs
3434
`
3535
).trim(),
3636
type: `string`,
37+
})
38+
.option(`restore`, {
39+
default: false,
40+
type: `boolean`,
3741
}).argv
3842

3943
async function update() {
4044
const history = await getHistory()
4145

42-
const { file: fileArg, replacements } = args
46+
const { file: fileArg, replacements, restore } = args
4347
const filePath = path.resolve(fileArg)
48+
if (restore) {
49+
const original = history.get(filePath)
50+
if (original) {
51+
await fs.writeFile(filePath, original, `utf-8`)
52+
} else if (original === false) {
53+
await fs.remove(filePath)
54+
} else {
55+
console.log(`Didn't make changes to "${fileArg}". Nothing to restore.`)
56+
}
57+
history.delete(filePath)
58+
return
59+
}
4460
let exists = true
4561
if (!fs.existsSync(filePath)) {
4662
exists = false
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react"
2+
3+
function CompileError() {
4+
// compile-error
5+
return <p data-testid="hot">Working</p>
6+
}
7+
8+
export default CompileError
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from "react"
2+
import { graphql } from "gatsby"
3+
4+
function PageQueryRuntimeError({ data }) {
5+
console.log(data.errorRecoveryJson)
6+
if (data.errorRecoveryJson.hasError) {
7+
throw new Error(`Page query results caused runtime error`)
8+
}
9+
return (
10+
<>
11+
<p data-testid="hot">Working</p>
12+
<pre data-testid="results">{JSON.stringify(data, null, 2)}</pre>
13+
</>
14+
)
15+
}
16+
17+
export default PageQueryRuntimeError
18+
19+
export const query = graphql`
20+
{
21+
errorRecoveryJson(selector: { eq: "page-query" }) {
22+
hasError
23+
}
24+
}
25+
`

0 commit comments

Comments
 (0)