diff --git a/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json b/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json index 0a42b7d4cd14dc9505a90fc05101d774b989aa3c..e45cf8218e132094432dc7c13142f4a91e40fa4e 100644 --- a/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json +++ b/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json @@ -1,12 +1,7 @@ { "dependencies": { - "@babel/plugin-transform-modules-commonjs": "7.0.0-beta.46", - "@babel/polyfill": "7.0.0-beta.46", - "@babel/register": "7.0.0-beta.46", - "bootstrap": "4.1.0", - "chai": "3.5.0", - "jsdom": "9.8.3", - "mocha": "3.2.0", + "bootstrap": "4.1.1", + "jest": "23.6.0", "node-sass": "4.8.3", "normalize.css": "7.0.0", "prop-types": "15.5.6", diff --git a/packages/react-scripts/fixtures/kitchensink/README.md b/packages/react-scripts/fixtures/kitchensink/README.md index 4e7725ce15f3b4ac9b9a4a30cd2b6c55bf88aeeb..0e64a76aed38b5ba5fc41857bcaa0c5807539741 100644 --- a/packages/react-scripts/fixtures/kitchensink/README.md +++ b/packages/react-scripts/fixtures/kitchensink/README.md @@ -51,4 +51,3 @@ An usual flow for the test itself is something similar to: - since `initDOM` returns a `Document` element, the previous `id` attribute is used to target the feature's DOM and `expect` accordingly -These tests are run by **mocha** (why not **jest**? See [this issue](https://github.com/facebook/jest/issues/2288)) and the environments used are both `development` and `production`. diff --git a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js index b1f5f5d55441d4632e0f027f7505f2a4b599c56f..79de16706dc9214ada3a8c88908b85341c0e9675 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import { expect } from 'chai'; import initDOM from './initDOM'; describe('Integration', () => { @@ -15,23 +14,23 @@ describe('Integration', () => { expect( doc.getElementById('feature-file-env-original-1').textContent - ).to.equal('from-original-env-1'); + ).toBe('from-original-env-1'); expect( doc.getElementById('feature-file-env-original-2').textContent - ).to.equal('override-from-original-local-env-2'); + ).toBe('override-from-original-local-env-2'); if (process.env.NODE_ENV === 'production') { - expect(doc.getElementById('feature-file-env').textContent).to.equal( + expect(doc.getElementById('feature-file-env').textContent).toBe( 'production' ); - expect(doc.getElementById('feature-file-env-x').textContent).to.equal( + expect(doc.getElementById('feature-file-env-x').textContent).toBe( 'x-from-production-env' ); } else { - expect(doc.getElementById('feature-file-env').textContent).to.equal( + expect(doc.getElementById('feature-file-env').textContent).toBe( 'development' ); - expect(doc.getElementById('feature-file-env-x').textContent).to.equal( + expect(doc.getElementById('feature-file-env-x').textContent).toBe( 'x-from-development-env' ); } @@ -41,9 +40,7 @@ describe('Integration', () => { it('NODE_PATH', async () => { const doc = await initDOM('node-path'); - expect( - doc.getElementById('feature-node-path').childElementCount - ).to.equal(4); + expect(doc.getElementById('feature-node-path').childElementCount).toBe(4); doc.defaultView.close(); }); @@ -54,12 +51,12 @@ describe('Integration', () => { process.env.NODE_ENV === 'development' ? '' : 'http://www.example.org/spa'; - expect(doc.getElementById('feature-public-url').textContent).to.equal( + expect(doc.getElementById('feature-public-url').textContent).toBe( `${prefix}.` ); expect( doc.querySelector('head link[rel="shortcut icon"]').getAttribute('href') - ).to.equal(`${prefix}/favicon.ico`); + ).toBe(`${prefix}/favicon.ico`); doc.defaultView.close(); }); @@ -68,25 +65,25 @@ describe('Integration', () => { expect( doc.getElementById('feature-shell-env-variables').textContent - ).to.equal('fromtheshell.'); + ).toBe('fromtheshell.'); doc.defaultView.close(); }); it('expand .env variables', async () => { const doc = await initDOM('expand-env-variables'); - expect(doc.getElementById('feature-expand-env-1').textContent).to.equal( + expect(doc.getElementById('feature-expand-env-1').textContent).toBe( 'basic' ); - expect(doc.getElementById('feature-expand-env-2').textContent).to.equal( + expect(doc.getElementById('feature-expand-env-2').textContent).toBe( 'basic' ); - expect(doc.getElementById('feature-expand-env-3').textContent).to.equal( + expect(doc.getElementById('feature-expand-env-3').textContent).toBe( 'basic' ); expect( doc.getElementById('feature-expand-env-existing').textContent - ).to.equal('fromtheshell'); + ).toBe('fromtheshell'); doc.defaultView.close(); }); }); diff --git a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js index 0ed5a9408911988a6f923be68acb38591f96281a..e807888d39722d5fef084888e94dde8daa846d4c 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js @@ -7,9 +7,8 @@ const fs = require('fs'); const http = require('http'); -const jsdom = require('jsdom'); +const jsdom = require('jsdom/lib/old-api.js'); const path = require('path'); -const { expect } = require('chai'); let getMarkup; export let resourceLoader; @@ -50,7 +49,7 @@ if (process.env.E2E_FILE) { it.only('can run jsdom (at least one of "E2E_FILE" or "E2E_URL" environment variables must be provided)', () => { expect( new Error("This isn't the error you are looking for.") - ).to.be.undefined(); + ).toBeUndefined(); }); } diff --git a/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js b/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js index 9e34b669d6e11919ba7a1c7f2964420175cb8f69..54920726fa5d07c5d55a6de04338610f60d12a45 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import { expect } from 'chai'; import initDOM from './initDOM'; describe('Integration', () => { @@ -15,25 +14,25 @@ describe('Integration', () => { expect( doc.getElementById('feature-array-destructuring').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); it('array spread', async () => { const doc = await initDOM('array-spread'); - expect( - doc.getElementById('feature-array-spread').childElementCount - ).to.equal(4); + expect(doc.getElementById('feature-array-spread').childElementCount).toBe( + 4 + ); doc.defaultView.close(); }); it('async/await', async () => { const doc = await initDOM('async-await'); - expect( - doc.getElementById('feature-async-await').childElementCount - ).to.equal(4); + expect(doc.getElementById('feature-async-await').childElementCount).toBe( + 4 + ); doc.defaultView.close(); }); @@ -42,7 +41,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-class-properties').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -51,7 +50,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-computed-properties').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -60,7 +59,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-custom-interpolation').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -69,7 +68,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-default-parameters').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -78,16 +77,16 @@ describe('Integration', () => { expect( doc.getElementById('feature-destructuring-and-await').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); it('generators', async () => { const doc = await initDOM('generators'); - expect( - doc.getElementById('feature-generators').childElementCount - ).to.equal(4); + expect(doc.getElementById('feature-generators').childElementCount).toBe( + 4 + ); doc.defaultView.close(); }); @@ -96,7 +95,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-object-destructuring').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -105,16 +104,14 @@ describe('Integration', () => { expect( doc.getElementById('feature-object-spread').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); it('promises', async () => { const doc = await initDOM('promises'); - expect(doc.getElementById('feature-promises').childElementCount).to.equal( - 4 - ); + expect(doc.getElementById('feature-promises').childElementCount).toBe(4); doc.defaultView.close(); }); @@ -123,7 +120,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-rest-and-default').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -132,7 +129,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-rest-parameters').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); @@ -141,7 +138,7 @@ describe('Integration', () => { expect( doc.getElementById('feature-template-interpolation').childElementCount - ).to.equal(4); + ).toBe(4); doc.defaultView.close(); }); }); diff --git a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js index 4aca73603dd56f47d22670a1896777355402d1df..ebd830dfaaa782970aeb89f1c8e4b8669d2e6121 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import { expect } from 'chai'; import initDOM, { resourceLoader } from './initDOM'; import url from 'url'; @@ -20,14 +19,14 @@ const matchCSS = (doc, regexes) => { } resourceLoader({ url: url.parse(href) }, (_, textContent) => { for (const regex of regexes) { - expect(textContent).to.match(regex); + expect(textContent).toMatch(regex); } }); } else { for (let i = 0; i < regexes.length; ++i) { expect( doc.getElementsByTagName('style')[i].textContent.replace(/\s/g, '') - ).to.match(regexes[i]); + ).toMatch(regexes[i]); } } }; @@ -87,7 +86,7 @@ describe('Integration', () => { const children = doc.getElementById('graphql-inclusion').children; // .graphql - expect(children[0].textContent.replace(/\s/g, '')).to.equal( + expect(children[0].textContent.replace(/\s/g, '')).toBe( '{"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","variableDefinitions":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"test"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"test"},"value":{"kind":"StringValue","value":"test","block":false}}],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"test"},"arguments":[],"directives":[]}]}}]}}],"loc":{"start":0,"end":40,"source":{"body":"{\\ntest(test:\\"test\\"){\\ntest\\n}\\n}\\n","name":"GraphQLrequest","locationOffset":{"line":1,"column":1}}}}' ); doc.defaultView.close(); @@ -96,7 +95,7 @@ describe('Integration', () => { it('image inclusion', async () => { const doc = await initDOM('image-inclusion'); - expect(doc.getElementById('feature-image-inclusion').src).to.match( + expect(doc.getElementById('feature-image-inclusion').src).toMatch( /^data:image\/jpeg;base64.+==$/ ); doc.defaultView.close(); @@ -105,7 +104,7 @@ describe('Integration', () => { it('no ext inclusion', async () => { const doc = await initDOM('no-ext-inclusion'); - expect(doc.getElementById('feature-no-ext-inclusion').href).to.match( + expect(doc.getElementById('feature-no-ext-inclusion').href).toMatch( /\/static\/media\/aFileWithoutExt\.[a-f0-9]{8}\.bin$/ ); doc.defaultView.close(); @@ -114,7 +113,7 @@ describe('Integration', () => { it('json inclusion', async () => { const doc = await initDOM('json-inclusion'); - expect(doc.getElementById('feature-json-inclusion').textContent).to.equal( + expect(doc.getElementById('feature-json-inclusion').textContent).toBe( 'This is an abstract.' ); doc.defaultView.close(); @@ -123,7 +122,7 @@ describe('Integration', () => { it('linked modules', async () => { const doc = await initDOM('linked-modules'); - expect(doc.getElementById('feature-linked-modules').textContent).to.equal( + expect(doc.getElementById('feature-linked-modules').textContent).toBe( '2.0.0' ); doc.defaultView.close(); @@ -131,7 +130,7 @@ describe('Integration', () => { it('svg inclusion', async () => { const doc = await initDOM('svg-inclusion'); - expect(doc.getElementById('feature-svg-inclusion').src).to.match( + expect(doc.getElementById('feature-svg-inclusion').src).toMatch( /\/static\/media\/logo\..+\.svg$/ ); doc.defaultView.close(); @@ -140,9 +139,7 @@ describe('Integration', () => { it('svg component', async () => { const doc = await initDOM('svg-component'); - expect(doc.getElementById('feature-svg-component').textContent).to.equal( - '' - ); + expect(doc.getElementById('feature-svg-component').textContent).toBe(''); doc.defaultView.close(); }); @@ -155,7 +152,7 @@ describe('Integration', () => { it('unknown ext inclusion', async () => { const doc = await initDOM('unknown-ext-inclusion'); - expect(doc.getElementById('feature-unknown-ext-inclusion').href).to.match( + expect(doc.getElementById('feature-unknown-ext-inclusion').href).toMatch( /\/static\/media\/aFileWithExt\.[a-f0-9]{8}\.unknown$/ ); doc.defaultView.close(); diff --git a/packages/react-scripts/fixtures/kitchensink/jest.integration.config.js b/packages/react-scripts/fixtures/kitchensink/jest.integration.config.js new file mode 100644 index 0000000000000000000000000000000000000000..fc77889249362baeb9f7814d3ba0a73e3d5d979f --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/jest.integration.config.js @@ -0,0 +1,4 @@ +module.exports = { + testEnvironment: 'node', + testMatch: ['**/integration/*.test.js'], +}; diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/scss-styles.scss b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/scss-styles.scss index 8aac77fbf6eed71fd176a93edb5195714f16c019..5a764ed2022ffa0ba8ec8fc00f03b86033eca0ff 100644 --- a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/scss-styles.scss +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/scss-styles.scss @@ -1,4 +1,12 @@ -@import "~bootstrap/scss/bootstrap"; +@import "~bootstrap/scss/functions"; +@import "~bootstrap/scss/variables"; +@import "~bootstrap/scss/mixins"; + +@import "~bootstrap/scss/reboot"; +@import "~bootstrap/scss/type"; +@import "~bootstrap/scss/images"; +@import "~bootstrap/scss/code"; +@import "~bootstrap/scss/grid"; #feature-scss-inclusion { background: ghostwhite; diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index 490eb5f5666a53d12988a1fbca48f52622874c42..47f3b417d17ed4ef10af537b26ff298be103938f 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -1475,7 +1475,7 @@ import App from './App'; it('renders welcome message', () => { const wrapper = shallow(<App />); const welcome = <h2>Welcome to React</h2>; - // expect(wrapper.contains(welcome)).to.equal(true); + // expect(wrapper.contains(welcome)).toBe(true); expect(wrapper.contains(welcome)).toEqual(true); }); ``` diff --git a/tasks/e2e-kitchensink-eject.sh b/tasks/e2e-kitchensink-eject.sh index ef7a511dc232c1d6c88595dc8e5733233102086f..41ea1ab0d1087bbbb6d8b36e73cdfda4e9253939 100755 --- a/tasks/e2e-kitchensink-eject.sh +++ b/tasks/e2e-kitchensink-eject.sh @@ -145,7 +145,7 @@ REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ CI=true \ NODE_PATH=src \ NODE_ENV=test \ - yarn test --no-cache --testPathPattern=src + yarn test --no-cache --runInBand --testPathPattern=src # Test "development" environment tmp_server_log=`mktemp` @@ -159,7 +159,7 @@ E2E_URL="http://localhost:3002" \ CI=true NODE_PATH=src \ NODE_ENV=development \ BABEL_ENV=test \ - node_modules/.bin/mocha --timeout 30000 --compilers js:@babel/register --require @babel/polyfill integration/*.test.js + node_modules/.bin/jest --no-cache --runInBand --config='jest.integration.config.js' # Test "production" environment E2E_FILE=./build/index.html \ @@ -168,7 +168,7 @@ E2E_FILE=./build/index.html \ BABEL_ENV=test \ NODE_PATH=src \ PUBLIC_URL=http://www.example.org/spa/ \ - node_modules/.bin/mocha --timeout 30000 --compilers js:@babel/register --require @babel/polyfill integration/*.test.js + node_modules/.bin/jest --no-cache --runInBand --config='jest.integration.config.js' # Cleanup cleanup diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh index c6011997cf823a8fc21fa2184497a1beb435b02f..a4cb3438f26fdad55a10d925a13dfc947c1102e1 100755 --- a/tasks/e2e-kitchensink.sh +++ b/tasks/e2e-kitchensink.sh @@ -131,11 +131,12 @@ exists build/*.html exists build/static/js/main.*.js # Unit tests +# https://facebook.github.io/jest/docs/en/troubleshooting.html#tests-are-extremely-slow-on-docker-and-or-continuous-integration-ci-server REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ CI=true \ NODE_PATH=src \ NODE_ENV=test \ - yarn test --no-cache --testPathPattern=src + yarn test --no-cache --runInBand --testPathPattern=src # Prepare "development" environment tmp_server_log=`mktemp` @@ -155,7 +156,7 @@ E2E_URL="http://localhost:3001" \ CI=true NODE_PATH=src \ NODE_ENV=development \ BABEL_ENV=test \ - node_modules/.bin/mocha --timeout 30000 --compilers js:@babel/register --require @babel/polyfill integration/*.test.js + node_modules/.bin/jest --no-cache --runInBand --config='jest.integration.config.js' # Test "production" environment E2E_FILE=./build/index.html \ CI=true \ @@ -163,11 +164,7 @@ E2E_FILE=./build/index.html \ NODE_ENV=production \ BABEL_ENV=test \ PUBLIC_URL=http://www.example.org/spa/ \ - node_modules/.bin/mocha --timeout 30000 --compilers js:@babel/register --require @babel/polyfill integration/*.test.js - -# Remove the config we just created for Mocha -# TODO: this is very hacky and we should find some other solution -rm .babelrc + node_modules/.bin/jest --no-cache --runInBand --config='jest.integration.config.js' # Cleanup cleanup