test(language-service): wrap setup() in beforeAll to speed up fit() test (#39305)

Test harness `setup()` is expensive, in the order of ~2.5 seconds.

We could speed up `fit()` tests considerably if `setup()` is wrapped
in `beforeAll()` to avoid running it unnecessarily.

PR Close #39305
This commit is contained in:
Keen Yee Liau 2020-10-16 11:21:24 -07:00 committed by Andrew Kushnir
parent 563fb6cdbe
commit 0c01c4a898
8 changed files with 160 additions and 98 deletions

View File

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {APP_COMPONENT, setup, TEST_TEMPLATE} from './mock_host';
import * as ts from 'typescript/lib/tsserverlibrary';
const {project, service} = setup();
import {APP_COMPONENT, MockService, setup, TEST_TEMPLATE} from './mock_host';
/**
* The following specs do not directly test the CompilerFactory class, rather
@ -17,6 +17,15 @@ const {project, service} = setup();
*/
describe('tsserver', () => {
let project: ts.server.Project;
let service: MockService;
beforeAll(() => {
const {project: _project, service: _service} = setup();
project = _project;
service = _service;
});
beforeEach(() => {
service.reset();
});

View File

@ -6,16 +6,20 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript/lib/tsserverlibrary';
import {LanguageService} from '../language_service';
import {APP_COMPONENT, setup} from './mock_host';
import {APP_COMPONENT, MockService, setup} from './mock_host';
import {humanizeDefinitionInfo} from './test_utils';
describe('definitions', () => {
const {project, service, tsLS} = setup();
const ngLS = new LanguageService(project, tsLS);
let service: MockService;
let ngLS: LanguageService;
beforeAll(() => {
const {project, service: _service, tsLS} = setup();
service = _service;
ngLS = new LanguageService(project, tsLS);
});
beforeEach(() => {
service.reset();

View File

@ -10,11 +10,17 @@ import * as ts from 'typescript/lib/tsserverlibrary';
import {LanguageService} from '../language_service';
import {APP_COMPONENT, setup, TEST_TEMPLATE} from './mock_host';
import {APP_COMPONENT, MockService, setup, TEST_TEMPLATE} from './mock_host';
describe('getSemanticDiagnostics', () => {
const {project, service, tsLS} = setup();
const ngLS = new LanguageService(project, tsLS);
let service: MockService;
let ngLS: LanguageService;
beforeAll(() => {
const {project, service: _service, tsLS} = setup();
service = _service;
ngLS = new LanguageService(project, tsLS);
});
beforeEach(() => {
service.reset();

View File

@ -6,12 +6,22 @@
* found in the LICENSE file at https://angular.io/license
*/
import {LanguageServiceAdapter} from '../language_service_adapter';
import {setup, TEST_TEMPLATE} from './mock_host';
import * as ts from 'typescript/lib/tsserverlibrary';
const {project, service} = setup();
import {LanguageServiceAdapter} from '../language_service_adapter';
import {MockService, setup, TEST_TEMPLATE} from './mock_host';
describe('Language service adapter', () => {
let project: ts.server.Project;
let service: MockService;
beforeAll(() => {
const {project: _project, service: _service} = setup();
project = _project;
service = _service;
});
it('should mark template dirty if it has not seen the template before', () => {
const adapter = new LanguageServiceAdapter(project);
expect(adapter.isTemplateDirty(TEST_TEMPLATE)).toBeTrue();

View File

@ -6,102 +6,113 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript/lib/tsserverlibrary';
import {LanguageService, parseNgCompilerOptions} from '../language_service';
import {setup, TEST_TEMPLATE} from './mock_host';
import {MockService, setup, TEST_TEMPLATE} from './mock_host';
const {project, tsLS, service} = setup();
describe('language service adapter', () => {
let project: ts.server.Project;
let service: MockService;
let ngLS: LanguageService;
describe('parseNgCompilerOptions', () => {
it('should read angularCompilerOptions in tsconfig.json', () => {
const options = parseNgCompilerOptions(project);
expect(options).toEqual(jasmine.objectContaining({
enableIvy: true, // default for ivy is true
strictTemplates: true,
strictInjectionParameters: true,
}));
});
});
describe('last known program', () => {
const ngLS = new LanguageService(project, tsLS);
beforeEach(() => {
service.reset();
beforeAll(() => {
const {project: _project, tsLS, service: _service} = setup();
project = _project;
service = _service;
ngLS = new LanguageService(project, tsLS);
});
it('should be set after getSemanticDiagnostics()', () => {
const d0 = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(d0.length).toBe(0);
const p0 = getLastKnownProgram(ngLS);
const d1 = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(d1.length).toBe(0);
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
const d2 = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(d2.length).toBe(0);
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
describe('parseNgCompilerOptions', () => {
it('should read angularCompilerOptions in tsconfig.json', () => {
const options = parseNgCompilerOptions(project);
expect(options).toEqual(jasmine.objectContaining({
enableIvy: true, // default for ivy is true
strictTemplates: true,
strictInjectionParameters: true,
}));
});
});
it('should be set after getDefinitionAndBoundSpan()', () => {
const {position: pos0} = service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
describe('last known program', () => {
beforeEach(() => {
service.reset();
});
const d0 = ngLS.getDefinitionAndBoundSpan(TEST_TEMPLATE, pos0);
expect(d0).toBeDefined();
const p0 = getLastKnownProgram(ngLS);
it('should be set after getSemanticDiagnostics()', () => {
const d0 = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(d0.length).toBe(0);
const p0 = getLastKnownProgram(ngLS);
const d1 = ngLS.getDefinitionAndBoundSpan(TEST_TEMPLATE, pos0);
expect(d1).toBeDefined();
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const d1 = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(d1.length).toBe(0);
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const {position: pos1} = service.overwrite(TEST_TEMPLATE, `{{ ti¦tle }}`);
const d2 = ngLS.getDefinitionAndBoundSpan(TEST_TEMPLATE, pos1);
expect(d2).toBeDefined();
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
});
service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
const d2 = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(d2.length).toBe(0);
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
});
it('should be set after getQuickInfoAtPosition()', () => {
const {position: pos0} = service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
it('should be set after getDefinitionAndBoundSpan()', () => {
const {position: pos0} = service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
const q0 = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, pos0);
expect(q0).toBeDefined();
const p0 = getLastKnownProgram(ngLS);
const d0 = ngLS.getDefinitionAndBoundSpan(TEST_TEMPLATE, pos0);
expect(d0).toBeDefined();
const p0 = getLastKnownProgram(ngLS);
const q1 = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, pos0);
expect(q1).toBeDefined();
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const d1 = ngLS.getDefinitionAndBoundSpan(TEST_TEMPLATE, pos0);
expect(d1).toBeDefined();
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const {position: pos1} = service.overwrite(TEST_TEMPLATE, `{{ ti¦tle }}`);
const q2 = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, pos1);
expect(q2).toBeDefined();
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
});
const {position: pos1} = service.overwrite(TEST_TEMPLATE, `{{ ti¦tle }}`);
const d2 = ngLS.getDefinitionAndBoundSpan(TEST_TEMPLATE, pos1);
expect(d2).toBeDefined();
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
});
it('should be set after getTypeDefinitionAtPosition()', () => {
const {position: pos0} = service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
it('should be set after getQuickInfoAtPosition()', () => {
const {position: pos0} = service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
const q0 = ngLS.getTypeDefinitionAtPosition(TEST_TEMPLATE, pos0);
expect(q0).toBeDefined();
const p0 = getLastKnownProgram(ngLS);
const q0 = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, pos0);
expect(q0).toBeDefined();
const p0 = getLastKnownProgram(ngLS);
const d1 = ngLS.getTypeDefinitionAtPosition(TEST_TEMPLATE, pos0);
expect(d1).toBeDefined();
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const q1 = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, pos0);
expect(q1).toBeDefined();
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const {position: pos1} = service.overwrite(TEST_TEMPLATE, `{{ ti¦tle }}`);
const d2 = ngLS.getTypeDefinitionAtPosition(TEST_TEMPLATE, pos1);
expect(d2).toBeDefined();
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
const {position: pos1} = service.overwrite(TEST_TEMPLATE, `{{ ti¦tle }}`);
const q2 = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, pos1);
expect(q2).toBeDefined();
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
});
it('should be set after getTypeDefinitionAtPosition()', () => {
const {position: pos0} = service.overwrite(TEST_TEMPLATE, `<test-c¦omp></test-comp>`);
const q0 = ngLS.getTypeDefinitionAtPosition(TEST_TEMPLATE, pos0);
expect(q0).toBeDefined();
const p0 = getLastKnownProgram(ngLS);
const d1 = ngLS.getTypeDefinitionAtPosition(TEST_TEMPLATE, pos0);
expect(d1).toBeDefined();
const p1 = getLastKnownProgram(ngLS);
expect(p1).toBe(p0); // last known program should not have changed
const {position: pos1} = service.overwrite(TEST_TEMPLATE, `{{ ti¦tle }}`);
const d2 = ngLS.getTypeDefinitionAtPosition(TEST_TEMPLATE, pos1);
expect(d2).toBeDefined();
const p2 = getLastKnownProgram(ngLS);
expect(p2).not.toBe(p1); // last known program should have changed
});
});
});

View File

@ -8,10 +8,19 @@
import * as ts from 'typescript/lib/tsserverlibrary';
import {APP_COMPONENT, APP_MAIN, setup, TEST_SRCDIR} from './mock_host';
import {APP_COMPONENT, APP_MAIN, MockService, setup, TEST_SRCDIR} from './mock_host';
describe('mock host', () => {
const {project, service, tsLS} = setup();
let service: MockService;
let project: ts.server.Project;
let tsLS: ts.LanguageService;
beforeAll(() => {
const {project: _project, service: _service, tsLS: _tsLS} = setup();
project = _project;
service = _service;
tsLS = _tsLS;
});
beforeEach(() => {
service.reset();

View File

@ -10,11 +10,17 @@ import * as ts from 'typescript/lib/tsserverlibrary';
import {LanguageService} from '../language_service';
import {APP_COMPONENT, setup, TEST_TEMPLATE} from './mock_host';
import {APP_COMPONENT, MockService, setup, TEST_TEMPLATE} from './mock_host';
describe('quick info', () => {
const {project, service, tsLS} = setup();
const ngLS = new LanguageService(project, tsLS);
let service: MockService;
let ngLS: LanguageService;
beforeAll(() => {
const {project, service: _service, tsLS} = setup();
service = _service;
ngLS = new LanguageService(project, tsLS);
});
beforeEach(() => {
service.reset();

View File

@ -8,12 +8,19 @@
import {LanguageService} from '../language_service';
import {APP_COMPONENT, setup} from './mock_host';
import {APP_COMPONENT, MockService, setup} from './mock_host';
import {HumanizedDefinitionInfo, humanizeDefinitionInfo} from './test_utils';
describe('type definitions', () => {
const {project, service, tsLS} = setup();
const ngLS = new LanguageService(project, tsLS);
let service: MockService;
let ngLS: LanguageService;
beforeAll(() => {
const {project, service: _service, tsLS} = setup();
service = _service;
ngLS = new LanguageService(project, tsLS);
});
const possibleArrayDefFiles = new Set([
'lib.es5.d.ts', 'lib.es2015.core.d.ts', 'lib.es2015.iterable.d.ts',
'lib.es2015.symbol.wellknown.d.ts', 'lib.es2016.array.include.d.ts'