import { Tree } from '@angular-devkit/schematics'; import { UnitTestTree } from '@angular-devkit/schematics/testing'; import { readJsonInTree } from '../ast-utils'; import { callRule, runSchematic, runExternalSchematic, } from '../../utils/testing'; import { createEmptyWorkspace } from '../../../testing'; import { renameNpmPackages, PackageRenameMapping } from './rename-npm-packages'; describe('renameNpmPackages Rule', () => { let tree: UnitTestTree; beforeEach(async () => { tree = new UnitTestTree(Tree.empty()); tree = createEmptyWorkspace(tree) as UnitTestTree; }); it('should rename an npm package in both package.json and any file that imports it', async () => { tree.overwrite( 'package.json', JSON.stringify({ dependencies: { 'package-to-rename': '1.2.3', }, }) ); tree = await runSchematic('lib', { name: 'library-1' }, tree); const moduleThatImports = 'libs/library-1/src/importer.ts'; tree.create( moduleThatImports, `import { something } from 'package-to-rename'; export const doSomething = (...args) => something(...args); ` ); tree = (await callRule( renameNpmPackages({ 'package-to-rename': '@package/renamed' }), tree )) as UnitTestTree; const packageJson = readJsonInTree(tree, '/package.json'); expect(packageJson).toMatchObject({ dependencies: { '@package/renamed': '1.2.3', }, }); expect(tree.read(moduleThatImports).toString()).toContain( `import { something } from '@package/renamed'` ); }); it('should accept a new version that will also be updated in the package.json when renamed', async () => { tree.overwrite( 'package.json', JSON.stringify({ dependencies: { 'package-to-rename': '1.2.3', }, }) ); tree = (await callRule( renameNpmPackages({ 'package-to-rename': ['@package/renamed', '9.9.9'] }), tree )) as UnitTestTree; const packageJson = readJsonInTree(tree, '/package.json'); expect(packageJson).toMatchObject({ dependencies: { '@package/renamed': '9.9.9', }, }); }); it('should rename multiple npm packages if more are passed in the PackageRenameMapping', async () => { tree.overwrite( 'package.json', JSON.stringify({ dependencies: { 'package-to-rename': '1.2.3', }, devDependencies: { '@old/packageName': '0.0.1', }, }) ); tree = await runSchematic('lib', { name: 'library-1' }, tree); tree = await runSchematic('lib', { name: 'library-2' }, tree); tree = await runExternalSchematic( '@nrwl/angular', 'application', { name: 'app-one' }, tree ); const lib1ImportFile = 'libs/library-1/src/importer.ts'; tree.create( lib1ImportFile, `import { something } from 'package-to-rename'; import { anotherThing } from '@old/packageName'; export const doSomething = (...args) => something(...args); export const doSomethingElse = (...args) => anotherThing(...args); ` ); const lib2ImportFile = 'libs/library-2/src/importer.ts'; tree.create( lib2ImportFile, `import { something } from 'package-to-rename'; export const doSomething = (...args) => something(...args); ` ); const lib2ImportFile2 = 'libs/library-2/src/lib/second-importer.ts'; tree.create( lib2ImportFile2, `import { something } from '@old/packageName'; export const doSomething = (...args) => something(...args); ` ); const appImportFile = 'apps/app-one/src/importer.ts'; tree.create( appImportFile, `import { something } from 'package-to-rename'; export const doSomething = (...args) => something(...args); ` ); tree = (await callRule( renameNpmPackages({ 'package-to-rename': '@package/renamed', '@old/packageName': 'new-improved-pacakge', }), tree )) as UnitTestTree; const packageJson = readJsonInTree(tree, '/package.json'); expect(packageJson).toMatchObject({ dependencies: { '@package/renamed': '1.2.3', }, devDependencies: { 'new-improved-pacakge': '0.0.1', }, }); // Lib1 (one file with multiple import name changes) expect(tree.read(lib1ImportFile).toString()).toContain( `import { anotherThing } from 'new-improved-pacakge'` ); expect(tree.read(lib1ImportFile).toString()).toContain( `import { something } from '@package/renamed'` ); // Lib2 (one lib with multiple files with import changes) expect(tree.read(lib2ImportFile).toString()).toContain( `import { something } from '@package/renamed'` ); expect(tree.read(lib2ImportFile2).toString()).toContain( `import { something } from 'new-improved-pacakge'` ); // App (make sure it's changed in apps too) expect(tree.read(appImportFile).toString()).toContain( `import { something } from '@package/renamed'` ); }); it('should only update libs / apps that import the npm package as a dep', async () => { tree.overwrite( 'package.json', JSON.stringify({ dependencies: { 'package-to-rename': '1.2.3', }, }) ); tree = await runSchematic('lib', { name: 'library-1' }, tree); tree = await runSchematic('lib', { name: 'library-2' }, tree); const lib1ImportFile = 'libs/library-1/src/importer.ts'; tree.create( lib1ImportFile, `import { something } from 'package-to-rename'; export const doSomething = (...args) => something(...args); ` ); const lib2ImportFile = 'libs/library-2/src/non-importer.ts'; tree.create( lib2ImportFile, `// just a comment about import { something } from 'package-to-rename'` ); tree = (await callRule( renameNpmPackages({ 'package-to-rename': '@package/renamed', }), tree )) as UnitTestTree; expect(tree.read(lib1ImportFile).toString()).toContain( `import { something } from '@package/renamed'` ); expect(tree.read(lib2ImportFile).toString()).toContain( `// just a comment about import { something } from 'package-to-rename'` ); }); it('should do nothing if the packages are not found in the package.json', async () => { tree.overwrite( 'package.json', JSON.stringify({ dependencies: { 'not-me': '1.0.0', }, devDependencies: { 'nor-me': '0.0.2', }, }) ); tree = (await callRule( renameNpmPackages({ 'package-to-rename': '@package/renamed', }), tree )) as UnitTestTree; const packageJson = readJsonInTree(tree, '/package.json'); expect(packageJson).toMatchObject({ dependencies: { 'not-me': '1.0.0', }, devDependencies: { 'nor-me': '0.0.2', }, }); }); });