diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts index b2d2eb20f2b..120cbb74de4 100644 --- a/cypress/support/index.d.ts +++ b/cypress/support/index.d.ts @@ -1,8 +1,7 @@ -import type { ReactNode } from 'react'; -import { mount } from 'cypress/react'; import { ContextObject, Result, RunOptions } from 'axe-core'; import { realPress } from 'cypress-real-events/commands/realPress'; -import type { EuiProviderProps } from '../../src/components/provider'; +import type { mountCommand } from './setup/mount'; +import type { realMountCommand } from './setup/realMount'; type KeyOrShortcut = Parameters[0]; type RealPressOptions = Parameters[1]; @@ -32,16 +31,13 @@ declare global { /** * Mounts components with a basic `EuiProvider` wrapper */ - mount: ( - children: ReactNode, - options?: { providerProps?: Partial> } - ) => ReturnType; + mount: mountCommand; /** * This ensures the correct testing window has focus when using Cypress Real Events. * @see https://github.com/dmtrKovalenko/cypress-real-events/issues/196 */ - realMount: typeof mount; + realMount: realMountCommand; /** * Repeat the Real Events `realPress()` method 2 or more times diff --git a/cypress/support/setup/mount.js b/cypress/support/setup/mount.js index c0f7edf3e3f..e69de29bb2d 100644 --- a/cypress/support/setup/mount.js +++ b/cypress/support/setup/mount.js @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { mount as cypressMount } from 'cypress/react'; -import { EuiProvider } from '../../../src'; - -Cypress.Commands.add('mount', (children, options = {}) => { - const { providerProps } = options; - return cypressMount({children}); -}); diff --git a/cypress/support/setup/mount.tsx b/cypress/support/setup/mount.tsx new file mode 100644 index 00000000000..3cc6aaaa9d6 --- /dev/null +++ b/cypress/support/setup/mount.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { ReactNode } from 'react'; +import { EuiProvider } from '../../../src'; +import type { mount } from '@cypress/react18'; + +// Pick cypress mount function based on which React version is currently being +// tested. It has to be directly compared against process.env.REACT_VERSION +// for tree-shaking to work and not throw an error because of a missing import. +let cypressMount: typeof mount; +if (process.env.REACT_VERSION === '18') { + cypressMount = require('@cypress/react18').mount; +} else { + cypressMount = require('@cypress/react').mount; +} + +const mountCommand = (children: ReactNode): ReturnType => { + return cypressMount({children}); +}; + +// Export only the type to not confuse code-completion tools +export type mountCommand = typeof mountCommand; + +Cypress.Commands.add('mount', mountCommand); diff --git a/cypress/support/setup/realMount.js b/cypress/support/setup/realMount.tsx similarity index 69% rename from cypress/support/setup/realMount.js rename to cypress/support/setup/realMount.tsx index 0324084d970..cb114cb5dcf 100644 --- a/cypress/support/setup/realMount.js +++ b/cypress/support/setup/realMount.tsx @@ -6,21 +6,26 @@ * Side Public License, v 1. */ -import { React, Fragment } from 'react'; +import React, { ReactNode } from 'react'; import './mount'; -Cypress.Commands.add('realMount', (children) => { +const realMountCommand = (children: ReactNode) => { cy.mount( - + <>
{children} - + ).then(() => { cy.get('[data-test-subj="cypress-real-event-target"]').realClick({ position: 'topLeft', }); }); -}); +}; + +// Export only the type to not confuse code-completion tools +export type realMountCommand = typeof realMountCommand; + +Cypress.Commands.add('realMount', realMountCommand); diff --git a/cypress/webpack.config.js b/cypress/webpack.config.js index b026d3515ef..c7704a93e3f 100644 --- a/cypress/webpack.config.js +++ b/cypress/webpack.config.js @@ -12,6 +12,15 @@ const { ProvidePlugin, DefinePlugin } = require('webpack'); const THEME_IMPORT = `'../../dist/eui_theme_${process.env.THEME}.css'`; +const alias = {}; +const reactVersion = process.env.REACT_VERSION || '18'; + +// Setup module aliasing when we're testing an older React version +if (['16', '17'].includes(reactVersion)) { + alias.react = `react-${reactVersion}`; + alias['react-dom'] = `react-dom-${reactVersion}`; +} + module.exports = { mode: 'development', @@ -26,6 +35,7 @@ module.exports = { os: false, process: require.resolve('process/browser'), }, + alias, }, module: { @@ -46,9 +56,9 @@ module.exports = { loader: 'style-loader', options: { insert: 'meta[name="css-styles"]', - } + }, }, - 'css-loader' + 'css-loader', ], exclude: /node_modules/, }, @@ -62,7 +72,8 @@ module.exports = { }), new DefinePlugin({ - THEME_IMPORT, // allow cypress/suport/index.js to require the correct css file + THEME_IMPORT, // allow cypress/support/component.tsx to require the correct css file + 'process.env.REACT_VERSION': JSON.stringify(reactVersion), }), ], }; diff --git a/package.json b/package.json index 0f4b49f4742..3ff00cd0b53 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,8 @@ "@babel/preset-typescript": "^7.21.5", "@babel/template": "^7.21.9", "@cypress/code-coverage": "^3.10.0", - "@cypress/react": "^5.10.3", + "@cypress/react": "^7.0.3", + "@cypress/react18": "^2.0.0", "@cypress/webpack-dev-server": "^1.7.0", "@elastic/charts": "^53.1.1", "@elastic/datemath": "^5.0.3", @@ -226,8 +227,12 @@ "puppeteer": "^5.5.0", "raw-loader": "^4.0.1", "react": "^18.2.0", + "react-16": "npm:react@^16.14.0", + "react-17": "npm:react@^17.0.2", "react-docgen-typescript": "^2.2.2", "react-dom": "^18.2.0", + "react-dom-16": "npm:react-dom@^16.14.0", + "react-dom-17": "npm:react-dom@^17.0.2", "react-helmet": "^6.1.0", "react-redux": "^7.2.1", "react-refresh": "^0.11.0", diff --git a/scripts/cypress.js b/scripts/cypress.js index 714e322b7ba..04ba81e7673 100644 --- a/scripts/cypress.js +++ b/scripts/cypress.js @@ -21,12 +21,18 @@ const argv = yargs(hideBin(process.argv)) dev: { type: 'boolean' }, theme: { type: 'string', default: 'light', choices: ['light', 'dark'] }, a11y: { type: 'boolean' }, + 'react-version': { + type: 'number', + default: 18, + choices: [16, 17, 18], + }, }).argv; const isDev = argv.hasOwnProperty('dev'); const isA11y = argv.hasOwnProperty('a11y'); const skipScss = argv.hasOwnProperty('skip-css'); const theme = argv.theme; +const reactVersion = argv['react-version']; const info = chalk.white; const log = chalk.grey; @@ -54,11 +60,13 @@ const cypressCommandParts = [ `THEME=${theme}`, // pass the theme 'BABEL_MODULES=false', // let webpack receive ES Module code 'NODE_ENV=cypress_test', // enable code coverage checks + `REACT_VERSION=${reactVersion}`, // set react version to test `cypress ${testParams}`, ...argv._, // pass any extra options given to this script ]; const cypressCommand = cypressCommandParts.join(' '); +console.log(info(`Running tests on React v${reactVersion}`)); console.log(info(`${isDev ? 'Opening' : 'Running'} cypress`)); console.log(log(cypressCommand)); execSync(cypressCommand, { diff --git a/wiki/contributing-to-eui/testing/cypress-testing.md b/wiki/contributing-to-eui/testing/cypress-testing.md index 7ff9fd048f9..093b125b40d 100644 --- a/wiki/contributing-to-eui/testing/cypress-testing.md +++ b/wiki/contributing-to-eui/testing/cypress-testing.md @@ -18,6 +18,11 @@ By default tests are run using the light theme. Dark mode can be enabled by pass To ensure tests use up-to-date styles, the test runner compiles our SCSS to CSS before executing Cypress. This adds some processing time before the tests can run, and often the existing locally-built styles are still accurate. The CSS compilation step can be skipped by passing the `--skip-css` flag to `yarn test-cypress`, `yarn test-cypress-dev` and `yarn test-cypress-a11y`. +### Testing specific version of React + +By default, EUI Cypress tests are run using the latest supported version of React. +You can change that behavior and run e2e tests using a different React version by passing the `--react-version` option set to `16`, `17` or `18`. + ### Cypress arguments You can also pass [Cypress CLI arguments](https://docs.cypress.io/guides/guides/command-line). For example: diff --git a/yarn.lock b/yarn.lock index 3e9f0e8a125..eb9fb063cb4 100755 --- a/yarn.lock +++ b/yarn.lock @@ -2231,20 +2231,15 @@ js-yaml "3.14.1" nyc "15.1.0" -"@cypress/mount-utils@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@cypress/mount-utils/-/mount-utils-1.0.2.tgz#afbc4f8c350b7cd86edc5ad0db0cbe1e0181edc8" - integrity sha512-Fn3fdTiyayHoy8Ol0RSu4MlBH2maQ2ZEXeEVKl/zHHXEQpld5HX3vdNLhK5YLij8cLynA4DxOT/nO9iEnIiOXw== +"@cypress/react18@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cypress/react18/-/react18-2.0.0.tgz#9923928328a1a775bc10b7046747d4d90452c754" + integrity sha512-I4iEzyPvSmADPUFT7fuihuo21zu5j5OdgB73KnuCI7VjFT6RaYnag8zBeSkXuwSBO1fbD4jeJWoDyPNLqwLspg== -"@cypress/react@^5.10.3": - version "5.10.3" - resolved "https://registry.yarnpkg.com/@cypress/react/-/react-5.10.3.tgz#7e459cb70d0287d2137305b79772164681b988d3" - integrity sha512-E68ws4P6CPFbtIqr98rWimf47E5nY6plWwKpHt98GKadSq/MN+57qego+Z5SA1CaDLk7Pvfdk98oYNzkmj20jA== - dependencies: - "@cypress/mount-utils" "1.0.2" - debug "4.3.2" - find-webpack "2.2.1" - find-yarn-workspace-root "2.0.0" +"@cypress/react@^7.0.3": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@cypress/react/-/react-7.0.3.tgz#e62d67c1344265ee959e99100ce237663f20abb1" + integrity sha512-YseqnMugTbdPV9YCYEMXVqIf+P7x+pfjXOdjv4dnDFqNCZeHaZfOZVFZ4XfEHVxMv0aDszxlaLiIp3QDPhr12w== "@cypress/request@^2.88.10": version "2.88.10" @@ -10653,15 +10648,6 @@ find-versions@^3.0.0: dependencies: semver-regex "^2.0.0" -find-webpack@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/find-webpack/-/find-webpack-2.2.1.tgz#96e7b701a2d37c3500cae30d4dc59e14923ba460" - integrity sha512-OdDtn2AzQvu3l9U1TS5ALc7uTVcLK/yv3fhjo+Pz7yuv4hG3ANKnbkKnPIPZ5ofd9mpYe6wRf5g5H4X9Lx48vQ== - dependencies: - debug "4.1.1" - find-yarn-workspace-root "1.2.1" - mocked-env "1.3.2" - find-yarn-workspace-root2@1.2.16: version "1.2.16" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz#60287009dd2f324f59646bdb4b7610a6b301c2a9" @@ -10670,21 +10656,6 @@ find-yarn-workspace-root2@1.2.16: micromatch "^4.0.2" pkg-dir "^4.2.0" -find-yarn-workspace-root@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" - integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== - dependencies: - fs-extra "^4.0.3" - micromatch "^3.1.4" - -find-yarn-workspace-root@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - findup@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb" @@ -10905,15 +10876,6 @@ fs-extra@^3.0.1: jsonfile "^3.0.0" universalify "^0.1.0" -fs-extra@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -14026,13 +13988,6 @@ jsonfile@^3.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" @@ -15267,16 +15222,6 @@ mkdirp@^1.0.0, mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mocked-env@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mocked-env/-/mocked-env-1.3.2.tgz#548eb2fde141d083de70dc6b231cd9f3210d8731" - integrity sha512-jwm3ziowCjpbLNhUNYwn2G0tawV/ZGRuWeEGt6PItrkQT74Nk3pDldL2pmwm9sQZw6a/x+ZBGeBVYq54acTauQ== - dependencies: - check-more-types "2.24.0" - debug "4.1.1" - lazy-ass "1.6.0" - ramda "0.26.1" - moment-timezone@^0.5.31: version "0.5.31" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05" @@ -17646,11 +17591,6 @@ rambda@^7.1.0: resolved "https://registry.yarnpkg.com/rambda/-/rambda-7.5.0.tgz#1865044c59bc0b16f63026c6e5a97e4b1bbe98fe" integrity sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA== -ramda@0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" - integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== - ramda@0.29.0: version "0.29.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.0.tgz#fbbb67a740a754c8a4cbb41e2a6e0eb8507f55fb" @@ -17709,6 +17649,23 @@ re-reselect@^3.4.0: resolved "https://registry.yarnpkg.com/re-reselect/-/re-reselect-3.4.0.tgz#0f2303f3c84394f57f0cd31fea08a1ca4840a7cd" integrity sha512-JsecfN+JlckncVXTWFWjn0Vk6uInl8GSf4eEd9tTk5qXHlgqkPdILpnYpgZcISXNYAzvfvsCZviaDk8AxyS5sg== +"react-16@npm:react@^16.14.0": + version "16.14.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" + integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + +"react-17@npm:react@^17.0.2": + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + react-clientside-effect@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a" @@ -17742,6 +17699,25 @@ react-docgen@^5.0.0: node-dir "^0.1.10" strip-indent "^3.0.0" +"react-dom-16@npm:react-dom@^16.14.0": + version "16.14.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" + integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.19.1" + +"react-dom-17@npm:react-dom@^17.0.2": + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -18932,6 +18908,14 @@ sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"