Skip to content

Commit 3b717f7

Browse files
committed
Re-enabling and stabilizing completion tests by de-coupling document modification requests from completion requests and adding retries.
1 parent bd362e8 commit 3b717f7

File tree

3 files changed

+66
-44
lines changed

3 files changed

+66
-44
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
// The profile can be found under /test/csharp-test-profile.
7777
"--profile",
7878
"csharp-test-profile",
79-
"${workspaceRoot}/test/razor/razorIntegrationTests/testAssets/RazorApp/.vscode/RazorApp.code-workspace",
79+
"${workspaceRoot}/test/razor/razorIntegrationTests/testAssets/RazorApp/.vscode/devkit_RazorApp.code-workspace",
8080
"--extensionDevelopmentPath=${workspaceRoot}",
8181
"--extensionTestsPath=${workspaceRoot}/out/test/razor/razorIntegrationTests",
8282
"--log",

test/razor/razorIntegrationTests/completion.integration.test.ts

Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
import * as path from 'path';
77
import * as vscode from 'vscode';
8-
import { beforeAll, afterAll, test, expect, beforeEach, describe } from '@jest/globals';
8+
import { beforeAll, afterAll, test, expect, beforeEach } from '@jest/globals';
99
import testAssetWorkspace from './testAssets/testAssetWorkspace';
1010
import * as integrationHelpers from '../../lsptoolshost/integrationTests/integrationHelpers';
1111

