refactor(compiler-cli): don't use FakeEnvironment for tcb tests (#41043)

For the tests in //packages/compiler-cli/src/ngtsc/typecheck, this
commits uses a `TypeCheckFile` for the environment, rather than a
`FakeEnvironment`. Using a real environment gives us more flexibility
with testing.

PR Close #41043
This commit is contained in:
Zach Arend 2021-02-24 14:21:59 -08:00 committed by Misko Hevery
parent 02e8901d9e
commit c267c680d8
6 changed files with 96 additions and 63 deletions

View File

@ -385,7 +385,8 @@ export class TypeCheckContextImpl implements TypeCheckContext {
path: pendingShimData.file.fileName, path: pendingShimData.file.fileName,
templates: pendingShimData.templates, templates: pendingShimData.templates,
}); });
updates.set(pendingShimData.file.fileName, pendingShimData.file.render()); updates.set(
pendingShimData.file.fileName, pendingShimData.file.render(false /* removeComments */));
} }
} }

View File

@ -49,12 +49,12 @@ export class TypeCheckFile extends Environment {
this.tcbStatements.push(fn); this.tcbStatements.push(fn);
} }
render(): string { render(removeComments: boolean): string {
let source: string = this.importManager.getAllImports(this.contextFile.fileName) let source: string = this.importManager.getAllImports(this.contextFile.fileName)
.map(i => `import * as ${i.qualifier.text} from '${i.specifier}';`) .map(i => `import * as ${i.qualifier.text} from '${i.specifier}';`)
.join('\n') + .join('\n') +
'\n\n'; '\n\n';
const printer = ts.createPrinter(); const printer = ts.createPrinter({removeComments});
source += '\n'; source += '\n';
for (const stmt of this.pipeInstStatements) { for (const stmt of this.pipeInstStatements) {
source += printer.printNode(ts.EmitHint.Unspecified, stmt, this.contextFile) + '\n'; source += printer.printNode(ts.EmitHint.Unspecified, stmt, this.contextFile) + '\n';

View File

@ -6,9 +6,12 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {initMockFileSystem} from '../../file_system/testing';
import {tcb, TestDeclaration} from './test_utils'; import {tcb, TestDeclaration} from './test_utils';
describe('type check blocks diagnostics', () => { describe('type check blocks diagnostics', () => {
beforeEach(() => initMockFileSystem('Native'));
describe('parse spans', () => { describe('parse spans', () => {
it('should annotate unary ops', () => { it('should annotate unary ops', () => {
expect(tcbWithSpans('{{ -a }}')).toContain('(-((ctx).a /*4,5*/) /*4,5*/) /*3,5*/'); expect(tcbWithSpans('{{ -a }}')).toContain('(-((ctx).a /*4,5*/) /*4,5*/) /*3,5*/');
@ -146,8 +149,9 @@ describe('type check blocks diagnostics', () => {
pipeName: 'test', pipeName: 'test',
}]; }];
const block = tcbWithSpans(TEMPLATE, PIPES); const block = tcbWithSpans(TEMPLATE, PIPES);
expect(block).toContain('var _pipe1: i0.TestPipe = null!');
expect(block).toContain( expect(block).toContain(
'((null as TestPipe).transform /*7,11*/(((ctx).a /*3,4*/) /*3,4*/, ((ctx).b /*12,13*/) /*12,13*/) /*3,13*/);'); '(_pipe1.transform /*7,11*/(((ctx).a /*3,4*/) /*3,4*/, ((ctx).b /*12,13*/) /*12,13*/) /*3,13*/);');
}); });
describe('attaching multiple comments for multiple references', () => { describe('attaching multiple comments for multiple references', () => {

View File

@ -11,7 +11,7 @@ import * as ts from 'typescript';
import {absoluteFrom, AbsoluteFsPath, getSourceFileOrError, LogicalFileSystem} from '../../file_system'; import {absoluteFrom, AbsoluteFsPath, getSourceFileOrError, LogicalFileSystem} from '../../file_system';
import {TestFile} from '../../file_system/testing'; import {TestFile} from '../../file_system/testing';
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, Reexport, Reference, ReferenceEmitter} from '../../imports'; import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, Reexport, Reference, ReferenceEmitter, RelativePathStrategy} from '../../imports';
import {NOOP_INCREMENTAL_BUILD} from '../../incremental'; import {NOOP_INCREMENTAL_BUILD} from '../../incremental';
import {ClassPropertyMapping, CompoundMetadataReader} from '../../metadata'; import {ClassPropertyMapping, CompoundMetadataReader} from '../../metadata';
import {ClassDeclaration, isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection'; import {ClassDeclaration, isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection';
@ -28,6 +28,7 @@ import {Environment} from '../src/environment';
import {OutOfBandDiagnosticRecorder} from '../src/oob'; import {OutOfBandDiagnosticRecorder} from '../src/oob';
import {TypeCheckShimGenerator} from '../src/shim'; import {TypeCheckShimGenerator} from '../src/shim';
import {generateTypeCheckBlock} from '../src/type_check_block'; import {generateTypeCheckBlock} from '../src/type_check_block';
import {TypeCheckFile} from '../src/type_check_file';
export function typescriptLibDts(): TestFile { export function typescriptLibDts(): TestFile {
return { return {
@ -201,6 +202,7 @@ export type TestDirective = Partial<Pick<
coercedInputFields?: string[], restrictedInputFields?: string[], coercedInputFields?: string[], restrictedInputFields?: string[],
stringLiteralInputFields?: string[], undeclaredInputFields?: string[], isGeneric?: boolean; stringLiteralInputFields?: string[], undeclaredInputFields?: string[], isGeneric?: boolean;
}; };
export type TestPipe = { export type TestPipe = {
name: string, name: string,
file?: AbsoluteFsPath, pipeName: string, type: 'pipe', file?: AbsoluteFsPath, pipeName: string, type: 'pipe',
@ -212,9 +214,14 @@ export function tcb(
template: string, declarations: TestDeclaration[] = [], config?: TypeCheckingConfig, template: string, declarations: TestDeclaration[] = [], config?: TypeCheckingConfig,
options?: {emitSpans?: boolean}): string { options?: {emitSpans?: boolean}): string {
const classes = ['Test', ...declarations.map(decl => decl.name)]; const classes = ['Test', ...declarations.map(decl => decl.name)];
const code = classes.map(name => `class ${name}<T extends string> {}`).join('\n'); const code = classes.map(name => `export class ${name}<T extends string> {}`).join('\n');
const sf = ts.createSourceFile('synthetic.ts', code, ts.ScriptTarget.Latest, true); const rootFilePath = absoluteFrom('/synthetic.ts');
const {program, host} = makeProgram([
{name: rootFilePath, contents: code, isRoot: true},
]);
const sf = getSourceFileOrError(program, rootFilePath);
const clazz = getClass(sf, 'Test'); const clazz = getClass(sf, 'Test');
const templateUrl = 'synthetic.html'; const templateUrl = 'synthetic.html';
const {nodes} = parseTemplate(template, templateUrl); const {nodes} = parseTemplate(template, templateUrl);
@ -251,13 +258,25 @@ export function tcb(
emitSpans: false, emitSpans: false,
}; };
const tcb = generateTypeCheckBlock( const fileName = absoluteFrom('/type-check-file.ts');
FakeEnvironment.newFake(config), new Reference(clazz), ts.createIdentifier('Test_TCB'), meta,
new NoopSchemaChecker(), new NoopOobRecorder());
const removeComments = !options.emitSpans; const reflectionHost = new TypeScriptReflectionHost(program.getTypeChecker());
const res = ts.createPrinter({removeComments}).printNode(ts.EmitHint.Unspecified, tcb, sf);
return res.replace(/\s+/g, ' '); const refEmmiter: ReferenceEmitter = new ReferenceEmitter(
[new LocalIdentifierStrategy(), new RelativePathStrategy(reflectionHost)]);
const env = new TypeCheckFile(fileName, config, refEmmiter, reflectionHost, host);
const ref = new Reference(clazz);
const tcb = generateTypeCheckBlock(
env, ref, ts.createIdentifier('Test_TCB'), meta, new NoopSchemaChecker(),
new NoopOobRecorder());
env.addTypeCheckBlock(ref, meta, new NoopSchemaChecker(), new NoopOobRecorder());
const rendered = env.render(!options.emitSpans /* removeComments */);
return rendered.replace(/\s+/g, ' ');
} }
/** /**

View File

@ -6,12 +6,15 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {initMockFileSystem} from '../../file_system/testing';
import {TypeCheckingConfig} from '../api'; import {TypeCheckingConfig} from '../api';
import {ALL_ENABLED_CONFIG, tcb, TestDeclaration, TestDirective} from './test_utils'; import {ALL_ENABLED_CONFIG, tcb, TestDeclaration, TestDirective} from './test_utils';
describe('type check blocks', () => { describe('type check blocks', () => {
beforeEach(() => initMockFileSystem('Native'));
it('should generate a basic block for a binding', () => { it('should generate a basic block for a binding', () => {
expect(tcb('{{hello}} {{world}}')).toContain('"" + (((ctx).hello)) + (((ctx).world));'); expect(tcb('{{hello}} {{world}}')).toContain('"" + (((ctx).hello)) + (((ctx).world));');
}); });
@ -60,7 +63,7 @@ describe('type check blocks', () => {
selector: '[dir]', selector: '[dir]',
inputs: {inputA: 'inputA'}, inputs: {inputA: 'inputA'},
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)).toContain('_t1: DirA = null!; _t1.inputA = ("value");'); expect(tcb(TEMPLATE, DIRECTIVES)).toContain('_t1: i0.DirA = null!; _t1.inputA = ("value");');
}); });
it('should handle multiple bindings to the same property', () => { it('should handle multiple bindings to the same property', () => {
@ -133,9 +136,11 @@ describe('type check blocks', () => {
}, },
isGeneric: true, isGeneric: true,
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) const actual = tcb(TEMPLATE, DIRECTIVES);
.toContain( expect(actual).toContain(
'var _t1 = Dir.ngTypeCtor({ "fieldA": (((ctx).foo)), "fieldB": null as any });'); 'const _ctor1: <T extends string = any>(init: Pick<i0.Dir<T>, "fieldA" | "fieldB">) => i0.Dir<T> = null!;');
expect(actual).toContain(
'var _t1 = _ctor1({ "fieldA": (((ctx).foo)), "fieldB": null as any });');
}); });
it('should handle multiple bindings to the same property', () => { it('should handle multiple bindings to the same property', () => {
@ -183,11 +188,14 @@ describe('type check blocks', () => {
inputs: {input: 'input'}, inputs: {input: 'input'},
isGeneric: true, isGeneric: true,
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( const actual = tcb(TEMPLATE, DIRECTIVES);
'var _t2 = Dir.ngTypeCtor({ "input": (null!) }); ' + expect(actual).toContain(
'var _t1 = _t2; ' + 'const _ctor1: <T extends string = any>(init: Pick<i0.Dir<T>, "input">) => i0.Dir<T> = null!;');
'_t2.input = (_t1);'); expect(actual).toContain(
'var _t2 = _ctor1({ "input": (null!) }); ' +
'var _t1 = _t2; ' +
'_t2.input = (_t1);');
}); });
it('should generate circular references between two directives correctly', () => { it('should generate circular references between two directives correctly', () => {
@ -213,14 +221,16 @@ describe('type check blocks', () => {
isGeneric: true, isGeneric: true,
} }
]; ];
expect(tcb(TEMPLATE, DIRECTIVES)) const actual = tcb(TEMPLATE, DIRECTIVES);
.toContain( expect(actual).toContain(
'var _t4 = DirA.ngTypeCtor({ "inputA": (null!) }); ' + 'const _ctor1: <T extends string = any>(init: Pick<i0.DirA<T>, "inputA">) => i0.DirA<T> = null!; const _ctor2: <T extends string = any>(init: Pick<i0.DirB<T>, "inputB">) => i0.DirB<T> = null!;');
'var _t3 = _t4; ' + expect(actual).toContain(
'var _t2 = DirB.ngTypeCtor({ "inputB": (_t3) }); ' + 'var _t4 = _ctor1({ "inputA": (null!) }); ' +
'var _t1 = _t2; ' + 'var _t3 = _t4; ' +
'_t4.inputA = (_t1); ' + 'var _t2 = _ctor2({ "inputB": (_t3) }); ' +
'_t2.inputB = (_t3);'); 'var _t1 = _t2; ' +
'_t4.inputA = (_t1); ' +
'_t2.inputB = (_t3);');
}); });
it('should handle empty bindings', () => { it('should handle empty bindings', () => {
@ -261,7 +271,7 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t1: typeof Dir.ngAcceptInputType_fieldA = null!; ' + 'var _t1: typeof i0.Dir.ngAcceptInputType_fieldA = null!; ' +
'_t1 = (((ctx).foo));'); '_t1 = (((ctx).foo));');
}); });
}); });
@ -321,11 +331,11 @@ describe('type check blocks', () => {
}, },
]; ];
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).toContain('var _t1: HasInput = null!'); expect(block).toContain('var _t1: i0.HasInput = null!');
expect(block).toContain('_t1.input = (((ctx).value));'); expect(block).toContain('_t1.input = (((ctx).value));');
expect(block).toContain('var _t2: HasOutput = null!'); expect(block).toContain('var _t2: i0.HasOutput = null!');
expect(block).toContain('_t2["output"]'); expect(block).toContain('_t2["output"]');
expect(block).toContain('var _t4: HasReference = null!'); expect(block).toContain('var _t4: i0.HasReference = null!');
expect(block).toContain('var _t3 = _t4;'); expect(block).toContain('var _t3 = _t4;');
expect(block).toContain('(_t3).a'); expect(block).toContain('(_t3).a');
expect(block).not.toContain('NoBindings'); expect(block).not.toContain('NoBindings');
@ -355,7 +365,7 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t2: Dir = null!; ' + 'var _t2: i0.Dir = null!; ' +
'var _t1 = _t2; ' + 'var _t1 = _t2; ' +
'"" + (((_t1).value));'); '"" + (((_t1).value));');
}); });
@ -403,7 +413,7 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t2: Dir = null!; ' + 'var _t2: i0.Dir = null!; ' +
'var _t1 = _t2; ' + 'var _t1 = _t2; ' +
'_t2.input = (_t1);'); '_t2.input = (_t1);');
}); });
@ -431,9 +441,9 @@ describe('type check blocks', () => {
]; ];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t2: DirB = null!; ' + 'var _t2: i0.DirB = null!; ' +
'var _t1 = _t2; ' + 'var _t1 = _t2; ' +
'var _t3: DirA = null!; ' + 'var _t3: i0.DirA = null!; ' +
'_t3.inputA = (_t1); ' + '_t3.inputA = (_t1); ' +
'var _t4 = _t3; ' + 'var _t4 = _t3; ' +
'_t2.inputA = (_t4);'); '_t2.inputA = (_t4);');
@ -468,7 +478,7 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t1: Dir = null!; ' + 'var _t1: i0.Dir = null!; ' +
'var _t2: typeof _t1["fieldA"] = null!; ' + 'var _t2: typeof _t1["fieldA"] = null!; ' +
'_t2 = (((ctx).foo)); '); '_t2 = (((ctx).foo)); ');
}); });
@ -487,7 +497,7 @@ describe('type check blocks', () => {
}]; }];
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).toContain( expect(block).toContain(
'var _t1: Dir = null!; ' + 'var _t1: i0.Dir = null!; ' +
'_t1["some-input.xs"] = (((ctx).foo)); '); '_t1["some-input.xs"] = (((ctx).foo)); ');
}); });
@ -504,7 +514,7 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t1: Dir = null!; ' + 'var _t1: i0.Dir = null!; ' +
'_t1.field2 = _t1.field1 = (((ctx).foo));'); '_t1.field2 = _t1.field1 = (((ctx).foo));');
}); });
@ -523,8 +533,8 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t1: typeof Dir.ngAcceptInputType_field1 = null!; ' + 'var _t1: typeof i0.Dir.ngAcceptInputType_field1 = null!; ' +
'var _t2: Dir = null!; ' + 'var _t2: i0.Dir = null!; ' +
'_t2.field2 = _t1 = (((ctx).foo));'); '_t2.field2 = _t1 = (((ctx).foo));');
}); });
@ -543,7 +553,7 @@ describe('type check blocks', () => {
}]; }];
expect(tcb(TEMPLATE, DIRECTIVES)) expect(tcb(TEMPLATE, DIRECTIVES))
.toContain( .toContain(
'var _t1: Dir = null!; ' + 'var _t1: i0.Dir = null!; ' +
'_t1.field2 = (((ctx).foo));'); '_t1.field2 = (((ctx).foo));');
}); });
@ -561,7 +571,7 @@ describe('type check blocks', () => {
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).not.toContain('var _t1: Dir = null!;'); expect(block).not.toContain('var _t1: Dir = null!;');
expect(block).toContain( expect(block).toContain(
'var _t1: typeof Dir.ngAcceptInputType_fieldA = null!; ' + 'var _t1: typeof i0.Dir.ngAcceptInputType_fieldA = null!; ' +
'_t1 = (((ctx).foo));'); '_t1 = (((ctx).foo));');
}); });
@ -580,7 +590,7 @@ describe('type check blocks', () => {
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).not.toContain('var _t1: Dir = null!;'); expect(block).not.toContain('var _t1: Dir = null!;');
expect(block).toContain( expect(block).toContain(
'var _t1: typeof Dir.ngAcceptInputType_fieldA = null!; ' + 'var _t1: typeof i0.Dir.ngAcceptInputType_fieldA = null!; ' +
'_t1 = (((ctx).foo));'); '_t1 = (((ctx).foo));');
}); });
@ -619,7 +629,7 @@ describe('type check blocks', () => {
}]; }];
const TEMPLATE = `<div *ngIf="person">{{person.name}}</div>`; const TEMPLATE = `<div *ngIf="person">{{person.name}}</div>`;
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).toContain('if (NgIf.ngTemplateGuard_ngIf(_t1, ((ctx).person)))'); expect(block).toContain('if (i0.NgIf.ngTemplateGuard_ngIf(_t1, ((ctx).person)))');
}); });
it('should emit binding guards', () => { it('should emit binding guards', () => {
@ -672,8 +682,7 @@ describe('type check blocks', () => {
it('should emit a listener function with AnimationEvent for animation events', () => { it('should emit a listener function with AnimationEvent for animation events', () => {
const TEMPLATE = `<div (@animation.done)="foo($event)"></div>`; const TEMPLATE = `<div (@animation.done)="foo($event)"></div>`;
const block = tcb(TEMPLATE); const block = tcb(TEMPLATE);
expect(block).toContain( expect(block).toContain('function ($event: i1.AnimationEvent): any { (ctx).foo($event); }');
'function ($event: animations.AnimationEvent): any { (ctx).foo($event); }');
}); });
it('should emit addEventListener calls for unclaimed outputs', () => { it('should emit addEventListener calls for unclaimed outputs', () => {
@ -740,7 +749,7 @@ describe('type check blocks', () => {
describe('config.applyTemplateContextGuards', () => { describe('config.applyTemplateContextGuards', () => {
const TEMPLATE = `<div *dir>{{ value }}</div>`; const TEMPLATE = `<div *dir>{{ value }}</div>`;
const GUARD_APPLIED = 'if (Dir.ngTemplateContextGuard('; const GUARD_APPLIED = 'if (i0.Dir.ngTemplateContextGuard(';
it('should apply template context guards when enabled', () => { it('should apply template context guards when enabled', () => {
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
@ -769,13 +778,13 @@ describe('type check blocks', () => {
it('generates a references var when enabled', () => { it('generates a references var when enabled', () => {
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).toContain('var _t1 = (_t2 as any as core.TemplateRef<any>);'); expect(block).toContain('var _t1 = (_t2 as any as i1.TemplateRef<any>);');
}); });
it('generates a reference var when disabled', () => { it('generates a reference var when disabled', () => {
const DISABLED_CONFIG: TypeCheckingConfig = {...BASE_CONFIG, checkTemplateBodies: false}; const DISABLED_CONFIG: TypeCheckingConfig = {...BASE_CONFIG, checkTemplateBodies: false};
const block = tcb(TEMPLATE, DIRECTIVES, DISABLED_CONFIG); const block = tcb(TEMPLATE, DIRECTIVES, DISABLED_CONFIG);
expect(block).toContain('var _t1 = (_t2 as any as core.TemplateRef<any>);'); expect(block).toContain('var _t1 = (_t2 as any as i1.TemplateRef<any>);');
}); });
}); });
@ -848,8 +857,7 @@ describe('type check blocks', () => {
it('should check types of animation events when enabled', () => { it('should check types of animation events when enabled', () => {
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).toContain( expect(block).toContain('function ($event: i1.AnimationEvent): any { (ctx).foo($event); }');
'function ($event: animations.AnimationEvent): any { (ctx).foo($event); }');
}); });
it('should not check types of animation events when disabled', () => { it('should not check types of animation events when disabled', () => {
const DISABLED_CONFIG: const DISABLED_CONFIG:
@ -919,7 +927,7 @@ describe('type check blocks', () => {
it('should trace references to an <ng-template> when enabled', () => { it('should trace references to an <ng-template> when enabled', () => {
const block = tcb(TEMPLATE, DIRECTIVES); const block = tcb(TEMPLATE, DIRECTIVES);
expect(block).toContain( expect(block).toContain(
'var _t3 = (_t4 as any as core.TemplateRef<any>); ' + 'var _t3 = (_t4 as any as i1.TemplateRef<any>); ' +
'"" + (((_t3).value2));'); '"" + (((_t3).value2));');
}); });
@ -968,13 +976,14 @@ describe('type check blocks', () => {
it('should check types of pipes when enabled', () => { it('should check types of pipes when enabled', () => {
const block = tcb(TEMPLATE, PIPES); const block = tcb(TEMPLATE, PIPES);
expect(block).toContain('(null as TestPipe).transform(((ctx).a), ((ctx).b), ((ctx).c))'); expect(block).toContain('var _pipe1: i0.TestPipe = null!;');
expect(block).toContain('(_pipe1.transform(((ctx).a), ((ctx).b), ((ctx).c)));');
}); });
it('should not check types of pipes when disabled', () => { it('should not check types of pipes when disabled', () => {
const DISABLED_CONFIG: TypeCheckingConfig = {...BASE_CONFIG, checkTypeOfPipes: false}; const DISABLED_CONFIG: TypeCheckingConfig = {...BASE_CONFIG, checkTypeOfPipes: false};
const block = tcb(TEMPLATE, PIPES, DISABLED_CONFIG); const block = tcb(TEMPLATE, PIPES, DISABLED_CONFIG);
expect(block).toContain( expect(block).toContain('var _pipe1: i0.TestPipe = null!;');
'((null as TestPipe) as any).transform(((ctx).a), ((ctx).b), ((ctx).c))'); expect(block).toContain('((_pipe1 as any).transform(((ctx).a), ((ctx).b), ((ctx).c)));');
}); });
}); });
@ -1016,13 +1025,13 @@ describe('type check blocks', () => {
it('should use the generic type of the context when enabled', () => { it('should use the generic type of the context when enabled', () => {
const block = tcb(TEMPLATE); const block = tcb(TEMPLATE);
expect(block).toContain('function Test_TCB<T extends string>(ctx: Test<T>)'); expect(block).toContain('function _tcb1<T extends string>(ctx: i0.Test<T>)');
}); });
it('should use any for the context generic type when disabled', () => { it('should use any for the context generic type when disabled', () => {
const DISABLED_CONFIG: TypeCheckingConfig = {...BASE_CONFIG, useContextGenericType: false}; const DISABLED_CONFIG: TypeCheckingConfig = {...BASE_CONFIG, useContextGenericType: false};
const block = tcb(TEMPLATE, undefined, DISABLED_CONFIG); const block = tcb(TEMPLATE, undefined, DISABLED_CONFIG);
expect(block).toContain('function Test_TCB(ctx: Test<any>)'); expect(block).toContain('function _tcb1(ctx: i0.Test<any>)');
}); });
}); });
@ -1045,7 +1054,7 @@ describe('type check blocks', () => {
TypeCheckingConfig = {...BASE_CONFIG, honorAccessModifiersForInputBindings: true}; TypeCheckingConfig = {...BASE_CONFIG, honorAccessModifiersForInputBindings: true};
const block = tcb(TEMPLATE, DIRECTIVES, enableChecks); const block = tcb(TEMPLATE, DIRECTIVES, enableChecks);
expect(block).toContain( expect(block).toContain(
'var _t1: Dir = null!; ' + 'var _t1: i0.Dir = null!; ' +
'_t1["some-input.xs"] = (((ctx).foo)); '); '_t1["some-input.xs"] = (((ctx).foo)); ');
}); });
@ -1063,7 +1072,7 @@ describe('type check blocks', () => {
TypeCheckingConfig = {...BASE_CONFIG, honorAccessModifiersForInputBindings: true}; TypeCheckingConfig = {...BASE_CONFIG, honorAccessModifiersForInputBindings: true};
const block = tcb(TEMPLATE, DIRECTIVES, enableChecks); const block = tcb(TEMPLATE, DIRECTIVES, enableChecks);
expect(block).toContain( expect(block).toContain(
'var _t1: Dir = null!; ' + 'var _t1: i0.Dir = null!; ' +
'_t1.fieldA = (((ctx).foo)); '); '_t1.fieldA = (((ctx).foo)); ');
}); });
}); });

View File

@ -43,7 +43,7 @@ runInEachFileSystem(() => {
const file = new TypeCheckFile( const file = new TypeCheckFile(
_('/_typecheck_.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([]), _('/_typecheck_.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([]),
/* reflector */ null!, host); /* reflector */ null!, host);
const sf = file.render(); const sf = file.render(false /* removeComments */);
expect(sf).toContain('export const IS_A_MODULE = true;'); expect(sf).toContain('export const IS_A_MODULE = true;');
}); });