Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(language-service): Move diagnostics tests to diagnostics_spec.ts #33158

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 64 additions & 4 deletions packages/language-service/test/diagnostics_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import {MockTypescriptHost} from './test_utils';
* as well.
*/

const EXPRESSION_CASES = '/app/expression-cases.ts';
const NG_FOR_CASES = '/app/ng-for-cases.ts';
const NG_IF_CASES = '/app/ng-if-cases.ts';

describe('diagnostics', () => {
let mockHost: MockTypescriptHost;
let ngHost: TypeScriptServiceHost;
Expand Down Expand Up @@ -57,6 +61,62 @@ describe('diagnostics', () => {
}
});

describe('in expression-cases.ts', () => {
it('should report access to an unknown field', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain(
`Identifier 'foo' is not defined. ` +
`The component declaration, template variable declarations, ` +
`and element references do not contain such a member`);
});

it('should report access to an unknown sub-field', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain(
`Identifier 'nam' is not defined. 'Person' does not contain such a member`);
});

it('should report access to a private member', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain(`Identifier 'myField' refers to a private member of the component`);
});

it('should report numeric operator errors', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain('Expected a numeric type');
});
});

describe('in ng-for-cases.ts', () => {
it('should report an unknown field', () => {
const diags = ngLS.getDiagnostics(NG_FOR_CASES).map(d => d.messageText);
expect(diags).toContain(
`Identifier 'people_1' is not defined. ` +
`The component declaration, template variable declarations, ` +
`and element references do not contain such a member`);
});

it('should report an unknown context reference', () => {
const diags = ngLS.getDiagnostics(NG_FOR_CASES).map(d => d.messageText);
expect(diags).toContain(`The template context does not define a member called 'even_1'`);
});

it('should report an unknown value in a key expression', () => {
const diags = ngLS.getDiagnostics(NG_FOR_CASES).map(d => d.messageText);
expect(diags).toContain(
`Identifier 'trackBy_1' is not defined. ` +
`The component declaration, template variable declarations, ` +
`and element references do not contain such a member`);
});
});

describe('in ng-if-cases.ts', () => {
it('should report an implicit context reference', () => {
const diags = ngLS.getDiagnostics(NG_IF_CASES).map(d => d.messageText);
expect(diags).toContain(`The template context does not define a member called 'unknown'`);
});
});

