diff --git a/e2e/utils.ts b/e2e/utils.ts index f1bfeff90158a5..9626f18b92a4ad 100644 --- a/e2e/utils.ts +++ b/e2e/utils.ts @@ -145,7 +145,7 @@ export function copyMissingPackages(): void { 'react-dom', '@types/react', '@types/react-dom', - 'react-testing-library', + '@testing-library', 'document-register-element' ]; diff --git a/package.json b/package.json index d00c106a2c8c9e..9a300fd68502cd 100644 --- a/package.json +++ b/package.json @@ -98,9 +98,9 @@ "opn": "^5.3.0", "precise-commits": "1.0.2", "prettier": "1.16.4", - "react": "^16.8.3", - "react-dom": "^16.8.3", - "react-testing-library": "6.0.0", + "react": "16.8.6", + "react-dom": "16.8.6", + "@testing-library/react": "8.0.5", "release-it": "^7.4.0", "rxjs": "~6.4.0", "semver": "5.4.1", diff --git a/packages/react/migrations.json b/packages/react/migrations.json index 63001b44588915..2e42d93da592c6 100644 --- a/packages/react/migrations.json +++ b/packages/react/migrations.json @@ -1,3 +1,9 @@ { - "schematics": {} + "schematics": { + "update-8.3.0": { + "version": "8.3.0-beta.1", + "description": "Update React libraries", + "factory": "./src/migrations/update-8-3-0/update-8-3-0" + } + } } diff --git a/packages/react/src/migrations/update-8-3-0/update-8-3-0.spec.ts b/packages/react/src/migrations/update-8-3-0/update-8-3-0.spec.ts new file mode 100644 index 00000000000000..611d1240cecbbc --- /dev/null +++ b/packages/react/src/migrations/update-8-3-0/update-8-3-0.spec.ts @@ -0,0 +1,74 @@ +import { Tree } from '@angular-devkit/schematics'; +import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; +import { updateJsonInTree, readJsonInTree } from '@nrwl/workspace'; + +import * as path from 'path'; +import { stripIndents } from '@angular-devkit/core/src/utils/literals'; + +describe('Update 8-0-0', () => { + let tree: Tree; + let schematicRunner: SchematicTestRunner; + + beforeEach(async () => { + tree = Tree.empty(); + schematicRunner = new SchematicTestRunner( + '@nrwl/react', + path.join(__dirname, '../../../migrations.json') + ); + tree = await schematicRunner + .callRule( + updateJsonInTree('package.json', () => ({ + dependencies: {}, + devDependencies: { + 'react-testing-library': '5.0.0' + } + })), + tree + ) + .toPromise(); + }); + + describe('imports', () => { + it(`should be migrate 'react-testing-library' to '@testing-library/react`, async () => { + tree.create( + 'Hello.spec.ts', + ` + import Hello from './Hello'; + import React from 'react'; + import { render } from 'react-testing-library'; + ` + ); + + tree = await schematicRunner + .runSchematicAsync('update-8.3.0', {}, tree) + .toPromise(); + + expect(tree.read('Hello.spec.ts').toString('utf-8')) + .toContain(stripIndents` + import Hello from './Hello'; + import React from 'react'; + import { render } from '@testing-library/react'; + `); + }); + }); + + describe('dependencies', () => { + it('should update dependencies', async () => { + tree = await schematicRunner + .runSchematicAsync('update-8.3.0', {}, tree) + .toPromise(); + + const result = readJsonInTree(tree, 'package.json'); + + expect(result).toEqual( + expect.objectContaining({ + devDependencies: expect.objectContaining({ + '@testing-library/react': '8.0.5' + }) + }) + ); + + expect(result.devDependencies['react-testing-library']).not.toBeDefined(); + }); + }); +}); diff --git a/packages/react/src/migrations/update-8-3-0/update-8-3-0.ts b/packages/react/src/migrations/update-8-3-0/update-8-3-0.ts new file mode 100644 index 00000000000000..84dab5444dfa82 --- /dev/null +++ b/packages/react/src/migrations/update-8-3-0/update-8-3-0.ts @@ -0,0 +1,108 @@ +import { + chain, + Rule, + SchematicContext, + Tree +} from '@angular-devkit/schematics'; +import { stripIndents } from '@angular-devkit/core/src/utils/literals'; +import { + addDepsToPackageJson, + formatFiles, + insert, + updateJsonInTree +} from '@nrwl/workspace'; +import { + createSourceFile, + isImportDeclaration, + isStringLiteral, + ScriptTarget +} from 'typescript'; +import { ReplaceChange } from '@nrwl/workspace/src/utils/ast-utils'; +import { relative } from 'path'; +import { testingLibraryVersion } from '../../utils/versions'; + +const ignore = require('ignore'); + +export default function update(): Rule { + return chain([ + displayInformation, + updateDependencies, + updateImports, + formatFiles() + ]); +} + +function displayInformation(host: Tree, context: SchematicContext) { + context.logger.info(stripIndents` + React Testing Library has been repackaged as \`@testing-library/react\` as of version 8. + + We are replacing your \`react-testing-library\` imports with \`@testing-library/react\`. + + See: https://github.com/testing-library/react-testing-library/releases/tag/v8.0.0 + `); +} + +function updateDependencies() { + const removeOld = updateJsonInTree( + 'package.json', + (json, context: SchematicContext) => { + json.dependencies = json.dependencies || {}; + json.devDependencies = json.devDependencies || {}; + // Just in case user installed it to dependencies instead of devDependencies. + delete json.dependencies['react-testing-library']; + delete json.devDependencies['react-testing-library']; + context.logger.info(`Removing \`react-testing-library\` as a dependency`); + return json; + } + ); + const addNew = addDepsToPackageJson( + {}, + { '@testing-library/react': testingLibraryVersion } + ); + + return chain([removeOld, addNew]); +} + +function updateImports(host: Tree) { + let ig = ignore().add(['*', '!*.ts']); // include only .ts files + + if (host.exists('.gitignore')) { + ig = ig.add(host.read('.gitignore').toString()); + } + + host.visit(path => { + if (ig && ig.ignores(relative('/', path))) { + return; + } + + const sourceFile = createSourceFile( + path, + host.read(path).toString(), + ScriptTarget.Latest, + true + ); + const changes = []; + sourceFile.statements.forEach(statement => { + if ( + isImportDeclaration(statement) && + isStringLiteral(statement.moduleSpecifier) + ) { + const nodeText = statement.moduleSpecifier.getText(sourceFile); + const modulePath = statement.moduleSpecifier + .getText(sourceFile) + .substr(1, nodeText.length - 2); + if (modulePath === 'react-testing-library') { + changes.push( + new ReplaceChange( + path, + statement.moduleSpecifier.getStart(sourceFile), + nodeText, + `'@testing-library/react'` + ) + ); + } + } + }); + insert(host, path, changes); + }); +} diff --git a/packages/react/src/schematics/application/files/app/src/app/__fileName__.spec.tsx__tmpl__ b/packages/react/src/schematics/application/files/app/src/app/__fileName__.spec.tsx__tmpl__ index ca2ec879994fa3..544d5ffa8e73d4 100644 --- a/packages/react/src/schematics/application/files/app/src/app/__fileName__.spec.tsx__tmpl__ +++ b/packages/react/src/schematics/application/files/app/src/app/__fileName__.spec.tsx__tmpl__ @@ -1,5 +1,5 @@ import React from 'react'; -import { render, cleanup } from 'react-testing-library'; +import { render, cleanup } from '@testing-library/react'; import App from './app'; diff --git a/packages/react/src/schematics/component/files/__name__/__fileName__.spec.tsx__tmpl__ b/packages/react/src/schematics/component/files/__name__/__fileName__.spec.tsx__tmpl__ index 8afedc72dd37ce..292630f8240453 100644 --- a/packages/react/src/schematics/component/files/__name__/__fileName__.spec.tsx__tmpl__ +++ b/packages/react/src/schematics/component/files/__name__/__fileName__.spec.tsx__tmpl__ @@ -1,5 +1,5 @@ import React from 'react'; -import { render, cleanup } from 'react-testing-library'; +import { render, cleanup } from '@testing-library/react'; import <%= className %> from './<%= fileName %>'; diff --git a/packages/react/src/schematics/ng-add/ng-add.spec.ts b/packages/react/src/schematics/ng-add/ng-add.spec.ts index 6d9155d5ee01b2..33d4c0a8b18e81 100644 --- a/packages/react/src/schematics/ng-add/ng-add.spec.ts +++ b/packages/react/src/schematics/ng-add/ng-add.spec.ts @@ -21,7 +21,7 @@ describe('ng-add', () => { expect(packageJson.devDependencies['@nrwl/react']).toBeDefined(); expect(packageJson.devDependencies['@types/react']).toBeDefined(); expect(packageJson.devDependencies['@types/react-dom']).toBeDefined(); - expect(packageJson.devDependencies['react-testing-library']).toBeDefined(); + expect(packageJson.devDependencies['@testing-library/react']).toBeDefined(); }); describe('defaultCollection', () => { diff --git a/packages/react/src/schematics/ng-add/ng-add.ts b/packages/react/src/schematics/ng-add/ng-add.ts index 41c3cdcb92f1e0..0d4c900a7c3156 100644 --- a/packages/react/src/schematics/ng-add/ng-add.ts +++ b/packages/react/src/schematics/ng-add/ng-add.ts @@ -25,7 +25,7 @@ export function addDependencies(): Rule { '@nrwl/react': nxVersion, '@types/react': typesVersion, '@types/react-dom': domTypesVersion, - 'react-testing-library': testingLibraryVersion + '@testing-library/react': testingLibraryVersion } ); } diff --git a/packages/react/src/utils/styled.ts b/packages/react/src/utils/styled.ts index 17b28c9c357c34..5445cbd4ba583f 100644 --- a/packages/react/src/utils/styled.ts +++ b/packages/react/src/utils/styled.ts @@ -1,7 +1,7 @@ import { emotionVersion, - styledComponentVersion, - styledComponentTypesVersion + styledComponentsVersion, + styledComponentsTypesVersion } from './versions'; import { PackageDependencies } from './dependencies'; @@ -10,10 +10,10 @@ export const CSS_IN_JS_DEPENDENCIES: { } = { 'styled-components': { dependencies: { - 'styled-components': styledComponentVersion + 'styled-components': styledComponentsVersion }, devDependencies: { - '@types/styled-components': styledComponentTypesVersion + '@types/styled-components': styledComponentsTypesVersion } }, '@emotion/styled': { diff --git a/packages/react/src/utils/versions.ts b/packages/react/src/utils/versions.ts index 54a6ec46a5c16b..9603fc2d2ea89c 100644 --- a/packages/react/src/utils/versions.ts +++ b/packages/react/src/utils/versions.ts @@ -1,9 +1,9 @@ export const nxVersion = '*'; -export const frameworkVersion = '16.8.3'; -export const typesVersion = '16.8.4'; -export const styledComponentVersion = '4.2.0'; -export const styledComponentTypesVersion = '4.1.15'; -export const emotionVersion = '10.0.10'; -export const domTypesVersion = '16.8.2'; -export const reactRouterVersion = '5.0.0'; -export const testingLibraryVersion = '6.0.0'; +export const frameworkVersion = '16.8.6'; +export const typesVersion = '16.8.23'; +export const styledComponentsVersion = '4.3.2'; +export const styledComponentsTypesVersion = '4.1.18'; +export const emotionVersion = '10.0.14'; +export const domTypesVersion = '16.8.4'; +export const reactRouterVersion = '5.0.1'; +export const testingLibraryVersion = '8.0.5'; diff --git a/tsconfig.json b/tsconfig.json index 19b23802beb3f4..bba3b18932bf7b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,8 @@ "paths": { "@nrwl/workspace": ["./packages/workspace"], "@nrwl/workspace/*": ["./packages/workspace/*"], - "@nrwl/workspace/testing": ["./packages/workspace/testing"] + "@nrwl/workspace/testing": ["./packages/workspace/testing"], + "@nrwl/react/*": ["./packages/react/*"] } }, "exclude": [ diff --git a/yarn.lock b/yarn.lock index c2efe6e2e3422c..78ab3db2914fa8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,10 +847,10 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/runtime@^7.3.1", "@babel/runtime@^7.4.3": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d" - integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg== +"@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== dependencies: regenerator-runtime "^0.13.2" @@ -1260,6 +1260,25 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== +"@testing-library/dom@^5.5.4": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-5.6.0.tgz#18a7c162a6a79964e731ad7b810022a28218047c" + integrity sha512-nAsRvQLr/b6TGNjuHMEbWXCNPLrQYnzqa/KKQZL7wBOtfptUxsa4Ah9aqkHW0ZmCSFmUDj4nFUxWPVTeMu0iCw== + dependencies: + "@babel/runtime" "^7.4.5" + "@sheerun/mutationobserver-shim" "^0.3.2" + aria-query "3.0.0" + pretty-format "^24.8.0" + wait-for-expect "^1.2.0" + +"@testing-library/react@6.0.0": + 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== + dependencies: + "@babel/runtime" "^7.5.4" + "@testing-library/dom" "^5.5.4" + "@types/anymatch@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" @@ -1928,7 +1947,7 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -aria-query@^3.0.0: +aria-query@3.0.0, aria-query@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= @@ -4931,16 +4950,6 @@ dom-serializer@0: domelementtype "^1.3.0" entities "^1.1.1" -dom-testing-library@^3.13.1: - version "3.19.4" - resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.19.4.tgz#f5b737f59ee9749a4568fa353f1f59be97c888c3" - integrity sha512-GJOx8CLpnkvM3takILOsld/itUUc9+7Qh6caN1Spj6+9jIgNPY36fsvoH7sEgYokC0lBRdttO7G7fIFYCXlmcA== - dependencies: - "@babel/runtime" "^7.4.3" - "@sheerun/mutationobserver-shim" "^0.3.2" - pretty-format "^24.7.0" - wait-for-expect "^1.1.1" - domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" @@ -10380,7 +10389,7 @@ pretty-error@^2.0.2: renderkid "^2.0.1" utila "~0.4" -pretty-format@^24.7.0, pretty-format@^24.8.0: +pretty-format@^24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw== @@ -10682,14 +10691,6 @@ react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== -react-testing-library@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.0.0.tgz#81edfcfae8a795525f48685be9bf561df45bb35d" - integrity sha512-h0h+YLe4KWptK6HxOMnoNN4ngu3W8isrwDmHjPC5gxc+nOZOCurOvbKVYCvvuAw91jdO7VZSm/5KR7TxKnz0qA== - dependencies: - "@babel/runtime" "^7.3.1" - dom-testing-library "^3.13.1" - react@^16.8.3: version "16.8.6" resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" @@ -13118,10 +13119,10 @@ w3c-xmlserializer@^1.0.1: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" -wait-for-expect@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.1.1.tgz#9cd10e07d52810af9e0aaf509872e38f3c3d81ae" - integrity sha512-vd9JOqqEcBbCDhARWhW85ecjaEcfBLuXgVBqatfS3iw6oU4kzAcs+sCNjF+TC9YHPImCW7ypsuQc+htscIAQCw== +wait-for-expect@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.2.0.tgz#fdab6a26e87d2039101db88bff3d8158e5c3e13f" + integrity sha512-EJhKpA+5UHixduMBEGhTFuLuVgQBKWxkFbefOdj2bbk2/OpA5Opsc4aUTGmF+qJ+v3kTGxDRNYwKaT4j6g5n8Q== walker@^1.0.7, walker@~1.0.5: version "1.0.7"