From 9099570b94712dc46da322219d659c045e5b7de4 Mon Sep 17 00:00:00 2001 From: Fabrizio Castellarin Date: Mon, 23 Jan 2017 20:43:16 +0100 Subject: [PATCH] Use a more sophisticated template for end-to-end testing. (#1187) * Use a more sophisticated template for end-to-end testing. * Not publish integration tests to npm * Use "commander" for cli argv handling * Handle different scripts version forms and exits without a name given * Prepare the commands for testing with a template * Fix dev "template" path * Add various features to test * Test various features separately * Test language features * Comment unused e2e.sh lines * Add "development" tests * Test environment variables * Test webpack plugins * Replace kitchensink README * Switch integration tests from jest to mocha * Use `fs-extra` * Use the correct folders * Do some cleanup * Print a better message for `--template` * Test `npm start` with and without https * Separate fast e2e testing from kitchensink testing * Hide `--internal-testing-template` (former `--template`) CLI option --- .travis.yml | 20 +- package.json | 2 +- packages/create-react-app/index.js | 21 +- packages/react-scripts/.npmignore | 1 + .../fixtures/kitchensink/.babelrc | 3 + .../react-scripts/fixtures/kitchensink/.env | 1 + .../fixtures/kitchensink/.flowconfig | 8 + .../kitchensink/.template.dependencies.json | 10 + .../fixtures/kitchensink/gitignore | 15 ++ .../kitchensink/integration/env.test.js | 24 ++ .../kitchensink/integration/initDOM.js | 62 +++++ .../kitchensink/integration/syntax.test.js | 96 ++++++++ .../kitchensink/integration/webpack.test.js | 44 ++++ .../fixtures/kitchensink/public/favicon.ico | Bin 0 -> 24838 bytes .../fixtures/kitchensink/public/index.html | 12 + .../fixtures/kitchensink/src/App.js | 103 +++++++++ .../fixtures/kitchensink/src/App.test.js | 8 + .../fixtures/kitchensink/src/absoluteLoad.js | 6 + .../src/features/env/FileEnvVariables.js | 5 + .../src/features/env/FileEnvVariables.test.js | 10 + .../kitchensink/src/features/env/NodePath.js | 25 ++ .../src/features/env/NodePath.test.js | 10 + .../src/features/env/ShellEnvVariables.js | 5 + .../features/env/ShellEnvVariables.test.js | 10 + .../src/features/syntax/ArrayDestructuring.js | 34 +++ .../syntax/ArrayDestructuring.test.js | 10 + .../src/features/syntax/ArraySpread.js | 33 +++ .../src/features/syntax/ArraySpread.test.js | 10 + .../src/features/syntax/AsyncAwait.js | 33 +++ .../src/features/syntax/AsyncAwait.test.js | 10 + .../src/features/syntax/ClassProperties.js | 20 ++ .../features/syntax/ClassProperties.test.js | 10 + .../src/features/syntax/ComputedProperties.js | 33 +++ .../syntax/ComputedProperties.test.js | 10 + .../features/syntax/CustomInterpolation.js | 43 ++++ .../syntax/CustomInterpolation.test.js | 10 + .../src/features/syntax/DefaultParameters.js | 33 +++ .../features/syntax/DefaultParameters.test.js | 10 + .../features/syntax/DestructuringAndAwait.js | 33 +++ .../syntax/DestructuringAndAwait.test.js | 10 + .../src/features/syntax/Generators.js | 35 +++ .../src/features/syntax/Generators.test.js | 10 + .../features/syntax/ObjectDestructuring.js | 34 +++ .../syntax/ObjectDestructuring.test.js | 10 + .../src/features/syntax/ObjectSpread.js | 33 +++ .../src/features/syntax/ObjectSpread.test.js | 10 + .../src/features/syntax/Promises.js | 34 +++ .../src/features/syntax/Promises.test.js | 10 + .../src/features/syntax/RestAndDefault.js | 33 +++ .../features/syntax/RestAndDefault.test.js | 10 + .../src/features/syntax/RestParameters.js | 33 +++ .../features/syntax/RestParameters.test.js | 10 + .../features/syntax/TemplateInterpolation.js | 33 +++ .../syntax/TemplateInterpolation.test.js | 10 + .../src/features/webpack/CssInclusion.js | 6 + .../src/features/webpack/CssInclusion.test.js | 10 + .../src/features/webpack/ImageInclusion.js | 6 + .../features/webpack/ImageInclusion.test.js | 10 + .../src/features/webpack/JsonInclusion.js | 6 + .../features/webpack/JsonInclusion.test.js | 10 + .../src/features/webpack/NoExtInclusion.js | 10 + .../features/webpack/NoExtInclusion.test.js | 10 + .../src/features/webpack/SvgInclusion.js | 6 + .../src/features/webpack/SvgInclusion.test.js | 10 + .../features/webpack/UnknownExtInclusion.js | 10 + .../webpack/UnknownExtInclusion.test.js | 10 + .../webpack/assets/aFileWithExt.unknown | 1 + .../features/webpack/assets/aFileWithoutExt | 1 + .../src/features/webpack/assets/abstract.json | 3 + .../src/features/webpack/assets/logo.svg | 7 + .../src/features/webpack/assets/style.css | 4 + .../features/webpack/assets/tiniest-cat.jpg | Bin 0 -> 691 bytes .../fixtures/kitchensink/src/index.js | 8 + .../fixtures/kitchensink/src/subfolder/lol.js | 1 + packages/react-scripts/scripts/init.js | 20 +- tasks/e2e-installs.sh | 152 ++++++++++++ tasks/e2e-kitchensink.sh | 218 ++++++++++++++++++ tasks/{e2e.sh => e2e-simple.sh} | 60 ----- 78 files changed, 1653 insertions(+), 74 deletions(-) create mode 100644 packages/react-scripts/.npmignore create mode 100644 packages/react-scripts/fixtures/kitchensink/.babelrc create mode 100644 packages/react-scripts/fixtures/kitchensink/.env create mode 100644 packages/react-scripts/fixtures/kitchensink/.flowconfig create mode 100644 packages/react-scripts/fixtures/kitchensink/.template.dependencies.json create mode 100644 packages/react-scripts/fixtures/kitchensink/gitignore create mode 100644 packages/react-scripts/fixtures/kitchensink/integration/env.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/integration/initDOM.js create mode 100644 packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/public/favicon.ico create mode 100644 packages/react-scripts/fixtures/kitchensink/public/index.html create mode 100644 packages/react-scripts/fixtures/kitchensink/src/App.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/App.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/absoluteLoad.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.test.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithExt.unknown create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithoutExt create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/abstract.json create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/logo.svg create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/style.css create mode 100644 packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/tiniest-cat.jpg create mode 100644 packages/react-scripts/fixtures/kitchensink/src/index.js create mode 100644 packages/react-scripts/fixtures/kitchensink/src/subfolder/lol.js create mode 100755 tasks/e2e-installs.sh create mode 100755 tasks/e2e-kitchensink.sh rename tasks/{e2e.sh => e2e-simple.sh} (73%) diff --git a/.travis.yml b/.travis.yml index bb9c8112081..8f358246614 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ --- language: node_js node_js: - - 0.10 - 4 - 6 cache: @@ -9,7 +8,20 @@ cache: - node_modules - packages/create-react-app/node_modules - packages/react-scripts/node_modules -script: tasks/e2e.sh +script: + - 'if [ $TEST_SUITE = "simple" ]; then tasks/e2e-simple.sh; fi' + - 'if [ $TEST_SUITE = "installs" ]; then tasks/e2e-installs.sh; fi' + - 'if [ $TEST_SUITE = "kitchensink" ]; then tasks/e2e-kitchensink.sh; fi' env: - - USE_YARN=no - - USE_YARN=yes + global: + - USE_YARN=no + matrix: + - TEST_SUITE=simple + - TEST_SUITE=installs + - TEST_SUITE=kitchensink +matrix: + include: + - node_js: 0.10 + env: TEST_SUITE=simple + - node_js: 6 + env: USE_YARN=yes TEST_SUITE=simple diff --git a/package.json b/package.json index 6645ea27971..6705e0413f9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "build": "node packages/react-scripts/scripts/build.js", "changelog": "lerna-changelog", "create-react-app": "tasks/cra.sh", - "e2e": "tasks/e2e.sh", + "e2e": "tasks/e2e-simple.sh", "postinstall": "lerna bootstrap", "publish": "tasks/release.sh", "start": "node packages/react-scripts/scripts/start.js", diff --git a/packages/create-react-app/index.js b/packages/create-react-app/index.js index 9ab11a5e938..4dbb37f4969 100644 --- a/packages/create-react-app/index.js +++ b/packages/create-react-app/index.js @@ -52,6 +52,7 @@ if (currentNodeVersion.split('.')[0] < 4) { process.exit(1); } +var commander = require('commander'); var fs = require('fs-extra'); var path = require('path'); var execSync = require('child_process').execSync; @@ -60,7 +61,7 @@ var semver = require('semver'); var projectName; -var program = require('commander') +var program = commander .version(require('./package.json').version) .arguments('') .usage(chalk.green('') + ' [options]') @@ -69,6 +70,7 @@ var program = require('commander') }) .option('--verbose', 'print additional logs') .option('--scripts-version ', 'use a non-standard version of react-scripts') + .allowUnknownOption() .on('--help', function () { console.log(' Only ' + chalk.green('') + ' is required.'); console.log(); @@ -82,7 +84,7 @@ var program = require('commander') console.log(' ' + chalk.cyan('https://github.com/facebookincubator/create-react-app/issues/new')); console.log(); }) - .parse(process.argv) + .parse(process.argv); if (typeof projectName === 'undefined') { console.error('Please specify the project directory:'); @@ -95,9 +97,14 @@ if (typeof projectName === 'undefined') { process.exit(1); } -createApp(projectName, program.verbose, program.scriptsVersion); +var hiddenProgram = new commander.Command() + .option('--internal-testing-template ', '(internal usage only, DO NOT RELY ON THIS) ' + + 'use a non-standard application template') + .parse(process.argv) + +createApp(projectName, program.verbose, program.scriptsVersion, hiddenProgram.internalTestingTemplate); -function createApp(name, verbose, version) { +function createApp(name, verbose, version, template) { var root = path.resolve(name); var appName = path.basename(root); @@ -130,7 +137,7 @@ function createApp(name, verbose, version) { console.log('Installing ' + chalk.cyan('react-scripts') + '...'); console.log(); - run(root, appName, version, verbose, originalDirectory); + run(root, appName, version, verbose, originalDirectory, template); } function shouldUseYarn() { @@ -163,7 +170,7 @@ function install(packageToInstall, verbose, callback) { }); } -function run(root, appName, version, verbose, originalDirectory) { +function run(root, appName, version, verbose, originalDirectory, template) { var packageToInstall = getInstallPackage(version); var packageName = getPackageName(packageToInstall); @@ -183,7 +190,7 @@ function run(root, appName, version, verbose, originalDirectory) { 'init.js' ); var init = require(scriptsPath); - init(root, appName, verbose, originalDirectory); + init(root, appName, verbose, originalDirectory, template); }); } diff --git a/packages/react-scripts/.npmignore b/packages/react-scripts/.npmignore new file mode 100644 index 00000000000..76163ab966a --- /dev/null +++ b/packages/react-scripts/.npmignore @@ -0,0 +1 @@ +/fixtures diff --git a/packages/react-scripts/fixtures/kitchensink/.babelrc b/packages/react-scripts/fixtures/kitchensink/.babelrc new file mode 100644 index 00000000000..5686105b953 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["latest"] +} diff --git a/packages/react-scripts/fixtures/kitchensink/.env b/packages/react-scripts/fixtures/kitchensink/.env new file mode 100644 index 00000000000..3e6e8a5a360 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/.env @@ -0,0 +1 @@ +REACT_APP_FILE_ENV_MESSAGE=fromtheenvfile diff --git a/packages/react-scripts/fixtures/kitchensink/.flowconfig b/packages/react-scripts/fixtures/kitchensink/.flowconfig new file mode 100644 index 00000000000..c658362285f --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/.flowconfig @@ -0,0 +1,8 @@ +[ignore] +/node_modules/fbjs/.* + +[include] + +[libs] + +[options] diff --git a/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json b/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json new file mode 100644 index 00000000000..8adac45708d --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "babel-preset-latest": "6.16.0", + "babel-register": "6.18.0", + "babel-polyfill": "6.20.0", + "chai": "3.5.0", + "jsdom": "9.8.3", + "mocha": "3.2.0" + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/gitignore b/packages/react-scripts/fixtures/kitchensink/gitignore new file mode 100644 index 00000000000..6c96c5cff12 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/gitignore @@ -0,0 +1,15 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# dependencies +node_modules + +# testing +coverage + +# production +build + +# misc +.DS_Store +.env +npm-debug.log diff --git a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js new file mode 100644 index 00000000000..a179aa7cbb2 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js @@ -0,0 +1,24 @@ +import { expect } from 'chai' +import initDOM from './initDOM' + +describe('Integration', () => { + describe('Environment variables', () => { + it('NODE_PATH', async () => { + const doc = await initDOM('node-path') + + expect(doc.getElementById('feature-node-path').childElementCount).to.equal(4) + }) + + it('shell env variables', async () => { + const doc = await initDOM('shell-env-variables') + + expect(doc.getElementById('feature-shell-env-variables').textContent).to.equal('fromtheshell.') + }) + + it('file env variables', async () => { + const doc = await initDOM('file-env-variables') + + expect(doc.getElementById('feature-file-env-variables').textContent).to.equal('fromtheenvfile.') + }) + }) +}) diff --git a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js new file mode 100644 index 00000000000..c04e60d4c87 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js @@ -0,0 +1,62 @@ +const fs = require('fs') +const http = require('http') +const jsdom = require('jsdom') +const path = require('path') + +let getMarkup +let resourceLoader +// this value could be tweaked in order to let the resource +// retriever get every file and jsdom execute react +let timeToWaitForJsToExecute + +if (process.env.E2E_FILE) { + const file = path.isAbsolute(process.env.E2E_FILE) + ? process.env.E2E_FILE + : path.join(process.cwd(), process.env.E2E_FILE) + + const markup = fs.readFileSync(file, 'utf8') + getMarkup = () => markup + + resourceLoader = (resource, callback) => callback( + null, + fs.readFileSync(path.join(path.dirname(file), resource.url.pathname), 'utf8') + ) + + timeToWaitForJsToExecute = 0 +} else if (process.env.E2E_URL) { + getMarkup = () => new Promise(resolve => { + http.get(process.env.E2E_URL, (res) => { + let rawData = '' + res.on('data', chunk => rawData += chunk) + res.on('end', () => resolve(rawData)) + }) + }) + + resourceLoader = (resource, callback) => { + return resource.defaultFetch(callback) + } + + timeToWaitForJsToExecute = 100 +} else { + 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.')).toBeUndefined() + }) +} + +export default feature => new Promise(async resolve => { + const markup = await getMarkup() + const host = process.env.E2E_URL || 'http://localhost:3000' + const doc = jsdom.jsdom(markup, { + features : { + FetchExternalResources : ['script', 'css'], + ProcessExternalResources : ['script'], + }, + resourceLoader, + url: `${host}#${feature}`, + virtualConsole: jsdom.createVirtualConsole().sendTo(console), + }) + + doc.defaultView.addEventListener('load', () => { + setTimeout(() => resolve(doc), timeToWaitForJsToExecute) + }, false) +}) diff --git a/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js b/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js new file mode 100644 index 00000000000..c8b7fbbc508 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/integration/syntax.test.js @@ -0,0 +1,96 @@ +import { expect } from 'chai' +import initDOM from './initDOM' + +describe('Integration', () => { + describe('Language syntax', () => { + it('array destructuring', async () => { + const doc = await initDOM('array-destructuring') + + expect(doc.getElementById('feature-array-destructuring').childElementCount).to.equal(4) + }) + + it('array spread', async () => { + const doc = await initDOM('array-spread') + + expect(doc.getElementById('feature-array-spread').childElementCount).to.equal(4) + }) + + it('async/await', async () => { + const doc = await initDOM('async-await') + + expect(doc.getElementById('feature-async-await').childElementCount).to.equal(4) + }) + + it('class properties', async () => { + const doc = await initDOM('class-properties') + + expect(doc.getElementById('feature-class-properties').childElementCount).to.equal(4) + }) + + it('computed properties', async () => { + const doc = await initDOM('computed-properties') + + expect(doc.getElementById('feature-computed-properties').childElementCount).to.equal(4) + }) + + it('custom interpolation', async () => { + const doc = await initDOM('custom-interpolation') + + expect(doc.getElementById('feature-custom-interpolation').childElementCount).to.equal(4) + }) + + it('default parameters', async () => { + const doc = await initDOM('default-parameters') + + expect(doc.getElementById('feature-default-parameters').childElementCount).to.equal(4) + }) + + it('destructuring and await', async () => { + const doc = await initDOM('destructuring-and-await') + + expect(doc.getElementById('feature-destructuring-and-await').childElementCount).to.equal(4) + }) + + it('generators', async () => { + const doc = await initDOM('generators') + + expect(doc.getElementById('feature-generators').childElementCount).to.equal(4) + }) + + it('object destructuring', async () => { + const doc = await initDOM('object-destructuring') + + expect(doc.getElementById('feature-object-destructuring').childElementCount).to.equal(4) + }) + + it('object spread', async () => { + const doc = await initDOM('object-spread') + + expect(doc.getElementById('feature-object-spread').childElementCount).to.equal(4) + }) + + it('promises', async () => { + const doc = await initDOM('promises') + + expect(doc.getElementById('feature-promises').childElementCount).to.equal(4) + }) + + it('rest + default', async () => { + const doc = await initDOM('rest-and-default') + + expect(doc.getElementById('feature-rest-and-default').childElementCount).to.equal(4) + }) + + it('rest parameters', async () => { + const doc = await initDOM('rest-parameters') + + expect(doc.getElementById('feature-rest-parameters').childElementCount).to.equal(4) + }) + + it('template interpolation', async () => { + const doc = await initDOM('template-interpolation') + + expect(doc.getElementById('feature-template-interpolation').childElementCount).to.equal(4) + }) + }) +}) diff --git a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js new file mode 100644 index 00000000000..9e2826b8fc6 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js @@ -0,0 +1,44 @@ +import { expect } from 'chai' +import initDOM from './initDOM' + +describe('Integration', () => { + describe('Webpack plugins', () => { + it('css inclusion', async () => { + const doc = await initDOM('css-inclusion') + + expect(doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '')) + .to.match(/#feature-css-inclusion\{background:.+;color:.+}/) + }) + + it('image inclusion', async () => { + const doc = await initDOM('image-inclusion') + + expect(doc.getElementById('feature-image-inclusion').src).to.match(/^data:image\/jpeg;base64.+==$/) + }) + + it('no ext inclusion', async () => { + const doc = await initDOM('no-ext-inclusion') + + expect(doc.getElementById('feature-no-ext-inclusion').textContent) + .to.equal('This is just a file without an extension.') + }) + + it('json inclusion', async () => { + const doc = await initDOM('json-inclusion') + + expect(doc.getElementById('feature-json-inclusion').textContent).to.equal('This is an abstract.') + }) + + it('svg inclusion', async () => { + const doc = await initDOM('svg-inclusion') + + expect(doc.getElementById('feature-svg-inclusion').src).to.match(/\/static\/media\/logo\..+\.svg$/) + }) + + it('unknown ext inclusion', async () => { + const doc = await initDOM('unknown-ext-inclusion') + + expect(doc.getElementById('feature-unknown-ext-inclusion').textContent).to.equal('Whoooo, spooky!.') + }) + }) +}) diff --git a/packages/react-scripts/fixtures/kitchensink/public/favicon.ico b/packages/react-scripts/fixtures/kitchensink/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5c125de5d897c1ff5692a656485b3216123dcd89 GIT binary patch literal 24838 zcmeI4X^>UL6@VY56)S&I{`6Nu0RscWCdj@GJHx(%?6_-;yKy1n;EEf9f}pr1CW5HA zYt$%U#C=}?jWH&%G@BaHBxsWAoUb3}&6%Ei@4Ii_JRa1`RQ23*yU)_wJ$?H0>6gj0 z${d_I^w5kvTW3xYEc?FvyP3>p$!py@`@T`|dVepIsjbbvR}af%KKy7YuQ%SDC^zmNWPYR^7avI5P-@dKev}UZ^aDAOyci9Nn zwR4qEz~tSvrp|#ACvWzo9`3B;`}^{t18dxaH;?xT7#hmJiKAaI;|O=$yxzXNOHGw~ z^!5pE^SW`av%t_$22LFPsM^l%=PSp!3r`>9w%s+^ZQYnnTQ*Ggd9-1~kj_o$YdW@b ztCkJ(ZGYjusqV5L4{^)R9Gt@gzU1t|?xhE&c^q(|(R#oa*}Sj5c({A$mhrB8*Y@tc zr)K#C{KOp-eHl35ZWJ1&zkmI>9DL%!KJE@_!=W?aH;i?ZDb0O1HPFy6 zcV0Kf)eZ0BHmz9vowF7EA{z*aue9M)iJP&Zd)qYlfJ-c^sS1qY^?>s)!!Ta@x zr@Lz|80r)7<{QVk9Z$}5SDaVtz*Rc?oH5~Wcjoc^eA&EdJ^h@aZ-BvL{K2s_7Cvfr zFL&(R?D&(9OxsS%z_BzI9^Ai^AOF$PUpGk~oO(=OpMc3@Zh&KH1a9>G%%0rC)t@oQ z4d~M`hX+g^Wf8P>A&&qjq|tZe*44Laq7qVPK#QIc)s*Qj34P`NL`Q{xBI`SnR!RC? zlGdTvC%oVZ@0BgcH>}qc!uzul@{i@sH}L0|=eZBJ9qF!HHaw?`s0(_DJj(v`(memI z6jH}=BfGlSlRV4)ouv#h*65yRR>G zo;I#~BVK&l&{+H=_~Nq$d%bFLh7GE5pS&>Fr{RMe>)MM19~z6F1oQo_y>vtlpEZF# zIc82TpMc3z9;{Q)=zG5B#4+96yHCvYy8p4;C%6x`%y$2HccC9|#vGVD)**C0xX|R| z%h)}ze!Tnrvvb@RZ!GX@2lMEq`=`08b`9$%FnN@*zJLo2wD5?MbE&LN)Z>Kty*;m= zt{Cn0>Q3nk)`bR^{dVf!3ECg6Yz4YcskI>$XH*L8E)MsudhnkP0B>+M(XEcErHUBKi~ z1`fEP&WPhp{@Ew?cPlR(ma9iw8NbJWHqp=btCtM*FnP*@ZwwlJ&-Y|LEjgvJzUtPc zz5CrWNBRV8d0-bpWAl<=zM1PU8lJseDxBK^QuuCj2fg{&2#*IG5ezf1B(o%lU+OZx7So4D?yi2*h zFBkr5pG3AJs83uy!~C3mQZLp~ss7-N9oAY>t)!eC#s)CrPukK!(!G*)H?v(~JCoj# zfvgTxMV{4?zL1neQ;ITVBAdFDf`1yG$o{g7^1sR_n{RZ7tnXio?tM%240}(z9xFY0 zlz{^-G*RET;-`7`>e0b{{`!2kM)t7Si9ZqD$~wh*hyGC>z~qs@0T&u*;h}hiKGEga zHkJ;%7aNc^o_0(>Z{Gp069H;TwPTUnvvX0SJ+kGGZ0lFBWocl>kaa)AoiMta+x_-J-?#KHFnJ*! zwD1V?)4s#|?O)DlMBhVv4IgZs?d>b<6%xK3<{o91H?-%8?PK!_fm#3d>{{gQ z?*8`b{G6?bZKdO{_9IVlz{R$PcGjeL|3*|@upby()_Lf^eQ&XQe)CjsbJ3Uolrgt< zweld3GH|fZpn(=1@PencO_a_)v6tU?WV-w8wfXLbOGae0{<*C?Ead$6v+> z|EQKThJTmwXK!c6AOD+FgtDv7i<48{-OPce!KDVkzR+XKOcREPha(;$}iUb!*)f-Fb}Y4@r9z-_{OIg z`xn^T#ZtEPv_T$M*Sr+=Z{q#~8$|7Y{0!*2u${D*Jj%dfOrS~FzpH*_|55J!7kl4w z?LT!7T(!3!632pmZh?dh`n-z$_ts42pn6;c`}hx;TSYd0idsqal5&0uGV=UM{c9xQ z1KK6&TS+a^H|6B_hPo1W3 zh+Dun!`UkP%H3}*@IE18q{7&MH2f3?T6o}Jf+xI@fh=SyUOArw`*w1_-PUlHZTHc@ z--yqIxPtI}IjPRzLIZ8cPv4P=>?A&=E~~0)>&J#V;TwAR*6}`01iu~U$@prtzW6YS ze}E>gUX+0YuF}B+Uhw2x7a7Q+oOzMNFHTNN<)40Rzg#`pABKF18@l}5A>RL`?Ri;Z zC8ExD$)im1@R{N7(wIog8$Yn(6%q$yd9(zKe};OnH%;mWBs7)>ls~T3Wi6!Xqw6+dpJLVS1P| z9qV%io-nE*rYcPxiS31>U_>mbPTXxkC*!?*zefr#2vF|qr8{|4|u^7-pD|f z&OPc->UKu)=iHgIpysp;Lsbyj}GJWoBkufOA={CRTUjr%af zc5pUH9{pg?M5%+)oN`q9yBbBt@+3xHV)qGm8b)Cp-w7~CwEhtBUk0rbjrqM zTb|tQ3-5-pw^cul`T+X&s?O;?V(FD!(Q9Qg@(LTCNz{0-vBM^SX5lti3|GpxFn4;Ax6pGc~t)R!Bo${lYH(* z!F&5X*?S&}YoDCyzwv1H+XI(+rL`;RN9}iLxlfr-r&vGG8OQa@=>+a)+Ij)sd_{wu z1Am(+3-RFr4&N8N6+hqo19S#;SA1-hG>07p3}&*j4CR+rqdV)^6n; z_vFr!(a%-=#=kb{pYmNL@6|DWkw~%E2V2jYl*e1}c{e$fib?(O+hs}eoBLRo&9(;J}YV}0Mi;LZAe{U$(s= zT<-IaV$Z+q-P!~3{HxN>Kbw30jXzM&I(S<6Ksx^}HvU2Vntb!etSsm0>)j}Me^+L5{2yz--)?W`Q?az z!WLG4UNP}+#C+NKH+ZG-Q=E>IPp%LuKLx$$8NAOGr(#~P>!EA zDYlpXDR=xM?Xv5(-qp74Cw3LzBeASHSBY`OezkbOyjP!G%WSymju_C$VBl--z + + + + + + React App + + +
+ + diff --git a/packages/react-scripts/fixtures/kitchensink/src/App.js b/packages/react-scripts/fixtures/kitchensink/src/App.js new file mode 100644 index 00000000000..66cd45541f7 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/App.js @@ -0,0 +1,103 @@ +import React from 'react'; + +class App extends React.Component { + constructor(props) { + super(props); + + this.state = { feature: null }; + + this.setFeature = this.setFeature.bind(this); + } + + componentDidMount() { + switch (location.hash.slice(1)) { + case 'array-destructuring': + require.ensure([], () => this.setFeature(require('./features/syntax/ArrayDestructuring').default)); + break; + case 'array-spread': + require.ensure([], () => this.setFeature(require('./features/syntax/ArraySpread').default)); + break; + case 'async-await': + require.ensure([], () => this.setFeature(require('./features/syntax/AsyncAwait').default)); + break; + case 'class-properties': + require.ensure([], () => this.setFeature(require('./features/syntax/ClassProperties').default)); + break; + case 'computed-properties': + require.ensure([], () => this.setFeature(require('./features/syntax/ComputedProperties').default)); + break; + case 'css-inclusion': + require.ensure([], () => this.setFeature(require('./features/webpack/CssInclusion').default)); + break; + case 'custom-interpolation': + require.ensure([], () => this.setFeature(require('./features/syntax/CustomInterpolation').default)); + break; + case 'default-parameters': + require.ensure([], () => this.setFeature(require('./features/syntax/DefaultParameters').default)); + break; + case 'destructuring-and-await': + require.ensure([], () => this.setFeature(require('./features/syntax/DestructuringAndAwait').default)); + break; + case 'file-env-variables': + require.ensure([], () => this.setFeature(require('./features/env/FileEnvVariables').default)); + break; + case 'generators': + require.ensure([], () => this.setFeature(require('./features/syntax/Generators').default)); + break; + case 'image-inclusion': + require.ensure([], () => this.setFeature(require('./features/webpack/ImageInclusion').default)); + break; + case 'json-inclusion': + require.ensure([], () => this.setFeature(require('./features/webpack/JsonInclusion').default)); + break; + case 'node-path': + require.ensure([], () => this.setFeature(require('./features/env/NodePath').default)); + break; + case 'no-ext-inclusion': + require.ensure([], () => this.setFeature(require('./features/webpack/NoExtInclusion').default)); + break; + case 'object-destructuring': + require.ensure([], () => this.setFeature(require('./features/syntax/ObjectDestructuring').default)); + break; + case 'object-spread': + require.ensure([], () => this.setFeature(require('./features/syntax/ObjectSpread').default)); + break; + case 'promises': + require.ensure([], () => this.setFeature(require('./features/syntax/Promises').default)); + break; + case 'rest-and-default': + require.ensure([], () => this.setFeature(require('./features/syntax/RestAndDefault').default)); + break; + case 'rest-parameters': + require.ensure([], () => this.setFeature(require('./features/syntax/RestParameters').default)); + break; + case 'shell-env-variables': + require.ensure([], () => this.setFeature(require('./features/env/ShellEnvVariables').default)); + break; + case 'svg-inclusion': + require.ensure([], () => this.setFeature(require('./features/webpack/SvgInclusion').default)); + break; + case 'template-interpolation': + require.ensure([], () => this.setFeature(require('./features/syntax/TemplateInterpolation').default)); + break; + case 'unknown-ext-inclusion': + require.ensure([], () => this.setFeature(require('./features/webpack/UnknownExtInclusion').default) + ); + break; + default: + this.setFeature(null); + break; + } + } + + setFeature(feature) { + this.setState({ feature }); + } + + render() { + const Feature = this.state.feature; + return Feature ? : null; + } +} + +export default App; diff --git a/packages/react-scripts/fixtures/kitchensink/src/App.test.js b/packages/react-scripts/fixtures/kitchensink/src/App.test.js new file mode 100644 index 00000000000..b84af98d720 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/App.test.js @@ -0,0 +1,8 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/absoluteLoad.js b/packages/react-scripts/fixtures/kitchensink/src/absoluteLoad.js new file mode 100644 index 00000000000..dc769fe1e53 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/absoluteLoad.js @@ -0,0 +1,6 @@ +export default () => [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } +] diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js new file mode 100644 index 00000000000..c7b7c5d537d --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.js @@ -0,0 +1,5 @@ +import React from 'react' + +export default () => ( + {process.env.REACT_APP_FILE_ENV_MESSAGE}. +) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.test.js new file mode 100644 index 00000000000..c9d802be975 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/FileEnvVariables.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import FileEnvVariables from './FileEnvVariables'; + +describe('.env variables', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.js new file mode 100644 index 00000000000..2d2f474f19e --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.js @@ -0,0 +1,25 @@ +import React from 'react' +import load from 'absoluteLoad' + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.test.js new file mode 100644 index 00000000000..05b981853b9 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/NodePath.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import NodePath from './NodePath'; + +describe('NODE_PATH', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.js new file mode 100644 index 00000000000..37b80ec6097 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.js @@ -0,0 +1,5 @@ +import React from 'react' + +export default () => ( + {process.env.REACT_APP_SHELL_ENV_MESSAGE}. +) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.test.js new file mode 100644 index 00000000000..981bee67c26 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/ShellEnvVariables.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ShellEnvVariables from './ShellEnvVariables'; + +describe('shell env variables', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.js new file mode 100644 index 00000000000..38e35120960 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.js @@ -0,0 +1,34 @@ +import React from 'react' + +function load() { + return [ + [1, '1'], + [2, '2'], + [3, '3'], + [4, '4'] + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => { + const [id, name] = user; + return
{name}
+ })} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.test.js new file mode 100644 index 00000000000..617df2a6c6c --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArrayDestructuring.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ArrayDestructuring from './ArrayDestructuring'; + +describe('array destructuring', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.js new file mode 100644 index 00000000000..d7d9a459133 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load(users) { + return [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + ...users + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load([{ id: 42, name: '42' }]); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.test.js new file mode 100644 index 00000000000..85fade6e3a9 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ArraySpread.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ArraySpread from './ArraySpread'; + +describe('array spread', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.js new file mode 100644 index 00000000000..01c68640575 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.js @@ -0,0 +1,33 @@ +import React from 'react' + +async function load() { + return [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = await load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.test.js new file mode 100644 index 00000000000..072f16fffea --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/AsyncAwait.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import AsyncAwait from './AsyncAwait'; + +describe('async/await', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.js new file mode 100644 index 00000000000..65e500d645b --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.js @@ -0,0 +1,20 @@ +import React from 'react' + +export default class extends React.Component { + users = [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } + ]; + + render() { + return ( +
+ {this.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.test.js new file mode 100644 index 00000000000..71d851dd2fc --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ClassProperties.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ClassProperties from './ClassProperties'; + +describe('class properties', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.js new file mode 100644 index 00000000000..c7a24cb7f3d --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load(prefix) { + return [ + { id: 1, [prefix + 'name']: '1' }, + { id: 2, [prefix + 'name']: '2' }, + { id: 3, [prefix + 'name']: '3' }, + { id: 4, [prefix + 'name']: '4' } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load('user_'); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.user_name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.test.js new file mode 100644 index 00000000000..4e9aaf17a1d --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ComputedProperties.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ComputedProperties from './ComputedProperties'; + +describe('computed properties', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.js new file mode 100644 index 00000000000..03298968375 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.js @@ -0,0 +1,43 @@ +import React from 'react' + +const styled = ([style]) => style.trim() + .split(/\s*;\s*/) + .map(rule => rule.split(/\s*:\s*/)) + .reduce((rules, rule) => ({ ...rules, [rule[0]]: rule[1] }), {}); + +function load() { + return [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + render() { + const veryInlineStyle = styled` + background: palevioletred; + color: papayawhip; + `; + + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.test.js new file mode 100644 index 00000000000..10b1df278c1 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/CustomInterpolation.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import CustomInterpolation from './CustomInterpolation'; + +describe('custom interpolation', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.js new file mode 100644 index 00000000000..3a676358a92 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load(id = 0) { + return [ + { id: id + 1, name: '1' }, + { id: id + 2, name: '2' }, + { id: id + 3, name: '3' }, + { id: id + 4, name: '4' } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.test.js new file mode 100644 index 00000000000..b5ece244681 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DefaultParameters.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import DefaultParameters from './DefaultParameters'; + +describe('default parameters', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.js new file mode 100644 index 00000000000..291ed3bccc4 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.js @@ -0,0 +1,33 @@ +import React from 'react' + +async function load() { + return { users: [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } + ] }; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const { users } = await load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.test.js new file mode 100644 index 00000000000..14521e30798 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/DestructuringAndAwait.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import DestructuringAndAwait from './DestructuringAndAwait'; + +describe('destructuring and await', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.js new file mode 100644 index 00000000000..4f2fc95ca6f --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.js @@ -0,0 +1,35 @@ +import React from 'react' + +function * load(limit) { + let i = 1; + while (i <= limit) { + yield { id: i, name: i }; + i++; + } +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + componentDidMount() { + const users = []; + for (let user of load(4)) { + users.push(user); + } + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.test.js new file mode 100644 index 00000000000..1fd36cdbed3 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Generators.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import Generators from './Generators'; + +describe('generators', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.js new file mode 100644 index 00000000000..c6edbee2702 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.js @@ -0,0 +1,34 @@ +import React from 'react' + +function load() { + return [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => { + const { id, name } = user; + return
{name}
+ })} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.test.js new file mode 100644 index 00000000000..7ed28147dec --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectDestructuring.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ObjectDestructuring from './ObjectDestructuring'; + +describe('object destructuring', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.js new file mode 100644 index 00000000000..ca41004f9f6 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load(baseUser) { + return [ + { id: 1, name: '1', ...baseUser }, + { id: 2, name: '2', ...baseUser }, + { id: 3, name: '3', ...baseUser }, + { id: 4, name: '4', ...baseUser } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load({ age: 42 }); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}: {user.age}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.test.js new file mode 100644 index 00000000000..9de96c26418 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/ObjectSpread.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ObjectSpread from './ObjectSpread'; + +describe('object spread', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.js new file mode 100644 index 00000000000..c0e13c81ebf --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.js @@ -0,0 +1,34 @@ +import React from 'react' + +function load() { + return Promise.resolve([ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' } + ]); +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + componentDidMount() { + load().then(users => { + this.setState({ users }); + }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.test.js new file mode 100644 index 00000000000..96b4d298d7c --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/Promises.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import Promises from './Promises'; + +describe('promises', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.js new file mode 100644 index 00000000000..a977e8c8340 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load({ id, ...rest } = { id: 0, user: { id: 42, name: '42' } }) { + return [ + { id: id + 1, name: '1' }, + { id: id + 2, name: '2' }, + { id: id + 3, name: '3' }, + rest.user + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.test.js new file mode 100644 index 00000000000..95f4a19fa0b --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestAndDefault.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import RestAndDefault from './RestAndDefault'; + +describe('rest + default', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.js new file mode 100644 index 00000000000..9dcc33fa00e --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load({ id = 0, ...rest }) { + return [ + { id: id + 1, name: '1' }, + { id: id + 2, name: '2' }, + { id: id + 3, name: '3' }, + rest.user + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load({ id: 0, user: { id: 42, name: '42' } }); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.test.js new file mode 100644 index 00000000000..8e097713318 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/RestParameters.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import RestParameters from './RestParameters'; + +describe('rest parameters', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.js new file mode 100644 index 00000000000..505ee6173d5 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.js @@ -0,0 +1,33 @@ +import React from 'react' + +function load(name) { + return [ + { id: 1, name: `${name}1` }, + { id: 2, name: `${name}2` }, + { id: 3, name: `${name}3` }, + { id: 4, name: `${name}4` } + ]; +} + +export default class extends React.Component { + constructor(props) { + super(props); + + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load('user_'); + this.setState({ users }); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.test.js new file mode 100644 index 00000000000..b49af029a44 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/syntax/TemplateInterpolation.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import TemplateInterpolation from './TemplateInterpolation'; + +describe('template interpolation', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.js new file mode 100644 index 00000000000..f35d11e0a82 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.js @@ -0,0 +1,6 @@ +import React from 'react' +import './assets/style.css' + +export default () => ( +

We love useless text.

+) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.test.js new file mode 100644 index 00000000000..f3e10a441a8 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssInclusion.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import CssInclusion from './CssInclusion'; + +describe('css inclusion', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.js new file mode 100644 index 00000000000..d793408a5c7 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.js @@ -0,0 +1,6 @@ +import React from 'react' +import tiniestCat from './assets/tiniest-cat.jpg' + +export default () => ( + tiniest cat +) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.test.js new file mode 100644 index 00000000000..85e68d51e85 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/ImageInclusion.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ImageInclusion from './ImageInclusion'; + +describe('image inclusion', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.js new file mode 100644 index 00000000000..8050b9cfd6c --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.js @@ -0,0 +1,6 @@ +import React from 'react' +import { abstract } from './assets/abstract.json' + +export default () => ( + {abstract} +) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.test.js new file mode 100644 index 00000000000..70043bd0503 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/JsonInclusion.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import JsonInclusion from './JsonInclusion'; + +describe('JSON inclusion', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.js new file mode 100644 index 00000000000..70b2d2b2155 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.js @@ -0,0 +1,10 @@ +import React from 'react' +import aFileWithoutExt from './assets/aFileWithoutExt' + +const text = aFileWithoutExt.includes('base64') + ? atob(aFileWithoutExt.split('base64,')[1]).trim() + : aFileWithoutExt + +export default () => ( +

{text}.

+) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.test.js new file mode 100644 index 00000000000..666f94f384c --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/NoExtInclusion.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import NoExtInclusion from './NoExtInclusion'; + +describe('no ext inclusion', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.js new file mode 100644 index 00000000000..7c2fdb2e44e --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.js @@ -0,0 +1,6 @@ +import React from 'react' +import logo from './assets/logo.svg' + +export default () => ( + logo +) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.test.js new file mode 100644 index 00000000000..507da01403c --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgInclusion.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import SvgInclusion from './SvgInclusion'; + +describe('svg inclusion', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.js new file mode 100644 index 00000000000..30aeccd6fb7 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.js @@ -0,0 +1,10 @@ +import React from 'react' +import aFileWithExtUnknown from './assets/aFileWithExt.unknown' + +const text = aFileWithExtUnknown.includes('base64') + ? atob(aFileWithExtUnknown.split('base64,')[1]).trim() + : aFileWithExtUnknown + +export default () => ( +

{text}.

+) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.test.js new file mode 100644 index 00000000000..46724e0a27b --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import UnknownExtInclusion from './UnknownExtInclusion'; + +describe('unknown ext inclusion', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithExt.unknown b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithExt.unknown new file mode 100644 index 00000000000..a5de8eb3264 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithExt.unknown @@ -0,0 +1 @@ +Whoooo, spooky! diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithoutExt b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithoutExt new file mode 100644 index 00000000000..dbcc1afda65 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/aFileWithoutExt @@ -0,0 +1 @@ +This is just a file without an extension diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/abstract.json b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/abstract.json new file mode 100644 index 00000000000..5d21a7168a8 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/abstract.json @@ -0,0 +1,3 @@ +{ + "abstract": "This is an abstract." +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/logo.svg b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/logo.svg new file mode 100644 index 00000000000..6b60c1042f5 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/style.css b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/style.css new file mode 100644 index 00000000000..c399d1acada --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/style.css @@ -0,0 +1,4 @@ +#feature-css-inclusion { + background: palevioletred; + color: papayawhip; +} diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/tiniest-cat.jpg b/packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/tiniest-cat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c658e9922a765fa62442f996a1c4fa028c731f45 GIT binary patch literal 691 zcmex=_1P|rX?qqI0P zFI~aY%U!`Mz|~!$%*;qrN1?DZF(OKUqjJ5@awPiGqsb6Y!WkRgm* z+}wP;d@=$8GS(VO8rCF({|6WZIT#oj7?~NB7?=bZnFSgDA7PMZU|?hgdKKhbC}3n_ zW?^Mx=iubx1}fMpz`(@F%*@2X%*x8b0#scKlxJWOWEE00bYv3_Ok`Io6ftU?xR68H zY2!iBpoX!XqN1l2cOC z(lau%ic3n%$}1|Xnp;}i+B-VCCQY6)b=ve9GiNPYykzOJeA&aSFc^aar4&0M~|O8efIpt%U2&ieg5+G+xH(oe}VkP$iNKo7TjlO z{t^WGi;0DWnS~wXFGi+vAZ8Y1VO2C_6LJh>Pb?HxGHT=yahkYr<3UbkKb$@|Xn~>>0YcG#2pxzX<@98RLln literal 0 HcmV?d00001 diff --git a/packages/react-scripts/fixtures/kitchensink/src/index.js b/packages/react-scripts/fixtures/kitchensink/src/index.js new file mode 100644 index 00000000000..0ea36197ba1 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/index.js @@ -0,0 +1,8 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +ReactDOM.render( + , + document.getElementById('root') +); diff --git a/packages/react-scripts/fixtures/kitchensink/src/subfolder/lol.js b/packages/react-scripts/fixtures/kitchensink/src/subfolder/lol.js new file mode 100644 index 00000000000..6c7375d5479 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/subfolder/lol.js @@ -0,0 +1 @@ +module.exports = function() { return `haha` } diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index e438e5a2ee2..864005ecac2 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -12,7 +12,7 @@ var path = require('path'); var spawn = require('cross-spawn'); var chalk = require('chalk'); -module.exports = function(appPath, appName, verbose, originalDirectory) { +module.exports = function(appPath, appName, verbose, originalDirectory, template) { var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name; var ownPath = path.join(appPath, 'node_modules', ownPackageName); var appPackage = require(path.join(appPath, 'package.json')); @@ -41,7 +41,13 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { } // Copy the files for the user - fs.copySync(path.join(ownPath, 'template'), appPath); + var templatePath = template ? path.resolve(originalDirectory, template) : path.join(ownPath, 'template'); + if (fs.existsSync(templatePath)) { + fs.copySync(templatePath, appPath); + } else { + console.error('Could not locate supplied template: ' + chalk.green(templatePath)); + return; + } // Rename gitignore after the fact to prevent npm from renaming it to .npmignore // See: https://github.com/npm/npm/issues/1862 @@ -76,6 +82,16 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { } args.push('react', 'react-dom'); + // Install additional template dependencies, if present + var templateDependenciesPath = path.join(appPath, '.template.dependencies.json'); + if (fs.existsSync(templateDependenciesPath)) { + var templateDependencies = require(templateDependenciesPath).dependencies; + args = args.concat(Object.keys(templateDependencies).map(function (key) { + return key + '@' + templateDependencies[key]; + })); + fs.unlinkSync(templateDependenciesPath); + } + console.log('Installing react and react-dom using ' + command + '...'); console.log(); diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh new file mode 100755 index 00000000000..f3c1d8d3bd0 --- /dev/null +++ b/tasks/e2e-installs.sh @@ -0,0 +1,152 @@ +#!/bin/bash +# Copyright (c) 2015-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +# ****************************************************************************** +# This is an end-to-end test intended to run on CI. +# You can also run it locally but it's slow. +# ****************************************************************************** + +# Start in tasks/ even if run from root directory +cd "$(dirname "$0")" + +# CLI and app temporary locations +# http://unix.stackexchange.com/a/84980 +temp_cli_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_cli_path'` +temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` + +function cleanup { + echo 'Cleaning up.' + cd $root_path + # Uncomment when snapshot testing is enabled by default: + # rm ./packages/react-scripts/template/src/__snapshots__/App.test.js.snap + rm -rf $temp_cli_path $temp_app_path +} + +# Error messages are redirected to stderr +function handle_error { + echo "$(basename $0): ERROR! An error was encountered executing line $1." 1>&2; + cleanup + echo 'Exiting with error.' 1>&2; + exit 1 +} + +function handle_exit { + cleanup + echo 'Exiting without error.' 1>&2; + exit +} + +function create_react_app { + node "$temp_cli_path"/node_modules/create-react-app/index.js $* +} + +# Exit the script with a helpful error message when any error is encountered +trap 'set +x; handle_error $LINENO $BASH_COMMAND' ERR + +# Cleanup before exit on any termination signal +trap 'set +x; handle_exit' SIGQUIT SIGTERM SIGINT SIGKILL SIGHUP + +# Echo every command being executed +set -x + +# Go to root +cd .. +root_path=$PWD + +npm install + +# If the node version is < 4, the script should just give an error. +if [ `node --version | sed -e 's/^v//' -e 's/\..\+//g'` -lt 4 ] +then + cd $temp_app_path + err_output=`node "$root_path"/packages/create-react-app/index.js test-node-version 2>&1 > /dev/null || echo ''` + [[ $err_output =~ You\ are\ running\ Node ]] && exit 0 || exit 1 +fi + +if [ "$USE_YARN" = "yes" ] +then + # Install Yarn so that the test can use it to install packages. + npm install -g yarn@0.17.10 # TODO: remove version when https://github.com/yarnpkg/yarn/issues/2142 is fixed. + yarn cache clean +fi + +# ****************************************************************************** +# First, pack and install create-react-app. +# ****************************************************************************** + +# Pack CLI +cd $root_path/packages/create-react-app +cli_path=$PWD/`npm pack` + +# Install the CLI in a temporary location +cd $temp_cli_path +npm install $cli_path + +# ****************************************************************************** +# Test --scripts-version with a version number +# ****************************************************************************** + +cd $temp_app_path +create_react_app --scripts-version=0.4.0 test-app-version-number +cd test-app-version-number + +# Check corresponding scripts version is installed. +test -e node_modules/react-scripts +grep '"version": "0.4.0"' node_modules/react-scripts/package.json + +# ****************************************************************************** +# Test --scripts-version with a tarball url +# ****************************************************************************** + +cd $temp_app_path +create_react_app --scripts-version=https://registry.npmjs.org/react-scripts/-/react-scripts-0.4.0.tgz test-app-tarball-url +cd test-app-tarball-url + +# Check corresponding scripts version is installed. +test -e node_modules/react-scripts +grep '"version": "0.4.0"' node_modules/react-scripts/package.json + +# ****************************************************************************** +# Test --scripts-version with a custom fork of react-scripts +# ****************************************************************************** + +cd $temp_app_path +create_react_app --scripts-version=react-scripts-fork test-app-fork +cd test-app-fork + +# Check corresponding scripts version is installed. +test -e node_modules/react-scripts-fork + +# ****************************************************************************** +# Test nested folder path as the project name +# ****************************************************************************** + +#Testing a path that exists +cd $temp_app_path +mkdir test-app-nested-paths-t1 +cd test-app-nested-paths-t1 +mkdir -p test-app-nested-paths-t1/aa/bb/cc/dd +create_react_app test-app-nested-paths-t1/aa/bb/cc/dd +cd test-app-nested-paths-t1/aa/bb/cc/dd +npm start -- --smoke-test + +#Testing a path that does not exist +cd $temp_app_path +create_react_app test-app-nested-paths-t2/aa/bb/cc/dd +cd test-app-nested-paths-t2/aa/bb/cc/dd +npm start -- --smoke-test + +#Testing a path that is half exists +cd $temp_app_path +mkdir -p test-app-nested-paths-t3/aa +create_react_app test-app-nested-paths-t3/aa/bb/cc/dd +cd test-app-nested-paths-t3/aa/bb/cc/dd +npm start -- --smoke-test + +# Cleanup +cleanup diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh new file mode 100755 index 00000000000..eecd6ed62a7 --- /dev/null +++ b/tasks/e2e-kitchensink.sh @@ -0,0 +1,218 @@ +#!/bin/bash +# Copyright (c) 2015-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +# ****************************************************************************** +# This is an end-to-end kitchensink test intended to run on CI. +# You can also run it locally but it's slow. +# ****************************************************************************** + +# Start in tasks/ even if run from root directory +cd "$(dirname "$0")" + +# CLI and app temporary locations +# http://unix.stackexchange.com/a/84980 +temp_cli_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_cli_path'` +temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` + +function cleanup { + echo 'Cleaning up.' + cd $root_path + # Uncomment when snapshot testing is enabled by default: + # rm ./packages/react-scripts/template/src/__snapshots__/App.test.js.snap + rm -rf $temp_cli_path $temp_app_path +} + +# Error messages are redirected to stderr +function handle_error { + echo "$(basename $0): ERROR! An error was encountered executing line $1." 1>&2; + cleanup + echo 'Exiting with error.' 1>&2; + exit 1 +} + +function handle_exit { + cleanup + echo 'Exiting without error.' 1>&2; + exit +} + +function create_react_app { + node "$temp_cli_path"/node_modules/create-react-app/index.js $* +} + +# Exit the script with a helpful error message when any error is encountered +trap 'set +x; handle_error $LINENO $BASH_COMMAND' ERR + +# Cleanup before exit on any termination signal +trap 'set +x; handle_exit' SIGQUIT SIGTERM SIGINT SIGKILL SIGHUP + +# Echo every command being executed +set -x + +# Go to root +cd .. +root_path=$PWD + +npm install + +# If the node version is < 4, the script should just give an error. +if [ `node --version | sed -e 's/^v//' -e 's/\..\+//g'` -lt 4 ] +then + cd $temp_app_path + err_output=`node "$root_path"/packages/create-react-app/index.js test-node-version 2>&1 > /dev/null || echo ''` + [[ $err_output =~ You\ are\ running\ Node ]] && exit 0 || exit 1 +fi + +if [ "$USE_YARN" = "yes" ] +then + # Install Yarn so that the test can use it to install packages. + npm install -g yarn@0.17.10 # TODO: remove version when https://github.com/yarnpkg/yarn/issues/2142 is fixed. + yarn cache clean +fi + +# ****************************************************************************** +# First, pack react-scripts and create-react-app so we can use them. +# ****************************************************************************** + +# Pack CLI +cd $root_path/packages/create-react-app +cli_path=$PWD/`npm pack` + +# Go to react-scripts +cd $root_path/packages/react-scripts + +# Save package.json because we're going to touch it +cp package.json package.json.orig + +# Replace own dependencies (those in the `packages` dir) with the local paths +# of those packages. +node $root_path/tasks/replace-own-deps.js + +# Remove .npmignore so the test template is added +rm $root_path/packages/react-scripts/.npmignore + +# Finally, pack react-scripts +scripts_path=$root_path/packages/react-scripts/`npm pack` + +# Restore package.json +rm package.json +mv package.json.orig package.json + +# ****************************************************************************** +# Now that we have packed them, create a clean app folder and install them. +# ****************************************************************************** + +# Install the CLI in a temporary location +cd $temp_cli_path +npm install $cli_path + +# Install the app in a temporary location +cd $temp_app_path +create_react_app --scripts-version=$scripts_path --internal-testing-template=$root_path/packages/react-scripts/fixtures/kitchensink test-kitchensink + +# ****************************************************************************** +# Now that we used create-react-app to create an app depending on react-scripts, +# let's make sure all npm scripts are in the working state. +# ****************************************************************************** + +# Enter the app directory +cd test-kitchensink + +# Test the build +NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build +# Check for expected output +test -e build/*.html +test -e build/static/js/main.*.js + +# Unit tests +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + CI=true \ + NODE_PATH=src \ + npm test -- --no-cache --testPathPattern="/src/" + +# Test "development" environment +tmp_server_log=`mktemp` +PORT=3001 \ + REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + NODE_PATH=src \ + nohup npm start &>$tmp_server_log & +grep -q 'The app is running at:' <(tail -f $tmp_server_log) +E2E_URL="http://localhost:3001" \ + REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + CI=true NODE_PATH=src \ + node node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js + +# Test "production" environment +E2E_FILE=./build/index.html \ + CI=true \ + NODE_PATH=src \ + node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.js + +# Uncomment when snapshot testing is enabled by default: +# test -e src/__snapshots__/App.test.js.snap + +# Test the server +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell NODE_PATH=src npm start -- --smoke-test +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell HTTPS=true NODE_PATH=src npm start -- --smoke-test + +# ****************************************************************************** +# Finally, let's check that everything still works after ejecting. +# ****************************************************************************** + +# Eject... +echo yes | npm run eject + +# ...but still link to the local packages +npm link $root_path/packages/babel-preset-react-app +npm link $root_path/packages/eslint-config-react-app +npm link $root_path/packages/react-dev-utils +npm link $root_path/packages/react-scripts + +# ...and we need to remove template's .babelrc +rm .babelrc + +# Test the build +NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build +# Check for expected output +test -e build/*.html +test -e build/static/js/main.*.js + +# Unit tests +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + CI=true \ + NODE_PATH=src \ + npm test -- --no-cache --testPathPattern="/src/" + +# Test "development" environment +tmp_server_log=`mktemp` +PORT=3002 \ + REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + NODE_PATH=src \ + nohup npm start &>$tmp_server_log & +grep -q 'The app is running at:' <(tail -f $tmp_server_log) +E2E_URL="http://localhost:3002" \ + REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + CI=true NODE_PATH=src \ + NODE_ENV=production \ + node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.js + +# Test "production" environment +E2E_FILE=./build/index.html \ + CI=true \ + NODE_ENV=production \ + NODE_PATH=src \ + node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.js + +# Uncomment when snapshot testing is enabled by default: +# test -e src/__snapshots__/App.test.js.snap + +# Test the server +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell NODE_PATH=src npm start -- --smoke-test + +# Cleanup +cleanup diff --git a/tasks/e2e.sh b/tasks/e2e-simple.sh similarity index 73% rename from tasks/e2e.sh rename to tasks/e2e-simple.sh index 27cd0ae45f6..f8baf743de7 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e-simple.sh @@ -195,66 +195,6 @@ npm test -- --watch=no # Test the server npm start -- --smoke-test -# ****************************************************************************** -# Test --scripts-version with a version number -# ****************************************************************************** - -cd $temp_app_path -create_react_app --scripts-version=0.4.0 test-app-version-number -cd test-app-version-number - -# Check corresponding scripts version is installed. -test -e node_modules/react-scripts -grep '"version": "0.4.0"' node_modules/react-scripts/package.json - -# ****************************************************************************** -# Test --scripts-version with a tarball url -# ****************************************************************************** - -cd $temp_app_path -create_react_app --scripts-version=https://registry.npmjs.org/react-scripts/-/react-scripts-0.4.0.tgz test-app-tarball-url -cd test-app-tarball-url - -# Check corresponding scripts version is installed. -test -e node_modules/react-scripts -grep '"version": "0.4.0"' node_modules/react-scripts/package.json - -# ****************************************************************************** -# Test --scripts-version with a custom fork of react-scripts -# ****************************************************************************** - -cd $temp_app_path -create_react_app --scripts-version=react-scripts-fork test-app-fork -cd test-app-fork - -# Check corresponding scripts version is installed. -test -e node_modules/react-scripts-fork - -# ****************************************************************************** -# Test nested folder path as the project name -# ****************************************************************************** - -#Testing a path that exists -cd $temp_app_path -mkdir test-app-nested-paths-t1 -cd test-app-nested-paths-t1 -mkdir -p test-app-nested-paths-t1/aa/bb/cc/dd -create_react_app test-app-nested-paths-t1/aa/bb/cc/dd -cd test-app-nested-paths-t1/aa/bb/cc/dd -npm start -- --smoke-test - -#Testing a path that does not exist -cd $temp_app_path -create_react_app test-app-nested-paths-t2/aa/bb/cc/dd -cd test-app-nested-paths-t2/aa/bb/cc/dd -npm start -- --smoke-test - -#Testing a path that is half exists -cd $temp_app_path -mkdir -p test-app-nested-paths-t3/aa -create_react_app test-app-nested-paths-t3/aa/bb/cc/dd -cd test-app-nested-paths-t3/aa/bb/cc/dd -npm start -- --smoke-test # Cleanup cleanup