From 7c8f02a7c056c9f43ee754c4b0e511a5579ec202 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 7 Jun 2019 23:08:51 +0200 Subject: [PATCH] chore: add @testing-library migration (#23) This change was manually released on npm as `@angular-extensions/testing-library@5.1.2` to not intervene with the current version. --- .../testing-library/migrations/5_1_2/index.ts | 53 ++++++++++++++ .../rules/noAngularExtensionsImportRule.ts | 26 +++++++ .../testing-library/migrations/migration.json | 5 ++ .../tests/migration/5_1_2.spec.ts | 70 +++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 projects/testing-library/migrations/5_1_2/index.ts create mode 100644 projects/testing-library/migrations/5_1_2/rules/noAngularExtensionsImportRule.ts create mode 100644 projects/testing-library/tests/migration/5_1_2.spec.ts diff --git a/projects/testing-library/migrations/5_1_2/index.ts b/projects/testing-library/migrations/5_1_2/index.ts new file mode 100644 index 00000000..06e87f2d --- /dev/null +++ b/projects/testing-library/migrations/5_1_2/index.ts @@ -0,0 +1,53 @@ +import { Rule, chain, Tree, SchematicContext } from '@angular-devkit/schematics'; +import { TslintFixTask } from '@angular-devkit/schematics/tasks'; +import * as path from 'path'; +import { stripIndents } from '@angular-devkit/core/src/utils/literals'; + +function createRule(ruleName: string): TslintFixTask { + return new TslintFixTask( + { + rulesDirectory: path.join(__dirname, 'rules'), + rules: { + [ruleName]: [true], + }, + }, + { + includes: ['**/*.spec.ts', '**/*.test.ts'], + silent: false, + }, + ); +} + +function displayInformation(tree, context: SchematicContext) { + context.logger.info(stripIndents` + @angular-extensions/testing-library has moved to @testing-library/angular. + + Learn more about this change here: https://github.com/testing-library/dom-testing-library/issues/260 + `); + + return tree; +} + +function updatePackageJson(host: Tree) { + if (host.exists('package.json')) { + // tslint:disable-next-line: no-non-null-assertion + const sourceText = host.read('package.json')!.toString('utf-8'); + const json = JSON.parse(sourceText); + + if (json['devDependencies'] && json['devDependencies']['@angular-extensions/testing-library']) { + json['devDependencies']['@testing-library/angular'] = '^6.0.0'; + delete json['devDependencies']['@angular-extensions/testing-library']; + host.overwrite('package.json', JSON.stringify(json, null, 2)); + } + } + + return host; +} + +export default function(): Rule { + return (host, context) => { + context.addTask(createRule('no-angular-extensions-import')); + + return chain([displayInformation, updatePackageJson])(host, context); + }; +} diff --git a/projects/testing-library/migrations/5_1_2/rules/noAngularExtensionsImportRule.ts b/projects/testing-library/migrations/5_1_2/rules/noAngularExtensionsImportRule.ts new file mode 100644 index 00000000..789bbb76 --- /dev/null +++ b/projects/testing-library/migrations/5_1_2/rules/noAngularExtensionsImportRule.ts @@ -0,0 +1,26 @@ +import * as ts from 'typescript'; +import { Replacement, RuleFailure, Rules } from 'tslint'; +import { tsquery } from '@phenomnomnominal/tsquery'; + +const IMPORT_QUERY = `ImportDeclaration StringLiteral[value="@angular-extensions/testing-library"]`; + +const FAILURE_MESSAGE = + 'Found the library `@angular-extensions/testing-library`, use `@testing-library/angular` instead.'; + +export class Rule extends Rules.AbstractRule { + public apply(ast: ts.SourceFile): Array { + const imports = this.getImports(ast); + return imports; + } + + private getImports(ast: ts.SourceFile): Array { + return tsquery(ast, IMPORT_QUERY).map(result => { + // replace text between (single) quotes + const replacement = new Replacement(result.getStart() + 1, result.getWidth() - 2, '@testing-library/angular'); + const start = result.getStart(); + const end = result.getEnd(); + + return new RuleFailure(ast, start, end, FAILURE_MESSAGE, this.ruleName, replacement); + }); + } +} diff --git a/projects/testing-library/migrations/migration.json b/projects/testing-library/migrations/migration.json index 2a98134b..7a7cc7a4 100644 --- a/projects/testing-library/migrations/migration.json +++ b/projects/testing-library/migrations/migration.json @@ -5,6 +5,11 @@ "version": "4.0.0", "description": "Align API to *-testing-libraries", "factory": "./4_0_0" + }, + "migration-5.1.2": { + "version": "5.1.2", + "description": "Migrate to @testing-library", + "factory": "./5_1_2" } } } diff --git a/projects/testing-library/tests/migration/5_1_2.spec.ts b/projects/testing-library/tests/migration/5_1_2.spec.ts new file mode 100644 index 00000000..d3706259 --- /dev/null +++ b/projects/testing-library/tests/migration/5_1_2.spec.ts @@ -0,0 +1,70 @@ +import { getSystemPath, normalize, virtualFs } from '@angular-devkit/core'; +import { TempScopedNodeJsSyncHost } from '@angular-devkit/core/node/testing'; +import { HostTree } from '@angular-devkit/schematics'; +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import { stripIndents } from '@angular-devkit/core/src/utils/literals'; + +describe('Migration to version 5.1.2', () => { + const schematicRunner = new SchematicTestRunner('migrations', require.resolve('../../migrations/migration.json')); + + test('it renames @angular-extensions to @testing-library (in files)', async () => { + const specPath = normalize('tests/home.spec.ts'); + + const host = new TempScopedNodeJsSyncHost(); + const tree = new UnitTestTree(new HostTree(host)); + tree.create('/package.json', JSON.stringify({})); + process.chdir(getSystemPath(host.root)); + await host + .write( + specPath, + virtualFs.stringToFileBuffer(stripIndents` + import { render } from '@angular-extensions/testing-library'; + import { render } from "@angular-extensions/testing-library"; + `), + ) + .toPromise(); + + await schematicRunner.runSchematicAsync('migration-5.1.2', {}, tree).toPromise(); + await schematicRunner.engine.executePostTasks().toPromise(); + + const actual = await host + .read(specPath) + .toPromise() + .then(virtualFs.fileBufferToString); + + expect(actual).toBe(stripIndents` + import { render } from '@testing-library/angular'; + import { render } from "@testing-library/angular"; + `); + }); + + test('it renames @angular-extensions to @testing-library (in package.json)', async () => { + const packageJson = normalize('/package.json'); + const host = new TempScopedNodeJsSyncHost(); + const tree = new UnitTestTree(new HostTree(host)); + + tree.create( + packageJson, + JSON.stringify({ + devDependencies: { + '@angular-extensions/testing-library': '🦔', + }, + }), + ); + + await schematicRunner.runSchematicAsync('migration-5.1.2', {}, tree).toPromise(); + await schematicRunner.engine.executePostTasks().toPromise(); + + expect(tree.readContent(packageJson)).toBe( + JSON.stringify( + { + devDependencies: { + '@testing-library/angular': '^6.0.0', + }, + }, + null, + 2, + ), + ); + }); +});