Skip to content

Commit

Permalink
feat(react): updates libraries for React to newest versions (#1584)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaysoo committed Jul 17, 2019
1 parent 93c000d commit b3bea39
Show file tree
Hide file tree
Showing 14 changed files with 322 additions and 50 deletions.
2 changes: 1 addition & 1 deletion e2e/utils.ts
Expand Up @@ -145,7 +145,7 @@ export function copyMissingPackages(): void {
'react-dom',
'@types/react',
'@types/react-dom',
'react-testing-library',
'@testing-library',

'document-register-element'
];
Expand Down
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -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",
Expand Down
8 changes: 7 additions & 1 deletion 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"
}
}
}
102 changes: 102 additions & 0 deletions packages/react/src/migrations/update-8-3-0/update-8-3-0.spec.ts
@@ -0,0 +1,102 @@
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: {
react: '16.8.1',
'react-dom': '16.8.1',
'react-router-dom': '5.0.0',
'styled-components': '4.0.0'
},
devDependencies: {
'@types/styled-components': '4.0.0',
'react-testing-library': '5.0.0',
'@types/react': '16.8.0',
'@types/react-dom': '16.8.0'
}
})),
tree
)
.toPromise();
});

describe('imports', () => {
it(`should be migrate 'react-testing-library' to '@testing-library/react`, async () => {
tree.create(
'Hello.spec.tsx',
`
import Hello from './Hello';
import React from 'react';
import { render } from 'react-testing-library';
`
);

tree.create(
'foo.spec.ts',
`
import { render } from 'react-testing-library';
`
);

tree = await schematicRunner
.runSchematicAsync('update-8.3.0', {}, tree)
.toPromise();

expect(tree.read('Hello.spec.tsx').toString('utf-8'))
.toContain(stripIndents`
import Hello from './Hello';
import React from 'react';
import { render } from '@testing-library/react';
`);

expect(tree.read('foo.spec.ts').toString('utf-8')).toContain(stripIndents`
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({
dependencies: {
react: '16.8.6',
'react-dom': '16.8.6',
'react-router-dom': '5.0.1',
'styled-components': '4.3.2'
},
devDependencies: {
'@testing-library/react': '8.0.5',
'@types/react': '16.8.23',
'@types/react-dom': '16.8.23',
'@types/styled-components': '4.1.18'
}
})
);

expect(result.devDependencies['react-testing-library']).not.toBeDefined();
});
});
});
140 changes: 140 additions & 0 deletions packages/react/src/migrations/update-8-3-0/update-8-3-0.ts
@@ -0,0 +1,140 @@
import {
chain,
Rule,
SchematicContext,
Tree
} from '@angular-devkit/schematics';
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
import {
formatFiles,
insert,
readJsonInTree,
updateJsonInTree,
updatePackageJsonDependencies
} 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(tree: Tree) {
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 packageJson = readJsonInTree(tree, '/package.json');

const candidates = {
react: '16.8.6',
'react-dom': '16.8.6',
'react-router-dom': '5.0.1',
'@types/react': '16.8.23',
'@types/react-dom': '16.8.23',
'styled-components': '4.3.2',
'@types/styled-components': '4.1.18',
'@emotion/styled': '10.0.14'
};

const updated = Object.entries(candidates).reduce(
(acc, [m, v]) => {
if (packageJson.dependencies[m]) {
acc.dependencies[m] = v;
} else if (packageJson.devDependencies[m]) {
acc.devDependencies[m] = v;
}
return acc;
},
{
dependencies: {},
devDependencies: {
'@testing-library/react': testingLibraryVersion
}
}
);

const addNew = updatePackageJsonDependencies(
updated.dependencies,
updated.devDependencies
);

return chain([removeOld, addNew]);
}

function updateImports(host: Tree) {
let ig = ignore().add(['*', '!*.ts', '!*.tsx']); // include only .tsx? files

if (host.exists('.gitignore')) {
ig = ig.add(host.read('.gitignore').toString());
}

host.visit(path => {
if (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);
});
}
@@ -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';

Expand Down
@@ -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 %>';

Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/schematics/ng-add/ng-add.spec.ts
Expand Up @@ -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', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/schematics/ng-add/ng-add.ts
Expand Up @@ -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
}
);
}
Expand Down
8 changes: 4 additions & 4 deletions packages/react/src/utils/styled.ts
@@ -1,7 +1,7 @@
import {
emotionVersion,
styledComponentVersion,
styledComponentTypesVersion
styledComponentsVersion,
styledComponentsTypesVersion
} from './versions';
import { PackageDependencies } from './dependencies';

Expand All @@ -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': {
Expand Down
16 changes: 8 additions & 8 deletions 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.23';
export const reactRouterVersion = '5.0.1';
export const testingLibraryVersion = '8.0.5';
3 changes: 2 additions & 1 deletion packages/workspace/index.ts
Expand Up @@ -36,7 +36,8 @@ export {
getProjectConfig,
addParameterToConstructor,
createOrUpdate,
findNodes
findNodes,
updatePackageJsonDependencies
} from './src/utils/ast-utils';

export {
Expand Down
22 changes: 22 additions & 0 deletions packages/workspace/src/utils/ast-utils.ts
Expand Up @@ -417,6 +417,28 @@ export function addDepsToPackageJson(
});
}

export function updatePackageJsonDependencies(
deps: any,
devDeps: any,
addInstall = true
): Rule {
return updateJsonInTree('package.json', (json, context: SchematicContext) => {
json.dependencies = {
...(json.dependencies || {}),
...deps
};
json.devDependencies = {
...(json.devDependencies || {}),
...devDeps
};
if (addInstall && !installAdded) {
context.addTask(new NodePackageInstallTask());
installAdded = true;
}
return json;
});
}

export function getProjectConfig(host: Tree, name: string): any {
const angularJson = readJsonInTree(host, '/angular.json');
const projectConfig = angularJson.projects[name];
Expand Down

0 comments on commit b3bea39

Please sign in to comment.