Skip to content

Commit

Permalink
test: add tests to verify language-service supports output() functi…
Browse files Browse the repository at this point in the history
…on (#54217)

Adds unit tests to verify that the language service supports
the `output()` function with completions, and definition jumping.

PR Close #54217
  • Loading branch information
devversion authored and thePunderWoman committed Feb 5, 2024
1 parent ee635f9 commit 02fdd8d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 4 deletions.
48 changes: 47 additions & 1 deletion packages/language-service/test/completions_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,52 @@ describe('completions', () => {
});
});

describe('initializer-based output() API', () => {
const initializerOutputDirectiveWithUnionType = {
'Dir': `
@Directive({
selector: '[dir]',
})
export class Dir {
bla = output<string>();
}
`
};

it('should return event completion', () => {
const {templateFile} =
setup(`<button dir ></button>`, ``, initializerOutputDirectiveWithUnionType);
templateFile.moveCursorToText(`<button dir ¦>`);
const completions = templateFile.getCompletionsAtPosition();
expectContain(completions, DisplayInfoKind.EVENT, ['(bla)']);
});

it('should return property access completions', () => {
const {templateFile} =
setup(`<input dir (bla)="'foo'.">`, '', initializerOutputDirectiveWithUnionType);
templateFile.moveCursorToText(`dir (bla)="'foo'.¦">`);

const completions = templateFile.getCompletionsAtPosition();
expectContain(
completions, ts.ScriptElementKind.memberFunctionElement,
[`charAt`, 'toLowerCase', /* etc. */]);
});

it('should return completions of string literals, number literals, `true`, ' +
'`false`, `null` and `undefined`',
() => {
const {templateFile} =
setup(`<input dir (bla)="$event.">`, '', initializerOutputDirectiveWithUnionType);
templateFile.moveCursorToText('dir (bla)="$event.¦">');

const completions = templateFile.getCompletionsAtPosition();

expectContain(
completions, ts.ScriptElementKind.memberFunctionElement,
[`charAt`, 'toLowerCase', /* etc. */]);
});
});

describe('for blocks', () => {
const completionPrefixes = ['@', '@i'];

Expand Down Expand Up @@ -1634,7 +1680,7 @@ function setup(
const env = LanguageServiceTestEnv.setup();
const project = env.addProject('test', {
'test.ts': `
import {Component, input, Directive, NgModule, Pipe, TemplateRef} from '@angular/core';
import {Component, input, output, Directive, NgModule, Pipe, TemplateRef} from '@angular/core';
${functionDeclarations}
Expand Down
15 changes: 12 additions & 3 deletions packages/language-service/test/definitions_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ describe('definitions', () => {
export class MyDir2 {
@Output() someEvent = new EventEmitter<void>();
}`,
'dir3.ts': `
import {Directive, output, EventEmitter} from '@angular/core';
@Directive({selector: '[dir]'})
export class MyDir3 {
someEvent = output();
}`,
'app.ts': `
import {Component, NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
Expand All @@ -190,13 +197,15 @@ describe('definitions', () => {
expect(template.contents.slice(textSpan.start, textSpan.start + textSpan.length))
.toEqual('someEvent');

expect(definitions.length).toEqual(2);
const [def, def2] = definitions;
expect(definitions.length).toEqual(3);
const [def3, def2, def] = definitions;
expect(def.textSpan).toContain('someEvent');
expect(def2.textSpan).toContain('someEvent');
expect(def3.textSpan).toContain('someEvent');
expect(def3.contextSpan!).toBe('someEvent = output();');
// TODO(atscott): investigate why the text span includes more than just 'someEvent'
// assertTextSpans([def, def2], ['someEvent']);
assertFileNames([def, def2], ['dir2.ts', 'dir.ts']);
assertFileNames([def3, def2, def], ['dir3.ts', 'dir2.ts', 'dir.ts']);
});

it('should go to the pre-compiled style sheet', () => {
Expand Down
36 changes: 36 additions & 0 deletions packages/language-service/test/type_definitions_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,42 @@ describe('type definitions', () => {
});
});

describe('initializer-based output() API', () => {
it('return the definition for an output', () => {
initMockFileSystem('Native');
const files = {
'app.ts': `
import {Component, Directive, output} from '@angular/core';
@Directive({
selector: 'my-dir',
standalone: true
})
export class MyDir {
nameChanges = output<string>();
}
@Component({
templateUrl: 'app.html',
standalone: true,
imports: [MyDir],
})
export class AppCmp {
doSmth() {}
}
`,
'app.html': `Will be overridden`,
};
env = LanguageServiceTestEnv.setup();
const project = env.addProject('test', files);
const definitions = getTypeDefinitionsAndAssertBoundSpan(
project, {templateOverride: `<my-dir (name¦Changes)="doSmth()" />`});
expect(definitions!.length).toEqual(1);

assertTextSpans(definitions, ['EventEmitter']);
assertFileNames(definitions, ['index.d.ts']);
});
});

function getTypeDefinitionsAndAssertBoundSpan(
project: Project, {templateOverride}: {templateOverride: string}) {
Expand Down

0 comments on commit 02fdd8d

Please sign in to comment.