Skip to content

Commit 2023c31

Browse files
serhalppieh
andcommitted
fix: ensure inserting <title> in <head> updates document.title (#39382)
* chore: add retries to flaky test * refactor: move guard earlier and colocate with comment * ci: disable browserslist console warnings These are nondeterministic and conflict with test output assertions * fix: ensure inserting <title> in <head> updates `document.title` In #39306 we introduced a workaround that wraps the Gatsby Head API elements in an `<svg>` wrapper. React under the hood creates these children elements in the "SVG" namespace. In the case of `<title>`, this is problematic because when we insert it into the real `<head>`, browsers (as far as we can tell) do not trigger an update of `document.title` because this only occurs for `<title>` nodes in the HTML namespace. A node's namespace is immutable, even when using `cloneNode()` or `importNode()`. The only way to "reset" the namespace is to recreate a node. * fix: remove svg workaround, use itemProp instead (#39385) * test: expand navigation tests to test if effects are applied and not just if tags are inserted/updated/removed * fix: remove svg workaround, use itemProp instead * fix: don't break rules of hooks in createElement patch --------- Co-authored-by: Michal Piechowiak <[email protected]>
1 parent 92d6c67 commit 2023c31

29 files changed

Lines changed: 448 additions & 143 deletions

.circleci/config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ executors:
1616
GATSBY_CPU_COUNT: 2
1717
COMPILER_OPTIONS: GATSBY_MAJOR=<< parameters.gatsby_major >>
1818
NODE_NO_WARNINGS: 1
19+
BROWSERSLIST_IGNORE_OLD_DATA: true
1920
# See https://sharp.pixelplumbing.com/install/#custom-libvips
2021
# libvips may or may not be installed in the CircleCI images we're using, but we
2122
# don't want to use it regardless, for consistency (and because it can cause problems)
@@ -800,6 +801,8 @@ jobs:
800801
no_output_timeout: 15m
801802
environment:
802803
NODE_OPTIONS: --max-old-space-size=2048
804+
NODE_NO_WARNINGS: 1
805+
BROWSERSLIST_IGNORE_OLD_DATA: true
803806
GENERATE_JEST_REPORT: "true"
804807
COMPILER_OPTIONS: GATSBY_MAJOR=5
805808
JEST_JUNIT_OUTPUT_DIR: ./test-results/jest-node/

e2e-tests/development-runtime/cypress/integration/functionality/queries-in-packages.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ describe(`queries in packages`, () => {
44
})
55

66
it(`Should extract and run query from gatsby component`, () => {
7-
// Note: in dev this may take a few ms to be populated due to the way the Gatsby Head API is
8-
// implemented
9-
cy.get("head > title").should(
10-
`have.text`,
7+
cy.title().should(
8+
`eq`,
119
`Testing queries in packages | Gatsby Default Starter`
1210
)
1311
})

e2e-tests/development-runtime/cypress/integration/head-function-export/head-with-wrap-root-element.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ describe(`Head with wrapRootElement`, () => {
2424
cy.getTestElement(`jsonLD`).should(`have.text`, data.static.jsonLD)
2525
})
2626

27+
it(`updates document title`, () => {
28+
cy.visit(
29+
headFunctionExportSharedData.page.headWithWrapRooElement
30+
).waitForRouteChange()
31+
32+
cy.title().should(`eq`, contextValue.posts[0].title)
33+
})
34+
2735
it(`can use context values provided in wrapRootElement`, () => {
2836
cy.visit(
2937
headFunctionExportSharedData.page.headWithWrapRooElement

e2e-tests/development-runtime/cypress/integration/head-function-export/html-insertion.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ describe(`Head function export html insertion`, () => {
77
.invoke(`attr`, `href`)
88
.should(`equal`, data.static.base)
99
cy.getTestElement(`title`).should(`have.text`, data.static.title)
10+
cy.title().should(`eq`, data.static.title)
1011
cy.getTestElement(`meta`)
1112
.invoke(`attr`, `content`)
1213
.should(`equal`, data.static.meta)
@@ -24,6 +25,7 @@ describe(`Head function export html insertion`, () => {
2425
.invoke(`attr`, `href`)
2526
.should(`equal`, data.queried.base)
2627
cy.getTestElement(`title`).should(`have.text`, data.queried.title)
28+
cy.title().should(`eq`, data.queried.title)
2729
cy.getTestElement(`meta`)
2830
.invoke(`attr`, `content`)
2931
.should(`equal`, data.queried.meta)
@@ -40,6 +42,7 @@ describe(`Head function export html insertion`, () => {
4042
.invoke(`attr`, `href`)
4143
.should(`equal`, data.static.base)
4244
cy.getTestElement(`title`).should(`have.text`, data.static.title)
45+
cy.title().should(`eq`, data.static.title)
4346
cy.getTestElement(`meta`)
4447
.invoke(`attr`, `content`)
4548
.should(`equal`, data.static.meta)
@@ -57,6 +60,7 @@ describe(`Head function export html insertion`, () => {
5760
.invoke(`attr`, `href`)
5861
.should(`equal`, data.queried.base)
5962
cy.getTestElement(`title`).should(`have.text`, data.queried.title)
63+
cy.title().should(`eq`, data.queried.title)
6064
cy.getTestElement(`meta`)
6165
.invoke(`attr`, `content`)
6266
.should(`equal`, data.queried.meta)
@@ -73,6 +77,7 @@ describe(`Head function export html insertion`, () => {
7377
.invoke(`attr`, `href`)
7478
.should(`equal`, data.dsg.base)
7579
cy.getTestElement(`title`).should(`have.text`, data.dsg.title)
80+
cy.title().should(`eq`, data.dsg.title)
7681
cy.getTestElement(`meta`)
7782
.invoke(`attr`, `content`)
7883
.should(`equal`, data.dsg.meta)
@@ -89,6 +94,7 @@ describe(`Head function export html insertion`, () => {
8994
.invoke(`attr`, `href`)
9095
.should(`equal`, data.ssr.base)
9196
cy.getTestElement(`title`).should(`have.text`, data.ssr.title)
97+
cy.title().should(`eq`, data.ssr.title)
9298
cy.getTestElement(`meta`)
9399
.invoke(`attr`, `content`)
94100
.should(`equal`, data.ssr.meta)

e2e-tests/development-runtime/cypress/integration/head-function-export/navigation.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ describe(`Head function export behavior during CSR navigation (Gatsby Link)`, ()
4444
.should(`equal`, data.static.link)
4545
cy.getTestElement(`jsonLD`).should(`have.text`, data.static.jsonLD)
4646

47+
// ensure that effects are applied
48+
cy.title().should(`eq`, data.static.title)
49+
cy.getTestElement(`linked-css-paragraph`).should(
50+
"have.css",
51+
"color",
52+
"rgb(102, 51, 153)"
53+
)
54+
4755
cy.getTestElement(`navigate-to-page-without-head-export`)
4856
.click()
4957
.waitForRouteChange()
@@ -55,6 +63,14 @@ describe(`Head function export behavior during CSR navigation (Gatsby Link)`, ()
5563
cy.getTestElement(`style`).should(`not.exist`)
5664
cy.getTestElement(`link`).should(`not.exist`)
5765
cy.getTestElement(`jsonLD`).should(`not.exist`)
66+
67+
// ensure that effects are applied
68+
cy.title().should(`eq`, ``)
69+
cy.getTestElement(`linked-css-paragraph`).should(
70+
"have.css",
71+
"color",
72+
"rgba(0, 0, 0, 0.8)"
73+
)
5874
})
5975

6076
/**
@@ -79,6 +95,14 @@ describe(`Head function export behavior during CSR navigation (Gatsby Link)`, ()
7995
.invoke(`attr`, `href`)
8096
.should(`equal`, data.static.link)
8197

98+
// ensure that effects are applied
99+
cy.title().should(`eq`, data.static.title)
100+
cy.getTestElement(`linked-css-paragraph`).should(
101+
"have.css",
102+
"color",
103+
"rgb(102, 51, 153)"
104+
)
105+
82106
// Navigate to a different page via Gatsby Link
83107
cy.getTestElement(`gatsby-link`).click()
84108

@@ -96,6 +120,14 @@ describe(`Head function export behavior during CSR navigation (Gatsby Link)`, ()
96120
.invoke(`attr`, `href`)
97121
.should(`equal`, data.queried.link)
98122

123+
// ensure that effects are applied
124+
cy.title().should(`eq`, data.queried.title)
125+
cy.getTestElement(`linked-css-paragraph`).should(
126+
"have.css",
127+
"color",
128+
"rgb(0, 0, 255)"
129+
)
130+
99131
// Navigate back to original page via Gatsby Link
100132
cy.getTestElement(`gatsby-link`).click().waitForRouteChange()
101133

@@ -112,5 +144,13 @@ describe(`Head function export behavior during CSR navigation (Gatsby Link)`, ()
112144
cy.getTestElement(`link`)
113145
.invoke(`attr`, `href`)
114146
.should(`equal`, data.static.link)
147+
148+
// ensure that effects are applied
149+
cy.title().should(`eq`, data.static.title)
150+
cy.getTestElement(`linked-css-paragraph`).should(
151+
"have.css",
152+
"color",
153+
"rgb(102, 51, 153)"
154+
)
115155
})
116156
})

e2e-tests/development-runtime/cypress/integration/head-function-export/typescript.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ describe(`Tsx Pages`, () => {
33
cy.visit(`/head-function-export/tsx-page`)
44

55
cy.getTestElement(`title`).should(`contain`, `TypeScript`)
6+
cy.title().should(`eq`, `TypeScript`)
67

78
cy.getTestElement(`name`)
89
.invoke(`attr`, `content`)

e2e-tests/development-runtime/cypress/integration/hot-reloading/head-export.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ describe(`hot reloading Head export`, () => {
77
cy.visit(`/head-function-export/basic`).waitForRouteChange()
88
})
99

10+
after(() => {
11+
cy.exec(
12+
`npm run update -- --file src/pages/head-function-export/basic.js --restore`
13+
)
14+
})
15+
1016
it(`displays placeholder content on launch`, () => {
1117
cy.getTestElement(TEST_ID)
1218
.invoke(`attr`, `content`)

e2e-tests/development-runtime/src/components/layout.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ html {
197197
box-sizing: inherit;
198198
}
199199
body {
200-
color: hsla(0, 0%, 0%, 0.8);
200+
color: rgba(0, 0, 0, 0.8);
201201
font-family: georgia, serif;
202202
font-weight: normal;
203203
word-wrap: break-word;

e2e-tests/development-runtime/src/pages/head-function-export/basic.js

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,16 @@ export default function HeadFunctionExportBasic() {
1818
>
1919
Navigate to without head export
2020
</Link>
21+
<p data-testid="linked-css-paragraph">
22+
Just some paragraph to test if linked css properly applies
23+
</p>
2124
</>
2225
)
2326
}
2427

2528
export function Head() {
26-
const {
27-
base,
28-
title,
29-
meta,
30-
noscript,
31-
style,
32-
link,
33-
extraMeta,
34-
jsonLD,
35-
} = data.static
29+
const { base, title, meta, noscript, style, link, extraMeta, jsonLD } =
30+
data.static
3631

3732
return (
3833
<>

e2e-tests/development-runtime/src/pages/head-function-export/page-query.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ export default function HeadFunctionExportPageQuery() {
77
<>
88
<h1>I test usage for the Head function export with a page query</h1>
99
<p>Some other words</p>
10+
<p data-testid="linked-css-paragraph">
11+
Just some paragraph to test if linked css properly applies
12+
</p>
1013
<Link data-testid="gatsby-link" to="/head-function-export/basic">
1114
Navigate to basic via Gatsby Link
1215
</Link>

0 commit comments

Comments
 (0)