diff --git a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js index a179aa7cbb2..414229b22ac 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js @@ -3,22 +3,30 @@ import initDOM from './initDOM' describe('Integration', () => { describe('Environment variables', () => { + it('file env variables', async () => { + const doc = await initDOM('file-env-variables') + + expect(doc.getElementById('feature-file-env-variables').textContent).to.equal('fromtheenvfile.') + }) + 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') + it('PUBLIC_URL', async () => { + const doc = await initDOM('public-url') - expect(doc.getElementById('feature-shell-env-variables').textContent).to.equal('fromtheshell.') + expect(doc.getElementById('feature-public-url').textContent).to.equal('http://www.example.org/spa.') + expect(doc.querySelector('head link[rel="shortcut icon"]').getAttribute('href')) + .to.equal('http://www.example.org/spa/favicon.ico') }) - it('file env variables', async () => { - const doc = await initDOM('file-env-variables') + it('shell env variables', async () => { + const doc = await initDOM('shell-env-variables') - expect(doc.getElementById('feature-file-env-variables').textContent).to.equal('fromtheenvfile.') + expect(doc.getElementById('feature-shell-env-variables').textContent).to.equal('fromtheshell.') }) }) }) diff --git a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js index cec02227493..7cf8134b79f 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js @@ -15,9 +15,11 @@ if (process.env.E2E_FILE) { const markup = fs.readFileSync(file, 'utf8') getMarkup = () => markup + const pathPrefix = process.env.PUBLIC_URL.replace(/^https?:\/\/[^\/]+\/?/, '') + resourceLoader = (resource, callback) => callback( null, - fs.readFileSync(path.join(path.dirname(file), resource.url.pathname), 'utf8') + fs.readFileSync(path.join(path.dirname(file), resource.url.pathname.replace(pathPrefix, '')), 'utf8') ) } else if (process.env.E2E_URL) { getMarkup = () => new Promise(resolve => { @@ -37,7 +39,7 @@ if (process.env.E2E_FILE) { export default feature => new Promise(async resolve => { const markup = await getMarkup() - const host = process.env.E2E_URL || 'http://localhost:3000' + const host = process.env.E2E_URL || 'http://www.example.org/spa:3000' const doc = jsdom.jsdom(markup, { features: { FetchExternalResources: ['script', 'css'], diff --git a/packages/react-scripts/fixtures/kitchensink/src/App.js b/packages/react-scripts/fixtures/kitchensink/src/App.js index cf93b4c132b..be9465ece36 100644 --- a/packages/react-scripts/fixtures/kitchensink/src/App.js +++ b/packages/react-scripts/fixtures/kitchensink/src/App.js @@ -32,7 +32,8 @@ class App extends React.Component { } componentDidMount() { - switch (location.hash.slice(1)) { + const feature = location.hash.slice(1) + switch (feature) { case 'array-destructuring': require.ensure([], () => this.setFeature(require('./features/syntax/ArrayDestructuring').default)); break; @@ -87,6 +88,9 @@ class App extends React.Component { case 'promises': require.ensure([], () => this.setFeature(require('./features/syntax/Promises').default)); break; + case 'public-url': + require.ensure([], () => this.setFeature(require('./features/env/PublicUrl').default)); + break; case 'rest-and-default': require.ensure([], () => this.setFeature(require('./features/syntax/RestAndDefault').default)); break; @@ -106,6 +110,9 @@ class App extends React.Component { require.ensure([], () => this.setFeature(require('./features/webpack/UnknownExtInclusion').default)); break; default: + if (feature) { + throw new Error(`Missing feature "${feature}"`); + } this.setFeature(null); break; } diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.js new file mode 100644 index 00000000000..bbb7b958b61 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.js @@ -0,0 +1,5 @@ +import React from 'react' + +export default () => ( + {process.env.PUBLIC_URL}. +) diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.test.js new file mode 100644 index 00000000000..31e699ece0b --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import PublicUrl from './PublicUrl'; + +describe('PUBLIC_URL', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 8615fb074a9..c326b9b94d9 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -241,7 +241,7 @@ function runDevServer(host, port, protocol) { // project directory is dangerous because we may expose sensitive files. // Instead, we establish a convention that only files in `public` directory // get served. Our build script will copy `public` into the `build` folder. - // In `index.html`, you can get URL of `public` folder with %PUBLIC_PATH%: + // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: // // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. // Note that we only recommend to use `public` folder as an escape hatch diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh index 892230ab747..3db6ef8d1d0 100755 --- a/tasks/e2e-kitchensink.sh +++ b/tasks/e2e-kitchensink.sh @@ -111,7 +111,11 @@ create_react_app --scripts-version=$scripts_path --internal-testing-template=$ro cd test-kitchensink # Test the build -NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + NODE_PATH=src \ + PUBLIC_URL=http://www.example.org/spa/ \ + npm run build + # Check for expected output test -e build/*.html test -e build/static/js/main.*.js @@ -127,6 +131,7 @@ tmp_server_log=`mktemp` PORT=3001 \ REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ NODE_PATH=src \ + PUBLIC_URL=http://www.example.org/spa/ \ nohup npm start &>$tmp_server_log & grep -q 'The app is running at:' <(tail -f $tmp_server_log) E2E_URL="http://localhost:3001" \ @@ -138,6 +143,7 @@ E2E_URL="http://localhost:3001" \ E2E_FILE=./build/index.html \ CI=true \ NODE_PATH=src \ + PUBLIC_URL=http://www.example.org/spa/ \ node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js # ****************************************************************************** @@ -157,7 +163,11 @@ npm link $root_path/packages/react-scripts rm .babelrc # Test the build -NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build +REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ + NODE_PATH=src \ + PUBLIC_URL=http://www.example.org/spa/ \ + npm run build + # Check for expected output test -e build/*.html test -e build/static/js/main.*.js @@ -173,6 +183,7 @@ tmp_server_log=`mktemp` PORT=3002 \ REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ NODE_PATH=src \ + PUBLIC_URL=http://www.example.org/spa/ \ nohup npm start &>$tmp_server_log & grep -q 'The app is running at:' <(tail -f $tmp_server_log) E2E_URL="http://localhost:3002" \ @@ -186,6 +197,7 @@ E2E_FILE=./build/index.html \ CI=true \ NODE_ENV=production \ NODE_PATH=src \ + PUBLIC_URL=http://www.example.org/spa/ \ node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js # Cleanup