diff --git a/circle.yml b/circle.yml index b44ec61d..bf0947c4 100644 --- a/circle.yml +++ b/circle.yml @@ -249,6 +249,32 @@ workflows: npm run only-covered working_directory: examples/webpack-file + - cypress/run: + name: Example Webpack5 file + requires: + - Component Tests + executor: cypress/base-12 + install-command: | + ls -la ../.. + echo ***Installing cypress-react-unit-test from root TGZ archive*** + npm install -D ../../cypress-react-unit-test-0.0.0-development.tgz + echo ***Installing other dependencies*** + npm install + echo ***rename root node_modules to avoid accidental dependencies*** + mv ../../node_modules ../../no_modules + verify-command: echo 'Already verified' + no-workspace: true + working_directory: examples/webpack5-file + command: npm test + store_artifacts: true + post-steps: + - run: + name: Check coverage 📈 + command: | + npm run check-coverage + npm run only-covered + working_directory: examples/webpack5-file + - cypress/run: name: Example Rollup requires: @@ -484,6 +510,7 @@ workflows: - Example Snapshots - Example Tailwind - Example Webpack file + - Example Webpack5 file - Example Webpack options - Example Rollup - Visual Sudoku diff --git a/examples/webpack5-file/.babelrc b/examples/webpack5-file/.babelrc new file mode 100644 index 00000000..2b7bafa5 --- /dev/null +++ b/examples/webpack5-file/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"] +} diff --git a/examples/webpack5-file/.npmrc b/examples/webpack5-file/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/examples/webpack5-file/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/examples/webpack5-file/README.md b/examples/webpack5-file/README.md new file mode 100644 index 00000000..343eb261 --- /dev/null +++ b/examples/webpack5-file/README.md @@ -0,0 +1,32 @@ +# example: webpack5-file + +> Component tests for projects using existing [webpack.config.js](webpack.config.js) file and [Webpack 5](https://webpack.js.org/blog/2020-10-10-webpack-5-release/) + +## Usage + +1. Make sure the root project has been built . + +```bash +# in the root of the project +npm install +npm run build +``` + +2. Run `npm install` in this folder to symlink the `cypress-react-unit-test` dependency. + +```bash +# in this folder +npm install +``` + +3. Start Cypress + +```bash +npm run cy:open +# or just run headless tests +npm test +``` + +## Notes + +See tests in the [cypress/component](cypress/component) folder. We also allow tests to load components using a [webpack alias](webpack.config.js) from `more-components/src` folder using `import Hello from '@components/Hello'`. diff --git a/examples/webpack5-file/cypress.json b/examples/webpack5-file/cypress.json new file mode 100644 index 00000000..00824cab --- /dev/null +++ b/examples/webpack5-file/cypress.json @@ -0,0 +1,7 @@ +{ + "fixturesFolder": false, + "testFiles": "**/*cy-spec.js", + "viewportWidth": 500, + "viewportHeight": 500, + "experimentalComponentTesting": true +} diff --git a/examples/webpack5-file/cypress/component/ChildComponent.cy-spec.js b/examples/webpack5-file/cypress/component/ChildComponent.cy-spec.js new file mode 100644 index 00000000..047e8dc3 --- /dev/null +++ b/examples/webpack5-file/cypress/component/ChildComponent.cy-spec.js @@ -0,0 +1,20 @@ +/// +import React from 'react' +import { mount } from 'cypress-react-unit-test' +import ChildComponent from './ChildComponent' +import * as calc from './calc' + +describe('ChildComponent unstubbed', () => { + it('works', () => { + cy.spy(calc, 'getRandomNumber').as('getRandomNumber') + mount() + // make sure the component shows the random value + // returned by the calc.getRandomNumber function + cy.get('@getRandomNumber') + .should('have.been.called') + .its('returnValues.0') + .then(n => { + cy.contains('.random', n) + }) + }) +}) diff --git a/examples/webpack5-file/cypress/component/ChildComponent.js b/examples/webpack5-file/cypress/component/ChildComponent.js new file mode 100644 index 00000000..15fe66da --- /dev/null +++ b/examples/webpack5-file/cypress/component/ChildComponent.js @@ -0,0 +1,10 @@ +import React from 'react' +import { getRandomNumber } from './calc' + +const ChildComponent = () => ( +
+ Child component

Random number {getRandomNumber()}

+
+) + +export default ChildComponent diff --git a/examples/webpack5-file/cypress/component/Hello.cy-spec.js b/examples/webpack5-file/cypress/component/Hello.cy-spec.js new file mode 100644 index 00000000..5f17674a --- /dev/null +++ b/examples/webpack5-file/cypress/component/Hello.cy-spec.js @@ -0,0 +1,12 @@ +/// +import React from 'react' +import { mount } from 'cypress-react-unit-test' +// use path alias defined in webpack config +import Hello from '@components/Hello' + +describe('Hello using path alias', () => { + it('works', () => { + mount() + cy.contains('Hello!').should('be.visible') + }) +}) diff --git a/examples/webpack5-file/cypress/component/Mock.cy-spec.js b/examples/webpack5-file/cypress/component/Mock.cy-spec.js new file mode 100644 index 00000000..8e3971a0 --- /dev/null +++ b/examples/webpack5-file/cypress/component/Mock.cy-spec.js @@ -0,0 +1,24 @@ +/// +import React from 'react' +import { mount } from 'cypress-react-unit-test' +import ParentComponent from './ParentComponent' +import * as calc from './calc' +import * as ChildComponent from './ChildComponent' + +describe('Mocking', () => { + it('named getRandomNumber imported in the child component', () => { + cy.stub(calc, 'getRandomNumber') + .as('lucky') + .returns(777) + mount() + cy.contains('.random', '777') + }) + + it('entire child component exported as default', () => { + cy.stub(ChildComponent, 'default') + .as('child') + .returns(
Mock child component
) + mount() + cy.contains('.mock-child', 'Mock child component') + }) +}) diff --git a/examples/webpack5-file/cypress/component/ParentComponent.js b/examples/webpack5-file/cypress/component/ParentComponent.js new file mode 100644 index 00000000..5596dad2 --- /dev/null +++ b/examples/webpack5-file/cypress/component/ParentComponent.js @@ -0,0 +1,12 @@ +import React from 'react' +import ChildComponent from './ChildComponent' + +const ParentComponent = () => ( +
+ Parent component, child component below +
+ +
+) + +export default ParentComponent diff --git a/examples/webpack5-file/cypress/component/Test.cy-spec.js b/examples/webpack5-file/cypress/component/Test.cy-spec.js new file mode 100644 index 00000000..467a77e6 --- /dev/null +++ b/examples/webpack5-file/cypress/component/Test.cy-spec.js @@ -0,0 +1,16 @@ +/// +import React from 'react' +import { mount } from 'cypress-react-unit-test' +import Test from './Test' + +describe('components', () => { + it('works', () => { + mount() + cy.contains('Text') + }) + + it('works with plain div', () => { + mount(
Text
) + cy.contains('Text') + }) +}) diff --git a/examples/webpack5-file/cypress/component/Test.js b/examples/webpack5-file/cypress/component/Test.js new file mode 100644 index 00000000..de74852b --- /dev/null +++ b/examples/webpack5-file/cypress/component/Test.js @@ -0,0 +1,5 @@ +import React from 'react' + +const Test = () =>
Text
+ +export default Test diff --git a/examples/webpack5-file/cypress/component/calc.js b/examples/webpack5-file/cypress/component/calc.js new file mode 100644 index 00000000..fe2bb220 --- /dev/null +++ b/examples/webpack5-file/cypress/component/calc.js @@ -0,0 +1 @@ +export const getRandomNumber = () => Math.round(Math.random() * 1000) diff --git a/examples/webpack5-file/cypress/integration/cy-spec.js b/examples/webpack5-file/cypress/integration/cy-spec.js new file mode 100644 index 00000000..d815fd54 --- /dev/null +++ b/examples/webpack5-file/cypress/integration/cy-spec.js @@ -0,0 +1,6 @@ +/// +describe('integration spec', () => { + it('works', () => { + expect(1).to.equal(1) + }) +}) diff --git a/examples/webpack5-file/cypress/plugins/index.js b/examples/webpack5-file/cypress/plugins/index.js new file mode 100644 index 00000000..604a3bcc --- /dev/null +++ b/examples/webpack5-file/cypress/plugins/index.js @@ -0,0 +1,10 @@ +// load file preprocessor that comes with this plugin +// https://github.com/bahmutov/cypress-react-unit-test#install +module.exports = (on, config) => { + // from the root of the project (folder with cypress.json file) + config.env.webpackFilename = 'webpack.config.js' + require('cypress-react-unit-test/plugins/load-webpack')(on, config) + // IMPORTANT to return the config object + // with the any changed environment variables + return config +} diff --git a/examples/webpack5-file/cypress/support/index.js b/examples/webpack5-file/cypress/support/index.js new file mode 100644 index 00000000..9d443012 --- /dev/null +++ b/examples/webpack5-file/cypress/support/index.js @@ -0,0 +1,3 @@ +require('cypress-react-unit-test/dist/hooks') +// if we need code coverage, need to include its custom support hook +require('@cypress/code-coverage/support') diff --git a/examples/webpack5-file/more-components/src/Hello.js b/examples/webpack5-file/more-components/src/Hello.js new file mode 100644 index 00000000..a8d8469b --- /dev/null +++ b/examples/webpack5-file/more-components/src/Hello.js @@ -0,0 +1,5 @@ +import React from 'react' + +const Hello = () =>
Hello!
+ +export default Hello diff --git a/examples/webpack5-file/package.json b/examples/webpack5-file/package.json new file mode 100644 index 00000000..09e2ecdf --- /dev/null +++ b/examples/webpack5-file/package.json @@ -0,0 +1,21 @@ +{ + "name": "example-webpack-options", + "description": "Using default Webpack options to transpile simple tests", + "private": true, + "scripts": { + "test": "cypress-expect run --passing 7", + "cy:open": "cypress open", + "check-coverage": "check-coverage Test.js calc.js ParentComponent.js ChildComponent.js", + "only-covered": "only-covered Test.js calc.js ParentComponent.js ChildComponent.js more-components/src/Hello.js" + }, + "devDependencies": { + "babel-loader": "8.1.0", + "check-code-coverage": "1.10.0", + "cypress": "5.3.0", + "cypress-expect": "2.1.0", + "cypress-react-unit-test": "file:../..", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "webpack": "5.2.0" + } +} diff --git a/examples/webpack5-file/webpack.config.js b/examples/webpack5-file/webpack.config.js new file mode 100644 index 00000000..6516ef45 --- /dev/null +++ b/examples/webpack5-file/webpack.config.js @@ -0,0 +1,25 @@ +const path = require('path') + +module.exports = { + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + }, + }, + ], + }, + // add alias to load "@components" from another folder + // so that tests in cypress/component can load components using + // import X from '@components/X' + // see https://glebbahmutov.com/blog/using-ts-aliases-in-cypress-tests/ + resolve: { + extensions: ['.js'], + alias: { + '@components': path.resolve(__dirname, 'more-components', 'src'), + }, + }, +}