From a07f019ca17104b0622bbef28a7cf20d0cfe46f7 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Tue, 16 Jul 2019 23:30:06 -0400 Subject: [PATCH] feat(react): move BrowserRouter to main.tsx for routing (#1588) Close #1558 --- e2e/react.test.ts | 52 +++------ e2e/utils.ts | 1 + package.json | 1 + .../application/application.spec.ts | 8 +- .../app/src/app/__fileName__.spec.tsx__tmpl__ | 11 ++ .../files/app/src/main.tsx__tmpl__ | 7 ++ packages/react/src/utils/ast-utils.ts | 14 --- yarn.lock | 101 ++++++++++++++++-- 8 files changed, 137 insertions(+), 58 deletions(-) diff --git a/e2e/react.test.ts b/e2e/react.test.ts index b4b2fc588b..af693d3ab3 100644 --- a/e2e/react.test.ts +++ b/e2e/react.test.ts @@ -29,42 +29,19 @@ describe('React Applications', () => { ); updateFile(mainPath, `import '@proj/${libName}';\n` + readFile(mainPath)); - const lintResults = runCLI(`lint ${appName}`); - expect(lintResults).toContain('All files pass linting.'); - runCLI(`build ${appName}`); - checkFilesExist( - `dist/apps/${appName}/index.html`, - `dist/apps/${appName}/polyfills-es2015.js`, - `dist/apps/${appName}/runtime-es2015.js`, - `dist/apps/${appName}/vendor-es2015.js`, - `dist/apps/${appName}/main-es2015.js`, - `dist/apps/${appName}/styles-es2015.js`, - `dist/apps/${appName}/polyfills-es5.js`, - `dist/apps/${appName}/runtime-es5.js`, - `dist/apps/${appName}/vendor-es5.js`, - `dist/apps/${appName}/main-es5.js`, - `dist/apps/${appName}/styles-es5.js` - ); - runCLI(`build ${appName} --prod --output-hashing none`); - checkFilesExist( - `dist/apps/${appName}/index.html`, - `dist/apps/${appName}/polyfills-es2015.js`, - `dist/apps/${appName}/runtime-es2015.js`, - `dist/apps/${appName}/main-es2015.js`, - `dist/apps/${appName}/polyfills-es5.js`, - `dist/apps/${appName}/runtime-es5.js`, - `dist/apps/${appName}/main-es5.js`, - `dist/apps/${appName}/styles.css` - ); - const testResults = await runCLIAsync(`test ${appName}`); - expect(testResults.stderr).toContain('Test Suites: 1 passed, 1 total'); - const lintE2eResults = runCLI(`lint ${appName}-e2e`); - expect(lintE2eResults).toContain('All files pass linting.'); - const e2eResults = runCLI(`e2e ${appName}-e2e`); - expect(e2eResults).toContain('All specs passed!'); - const libTestResults = await runCLIAsync(`test ${libName}`); expect(libTestResults.stderr).toContain('Test Suites: 1 passed, 1 total'); + + await testGeneratedApp(appName); + }, 120000); + + it('should generate app with routing', async () => { + ensureProject(); + const appName = uniq('app'); + + runCLI(`generate @nrwl/react:app ${appName} --routing --no-interactive`); + + await testGeneratedApp(appName); }, 120000); it('should be able to use JSX', async () => { @@ -101,8 +78,13 @@ describe('React Applications', () => { const mainPath = `apps/${appName}/src/main.jsx`; updateFile(mainPath, `import '@proj/${libName}';\n` + readFile(mainPath)); + await testGeneratedApp(appName); + }, 30000); + + async function testGeneratedApp(appName) { const lintResults = runCLI(`lint ${appName}`); expect(lintResults).toContain('All files pass linting.'); + runCLI(`build ${appName}`); checkFilesExist( `dist/apps/${appName}/index.html`, @@ -134,5 +116,5 @@ describe('React Applications', () => { expect(lintE2eResults).toContain('All files pass linting.'); const e2eResults = runCLI(`e2e ${appName}-e2e`); expect(e2eResults).toContain('All specs passed!'); - }, 30000); + } }); diff --git a/e2e/utils.ts b/e2e/utils.ts index 9626f18b92..ef187f2e17 100644 --- a/e2e/utils.ts +++ b/e2e/utils.ts @@ -143,6 +143,7 @@ export function copyMissingPackages(): void { 'react', 'react-dom', + 'react-router-dom', '@types/react', '@types/react-dom', '@testing-library', diff --git a/package.json b/package.json index 86250ba24f..edf0c5f246 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "react": "16.8.6", "react-dom": "16.8.6", "@testing-library/react": "8.0.5", + "react-router-dom": "5.0.1", "release-it": "^7.4.0", "rxjs": "~6.4.0", "semver": "5.4.1", diff --git a/packages/react/src/schematics/application/application.spec.ts b/packages/react/src/schematics/application/application.spec.ts index d9c7013f76..46adda06b6 100644 --- a/packages/react/src/schematics/application/application.spec.ts +++ b/packages/react/src/schematics/application/application.spec.ts @@ -452,13 +452,15 @@ describe('app', () => { appTree ); + const mainSource = tree.read('apps/my-app/src/main.tsx').toString(); + const componentSource = tree .read('apps/my-app/src/app/app.tsx') .toString(); - expect(componentSource).toContain('react-router-dom'); - expect(componentSource).toContain(''); - expect(componentSource).toContain(''); + expect(mainSource).toContain('react-router-dom'); + expect(mainSource).toContain(''); + expect(mainSource).toContain(''); expect(componentSource).toMatch(/ +import { BrowserRouter } from 'react-router-dom'; +<% } %> import App from './app'; @@ -7,12 +10,20 @@ describe('App', () => { afterEach(cleanup); it('should render successfully', () => { + <% if (routing) { %> + const { baseElement } = render(); + <% } else { %> const { baseElement } = render(); + <% } %> expect(baseElement).toBeTruthy(); }); it('should have a greeting as the title', () => { + <% if (routing) { %> + const { getByText } = render(); + <% } else { %> const { getByText } = render(); + <% } %> expect(getByText('Welcome to <%= projectName %>!')).toBeTruthy(); }); }); diff --git a/packages/react/src/schematics/application/files/app/src/main.tsx__tmpl__ b/packages/react/src/schematics/application/files/app/src/main.tsx__tmpl__ index 76f479848c..32224f52bc 100644 --- a/packages/react/src/schematics/application/files/app/src/main.tsx__tmpl__ +++ b/packages/react/src/schematics/application/files/app/src/main.tsx__tmpl__ @@ -1,6 +1,13 @@ import React from 'react'; import ReactDOM from 'react-dom'; +<% if (routing) { %> +import { BrowserRouter } from 'react-router-dom'; +<% } %> import App from './app/app'; +<% if (routing) { %> +ReactDOM.render(, document.getElementById('root')); +<% } else { %> ReactDOM.render(, document.getElementById('root')); +<% } %> diff --git a/packages/react/src/utils/ast-utils.ts b/packages/react/src/utils/ast-utils.ts index 2e96a25804..9057fb5fc6 100644 --- a/packages/react/src/utils/ast-utils.ts +++ b/packages/react/src/utils/ast-utils.ts @@ -13,18 +13,6 @@ export function addRouter(sourcePath: string, source: ts.SourceFile): Change[] { const outerMostJsxOpening = jsxOpening[0]; const outerMostJsxClosing = jsxClosing[jsxClosing.length - 1]; - const insertOpening = new InsertChange( - sourcePath, - outerMostJsxOpening.getStart(), - '' - ); - - const insertClosing = new InsertChange( - sourcePath, - outerMostJsxClosing.getEnd(), - '' - ); - const insertRoute = new InsertChange( sourcePath, outerMostJsxClosing.getStart(), @@ -51,8 +39,6 @@ export function addRouter(sourcePath: string, source: ts.SourceFile): Change[] { sourcePath, `import { BrowserRouter as Router, Route, Link} from 'react-router-dom';` ), - insertOpening, - insertClosing, insertRoute, insertLink ]; diff --git a/yarn.lock b/yarn.lock index 4e1c04eda9..950f6a3575 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,7 +847,7 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/runtime@^7.4.5", "@babel/runtime@^7.5.4": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.4": version "7.5.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.4.tgz#cb7d1ad7c6d65676e66b47186577930465b5271b" integrity sha512-Na84uwyImZZc3FKf4aUF1tysApzwf3p2yuFBIyBfbzT5glzKTdvYI4KVW4kcgjrzoGUjC7w3YyCHcJKaRxsr2Q== @@ -1271,7 +1271,7 @@ pretty-format "^24.8.0" wait-for-expect "^1.2.0" -"@testing-library/react@6.0.0": +"@testing-library/react@8.0.5": version "8.0.5" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-8.0.5.tgz#2301011a8c5567eba59691860df19a3cfc9d7425" integrity sha512-2EzVi7HjUUF8gKzB4s+oCJ1+F4VOrphO+DlUO6Ptgtcz1ko4J2zqnr0t7g+T7uedXXjJ0wdq70zQMhJXP3w37A== @@ -6429,6 +6429,11 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== + handle-thing@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" @@ -6568,6 +6573,18 @@ he@1.2.x: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +history@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca" + integrity sha512-H2DkjCjXf0Op9OAr6nJ56fcRkTSNrUiv41vNJ6IswJjif6wlpZK0BTfFbi7qK9dXLSYZxkq5lBsj3vUjlYBYZA== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^2.2.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^0.4.0" + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -6577,6 +6594,13 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" + integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== + dependencies: + react-is "^16.7.0" + home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" @@ -8691,7 +8715,7 @@ longest@^1.0.1: resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -9058,6 +9082,15 @@ mimic-response@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mini-create-react-context@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189" + integrity sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw== + dependencies: + "@babel/runtime" "^7.4.0" + gud "^1.0.0" + tiny-warning "^1.0.2" + mini-css-extract-plugin@0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz#a3f13372d6fcde912f3ee4cd039665704801e3b9" @@ -10199,6 +10232,13 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + integrity sha1-Wf3g9DW62suhA6hOnTvGTpa5k30= + dependencies: + isarray "0.0.1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -10710,7 +10750,7 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-dom@^16.8.3: +react-dom@16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== @@ -10720,12 +10760,41 @@ react-dom@^16.8.3: prop-types "^15.6.2" scheduler "^0.13.6" -react-is@^16.8.1, react-is@^16.8.4: +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.8.6" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== -react@^16.8.3: +react-router-dom@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be" + integrity sha512-zaVHSy7NN0G91/Bz9GD4owex5+eop+KvgbxXsP/O+iW1/Ln+BrJ8QiIR5a6xNPtrdTvLkxqlDClx13QO1uB8CA== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.0.1" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.0.1.tgz#04ee77df1d1ab6cb8939f9f01ad5702dbadb8b0f" + integrity sha512-EM7suCPNKb1NxcTZ2LEOWFtQBQRQXecLxVpdsP4DW4PbbqYWeRiLyV/Tt1SdCrvT2jcyXAXmVTmzvSzrPR63Bg== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.3.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react@16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== @@ -11209,6 +11278,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-pathname@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" + integrity sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -12530,6 +12604,16 @@ timers-ext@^0.1.5: es5-ext "~0.10.46" next-tick "1" +tiny-invariant@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" + integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== + +tiny-warning@^1.0.0, tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp-promise@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-1.0.5.tgz#3208d7fa44758f86a2a4c4060f3c33fea30e8038" @@ -13102,6 +13186,11 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" +value-equal@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" + integrity sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"