Skip to content

Commit

Permalink
fix: avoid unmounting React components twice (#16280)
Browse files Browse the repository at this point in the history
  • Loading branch information
elevatebart committed Apr 30, 2021
1 parent cd41077 commit bd629d3
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
2 changes: 1 addition & 1 deletion npm/mount-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export function setupHooks (optionalCallback?: Function) {
})

// @ts-ignore
beforeEach(() => {
Cypress.on('test:before:run', () => {
optionalCallback?.()
cleanupStyles()
})
Expand Down
46 changes: 26 additions & 20 deletions npm/react/src/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const injectStyles = (options: MountOptions) => {
**/
export const mount = (jsx: React.ReactNode, options: MountOptions = {}) => _mount('mount', jsx, options)

let lastMountedReactDom: (typeof ReactDOM) | undefined

/**
* @see `mount`
* @param type The type of mount executed
Expand All @@ -62,6 +64,8 @@ const _mount = (type: 'mount' | 'rerender', jsx: React.ReactNode, options: Mount
.then(() => {
const reactDomToUse = options.ReactDom || ReactDOM

lastMountedReactDom = reactDomToUse

const el = document.getElementById(ROOT_ID)

if (!el) {
Expand Down Expand Up @@ -153,21 +157,23 @@ const _unmount = (options: { boundComponentMessage?: string, log: boolean }) =>
const selector = `#${ROOT_ID}`

return cy.get(selector, { log: false }).then(($el) => {
const wasUnmounted = ReactDOM.unmountComponentAtNode($el[0])

if (wasUnmounted && options.log) {
Cypress.log({
name: 'unmount',
type: 'parent',
message: [options.boundComponentMessage ?? 'Unmounted component'],
consoleProps: () => {
return {
description: 'Unmounts React component',
parent: $el[0],
home: 'https://github.com/cypress-io/cypress',
}
},
})
if (lastMountedReactDom) {
const wasUnmounted = lastMountedReactDom.unmountComponentAtNode($el[0])

if (wasUnmounted && options.log) {
Cypress.log({
name: 'unmount',
type: 'parent',
message: [options.boundComponentMessage ?? 'Unmounted component'],
consoleProps: () => {
return {
description: 'Unmounts React component',
parent: $el[0],
home: 'https://github.com/cypress-io/cypress',
}
},
})
}
}
})
})
Expand All @@ -176,13 +182,13 @@ const _unmount = (options: { boundComponentMessage?: string, log: boolean }) =>
// Cleanup before each run
// NOTE: we cannot use unmount here because
// we are not in the context of a test
Cypress.on('test:before:run', () => {
const preMountCleanup = () => {
const el = document.getElementById(ROOT_ID)

if (el) {
ReactDOM.unmountComponentAtNode(el)
if (el && lastMountedReactDom) {
lastMountedReactDom.unmountComponentAtNode(el)
}
})
}

/**
* Creates new instance of `mount` function with default options
Expand Down Expand Up @@ -317,4 +323,4 @@ export declare namespace Cypress {
// it is required to unmount component in beforeEach hook in order to provide a clean state inside test
// because `mount` can be called after some preparation that can side effect unmount
// @see npm/react/cypress/component/advanced/set-timeout-example/loading-indicator-spec.js
setupHooks(unmount)
setupHooks(preMountCleanup)

0 comments on commit bd629d3

Please sign in to comment.