// #17611
it('should not report diagnostic on iteration of any', () => {
const fileName = '/app/test.ng';
Expand Down Expand Up @@ -487,7 +547,7 @@ describe('diagnostics', () => {
describe('templates', () => {
it('should report errors for invalid templateUrls', () => {
const fileName = mockHost.addCode(`
@Component({
@Component({
templateUrl: '«notAFile»',
})
export class MyComponent {}`);
Expand All @@ -506,10 +566,10 @@ describe('diagnostics', () => {

it('should not report errors for valid templateUrls', () => {
const fileName = mockHost.addCode(`
@Component({
@Component({
templateUrl: './test.ng',
})
export class MyComponent {}`);
})
export class MyComponent {}`);

const diagnostics = ngLS.getDiagnostics(fileName) !;
const urlDiagnostic =
Expand Down
30 changes: 20 additions & 10 deletions packages/language-service/test/language_service_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,31 @@ import {TypeScriptServiceHost} from '../src/typescript_host';
import {MockTypescriptHost} from './test_utils';

describe('service without angular', () => {
let mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
mockHost.forgetAngular();
let service = ts.createLanguageService(mockHost);
let ngHost = new TypeScriptServiceHost(mockHost, service);
let ngService = createLanguageService(ngHost);
const mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
const service = ts.createLanguageService(mockHost);
const ngHost = new TypeScriptServiceHost(mockHost, service);
const ngService = createLanguageService(ngHost);
const fileName = '/app/test.ng';
const position = mockHost.getLocationMarkerFor(fileName, 'h1-content').start;

beforeEach(() => { mockHost.reset(); });

it('should not crash a get template references',
() => expect(() => ngService.getTemplateReferences()));
() => { expect(() => ngService.getTemplateReferences()).not.toThrow(); });
it('should not crash a get diagnostics',
() => expect(() => ngService.getDiagnostics(fileName)).not.toThrow());
() => { expect(() => ngService.getDiagnostics(fileName)).not.toThrow(); });

it('should not crash a completion',
() => expect(() => ngService.getCompletionsAt(fileName, position)).not.toThrow());
() => { expect(() => ngService.getCompletionsAt(fileName, position)).not.toThrow(); });

it('should not crash a get definition',
() => expect(() => ngService.getDefinitionAt(fileName, position)).not.toThrow());
it('should not crash a hover', () => expect(() => ngService.getHoverAt(fileName, position)));
() => { expect(() => ngService.getDefinitionAt(fileName, position)).not.toThrow(); });

it('should not crash a hover',
() => { expect(() => ngService.getHoverAt(fileName, position)).not.toThrow(); });

it('should not crash with an incomplete class', () => {
mockHost.addCode('\nexport class');
expect(() => ngHost.getAnalyzedModules()).not.toThrow();
});
});
60 changes: 0 additions & 60 deletions packages/language-service/test/ts_plugin_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,51 +139,6 @@ describe('plugin', () => {
});

describe('for semantic errors', () => {
it('should report access to an unknown field', () => {
expectSemanticError(
'/app/expression-cases.ts', 'foo',
'Identifier \'foo\' is not defined. The component declaration, template variable declarations, and element references do not contain such a member');
});
it('should report access to an unknown sub-field', () => {
expectSemanticError(
'/app/expression-cases.ts', 'nam',
'Identifier \'nam\' is not defined. \'Person\' does not contain such a member');
});
it('should report access to a private member', () => {
expectSemanticError(
'/app/expression-cases.ts', 'myField',
'Identifier \'myField\' refers to a private member of the component');
});
it('should report numeric operator errors', () => {
expectSemanticError('/app/expression-cases.ts', 'mod', 'Expected a numeric type');
});
describe('in ngFor', () => {
function expectError(locationMarker: string, message: string) {
expectSemanticError('/app/ng-for-cases.ts', locationMarker, message);
}
it('should report an unknown field', () => {
expectError(
'people_1',
'Identifier \'people_1\' is not defined. The component declaration, template variable declarations, and element references do not contain such a member');
});
it('should report an unknown context reference', () => {
expectError('even_1', `The template context does not define a member called 'even_1'`);
});
it('should report an unknown value in a key expression', () => {
expectError(
'trackBy_1',
'Identifier \'trackBy_1\' is not defined. The component declaration, template variable declarations, and element references do not contain such a member');
});
});
describe('in ngIf', () => {
function expectError(locationMarker: string, message: string) {
expectSemanticError('/app/ng-if-cases.ts', locationMarker, message);
}
it('should report an implicit context reference', () => {
expectError('implicit', `The template context does not define a member called 'unknown'`);
});
});

describe(`with config 'angularOnly = true`, () => {
const ngLS = createPlugin(service, mockHost, {angularOnly: true});
it('should not report template errors on TOH', () => {
Expand Down Expand Up @@ -236,21 +191,6 @@ describe('plugin', () => {
locationMarker, plugin.getCompletionsAtPosition(fileName, marker.start, undefined) !,
...names);
}

function expectSemanticError(fileName: string, locationMarker: string, message: string) {
const marker = mockHost.getLocationMarkerFor(fileName, locationMarker);
const errors = plugin.getSemanticDiagnostics(fileName);
for (const error of errors) {
if (error.messageText.toString().indexOf(message) >= 0) {
expect(error.start).toEqual(marker.start);
expect(error.length).toEqual(marker.length);
return;
}
}
throw new Error(`Expected error messages to contain ${message}, in messages:\n ${errors
.map(e => e.messageText.toString())
.join(',\n ')}`);
}
});


Expand Down