refactor(@angular-devkit/architect): remove deprecated TestLogger

BREAKING CHANGE:

Deprecated `TestLogger` has been removed. Use `logging` API from `'@angular-devkit/core'` instead.

**Note:** this change doesn't effect application developers.
This commit is contained in:
Alan Agius 2020-09-22 12:52:33 +02:00 committed by Filipe Silva
parent ab9968d76e
commit d3ad09508f
10 changed files with 105 additions and 113 deletions

View File

@ -14,13 +14,6 @@ export declare class TestingArchitectHost implements ArchitectHost {
resolveBuilder(builderName: string): Promise<BuilderInfo | null>;
}
export declare class TestLogger extends logging.Logger {
constructor(name: string, parent?: logging.Logger | null);
clear(): void;
includes(message: string): boolean;
test(re: RegExp): boolean;
}
export declare class TestProjectHost extends NodeJsSyncHost {
protected _templateRoot: Path;
constructor(_templateRoot: Path);

View File

@ -7,4 +7,3 @@
*/
export * from './testing-architect-host';
export * from './test-project-host';
export * from './test-logger';

View File

@ -1,33 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { logging } from '@angular-devkit/core';
/**
* @deprecated
*/
export class TestLogger extends logging.Logger {
private _latestEntries: logging.LogEntry[] = [];
constructor(name: string, parent: logging.Logger | null = null) {
super(name, parent);
this.subscribe((entry) => this._latestEntries.push(entry));
}
clear() {
this._latestEntries = [];
}
includes(message: string) {
return this._latestEntries.some((entry) => entry.message.includes(message));
}
test(re: RegExp) {
return this._latestEntries.some((entry) => re.test(entry.message));
}
}

View File

@ -7,7 +7,8 @@
*/
import { Architect } from '@angular-devkit/architect';
import { TestLogger, TestProjectHost } from '@angular-devkit/architect/testing';
import { TestProjectHost } from '@angular-devkit/architect/testing';
import { logging } from '@angular-devkit/core';
import { take, tap, timeout } from 'rxjs/operators';
import {
browserBuild,
@ -45,12 +46,12 @@ describe('Browser Builder lazy modules', () => {
);
}
function hasMissingModuleError(logger: TestLogger) {
function hasMissingModuleError(logs: string): boolean {
// TS type error when using import().
return logger.includes('Cannot find module') ||
return logs.includes('Cannot find module') ||
// Webpack error when using import() on a rebuild.
// There is no TS error because the type checker is forked on rebuilds.
logger.includes('Module not found');
logs.includes('Module not found');
}
const cases: [string, Record<string, string>][] = [
@ -96,11 +97,14 @@ describe('Browser Builder lazy modules', () => {
host.writeMultipleFiles(lazyModuleFnImport);
host.replaceInFile('src/app/app.module.ts', 'lazy.module', 'invalid.module');
const logger = new TestLogger('build-lazy-errors');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const run = await architect.scheduleTarget(target, {}, { logger });
const output = await run.result;
expect(output.success).toBe(false);
expect(hasMissingModuleError(logger)).toBe(true, 'Should show missing module error');
expect(hasMissingModuleError(logs.join())).toBe(true, 'Should show missing module error');
});
it('should show error when lazy route is invalid on watch mode AOT', async () => {
@ -108,9 +112,9 @@ describe('Browser Builder lazy modules', () => {
host.writeMultipleFiles(lazyModuleFnImport);
let buildNumber = 0;
const logger = new TestLogger('rebuild-lazy-errors');
const overrides = { watch: true, aot: true };
const run = await architect.scheduleTarget(target, overrides, { logger });
const run = await architect.scheduleTarget(target, overrides);
await run.output
.pipe(
timeout(15000),
@ -120,7 +124,6 @@ describe('Browser Builder lazy modules', () => {
case 1:
expect(buildEvent.success).toBe(true);
host.replaceInFile('src/app/app.module.ts', 'lazy.module', 'invalid.module');
logger.clear();
break;
case 2:
expect(buildEvent.success).toBe(false);

View File

@ -7,7 +7,7 @@
*/
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { logging } from '@angular-devkit/core';
import { browserBuild, createArchitect, host, veEnabled } from '../../test-utils';
describe('Browser Builder no entry module', () => {
@ -38,8 +38,11 @@ describe('Browser Builder no entry module', () => {
host.replaceInFile('src/main.ts', /./g, '');
host.appendToFile('src/main.ts', `import './app/app.module';`);
const logger = new TestLogger('no-bootstrap');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
await browserBuild(architect, host, target, { baseHref: '/myUrl' }, { logger });
expect(logger.includes('Lazy routes discovery is not enabled')).toBe(true);
expect(logs.join().includes('Lazy routes discovery is not enabled')).toBe(true);
});
});

View File

@ -7,8 +7,7 @@
*/
// tslint:disable:no-big-function
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { join, normalize, virtualFs } from '@angular-devkit/core';
import { join, logging, normalize, virtualFs } from '@angular-devkit/core';
import { debounceTime, take, takeWhile, tap } from 'rxjs/operators';
import {
createArchitect,
@ -154,7 +153,10 @@ describe('Browser Builder rebuilds', () => {
);
const overrides = { watch: true, forkTypeChecker: false };
const logger = new TestLogger('rebuild-type-errors');
const logger = new logging.Logger('');
let logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const typeError = `is not assignable to parameter of type 'number'`;
let buildNumber = 0;
@ -177,8 +179,8 @@ describe('Browser Builder rebuilds', () => {
case 2:
// The second build should error out with a type error on the type of an argument.
expect(buildEvent.success).toBe(false);
expect(logger.includes(typeError)).toBe(true);
logger.clear();
expect(logs.join().includes(typeError)).toBe(true);
logs = [];
// Change an UNRELATED file and the error should still happen.
// Should trigger a rebuild, this time an error is also expected.
host.appendToFile('src/app/app.module.ts', `console.log(1);`);
@ -187,8 +189,8 @@ describe('Browser Builder rebuilds', () => {
case 3:
// The third build should have the same error as the first.
expect(buildEvent.success).toBe(false);
expect(logger.includes(typeError)).toBe(true);
logger.clear();
expect(logs.join().includes(typeError)).toBe(true);
logs = [];
// Fix the error.
host.writeMultipleFiles({
'src/funky2.ts': `export const funky2 = (value: string) => value + 'hello';`,
@ -350,7 +352,9 @@ describe('Browser Builder rebuilds', () => {
// show up in getNgSemanticDiagnostics. Since getNgSemanticDiagnostics is only called on the
// type checker, we must disable it to get a failing fourth build with Ivy.
const overrides = { watch: true, aot: true, forkTypeChecker: veEnabled };
const logger = new TestLogger('rebuild-aot-errors');
const logger = new logging.Logger('');
let logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const staticAnalysisError = !veEnabled
? 'selector must be a string'
: 'Function expressions are not supported in decorators';
@ -367,18 +371,18 @@ describe('Browser Builder rebuilds', () => {
case 1:
// The first build should error out with a static analysis error.
expect(buildEvent.success).toBe(false, 'First build should not succeed.');
expect(logger.includes(staticAnalysisError)).toBe(true,
expect(logs.join().includes(staticAnalysisError)).toBe(true,
'First build should have static analysis error.');
logger.clear();
logs = [];
// Fix the static analysis error.
host.writeMultipleFiles({ 'src/app/app.component.ts': origContent });
break;
case 2:
expect(buildEvent.success).toBe(true, 'Second build should succeed.');
expect(logger.includes(staticAnalysisError)).toBe(false,
expect(logs.join().includes(staticAnalysisError)).toBe(false,
'Second build should not have static analysis error.');
logger.clear();
logs = [];
// Add an syntax error to a non-main file.
host.appendToFile('src/app/app.component.ts', `]]]`);
break;
@ -386,11 +390,11 @@ describe('Browser Builder rebuilds', () => {
case 3:
// The third build should have TS syntax error.
expect(buildEvent.success).toBe(false, 'Third build should not succeed.');
expect(logger.includes(syntaxError)).toBe(true,
expect(logs.join().includes(syntaxError)).toBe(true,
'Third build should have syntax analysis error.');
expect(logger.includes(staticAnalysisError)).toBe(false,
expect(logs.join().includes(staticAnalysisError)).toBe(false,
'Third build should not have static analysis error.');
logger.clear();
logs = [];
// Fix the syntax error, but add the static analysis error again.
host.writeMultipleFiles({
'src/app/app.component.ts': origContent.replace(
@ -402,11 +406,11 @@ describe('Browser Builder rebuilds', () => {
case 4:
expect(buildEvent.success).toBe(false, 'Fourth build should not succeed.');
expect(logger.includes(syntaxError)).toBe(false,
expect(logs.join().includes(syntaxError)).toBe(false,
'Fourth build should not have syntax analysis error.');
expect(logger.includes(staticAnalysisError)).toBe(true,
expect(logs.join().includes(staticAnalysisError)).toBe(true,
'Fourth build should have static analysis error.');
logger.clear();
logs = [];
// Restore the file to a error-less state.
host.writeMultipleFiles({ 'src/app/app.component.ts': origContent });
break;
@ -414,9 +418,9 @@ describe('Browser Builder rebuilds', () => {
case 5:
// The fifth build should have everything fixed..
expect(buildEvent.success).toBe(true, 'Fifth build should succeed.');
expect(logger.includes(syntaxError)).toBe(false,
expect(logs.join().includes(syntaxError)).toBe(false,
'Fifth build should not have syntax analysis error.');
expect(logger.includes(staticAnalysisError)).toBe(false,
expect(logs.join().includes(staticAnalysisError)).toBe(false,
'Fifth build should not have static analysis error.');
break;
}

View File

@ -7,8 +7,7 @@
*/
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { normalize, virtualFs } from '@angular-devkit/core';
import { logging, normalize, virtualFs } from '@angular-devkit/core';
import { of, race } from 'rxjs';
import { delay, filter, map, take, takeUntil, takeWhile, tap, timeout } from 'rxjs/operators';
import { browserBuild, createArchitect, host } from '../../test-utils';
@ -179,7 +178,8 @@ describe('Browser Builder file replacements', () => {
const unexpectedError = `Property 'two' does not exist on type '{ one: number; }'`;
const expectedError = `Property 'prop' does not exist on type '{}'`;
const logger = new TestLogger('rebuild-type-errors');
const logger = new logging.Logger('');
// Race between a timeout and the expected log entry.
const stop$ = race<null | string>(

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { BrowserBuilderOutput } from '@angular-devkit/build-angular';
import { logging } from '@angular-devkit/core';
import { debounceTime, take, tap } from 'rxjs/operators';
import { createArchitect, host, veEnabled } from '../../test-utils';
@ -32,12 +32,14 @@ describe('Browser Builder unused files warnings', () => {
return;
}
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const run = await architect.scheduleTarget(targetSpec, undefined, { logger });
const output = await run.result as BrowserBuilderOutput;
expect(output.success).toBe(true);
expect(logger.includes(warningMessageSuffix)).toBe(false);
logger.clear();
expect(logs.join().includes(warningMessageSuffix)).toBe(false);
await run.stop();
});
@ -56,12 +58,14 @@ describe('Browser Builder unused files warnings', () => {
'"main.ts", "environments/environment.prod.ts"',
);
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const run = await architect.scheduleTarget(targetSpec, undefined, { logger });
const output = await run.result as BrowserBuilderOutput;
expect(output.success).toBe(true);
expect(logger.includes(`environment.prod.ts ${warningMessageSuffix}`)).toBe(true);
logger.clear();
expect(logs.join().includes(`environment.prod.ts ${warningMessageSuffix}`)).toBe(true);
await run.stop();
});
@ -90,12 +94,14 @@ describe('Browser Builder unused files warnings', () => {
`"main.ts", ${Object.keys(ignoredFiles).map(f => `"${f.replace('src/', '')}"`).join(',')}`,
);
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const run = await architect.scheduleTarget(targetSpec, undefined, { logger });
const output = await run.result as BrowserBuilderOutput;
expect(output.success).toBe(true);
expect(logger.includes(warningMessageSuffix)).toBe(false);
logger.clear();
expect(logs.join().includes(warningMessageSuffix)).toBe(false);
await run.stop();
});
@ -118,12 +124,14 @@ describe('Browser Builder unused files warnings', () => {
`'@angular/core';\nimport { MyType } from './type';\n`,
);
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const run = await architect.scheduleTarget(targetSpec, undefined, { logger });
const output = await run.result as BrowserBuilderOutput;
expect(output.success).toBe(true);
expect(logger.includes(warningMessageSuffix)).toBe(false);
logger.clear();
expect(logs.join().includes(warningMessageSuffix)).toBe(false);
await run.stop();
});
@ -148,12 +156,14 @@ describe('Browser Builder unused files warnings', () => {
`'@angular/core';\nimport { MyType } from './type';\n`,
);
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const run = await architect.scheduleTarget(targetSpec, undefined, { logger });
const output = await run.result as BrowserBuilderOutput;
expect(output.success).toBe(true);
expect(logger.includes(warningMessageSuffix)).toBe(false);
logger.clear();
expect(logs.join().includes(warningMessageSuffix)).toBe(false);
await run.stop();
});
@ -172,7 +182,10 @@ describe('Browser Builder unused files warnings', () => {
'"**/*.d.ts", "testing/**/*.ts"',
);
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
let logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
let buildNumber = 0;
const run = await architect.scheduleTarget(targetSpec, { watch: true }, { logger });
@ -186,7 +199,7 @@ describe('Browser Builder unused files warnings', () => {
switch (buildNumber) {
case 1:
// The first should not have unused files
expect(logger.includes(warningMessageSuffix)).toBe(false, `Case ${buildNumber} failed.`);
expect(logs.join().includes(warningMessageSuffix)).toBe(false, `Case ${buildNumber} failed.`);
// Write a used file
host.writeMultipleFiles({
@ -203,7 +216,7 @@ describe('Browser Builder unused files warnings', () => {
case 2:
// The second should have type.ts as unused
expect(logger.includes(`type.ts ${warningMessageSuffix}`)).toBe(true, `Case ${buildNumber} failed.`);
expect(logs.join().includes(`type.ts ${warningMessageSuffix}`)).toBe(true, `Case ${buildNumber} failed.`);
host.replaceInFile(
'src/app/app.component.ts',
@ -214,11 +227,11 @@ describe('Browser Builder unused files warnings', () => {
case 3:
// The third should not have any unused files
expect(logger.includes(warningMessageSuffix)).toBe(false, `Case ${buildNumber} failed.`);
expect(logs.join().includes(warningMessageSuffix)).toBe(false, `Case ${buildNumber} failed.`);
break;
}
logger.clear();
logs = [];
}),
take(3),
)
@ -245,7 +258,9 @@ describe('Browser Builder unused files warnings', () => {
'src/testing/type.ts': 'export type MyType = number;',
});
const logger = new TestLogger('unused-files-warnings');
const logger = new logging.Logger('');
let logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
let buildNumber = 0;
const run = await architect.scheduleTarget(targetSpec, { watch: true }, { logger });
@ -259,18 +274,18 @@ describe('Browser Builder unused files warnings', () => {
switch (buildNumber) {
case 1:
// The first should have type.ts as unused.
expect(logger.includes(`type.ts ${warningMessageSuffix}`)).toBe(true, `Case ${buildNumber} failed.`);
expect(logs.join().includes(`type.ts ${warningMessageSuffix}`)).toBe(true, `Case ${buildNumber} failed.`);
// touch a file to trigger a rebuild
host.appendToFile('src/main.ts', '');
break;
case 2:
// The second should should have type.ts as unused but shouldn't warn.
expect(logger.includes(warningMessageSuffix)).toBe(false, `Case ${buildNumber} failed.`);
expect(logs.join().includes(warningMessageSuffix)).toBe(false, `Case ${buildNumber} failed.`);
break;
}
logger.clear();
logs = [];
}),
take(2),
)

View File

@ -7,8 +7,7 @@
*/
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { join, virtualFs } from '@angular-devkit/core';
import { join, logging, virtualFs } from '@angular-devkit/core';
import { timer } from 'rxjs';
import { debounceTime, map, switchMap, takeWhile, tap } from 'rxjs/operators';
import { browserBuild, createArchitect, host, outputPath } from '../../test-utils';
@ -87,7 +86,11 @@ describe('Browser Builder Web Worker support', () => {
it('bundles TS worker', async () => {
host.writeMultipleFiles(workerFiles);
const logger = new TestLogger('worker-warnings');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
const overrides = { webWorkerTsConfig: 'src/tsconfig.worker.json' };
await browserBuild(architect, host, target, overrides, { logger });
@ -101,7 +104,7 @@ describe('Browser Builder Web Worker support', () => {
const mainContent = virtualFs.fileBufferToString(
host.scopedSync().read(join(outputPath, 'main.js')));
expect(mainContent).toContain('0.worker.js');
expect(logger.includes('WARNING')).toBe(false, 'Should show no warnings.');
expect(logs.join().includes('WARNING')).toBe(false, 'Should show no warnings.');
});
it('minimizes and hashes worker', async () => {

View File

@ -6,8 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { join, normalize, virtualFs } from '@angular-devkit/core';
import { join, logging, normalize, virtualFs } from '@angular-devkit/core';
import { createArchitect, extractI18nTargetSpec, host } from '../test-utils';
@ -41,21 +40,27 @@ describe('Extract i18n Target', () => {
}, 30000);
it('does not show full build logs', async () => {
const logger = new TestLogger('i18n');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
host.appendToFile('src/app/app.component.html', '<p i18n>i18n test</p>');
const run = await architect.scheduleTarget(extractI18nTargetSpec);
const run = await architect.scheduleTarget(extractI18nTargetSpec, undefined, { logger });
await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));
await run.stop();
expect(logger.includes('Chunk Names')).toBe(false);
expect(logger.includes('[emitted]')).toBe(false);
expect(logs.join().includes('Chunk Names')).toBe(false);
expect(logs.join().includes('[emitted]')).toBe(false);
}, 30000);
it('shows errors', async () => {
const logger = new TestLogger('i18n-errors');
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe(e => logs.push(e.message));
host.appendToFile('src/app/app.component.html',
'<p i18n>Hello world <span i18n>inner</span></p>');
@ -66,7 +71,7 @@ describe('Extract i18n Target', () => {
await run.stop();
const msg = 'Could not mark an element as translatable inside a translatable section';
expect(logger.includes(msg)).toBe(true);
expect(logs.join().includes(msg)).toBe(true);
}, 30000);
it('supports locale', async () => {