From 1dc8c9800e6dba6db0b89bc9daf33a287671d1bc Mon Sep 17 00:00:00 2001 From: AtofStryker Date: Fri, 1 Nov 2024 16:59:28 -0400 Subject: [PATCH] chore: update to react 18 for the reporter from 17.0.2 to 18.3.1 [run ci] --- cli/CHANGELOG.md | 2 +- npm/react18/src/index.ts | 3 +- package.json | 9 +++-- packages/app/src/runner/reporter.ts | 11 ++---- .../driver/cypress/e2e/e2e/dom_hitbox.cy.js | 21 +++++++--- packages/driver/cypress/support/utils.ts | 39 +++++++------------ .../reporter/cypress/support/component.ts | 2 +- packages/reporter/package.json | 1 - packages/reporter/src/main.tsx | 8 ++-- packages/runner/unified-runner.tsx | 6 ++- .../protocol/cypress/support/component.ts | 2 +- yarn.lock | 39 ++++++++++++++++++- 12 files changed, 89 insertions(+), 54 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index db2572e60b09..7094169d8bd3 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -40,7 +40,7 @@ in this [GitHub issue](https://github.com/cypress-io/cypress/issues/30447). Addr - Upgraded `electron` from `27.3.10` to `32.2.0`. Addresses [#29547](https://github.com/cypress-io/cypress/issues/29547). - Upgraded bundled Chromium version from `118.0.5993.159` to `128.0.6613.178`. Addresses [#29547](https://github.com/cypress-io/cypress/issues/29547). - Updated `jQuery` from `3.4.1` to `3.7.1`. Addressed in [#30345](https://github.com/cypress-io/cypress/pull/30345). - +- Updated `react` from `17.0.2` to `18.3.1` and `react-dom` from `17.0.2` to `18.3.1`. Addresses [#30511](https://github.com/cypress-io/cypress/issues/30511). ## 13.15.2 diff --git a/npm/react18/src/index.ts b/npm/react18/src/index.ts index 4d5c3f6766df..9ab7390dfc87 100644 --- a/npm/react18/src/index.ts +++ b/npm/react18/src/index.ts @@ -1,5 +1,4 @@ import React from 'react' -// @ts-expect-error import ReactDOM from 'react-dom/client' import { getContainerEl } from '@cypress/mount-utils' import { @@ -53,6 +52,7 @@ export function mount (jsx: React.ReactNode, options: MountOptions = {}, rerende // to wipe away any state cleanup() const internalOptions: InternalMountOptions = { + // @ts-expect-error reactDom: ReactDOM, render: (reactComponent: ReturnType, el: HTMLElement) => { if (!root) { @@ -65,6 +65,7 @@ export function mount (jsx: React.ReactNode, options: MountOptions = {}, rerende cleanup, } + // @ts-expect-error return makeMountFn('mount', jsx, { ReactDom: ReactDOM, ...options }, rerenderKey, internalOptions) } diff --git a/package.json b/package.json index 294f198ee8d7..883480ac2f84 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "@octokit/auth-app": "6.0.3", "@octokit/core": "5.0.2", "@percy/cli": "1.27.4", + "@reach/dialog": "0.10.5", "@semantic-release/changelog": "6.0.3", "@semantic-release/git": "10.0.1", "@types/better-sqlite3": "^7.6.3", @@ -112,8 +113,8 @@ "@types/mocha": "8.0.3", "@types/node": "20.16.0", "@types/prismjs": "1.16.0", - "@types/react": "17.0.83", - "@types/react-dom": "17.0.25", + "@types/react": "18.3.12", + "@types/react-dom": "18.3.1", "@types/request-promise": "4.1.45", "@types/send": "^0.17.1", "@types/sinon-chai": "3.2.3", @@ -189,8 +190,8 @@ "pluralize": "8.0.0", "print-arch": "1.0.0", "proxyquire": "2.1.3", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "18.3.1", + "react-dom": "18.3.1", "rimraf": "5.0.10", "semantic-release": "22.0.12", "semantic-release-monorepo": "8.0.2", diff --git a/packages/app/src/runner/reporter.ts b/packages/app/src/runner/reporter.ts index 9062b2753141..b2c88002534d 100644 --- a/packages/app/src/runner/reporter.ts +++ b/packages/app/src/runner/reporter.ts @@ -11,12 +11,6 @@ export function setInitializedReporter (val: boolean) { hasInitializeReporter = val } -async function unmountReporter () { - // We do not need to unmount the reporter at any point right now, - // but this will likely be useful for cleaning up at some point. - window.UnifiedRunner.ReactDOM.unmountComponentAtNode(getReporterElement()) -} - async function resetReporter () { if (hasInitializeReporter) { await getEventManager().resetReporter() @@ -56,11 +50,12 @@ function renderReporter ( testFilter: specsStore.testFilter, }) - window.UnifiedRunner.ReactDOM.render(reporter, root) + const reactDomRoot = window.UnifiedRunner.ReactDOM.createRoot(root) + + reactDomRoot.render(reporter) } export const UnifiedReporterAPI = { - unmountReporter, setupReporter, hasInitializeReporter, resetReporter, diff --git a/packages/driver/cypress/e2e/e2e/dom_hitbox.cy.js b/packages/driver/cypress/e2e/e2e/dom_hitbox.cy.js index 6f226aacc1c7..9f380366b2c2 100644 --- a/packages/driver/cypress/e2e/e2e/dom_hitbox.cy.js +++ b/packages/driver/cypress/e2e/e2e/dom_hitbox.cy.js @@ -54,7 +54,14 @@ describe('rect highlight', { browser: '!webkit' }, () => { it('correct target position during click', () => { clickAndPin('#button') - ensureCorrectHighlightPositions('#button') + // TODO: We are currently skipping the element comparison on the highlight. + // What looks to be occurring, is that the DOM reference fetched in elementFromPoint + // is a stale detached DOM reference of the highlight container over the button. + // In React 17, the "elementFromPoint" and "div[data-layer=Content]" share the same reference. + // Since updating the Reporter to React 18, this is no longer the case. The element looks to be rerendered + // and the previous reference detached. We will need to come up with a different way to test this. + // @see https://github.com/cypress-io/cypress/issues/30526. + ensureCorrectHighlightPositions('#button', true) ensureCorrectTargetPosition('#button') }) @@ -100,7 +107,7 @@ const ensureCorrectTargetPosition = (sel) => { }) } -const ensureCorrectHighlightPositions = (sel) => { +const ensureCorrectHighlightPositions = (sel, skipElementComparison) => { return cy.wrap(null, { timeout: 4000 }).should(() => { const els = { content: cy.$$('div[data-layer=Content]'), @@ -112,12 +119,14 @@ const ensureCorrectHighlightPositions = (sel) => { return $el[0].getBoundingClientRect() }) - const doc = els.content[0].ownerDocument + if (!skipElementComparison) { + const doc = els.content[0].ownerDocument - const contentHighlightCenter = [dims.content.x + dims.content.width / 2, dims.content.y + dims.content.height / 2] - const highlightedEl = doc.elementFromPoint(...contentHighlightCenter) + const contentHighlightCenter = [dims.content.x + dims.content.width / 2, dims.content.y + dims.content.height / 2] + const highlightedEl = doc.elementFromPoint(...contentHighlightCenter) - expect(highlightedEl).eq(els.content[0]) + expect(highlightedEl).eq(els.content[0]) + } expectToBeInside(dims.content, dims.padding, 'content to be inside padding') expectToBeInside(dims.padding, dims.border, 'padding to be inside border') diff --git a/packages/driver/cypress/support/utils.ts b/packages/driver/cypress/support/utils.ts index d0febb3c3b8b..dfd2771c5364 100644 --- a/packages/driver/cypress/support/utils.ts +++ b/packages/driver/cypress/support/utils.ts @@ -21,42 +21,31 @@ export const findReactInstance = function (dom) { } export const clickCommandLog = (sel, type) => { - return cy.wait(10) + // trigger the LONG_RUNNING_THRESHOLD to display the command line + // this adds time to test but makes a more accurate test as React 18+ does not rerender when setting internals + return cy.wait(2000) .then(() => { - return withMutableReporterState(() => { - const commandLogEl = getCommandLogWithText(sel, type) - const reactCommandInstance = findReactInstance(commandLogEl[0]) + const commandLogEl = getCommandLogWithText(sel, type) - if (!reactCommandInstance) { - assert(false, 'failed to get command log React instance') - } + const reactCommandInstance = findReactInstance(commandLogEl[0]) - reactCommandInstance.props.appState.isRunning = false - const inner = $(commandLogEl).find('.command-wrapper-text') + if (!reactCommandInstance) { + assert(false, 'failed to get command log React instance') + } + + reactCommandInstance.props.appState.isRunning = false + const inner = $(commandLogEl).find('.command-wrapper-text') - inner.get(0).click() + inner.get(0).click() + // wait slightly for a repaint of the reporter + cy.wait(10).then(() => { // make sure command was pinned, otherwise throw a better error message expect(cy.$$('.runnable-active .command-pin', top?.document).length, 'command should be pinned').ok }) }) } -export const withMutableReporterState = (fn) => { - // @ts-ignore - top?.UnifiedRunner.MobX.configure({ enforceActions: 'never' }) - - const currentTestLog = findReactInstance(cy.$$('.runnable-active', top?.document)[0]) - - currentTestLog.props.model._isOpen = true - - return Promise.try(fn) - .then(() => { - // @ts-ignore - top?.UnifiedRunner.MobX.configure({ enforceActions: 'always' }) - }) -} - const wrapped = (obj) => cy.wrap(obj, { log: false }) export const shouldBeCalled = (stub) => wrapped(stub).should('be.called') diff --git a/packages/reporter/cypress/support/component.ts b/packages/reporter/cypress/support/component.ts index 4fe6c1860b90..7ffa238e8510 100644 --- a/packages/reporter/cypress/support/component.ts +++ b/packages/reporter/cypress/support/component.ts @@ -1,4 +1,4 @@ -import { mount } from 'cypress/react' +import { mount } from 'cypress/react18' import 'cypress-real-events/support' import { installCustomPercyCommand } from '@packages/frontend-shared/cypress/support/customPercyCommand' diff --git a/packages/reporter/package.json b/packages/reporter/package.json index f7dc24ccde8f..96bc6bc0b16a 100644 --- a/packages/reporter/package.json +++ b/packages/reporter/package.json @@ -20,7 +20,6 @@ "@packages/driver": "0.0.0-development", "@packages/types": "0.0.0-development", "@packages/web-config": "0.0.0-development", - "@reach/dialog": "0.10.5", "classnames": "2.3.1", "css-element-queries": "1.2.3", "cypress-multi-reporters": "1.4.0", diff --git a/packages/reporter/src/main.tsx b/packages/reporter/src/main.tsx index fbc2fed10517..e299c25f9a85 100644 --- a/packages/reporter/src/main.tsx +++ b/packages/reporter/src/main.tsx @@ -3,7 +3,7 @@ import { action, runInAction } from 'mobx' import { observer } from 'mobx-react' import cs from 'classnames' import React, { Component } from 'react' -import { render } from 'react-dom' +import { createRoot } from 'react-dom/client' // @ts-ignore import EQ from 'css-element-queries/src/ElementQueries' @@ -154,8 +154,10 @@ declare global { if (window.Cypress) { window.state = appState window.render = (props) => { - // @ts-ignore - render(} />, document.getElementById('app')) + const container: HTMLElement = document.getElementById('app') as HTMLElement + const root = createRoot(container) + + root.render(} />) } } diff --git a/packages/runner/unified-runner.tsx b/packages/runner/unified-runner.tsx index 01c18e1f0630..77a326f684a1 100644 --- a/packages/runner/unified-runner.tsx +++ b/packages/runner/unified-runner.tsx @@ -1,5 +1,5 @@ import React from 'react' -import ReactDOM from 'react-dom' +import { createRoot } from 'react-dom/client' import $Cypress from '@packages/driver' import { Reporter } from '@packages/reporter/src/main' import shortcuts from '@packages/reporter/src/lib/shortcuts' @@ -16,7 +16,9 @@ export const UnifiedRunner = { MobX, - ReactDOM, + ReactDOM: { + createRoot, + }, Reporter, } diff --git a/system-tests/projects/protocol/cypress/support/component.ts b/system-tests/projects/protocol/cypress/support/component.ts index b3c30eabe612..52b74e5f5862 100644 --- a/system-tests/projects/protocol/cypress/support/component.ts +++ b/system-tests/projects/protocol/cypress/support/component.ts @@ -1,4 +1,4 @@ -import { mount } from 'cypress/react' +import { mount } from 'cypress/react18' // Augment the Cypress namespace to include type definitions for // your custom command. diff --git a/yarn.lock b/yarn.lock index 68c26e1532db..67553298baab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8201,7 +8201,22 @@ dependencies: "@types/react" "^17" -"@types/react@*", "@types/react@17.0.83", "@types/react@^17": +"@types/react-dom@18.3.1": + version "18.3.1" + resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07" + integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@18.3.12": + version "18.3.12" + resolved "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz#99419f182ccd69151813b7ee24b792fe08774f60" + integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +"@types/react@17.0.83", "@types/react@^17": version "17.0.83" resolved "https://registry.npmjs.org/@types/react/-/react-17.0.83.tgz#b477c56387b74279281149dcf5ba2a1e2216d131" integrity sha512-l0m4ArKJvmFtR4e8UmKrj1pB4tUgOhJITf+mADyF/p69Ts1YAR/E+G9XEM0mHXKVRa1dQNHseyyDNzeuAXfXQw== @@ -26296,6 +26311,14 @@ react-dom@17.0.2, react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" +react-dom@18.3.1: + version "18.3.1" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.2" + react-dom@^15.3.2: version "15.7.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.7.0.tgz#39106dee996d0742fb0f43d567ef8b8153483ab2" @@ -26409,6 +26432,13 @@ react@17.0.2, react@^17.0.2: loose-envify "^1.1.0" object-assign "^4.1.1" +react@18.3.1: + version "18.3.1" + resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== + dependencies: + loose-envify "^1.1.0" + react@^15.3.2: version "15.7.0" resolved "https://registry.yarnpkg.com/react/-/react-15.7.0.tgz#10308fd42ac6912a250bf00380751abc41ac7106" @@ -27548,6 +27578,13 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== + dependencies: + loose-envify "^1.1.0" + schema-utils@>1.0.0, schema-utils@^4.0.0, schema-utils@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b"