12-
describe.skip(`Razor Completion ${testAssetWorkspace.description}`, function () {
12+
integrationHelpers.describeIfDevKit(`Razor Hover ${testAssetWorkspace.description}`, function () {
1313
beforeAll(async function () {
1414
if (!integrationHelpers.isRazorWorkspace(vscode.workspace)) {
1515
return;
@@ -31,48 +31,41 @@ describe.skip(`Razor Completion ${testAssetWorkspace.description}`, function ()
3131
return;
3232
}
3333

34-
const insertPosition = new vscode.Position(4, 4);
35-
await insertText(insertPosition, '<te');
36-
const completionList = await getCompletionsAsync(new vscode.Position(4, 7), 'e', undefined);
37-
expect(completionList.items.length).toBeGreaterThan(0);
38-
const textTagCompletionItem = completionList.items.find((item) => item.label === 'text');
39-
40-
if (!textTagCompletionItem) {
41-
throw new Error(completionList.items.reduce((acc, item) => acc + item.label + '\n', ''));
34+
const activeDocument = vscode.window.activeTextEditor?.document.uri;
35+
if (!activeDocument) {
36+
throw new Error('No active document');
4237
}
4338

44-
expect(textTagCompletionItem).toBeDefined();
45-
expect(textTagCompletionItem!.kind).toEqual(vscode.CompletionItemKind.Text);
46-
expect(textTagCompletionItem!.insertText).toBe('text');
39+
await waitForExpectedCompletionItemAsync(
40+
new vscode.Position(4, 7),
41+
undefined,
42+
undefined,
43+
'text',
44+
vscode.CompletionItemKind.TypeParameter,
45+
'text'
46+
);
4747
});
4848

4949
test('Div Tag', async () => {
5050
if (!integrationHelpers.isRazorWorkspace(vscode.workspace)) {
5151
return;
5252
}
5353

54-
const insertPosition = new vscode.Position(6, 0);
55-
await insertText(insertPosition, '<di');
56-
const completionList = await getCompletionsAsync(new vscode.Position(6, 3), undefined, 10);
57-
expect(completionList.items.length).toBeGreaterThan(0);
58-
const divTagCompletionItem = completionList.items.find((item) => item.label === 'div');
59-
60-
if (!divTagCompletionItem) {
61-
throw new Error(completionList.items.reduce((acc, item) => acc + item.label + '\n', ''));
62-
}
54+
const expectedDocumentation = `The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.
6355
64-
expect(divTagCompletionItem).toBeDefined();
56+
![Baseline icon](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgIGZpbGw6ICNDNEVFRDA7IC8qIExpZ2h0IG1vZGUgKi8KICAgIH0KCiAgICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7CiAgICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgICAgZmlsbDogIzEyNTIyNTsgLyogRGFyayBtb2RlICovCiAgICAgIH0KICAgIH0KICA8L3N0eWxlPgogIDxwYXRoIGQ9Ik00MjAgMzBMMzkwIDYwTDQ4MCAxNTBMMzkwIDI0MEwzMzAgMTgwTDMwMCAyMTBMMzkwIDMwMEw1NDAgMTUwTDQyMCAzMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0xNTAgMEwzMCAxMjBMNjAgMTUwTDE1MCA2MEwyMTAgMTIwTDI0MCA5MEwxNTAgMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0zOTAgMEw0MjAgMzBMMTUwIDMwMEwwIDE1MEwzMCAxMjBMMTUwIDI0MEwzOTAgMFoiIGZpbGw9IiMxRUE0NDYiLz4KPC9zdmc+) _Widely available across major browsers (Baseline since 2015)_
6557
66-
// Reader, you may be wondering why the kind is a Property. To that I say: I don't know.
67-
// If you find out please add a detailed explanation. Thank you in advance.
68-
expect(divTagCompletionItem!.kind).toEqual(vscode.CompletionItemKind.Property);
69-
expect(divTagCompletionItem!.insertText).toBe('div');
70-
71-
const documentation = divTagCompletionItem!.documentation as vscode.MarkdownString;
72-
expect(documentation.value).toBe(
73-
'The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/HTML/Element/div)'
58+
[MDN Reference](https://developer.mozilla.org/docs/Web/HTML/Reference/Elements/div)`;
59+
await waitForExpectedCompletionItemAsync(
60+
new vscode.Position(6, 3),
61+
undefined,
62+
undefined,
63+
'div',
64+
vscode.CompletionItemKind.Property,
65+
'div',
66+
expectedDocumentation
7467
);
75-
});
68+
}, 30000);
7669

7770
async function getCompletionsAsync(
7871
position: vscode.Position,
@@ -93,14 +86,43 @@ describe.skip(`Razor Completion ${testAssetWorkspace.description}`, function ()
9386
);
9487
}
9588

96-
async function insertText(position: vscode.Position, text: string): Promise<void> {
97-
const activeEditor = vscode.window.activeTextEditor;
98-
if (!activeEditor) {
99-
throw new Error('No active editor');
100-
}
101-
102-
await activeEditor.edit((builder) => {
103-
builder.insert(position, text);
104-
});
89+
async function waitForExpectedCompletionItemAsync(
90+
position: vscode.Position,
91+
triggerCharacter: string | undefined,
92+
resolvedItemCount: number | undefined,
93+
expectedLabel: string,
94+
expectedKind: vscode.CompletionItemKind,
95+
expectedInsertText: string,
96+
expectedDocumentation: string | undefined = undefined
97+
): Promise<void> {
98+
const duration = 30 * 1000;
99+
const step = 500;
100+
101+
await integrationHelpers.waitForExpectedResult<vscode.CompletionList>(
102+
async () => {
103+
const completions = await getCompletionsAsync(position, undefined, resolvedItemCount);
104+
return completions;
105+
},
106+
duration,
107+
step,
108+
(completionList) => {
109+
if (!completionList) {
110+
throw new Error('No completion list');
111+
}
112+
expect(completionList.items.length).toBeGreaterThan(0);
113+
114+
const completionItem = completionList.items.find((item) => item.label === expectedLabel);
115+
if (!completionItem) {
116+
throw new Error();
117+
}
118+
expect(completionItem).toBeDefined();
119+
expect(completionItem!.kind).toEqual(expectedKind);
120+
expect(completionItem!.insertText).toBe(expectedInsertText);
121+
if (expectedDocumentation) {
122+
const documentation = completionItem!.documentation as vscode.MarkdownString;
123+
expect(documentation.value).toBe(expectedDocumentation);
124+
}
125+
}
126+
);
105127
}
106128
});

test/razor/razorIntegrationTests/testAssets/RazorApp/Pages/Completion.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
@* Insert text tag in below using completion *@
44
@{
5-
5+
<te
66
}
7-
7+
<di
88
@code {
99

1010
}

0 commit comments

Comments
 (0)