test(compiler-cli): re-enable dynamic value diagnostic tests on Windows CI (#37782)

This commit re-enables some tests that were temporarily disabled on Windows,
as they failed on native Windows CI. The Windows filesystem emulation has
been corrected in an earlier commit, such that the original failure would
now also occur during emulation on Linux CI.

PR Close #37782
This commit is contained in:
JoostK 2020-06-26 23:06:36 +02:00 committed by Misko Hevery
parent 1a62f74496
commit 49f27e31ed
2 changed files with 116 additions and 128 deletions

View File

@ -6,27 +6,21 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {platform} from 'os';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {FatalDiagnosticError} from '../../diagnostics'; import {absoluteFrom as _, getSourceFileOrError} from '../../file_system';
import {absoluteFrom as _} from '../../file_system';
import {runInEachFileSystem, TestFile} from '../../file_system/testing'; import {runInEachFileSystem, TestFile} from '../../file_system/testing';
import {PartialEvaluator} from '../../partial_evaluator'; import {PartialEvaluator} from '../../partial_evaluator';
import {TypeScriptReflectionHost} from '../../reflection'; import {TypeScriptReflectionHost} from '../../reflection';
import {getDeclaration, makeProgram} from '../../testing'; import {getDeclaration, makeProgram} from '../../testing';
import {createValueHasWrongTypeError} from '../src/diagnostics'; import {createValueHasWrongTypeError} from '../src/diagnostics';
runInEachFileSystem(os => { runInEachFileSystem(() => {
describe('ngtsc annotation diagnostics', () => { describe('ngtsc annotation diagnostics', () => {
// These tests are currently disabled when running in Windows mode as the assertions involving
// the filename attached to the diagnostic are suffering from a case-sensitivity issue.
//
// TODO(JoostK): re-enable on Windows once the case issue has been solved.
if (os !== 'Windows' && platform() !== 'win32') {
describe('createValueError()', () => { describe('createValueError()', () => {
it('should include a trace for dynamic values', () => { it('should include a trace for dynamic values', () => {
const error = createError('', 'nonexistent', 'Error message'); const {error, program} = createError('', 'nonexistent', 'Error message');
const entrySf = getSourceFileOrError(program, _('/entry.ts'));
if (typeof error.message === 'string') { if (typeof error.message === 'string') {
return fail('Created error must have a message chain'); return fail('Created error must have a message chain');
@ -40,14 +34,15 @@ runInEachFileSystem(os => {
expect(error.relatedInformation!.length).toBe(1); expect(error.relatedInformation!.length).toBe(1);
expect(error.relatedInformation![0].messageText).toBe('Unknown reference.'); expect(error.relatedInformation![0].messageText).toBe('Unknown reference.');
expect(error.relatedInformation![0].file!.fileName).toBe(_('/entry.ts')); expect(error.relatedInformation![0].file!.fileName).toBe(entrySf.fileName);
expect(getSourceCode(error.relatedInformation![0])).toBe('nonexistent'); expect(getSourceCode(error.relatedInformation![0])).toBe('nonexistent');
}); });
it('should include a pointer for a reference to a named declaration', () => { it('should include a pointer for a reference to a named declaration', () => {
const error = createError( const {error, program} = createError(
`import {Foo} from './foo';`, 'Foo', 'Error message', `import {Foo} from './foo';`, 'Foo', 'Error message',
[{name: _('/foo.ts'), contents: 'export class Foo {}'}]); [{name: _('/foo.ts'), contents: 'export class Foo {}'}]);
const fooSf = getSourceFileOrError(program, _('/foo.ts'));
if (typeof error.message === 'string') { if (typeof error.message === 'string') {
return fail('Created error must have a message chain'); return fail('Created error must have a message chain');
@ -59,14 +54,15 @@ runInEachFileSystem(os => {
expect(error.relatedInformation).toBeDefined(); expect(error.relatedInformation).toBeDefined();
expect(error.relatedInformation!.length).toBe(1); expect(error.relatedInformation!.length).toBe(1);
expect(error.relatedInformation![0].messageText).toBe('Reference is declared here.'); expect(error.relatedInformation![0].messageText).toBe('Reference is declared here.');
expect(error.relatedInformation![0].file!.fileName).toBe(_('/foo.ts')); expect(error.relatedInformation![0].file!.fileName).toBe(fooSf.fileName);
expect(getSourceCode(error.relatedInformation![0])).toBe('Foo'); expect(getSourceCode(error.relatedInformation![0])).toBe('Foo');
}); });
it('should include a pointer for a reference to an anonymous declaration', () => { it('should include a pointer for a reference to an anonymous declaration', () => {
const error = createError( const {error, program} = createError(
`import Foo from './foo';`, 'Foo', 'Error message', `import Foo from './foo';`, 'Foo', 'Error message',
[{name: _('/foo.ts'), contents: 'export default class {}'}]); [{name: _('/foo.ts'), contents: 'export default class {}'}]);
const fooSf = getSourceFileOrError(program, _('/foo.ts'));
if (typeof error.message === 'string') { if (typeof error.message === 'string') {
return fail('Created error must have a message chain'); return fail('Created error must have a message chain');
@ -79,12 +75,12 @@ runInEachFileSystem(os => {
expect(error.relatedInformation).toBeDefined(); expect(error.relatedInformation).toBeDefined();
expect(error.relatedInformation!.length).toBe(1); expect(error.relatedInformation!.length).toBe(1);
expect(error.relatedInformation![0].messageText).toBe('Reference is declared here.'); expect(error.relatedInformation![0].messageText).toBe('Reference is declared here.');
expect(error.relatedInformation![0].file!.fileName).toBe(_('/foo.ts')); expect(error.relatedInformation![0].file!.fileName).toBe(fooSf.fileName);
expect(getSourceCode(error.relatedInformation![0])).toBe('export default class {}'); expect(getSourceCode(error.relatedInformation![0])).toBe('export default class {}');
}); });
it('should include a representation of the value\'s type', () => { it('should include a representation of the value\'s type', () => {
const error = createError('', '{a: 2}', 'Error message'); const {error} = createError('', '{a: 2}', 'Error message');
if (typeof error.message === 'string') { if (typeof error.message === 'string') {
return fail('Created error must have a message chain'); return fail('Created error must have a message chain');
@ -96,9 +92,6 @@ runInEachFileSystem(os => {
expect(error.relatedInformation).not.toBeDefined(); expect(error.relatedInformation).not.toBeDefined();
}); });
}); });
}
it('should not be empty', () => {});
}); });
}); });
@ -108,8 +101,7 @@ function getSourceCode(diag: ts.DiagnosticRelatedInformation): string {
} }
function createError( function createError(
code: string, expr: string, messageText: string, code: string, expr: string, messageText: string, supportingFiles: TestFile[] = []) {
supportingFiles: TestFile[] = []): FatalDiagnosticError {
const {program} = makeProgram( const {program} = makeProgram(
[{name: _('/entry.ts'), contents: `${code}; const target$ = ${expr}`}, ...supportingFiles], [{name: _('/entry.ts'), contents: `${code}; const target$ = ${expr}`}, ...supportingFiles],
/* options */ undefined, /* host */ undefined, /* checkForErrors */ false); /* options */ undefined, /* host */ undefined, /* checkForErrors */ false);
@ -121,5 +113,6 @@ function createError(
const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null); const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null);
const value = evaluator.evaluate(valueExpr); const value = evaluator.evaluate(valueExpr);
return createValueHasWrongTypeError(valueExpr, value, messageText); const error = createValueHasWrongTypeError(valueExpr, value, messageText);
return {error, program};
} }

View File

@ -6,8 +6,6 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {platform} from 'os';
import {ErrorCode, ngErrorCode} from '../../diagnostics'; import {ErrorCode, ngErrorCode} from '../../diagnostics';
import {absoluteFrom, absoluteFromSourceFile, getSourceFileOrError} from '../../file_system'; import {absoluteFrom, absoluteFromSourceFile, getSourceFileOrError} from '../../file_system';
import {runInEachFileSystem} from '../../file_system/testing'; import {runInEachFileSystem} from '../../file_system/testing';
@ -15,7 +13,7 @@ import {OptimizeFor} from '../api';
import {getClass, setup, TestDeclaration} from './test_utils'; import {getClass, setup, TestDeclaration} from './test_utils';
runInEachFileSystem(os => { runInEachFileSystem(() => {
describe('TemplateTypeChecker', () => { describe('TemplateTypeChecker', () => {
it('should batch diagnostic operations when requested in WholeProgram mode', () => { it('should batch diagnostic operations when requested in WholeProgram mode', () => {
const file1 = absoluteFrom('/file1.ts'); const file1 = absoluteFrom('/file1.ts');
@ -172,9 +170,6 @@ runInEachFileSystem(os => {
expect(diags[0].code).toBe(ngErrorCode(ErrorCode.INLINE_TCB_REQUIRED)); expect(diags[0].code).toBe(ngErrorCode(ErrorCode.INLINE_TCB_REQUIRED));
}); });
// These tests are currently disabled when running in Windows mode as the assertions involving
// the filename attached to the diagnostic are suffering from a case-sensitivity issue.
if (os !== 'Windows' && platform() !== 'win32') {
it('should produce errors for components that require type constructor inlining', () => { it('should produce errors for components that require type constructor inlining', () => {
const fileName = absoluteFrom('/main.ts'); const fileName = absoluteFrom('/main.ts');
const dirFile = absoluteFrom('/dir.ts'); const dirFile = absoluteFrom('/dir.ts');
@ -198,7 +193,7 @@ runInEachFileSystem(os => {
// A non-exported interface used as a type bound for a generic directive causes // A non-exported interface used as a type bound for a generic directive causes
// an inline type constructor to be required. // an inline type constructor to be required.
interface NotExported {} interface NotExported {}
export abstract class TestDir<T extends NotExported> {}`, export class TestDir<T extends NotExported> {}`,
templates: {}, templates: {},
} }
], ],
@ -210,12 +205,12 @@ runInEachFileSystem(os => {
// The relatedInformation of the diagnostic should point to the directive which required // The relatedInformation of the diagnostic should point to the directive which required
// the inline type constructor. // the inline type constructor.
const dirSf = getSourceFileOrError(program, dirFile);
expect(diags[0].relatedInformation).not.toBeUndefined(); expect(diags[0].relatedInformation).not.toBeUndefined();
expect(diags[0].relatedInformation!.length).toBe(1); expect(diags[0].relatedInformation!.length).toBe(1);
expect(diags[0].relatedInformation![0].file).not.toBeUndefined(); expect(diags[0].relatedInformation![0].file).not.toBeUndefined();
expect(absoluteFromSourceFile(diags[0].relatedInformation![0].file!)).toBe(dirFile); expect(absoluteFromSourceFile(diags[0].relatedInformation![0].file!)).toBe(dirSf.fileName);
}); });
}
}); });
describe('template overrides', () => { describe('template overrides', () => {