-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(gatsby): don't remount matchPath pages (#10261)
* fix: don't remount page component when navigating inside matchPath * test: add tests to ensure remounting behaviour stays consistent and avoid future regressions * switch from snapshot testing to more descriptive assert * abstract lifecycleCallCount, so tests are more readable
- Loading branch information
Showing
11 changed files
with
191 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
e2e-tests/production-runtime/cypress/integration/lifecycle-methods.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
describe(`Production build tests`, () => { | ||
it(`should remount when navigating to different template`, () => { | ||
cy.visit(`/`).waitForAPI(`onRouteUpdate`) | ||
|
||
cy.getTestElement(`page2`) | ||
.click() | ||
.waitForAPI(`onRouteUpdate`) | ||
|
||
// we expect 2 `componentDidMount` calls - 1 for initial page and 1 for second page | ||
cy.lifecycleCallCount(`componentDidMount`).should(`equal`, 2) | ||
cy.lifecycleCallCount(`render`).should(`equal`, 2) | ||
}) | ||
|
||
it(`should remount when navigating to different page using same template`, () => { | ||
cy.visit(`/`).waitForAPI(`onRouteUpdate`) | ||
|
||
cy.getTestElement(`duplicated`) | ||
.click() | ||
.waitForAPI(`onRouteUpdate`) | ||
|
||
// we expect 2 `componentDidMount` calls - 1 for initial page and 1 for duplicated page | ||
cy.lifecycleCallCount(`componentDidMount`).should(`equal`, 2) | ||
cy.lifecycleCallCount(`render`).should(`equal`, 2) | ||
}) | ||
|
||
it(`should NOT remount when navigating within client only paths`, () => { | ||
cy.visit(`/client-only-paths`).waitForAPI(`onRouteUpdate`) | ||
|
||
cy.getTestElement(`/profile`) | ||
.click() | ||
.waitForAPI(`onRouteUpdate`) | ||
|
||
cy.getTestElement(`/dashboard`) | ||
.click() | ||
.waitForAPI(`onRouteUpdate`) | ||
|
||
// we expect just 1 `componentDidMount` call, when navigating inside matchPath | ||
cy.lifecycleCallCount(`componentDidMount`).should(`equal`, 1) | ||
cy.lifecycleCallCount(`render`).should(`equal`, 3) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Cypress.Commands.add(`lifecycleCallCount`, action => | ||
cy | ||
.window() | ||
.then( | ||
win => | ||
win.___PageComponentLifecycleCallsLog.filter( | ||
entry => entry.action === action | ||
).length | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,20 @@ | ||
/** | ||
* Implement Gatsby's Browser APIs in this file. | ||
* | ||
* See: https://www.gatsbyjs.org/docs/browser-apis/ | ||
*/ | ||
if (typeof window !== `undefined`) { | ||
window.___PageComponentLifecycleCallsLog = [] | ||
} | ||
|
||
// You can delete this file if you're not using it | ||
const addLogEntry = (action, location) => { | ||
const idElement = document.querySelector(`[data-testid="dom-marker"]`) | ||
window.___PageComponentLifecycleCallsLog.push({ | ||
action, | ||
pathname: location.pathname, | ||
domContent: idElement ? idElement.innerText : null, | ||
}) | ||
} | ||
|
||
exports.onPreRouteUpdate = ({ location }) => { | ||
addLogEntry(`onPreRouteUpdate`, location) | ||
} | ||
|
||
exports.onRouteUpdate = ({ location }) => { | ||
addLogEntry(`onRouteUpdate`, location) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,17 @@ | ||
/** | ||
* Implement Gatsby's Node APIs in this file. | ||
* | ||
* See: https://www.gatsbyjs.org/docs/node-apis/ | ||
*/ | ||
|
||
// You can delete this file if you're not using it | ||
exports.onCreatePage = ({ page, actions }) => { | ||
if (page.path === `/client-only-paths/`) { | ||
// create client-only-paths | ||
page.matchPath = `/client-only-paths/*` | ||
actions.createPage(page) | ||
} else if (page.path === `/`) { | ||
// use index page as template | ||
// (mimics) | ||
actions.createPage({ | ||
...page, | ||
path: `/duplicated`, | ||
context: { | ||
DOMMarker: `duplicated`, | ||
}, | ||
}) | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
e2e-tests/production-runtime/src/pages/client-only-paths.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React from 'react' | ||
import { Router } from '@reach/router' | ||
import { Link } from 'gatsby' | ||
|
||
import Layout from '../components/layout' | ||
import InstrumentPage from '../utils/instrument-page' | ||
|
||
const Page = props => ( | ||
<pre data-testid="dom-marker">[client-only-path] {props.page}</pre> | ||
) | ||
|
||
const routes = [`/`, `/profile`, `/dashboard`] | ||
|
||
const basePath = `/client-only-paths` | ||
|
||
const ClientOnlyPathPage = props => ( | ||
<Layout> | ||
<Router location={props.location} basepath={basePath}> | ||
<Page path="/" page="index" /> | ||
<Page path="/:page" /> | ||
</Router> | ||
<ul> | ||
{routes.map(route => ( | ||
<li key={route}> | ||
<Link to={`${basePath}${route}`} data-testid={route}> | ||
{route} | ||
</Link> | ||
</li> | ||
))} | ||
</ul> | ||
</Layout> | ||
) | ||
|
||
export default InstrumentPage(ClientOnlyPathPage) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React from 'react' | ||
|
||
export default Page => | ||
class extends React.Component { | ||
addLogEntry(action) { | ||
if (typeof window !== `undefined`) { | ||
window.___PageComponentLifecycleCallsLog.push({ | ||
action, | ||
pageComponent: this.props.pageResources.page.componentChunkName, | ||
locationPath: this.props.location.pathname, | ||
pagePath: this.props.pageResources.page.path, | ||
}) | ||
} | ||
} | ||
|
||
constructor(props) { | ||
super(props) | ||
this.addLogEntry(`constructor`) | ||
} | ||
|
||
componentDidMount() { | ||
this.addLogEntry(`componentDidMount`) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.addLogEntry(`componentWillUnmount`) | ||
} | ||
|
||
render() { | ||
this.addLogEntry(`render`) | ||
return <Page {...this.props} /> | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters