In preparation for in-memory testing infrastructure, the existing Ivy language service tests are moved to a `legacy` directory. These existing tests rely on a single integration project in `test/project/app`, which presents a number of challenges: * adding extra fields/properties to the integration project for one test can cause others to fail/flake. * it's especially difficult to test any cases that require introducing intentional errors, as those tend to break other tests. * tests load files from disk, which is slower. * tests rely on the real built versions of @angular/core and @angular/common, which makes them both slow to build and require rebuilds on every compiler change. * tests share a single tsconfig.json, making it extremely difficult to test how the language service handles different configuration scenarios (e.g. different type-checking flags). PR Close #39594
		
			
				
	
	
		
			88 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * @license
 | |
|  * Copyright Google LLC 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 * as ts from 'typescript/lib/tsserverlibrary';
 | |
| 
 | |
| import {APP_COMPONENT, MockService, setup, TEST_TEMPLATE} from './mock_host';
 | |
| 
 | |
| /**
 | |
|  * The following specs do not directly test the CompilerFactory class, rather
 | |
|  * it asserts our understanding of the project/program/template interaction
 | |
|  * which forms the underlying assumption used in the CompilerFactory.
 | |
|  */
 | |
| 
 | |
| describe('tsserver', () => {
 | |
|   let project: ts.server.Project;
 | |
|   let service: MockService;
 | |
| 
 | |
|   beforeAll(() => {
 | |
|     const {project: _project, service: _service} = setup();
 | |
|     project = _project;
 | |
|     service = _service;
 | |
|   });
 | |
| 
 | |
|   beforeEach(() => {
 | |
|     service.reset();
 | |
|   });
 | |
| 
 | |
|   describe('project version', () => {
 | |
|     it('is updated after TS changes', () => {
 | |
|       const v0 = project.getProjectVersion();
 | |
|       service.overwriteInlineTemplate(APP_COMPONENT, `{{ foo }}`);
 | |
|       const v1 = project.getProjectVersion();
 | |
|       expect(v1).not.toBe(v0);
 | |
|     });
 | |
| 
 | |
|     it('is updated after template changes', () => {
 | |
|       const v0 = project.getProjectVersion();
 | |
|       service.overwrite(TEST_TEMPLATE, `{{ bar }}`);
 | |
|       const v1 = project.getProjectVersion();
 | |
|       expect(v1).not.toBe(v0);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('program', () => {
 | |
|     it('is updated after TS changes', () => {
 | |
|       const p0 = project.getLanguageService().getProgram();
 | |
|       expect(p0).toBeDefined();
 | |
|       service.overwriteInlineTemplate(APP_COMPONENT, `{{ foo }}`);
 | |
|       const p1 = project.getLanguageService().getProgram();
 | |
|       expect(p1).not.toBe(p0);
 | |
|     });
 | |
| 
 | |
|     it('is not updated after template changes', () => {
 | |
|       const p0 = project.getLanguageService().getProgram();
 | |
|       expect(p0).toBeDefined();
 | |
|       service.overwrite(TEST_TEMPLATE, `{{ bar }}`);
 | |
|       const p1 = project.getLanguageService().getProgram();
 | |
|       expect(p1).toBe(p0);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('external template', () => {
 | |
|     it('should not be part of the project root', () => {
 | |
|       // Templates should _never_ be added to the project root, otherwise they
 | |
|       // will be parsed as TS files.
 | |
|       const scriptInfo = service.getScriptInfo(TEST_TEMPLATE);
 | |
|       expect(project.isRoot(scriptInfo)).toBeFalse();
 | |
|     });
 | |
| 
 | |
|     it('should be attached to project', () => {
 | |
|       const scriptInfo = service.getScriptInfo(TEST_TEMPLATE);
 | |
|       // Script info for external template must be attached to a project because
 | |
|       // that's the primary mechanism used in the extension to locate the right
 | |
|       // language service instance. See
 | |
|       // https://github.com/angular/vscode-ng-language-service/blob/b048f5f6b9996c5cf113b764c7ffe13d9eeb4285/server/src/session.ts#L192
 | |
|       expect(scriptInfo.isAttached(project)).toBeTrue();
 | |
|       // Attaching a script info to a project does not mean that the project
 | |
|       // will contain the script info. Kinda like friendship on social media.
 | |
|       expect(project.containsScriptInfo(scriptInfo)).toBeFalse();
 | |
|     });
 | |
|   });
 | |
| });
 |