Adding assertEditorContents helper function and fixing jsdoc completion tests

This commit is contained in:
Matt Bierner 2020-02-04 17:52:11 -08:00
parent a32cb805a2
commit e7451b12ce
3 changed files with 164 additions and 149 deletions

View file

@ -3,37 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import 'mocha'; import 'mocha';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { disposeAll } from '../utils/dispose'; import { disposeAll } from '../utils/dispose';
import { createTestEditor, joinLines, wait } from './testUtils';
import { acceptFirstSuggestion, typeCommitCharacter } from './suggestTestHelpers'; import { acceptFirstSuggestion, typeCommitCharacter } from './suggestTestHelpers';
import { assertEditorContents, Config, createTestEditor, joinLines, updateConfig, VsCodeConfiguration, wait } from './testUtils';
const testDocumentUri = vscode.Uri.parse('untitled:test.ts'); const testDocumentUri = vscode.Uri.parse('untitled:test.ts');
type VsCodeConfiguration = { [key: string]: any };
async function updateConfig(newConfig: VsCodeConfiguration): Promise<VsCodeConfiguration> {
const oldConfig: VsCodeConfiguration = {};
const config = vscode.workspace.getConfiguration(undefined, testDocumentUri);
for (const configKey of Object.keys(newConfig)) {
oldConfig[configKey] = config.get(configKey);
await new Promise((resolve, reject) =>
config.update(configKey, newConfig[configKey], vscode.ConfigurationTarget.Global)
.then(() => resolve(), reject));
}
return oldConfig;
}
namespace Config {
export const autoClosingBrackets = 'editor.autoClosingBrackets';
export const completeFunctionCalls = 'typescript.suggest.completeFunctionCalls';
export const insertMode = 'editor.suggest.insertMode';
export const snippetSuggestions = 'editor.snippetSuggestions';
export const suggestSelection = 'editor.suggestSelection';
}
const insertModes = Object.freeze(['insert', 'replace']); const insertModes = Object.freeze(['insert', 'replace']);
suite('TypeScript Completions', () => { suite('TypeScript Completions', () => {
@ -52,28 +29,27 @@ suite('TypeScript Completions', () => {
await wait(100); await wait(100);
// Save off config and apply defaults // Save off config and apply defaults
oldConfig = await updateConfig(configDefaults); oldConfig = await updateConfig(testDocumentUri, configDefaults);
}); });
teardown(async () => { teardown(async () => {
disposeAll(_disposables); disposeAll(_disposables);
// Restore config // Restore config
await updateConfig(oldConfig); await updateConfig(testDocumentUri, oldConfig);
return vscode.commands.executeCommand('workbench.action.closeAllEditors'); return vscode.commands.executeCommand('workbench.action.closeAllEditors');
}); });
test('Basic var completion', async () => { test('Basic var completion', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`const abcdef = 123;`, `const abcdef = 123;`,
`ab$0;` `ab$0;`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`const abcdef = 123;`, `const abcdef = 123;`,
`abcdef;` `abcdef;`
@ -85,14 +61,14 @@ suite('TypeScript Completions', () => {
test('Should treat period as commit character for var completions', async () => { test('Should treat period as commit character for var completions', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`const abcdef = 123;`, `const abcdef = 123;`,
`ab$0;` `ab$0;`
); );
const document = await typeCommitCharacter(testDocumentUri, '.', _disposables); await typeCommitCharacter(testDocumentUri, '.', _disposables);
assert.strictEqual(
document.getText(), assertEditorContents(editor,
joinLines( joinLines(
`const abcdef = 123;`, `const abcdef = 123;`,
`abcdef.;` `abcdef.;`
@ -103,14 +79,14 @@ suite('TypeScript Completions', () => {
test('Should treat paren as commit character for function completions', async () => { test('Should treat paren as commit character for function completions', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`function abcdef() {};`, `function abcdef() {};`,
`ab$0;` `ab$0;`
); );
const document = await typeCommitCharacter(testDocumentUri, '(', _disposables); await typeCommitCharacter(testDocumentUri, '(', _disposables);
assert.strictEqual(
document.getText(), assertEditorContents(editor,
joinLines( joinLines(
`function abcdef() {};`, `function abcdef() {};`,
`abcdef();` `abcdef();`
@ -120,14 +96,13 @@ suite('TypeScript Completions', () => {
test('Should insert backets when completing dot properties with spaces in name', async () => { test('Should insert backets when completing dot properties with spaces in name', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
'const x = { "hello world": 1 };', 'const x = { "hello world": 1 };',
'x.$0' 'x.$0'
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
'const x = { "hello world": 1 };', 'const x = { "hello world": 1 };',
'x["hello world"]' 'x["hello world"]'
@ -140,14 +115,14 @@ suite('TypeScript Completions', () => {
{ char: '.', insert: '.' }, { char: '.', insert: '.' },
{ char: '(', insert: '()' }, { char: '(', insert: '()' },
]) { ]) {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
'const x = { "hello world2": 1 };', 'const x = { "hello world2": 1 };',
'x.$0' 'x.$0'
); );
const document = await typeCommitCharacter(testDocumentUri, char, _disposables); await typeCommitCharacter(testDocumentUri, char, _disposables);
assert.strictEqual(
document.getText(), assertEditorContents(editor,
joinLines( joinLines(
'const x = { "hello world2": 1 };', 'const x = { "hello world2": 1 };',
`x["hello world2"]${insert}` `x["hello world2"]${insert}`
@ -161,14 +136,13 @@ suite('TypeScript Completions', () => {
test('Should not prioritize bracket accessor completions. #63100', async () => { test('Should not prioritize bracket accessor completions. #63100', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
// 'a' should be first entry in completion list // 'a' should be first entry in completion list
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
'const x = { "z-z": 1, a: 1 };', 'const x = { "z-z": 1, a: 1 };',
'x.$0' 'x.$0'
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
'const x = { "z-z": 1, a: 1 };', 'const x = { "z-z": 1, a: 1 };',
'x.a' 'x.a'
@ -178,7 +152,7 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a string completion should replace the entire string. #53962', async () => { test('Accepting a string completion should replace the entire string. #53962', async () => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
'interface TFunction {', 'interface TFunction {',
` (_: 'abc.abc2', __ ?: {}): string;`, ` (_: 'abc.abc2', __ ?: {}): string;`,
` (_: 'abc.abc', __?: {}): string;`, ` (_: 'abc.abc', __?: {}): string;`,
@ -187,9 +161,8 @@ suite('TypeScript Completions', () => {
`f('abc.abc$0')` `f('abc.abc$0')`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
'interface TFunction {', 'interface TFunction {',
` (_: 'abc.abc2', __ ?: {}): string;`, ` (_: 'abc.abc2', __ ?: {}): string;`,
@ -201,17 +174,16 @@ suite('TypeScript Completions', () => {
}); });
test('completeFunctionCalls should complete function parameters when at end of word', async () => { test('completeFunctionCalls should complete function parameters when at end of word', async () => {
await updateConfig({ [Config.completeFunctionCalls]: true }); await updateConfig(testDocumentUri, { [Config.completeFunctionCalls]: true });
// Complete with-in word // Complete with-in word
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcdef$0` `abcdef$0`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcdef(x, y, z)` `abcdef(x, y, z)`
@ -219,16 +191,15 @@ suite('TypeScript Completions', () => {
}); });
test.skip('completeFunctionCalls should complete function parameters when within word', async () => { test.skip('completeFunctionCalls should complete function parameters when within word', async () => {
await updateConfig({ [Config.completeFunctionCalls]: true }); await updateConfig(testDocumentUri, { [Config.completeFunctionCalls]: true });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcd$0ef` `abcd$0ef`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcdef(x, y, z)` `abcdef(x, y, z)`
@ -236,16 +207,15 @@ suite('TypeScript Completions', () => {
}); });
test('completeFunctionCalls should not complete function parameters at end of word if we are already in something that looks like a function call, #18131', async () => { test('completeFunctionCalls should not complete function parameters at end of word if we are already in something that looks like a function call, #18131', async () => {
await updateConfig({ [Config.completeFunctionCalls]: true }); await updateConfig(testDocumentUri, { [Config.completeFunctionCalls]: true });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcdef$0(1, 2, 3)` `abcdef$0(1, 2, 3)`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcdef(1, 2, 3)` `abcdef(1, 2, 3)`
@ -253,16 +223,15 @@ suite('TypeScript Completions', () => {
}); });
test.skip('completeFunctionCalls should not complete function parameters within word if we are already in something that looks like a function call, #18131', async () => { test.skip('completeFunctionCalls should not complete function parameters within word if we are already in something that looks like a function call, #18131', async () => {
await updateConfig({ [Config.completeFunctionCalls]: true }); await updateConfig(testDocumentUri, { [Config.completeFunctionCalls]: true });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcd$0ef(1, 2, 3)` `abcd$0ef(1, 2, 3)`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`function abcdef(x, y, z) { }`, `function abcdef(x, y, z) { }`,
`abcdef(1, 2, 3)` `abcdef(1, 2, 3)`
@ -271,7 +240,7 @@ suite('TypeScript Completions', () => {
test('should not de-prioritize `this.member` suggestion, #74164', async () => { test('should not de-prioritize `this.member` suggestion, #74164', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` private detail = '';`, ` private detail = '';`,
` foo() {`, ` foo() {`,
@ -280,9 +249,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` private detail = '';`, ` private detail = '';`,
@ -297,7 +265,7 @@ suite('TypeScript Completions', () => {
test('Member completions for string property name should insert `this.` and use brackets', async () => { test('Member completions for string property name should insert `this.` and use brackets', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` ['xyz 123'] = 1`, ` ['xyz 123'] = 1`,
` foo() {`, ` foo() {`,
@ -306,9 +274,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` ['xyz 123'] = 1`, ` ['xyz 123'] = 1`,
@ -323,7 +290,7 @@ suite('TypeScript Completions', () => {
test('Member completions for string property name already using `this.` should add brackets', async () => { test('Member completions for string property name already using `this.` should add brackets', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` ['xyz 123'] = 1`, ` ['xyz 123'] = 1`,
` foo() {`, ` foo() {`,
@ -332,9 +299,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` ['xyz 123'] = 1`, ` ['xyz 123'] = 1`,
@ -348,16 +314,15 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a completion in word using `insert` mode should insert', async () => { test('Accepting a completion in word using `insert` mode should insert', async () => {
await updateConfig({ [Config.insertMode]: 'insert' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'insert' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`const abc = 123;`, `const abc = 123;`,
`ab$0c` `ab$0c`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`const abc = 123;`, `const abc = 123;`,
`abcc` `abcc`
@ -365,16 +330,15 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a completion in word using `replace` mode should replace', async () => { test('Accepting a completion in word using `replace` mode should replace', async () => {
await updateConfig({ [Config.insertMode]: 'replace' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'replace' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`const abc = 123;`, `const abc = 123;`,
`ab$0c` `ab$0c`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`const abc = 123;`, `const abc = 123;`,
`abc` `abc`
@ -382,9 +346,9 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a member completion in word using `insert` mode add `this.` and insert', async () => { test('Accepting a member completion in word using `insert` mode add `this.` and insert', async () => {
await updateConfig({ [Config.insertMode]: 'insert' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'insert' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class Foo {`, `class Foo {`,
` abc = 1;`, ` abc = 1;`,
` foo() {`, ` foo() {`,
@ -393,9 +357,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class Foo {`, `class Foo {`,
` abc = 1;`, ` abc = 1;`,
@ -407,9 +370,9 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a member completion in word using `replace` mode should add `this.` and replace', async () => { test('Accepting a member completion in word using `replace` mode should add `this.` and replace', async () => {
await updateConfig({ [Config.insertMode]: 'replace' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'replace' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class Foo {`, `class Foo {`,
` abc = 1;`, ` abc = 1;`,
` foo() {`, ` foo() {`,
@ -418,9 +381,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class Foo {`, `class Foo {`,
` abc = 1;`, ` abc = 1;`,
@ -432,16 +394,15 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting string completion inside string using `insert` mode should insert', async () => { test('Accepting string completion inside string using `insert` mode should insert', async () => {
await updateConfig({ [Config.insertMode]: 'insert' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'insert' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`const abc = { 'xy z': 123 }`, `const abc = { 'xy z': 123 }`,
`abc["x$0y w"]` `abc["x$0y w"]`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`const abc = { 'xy z': 123 }`, `const abc = { 'xy z': 123 }`,
`abc["xy zy w"]` `abc["xy zy w"]`
@ -450,16 +411,15 @@ suite('TypeScript Completions', () => {
// Waiting on https://github.com/microsoft/TypeScript/issues/35602 // Waiting on https://github.com/microsoft/TypeScript/issues/35602
test.skip('Accepting string completion inside string using insert mode should insert', async () => { test.skip('Accepting string completion inside string using insert mode should insert', async () => {
await updateConfig({ [Config.insertMode]: 'replace' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'replace' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`const abc = { 'xy z': 123 }`, `const abc = { 'xy z': 123 }`,
`abc["x$0y w"]` `abc["x$0y w"]`
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`const abc = { 'xy z': 123 }`, `const abc = { 'xy z': 123 }`,
`abc["xy w"]` `abc["xy w"]`
@ -468,7 +428,7 @@ suite('TypeScript Completions', () => {
test('Private field completions on `this.#` should work', async () => { test('Private field completions on `this.#` should work', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
` foo() {`, ` foo() {`,
@ -477,9 +437,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
@ -494,7 +453,7 @@ suite('TypeScript Completions', () => {
test('Private field completions on `#` should insert `this.`', async () => { test('Private field completions on `#` should insert `this.`', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
` foo() {`, ` foo() {`,
@ -503,9 +462,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
@ -520,7 +478,7 @@ suite('TypeScript Completions', () => {
test('Private field completions should not require strict prefix match (#89556)', async () => { test('Private field completions should not require strict prefix match (#89556)', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
` foo() {`, ` foo() {`,
@ -529,9 +487,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
@ -546,7 +503,7 @@ suite('TypeScript Completions', () => {
test('Private field completions without `this.` should not require strict prefix match (#89556)', async () => { test('Private field completions without `this.` should not require strict prefix match (#89556)', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
` foo() {`, ` foo() {`,
@ -555,9 +512,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` #xyz = 1;`, ` #xyz = 1;`,
@ -571,9 +527,9 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a completion for async property in `insert` mode should insert and add await', async () => { test('Accepting a completion for async property in `insert` mode should insert and add await', async () => {
await updateConfig({ [Config.insertMode]: 'insert' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'insert' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` xyz = Promise.resolve({ 'abc': 1 });`, ` xyz = Promise.resolve({ 'abc': 1 });`,
` async foo() {`, ` async foo() {`,
@ -582,9 +538,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` xyz = Promise.resolve({ 'abc': 1 });`, ` xyz = Promise.resolve({ 'abc': 1 });`,
@ -596,9 +551,9 @@ suite('TypeScript Completions', () => {
}); });
test('Accepting a completion for async property in `replace` mode should replace and add await', async () => { test('Accepting a completion for async property in `replace` mode should replace and add await', async () => {
await updateConfig({ [Config.insertMode]: 'replace' }); await updateConfig(testDocumentUri, { [Config.insertMode]: 'replace' });
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` xyz = Promise.resolve({ 'abc': 1 });`, ` xyz = Promise.resolve({ 'abc': 1 });`,
` async foo() {`, ` async foo() {`,
@ -607,9 +562,8 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual( assertEditorContents(editor,
document.getText(),
joinLines( joinLines(
`class A {`, `class A {`,
` xyz = Promise.resolve({ 'abc': 1 });`, ` xyz = Promise.resolve({ 'abc': 1 });`,
@ -622,7 +576,7 @@ suite('TypeScript Completions', () => {
test.skip('Accepting a completion for async string property should add await plus brackets', async () => { test.skip('Accepting a completion for async string property should add await plus brackets', async () => {
await enumerateConfig(Config.insertMode, insertModes, async config => { await enumerateConfig(Config.insertMode, insertModes, async config => {
await createTestEditor(testDocumentUri, const editor = await createTestEditor(testDocumentUri,
`class A {`, `class A {`,
` xyz = Promise.resolve({ 'ab c': 1 });`, ` xyz = Promise.resolve({ 'ab c': 1 });`,
` async foo() {`, ` async foo() {`,
@ -631,9 +585,9 @@ suite('TypeScript Completions', () => {
`}`, `}`,
); );
const document = await acceptFirstSuggestion(testDocumentUri, _disposables); await acceptFirstSuggestion(testDocumentUri, _disposables);
assert.strictEqual(
document.getText(), assertEditorContents(editor,
joinLines( joinLines(
`class A {`, `class A {`,
` xyz = Promise.resolve({ 'abc': 1 });`, ` xyz = Promise.resolve({ 'abc': 1 });`,
@ -650,7 +604,7 @@ suite('TypeScript Completions', () => {
async function enumerateConfig(configKey: string, values: readonly string[], f: (message: string) => Promise<void>): Promise<void> { async function enumerateConfig(configKey: string, values: readonly string[], f: (message: string) => Promise<void>): Promise<void> {
for (const value of values) { for (const value of values) {
const newConfig = { [configKey]: value }; const newConfig = { [configKey]: value };
await updateConfig(newConfig); await updateConfig(testDocumentUri, newConfig);
await f(JSON.stringify(newConfig)); await f(JSON.stringify(newConfig));
} }
} }

View file

@ -7,20 +7,34 @@ import * as assert from 'assert';
import 'mocha'; import 'mocha';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { disposeAll } from '../utils/dispose'; import { disposeAll } from '../utils/dispose';
import { createTestEditor, joinLines, wait } from './testUtils';
import { acceptFirstSuggestion } from './suggestTestHelpers'; import { acceptFirstSuggestion } from './suggestTestHelpers';
import { Config, createTestEditor, joinLines, updateConfig, VsCodeConfiguration, wait } from './testUtils';
const testDocumentUri = vscode.Uri.parse('untitled:test.ts'); const testDocumentUri = vscode.Uri.parse('untitled:test.ts');
suite('JSDoc Completions', () => { suite('JSDoc Completions', () => {
const _disposables: vscode.Disposable[] = []; const _disposables: vscode.Disposable[] = [];
const configDefaults: VsCodeConfiguration = Object.freeze({
[Config.snippetSuggestions]: 'inline',
});
let oldConfig: { [key: string]: any } = {};
setup(async () => { setup(async () => {
await wait(100); await wait(100);
// Save off config and apply defaults
oldConfig = await updateConfig(testDocumentUri, configDefaults);
}); });
teardown(async () => { teardown(async () => {
disposeAll(_disposables); disposeAll(_disposables);
// Restore config
await updateConfig(testDocumentUri, oldConfig);
return vscode.commands.executeCommand('workbench.action.closeAllEditors');
}); });
test('Should complete jsdoc inside single line comment', async () => { test('Should complete jsdoc inside single line comment', async () => {

View file

@ -3,10 +3,11 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode'; import * as assert from 'assert';
import * as fs from 'fs'; import * as fs from 'fs';
import * as os from 'os'; import * as os from 'os';
import { join } from 'path'; import { join } from 'path';
import * as vscode from 'vscode';
function rndName() { function rndName() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
@ -80,4 +81,50 @@ export async function createTestEditor(uri: vscode.Uri, ...lines: string[]) {
} }
await activeEditor.insertSnippet(new vscode.SnippetString(joinLines(...lines)), new vscode.Range(0, 0, 1000, 0)); await activeEditor.insertSnippet(new vscode.SnippetString(joinLines(...lines)), new vscode.Range(0, 0, 1000, 0));
return activeEditor;
} }
export function assertEditorContents(editor: vscode.TextEditor, expectedDocContent: string, message?: string): void {
const cursorIndex = expectedDocContent.indexOf(CURSOR);
assert.strictEqual(
editor.document.getText(),
expectedDocContent.replace(CURSOR, ''),
message);
if (cursorIndex >= 0) {
const expectedCursorPos = editor.document.positionAt(cursorIndex);
assert.strictEqual(
editor.selection.active.line,
expectedCursorPos.line
);
assert.strictEqual(
editor.selection.active.character,
expectedCursorPos.character
);
}
}
export type VsCodeConfiguration = { [key: string]: any };
export async function updateConfig(documentUri: vscode.Uri, newConfig: VsCodeConfiguration): Promise<VsCodeConfiguration> {
const oldConfig: VsCodeConfiguration = {};
const config = vscode.workspace.getConfiguration(undefined, documentUri);
for (const configKey of Object.keys(newConfig)) {
oldConfig[configKey] = config.get(configKey);
await new Promise((resolve, reject) =>
config.update(configKey, newConfig[configKey], vscode.ConfigurationTarget.Global)
.then(() => resolve(), reject));
}
return oldConfig;
}
export const Config = Object.freeze({
autoClosingBrackets: 'editor.autoClosingBrackets',
completeFunctionCalls: 'typescript.suggest.completeFunctionCalls',
insertMode: 'editor.suggest.insertMode',
snippetSuggestions: 'editor.snippetSuggestions',
suggestSelection: 'editor.suggestSelection',
} as const);