Skip to content

Commit b2e25cd

Browse files
tingwaiclaude
andcommitted
Fix e2e tests for newer VS Code versions by adding EditorTestUtils workaround
The newer VS Code versions (1.93+) have removed the .native-edit-context selector that vscode-extension-tester relies on for TextEditor methods like clearText(), typeTextAt(), setText(), and moveCursor(). This commit adds EditorTestUtils.ts which provides workaround implementations using keyboard shortcuts as fallbacks when the native methods fail. The workarounds: - clearText: Falls back to Ctrl+A and Delete keys - typeTextAt: Falls back to cursor navigation and direct typing - setText: Falls back to clearText + typing - moveCursor: Falls back to Go to Line command Updated all e2e test files to use the EditorTestUtils methods instead of direct TextEditor methods: - Autocomplete.test.ts - KeyboardShortcuts.test.ts - Edit.test.ts - PromptFile.test.ts - Autocomplete.actions.ts - NextEdit.actions.ts This ensures e2e tests work with both older and newer VS Code versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 514c360 commit b2e25cd

File tree

7 files changed

+120
-20
lines changed

7 files changed

+120
-20
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { TextEditor, Key, Workbench } from "vscode-extension-tester";
2+
3+
/**
4+
* Utility class providing workarounds for TextEditor methods that fail
5+
* with newer VS Code versions due to missing .native-edit-context selector
6+
*/
7+
export class EditorTestUtils {
8+
/**
9+
* Clears all text in the editor using keyboard shortcuts
10+
* Workaround for editor.clearText() which fails with native-edit-context error
11+
*/
12+
public static async clearText(editor: TextEditor): Promise<void> {
13+
try {
14+
// Try the native method first
15+
await editor.clearText();
16+
} catch (error) {
17+
// If it fails, use keyboard shortcuts as workaround
18+
// Select all text
19+
await editor.sendKeys(Key.chord(Key.CONTROL, "a"));
20+
// Delete selected text
21+
await editor.sendKeys(Key.DELETE);
22+
}
23+
}
24+
25+
/**
26+
* Types text at a specific position using keyboard navigation
27+
* Workaround for editor.typeTextAt() which fails with native-edit-context error
28+
*/
29+
public static async typeTextAt(
30+
editor: TextEditor,
31+
line: number,
32+
column: number,
33+
text: string,
34+
): Promise<void> {
35+
try {
36+
// Try the native method first
37+
await editor.typeTextAt(line, column, text);
38+
} catch (error) {
39+
// If it fails, use keyboard navigation as workaround
40+
// Go to line/column
41+
await EditorTestUtils.moveCursor(editor, line, column);
42+
// Type the text
43+
await editor.sendKeys(text);
44+
}
45+
}
46+
47+
/**
48+
* Sets text in the editor by clearing and typing
49+
* Workaround for editor.setText() which fails with native-edit-context error
50+
*/
51+
public static async setText(editor: TextEditor, text: string): Promise<void> {
52+
try {
53+
// Try the native method first
54+
await editor.setText(text);
55+
} catch (error) {
56+
// If it fails, clear and type text
57+
await EditorTestUtils.clearText(editor);
58+
await editor.sendKeys(text);
59+
}
60+
}
61+
62+
/**
63+
* Moves cursor to a specific position using Go to Line command
64+
* Workaround for editor.moveCursor() which fails with native-edit-context error
65+
*/
66+
public static async moveCursor(
67+
editor: TextEditor,
68+
line: number,
69+
column: number,
70+
): Promise<void> {
71+
try {
72+
// Try the native method first
73+
await editor.moveCursor(line, column);
74+
} catch (error) {
75+
// If it fails, use Go to Line command as workaround
76+
const workbench = new Workbench();
77+
// Open Go to Line dialog
78+
await workbench.executeCommand("Go to Line...");
79+
// Type line:column format
80+
await editor.sendKeys(`${line}:${column}`);
81+
await editor.sendKeys(Key.ENTER);
82+
}
83+
}
84+
}

extensions/vscode/e2e/actions/Autocomplete.actions.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,46 @@ import { TextEditor, VSBrowser, Workbench } from "vscode-extension-tester";
44
import { DEFAULT_TIMEOUT } from "../constants";
55
import { AutocompleteSelectors } from "../selectors/Autocomplete.selectors";
66
import { TestUtils } from "../TestUtils";
7+
import { EditorTestUtils } from "../EditorTestUtils";
78

89
export class AutocompleteActions {
910
public static async testCompletions(editor: TextEditor) {
1011
const driver = editor.getDriver();
1112

1213
const messagePair0 = TestUtils.generateTestMessagePair(0);
13-
await editor.typeTextAt(1, 1, messagePair0.userMessage);
14-
await editor.typeTextAt(1, messagePair0.userMessage.length + 1, " ");
14+
await EditorTestUtils.typeTextAt(editor, 1, 1, messagePair0.userMessage);
15+
await EditorTestUtils.typeTextAt(
16+
editor,
17+
1,
18+
messagePair0.userMessage.length + 1,
19+
" ",
20+
);
1521
const ghostText0 = await TestUtils.waitForSuccess(
1622
() => AutocompleteSelectors.getGhostTextContent(driver),
1723
// The first completion takes longer because Continue needs to load
1824
DEFAULT_TIMEOUT.XL,
1925
);
2026
expect(ghostText0).to.equal(messagePair0.llmResponse);
2127

22-
await editor.clearText();
28+
await EditorTestUtils.clearText(editor);
2329

2430
const messagePair1 = TestUtils.generateTestMessagePair(1);
25-
await editor.typeTextAt(1, 1, messagePair1.userMessage);
26-
await editor.typeTextAt(1, messagePair1.userMessage.length + 1, " ");
31+
await EditorTestUtils.typeTextAt(editor, 1, 1, messagePair1.userMessage);
32+
await EditorTestUtils.typeTextAt(
33+
editor,
34+
1,
35+
messagePair1.userMessage.length + 1,
36+
" ",
37+
);
2738
const ghostText1 = await TestUtils.waitForSuccess(() =>
2839
AutocompleteSelectors.getGhostTextContent(driver),
2940
);
3041
expect(ghostText1).to.equal(messagePair1.llmResponse);
3142
}
3243

3344
public static async forceCompletion(editor: TextEditor): Promise<string> {
34-
await editor.setText("def main():\n ");
35-
await editor.moveCursor(2, 5);
45+
await EditorTestUtils.setText(editor, "def main():\n ");
46+
await EditorTestUtils.moveCursor(editor, 2, 5);
3647

3748
await new Workbench().executeCommand("Continue: Force Autocomplete");
3849

extensions/vscode/e2e/actions/NextEdit.actions.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { TextEditor, VSBrowser, Workbench } from "vscode-extension-tester";
44
import { DEFAULT_TIMEOUT } from "../constants";
55
import { NextEditSelectors } from "../selectors/NextEdit.selectors";
66
import { TestUtils } from "../TestUtils";
7+
import { EditorTestUtils } from "../EditorTestUtils";
78

89
export class NextEditActions {
910
/**
@@ -43,9 +44,9 @@ export class NextEditActions {
4344
*/
4445
public static async forceNextEdit(editor: TextEditor): Promise<boolean> {
4546
console.log("Starting forceNextEdit...");
46-
await editor.setText("def main():\n s");
47+
await EditorTestUtils.setText(editor, "def main():\n s");
4748
console.log("Text set in editor");
48-
await editor.moveCursor(2, 4);
49+
await EditorTestUtils.moveCursor(editor, 2, 4);
4950
console.log("Cursor moved to position 2, 4");
5051

5152
await new Workbench().executeCommand("Continue: Force Next Edit");

extensions/vscode/e2e/tests/Autocomplete.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { EditorView, TextEditor } from "vscode-extension-tester";
44
import { AutocompleteActions } from "../actions/Autocomplete.actions";
55
import { GlobalActions } from "../actions/Global.actions";
66
import { DEFAULT_TIMEOUT } from "../constants";
7+
import { EditorTestUtils } from "../EditorTestUtils";
78

89
describe("Autocomplete", () => {
910
let editor: TextEditor;
@@ -23,7 +24,7 @@ describe("Autocomplete", () => {
2324

2425
afterEach(async function () {
2526
this.timeout(DEFAULT_TIMEOUT.XL);
26-
await editor.clearText();
27+
await EditorTestUtils.clearText(editor);
2728
await new EditorView().closeAllEditors();
2829
});
2930

extensions/vscode/e2e/tests/Edit.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { GUIActions } from "../actions/GUI.actions";
1212
import { DEFAULT_TIMEOUT } from "../constants";
1313
import { GUISelectors } from "../selectors/GUI.selectors";
1414
import { TestUtils } from "../TestUtils";
15+
import { EditorTestUtils } from "../EditorTestUtils";
1516

1617
describe("Edit Test", () => {
1718
let view: WebView;
@@ -32,7 +33,7 @@ describe("Edit Test", () => {
3233

3334
await GUIActions.toggleGui();
3435

35-
await editor.typeTextAt(1, 1, originalEditorText);
36+
await EditorTestUtils.typeTextAt(editor, 1, 1, originalEditorText);
3637
await editor.selectText(originalEditorText);
3738

3839
await EditActions.invokeEditShortcut(editor);
@@ -56,7 +57,7 @@ describe("Edit Test", () => {
5657
afterEach(async function () {
5758
this.timeout(DEFAULT_TIMEOUT.XL);
5859

59-
await editor.clearText();
60+
await EditorTestUtils.clearText(editor);
6061

6162
({ view } = await GUIActions.switchToReactIframe());
6263

extensions/vscode/e2e/tests/KeyboardShortcuts.test.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { KeyboardShortcutsActions } from "../actions/KeyboardShortcuts.actions";
1818
import { DEFAULT_TIMEOUT } from "../constants";
1919
import { GUISelectors } from "../selectors/GUI.selectors";
2020
import { TestUtils } from "../TestUtils";
21+
import { EditorTestUtils } from "../EditorTestUtils";
2122

2223
describe("Keyboard Shortcuts", () => {
2324
let driver: WebDriver;
@@ -49,7 +50,7 @@ describe("Keyboard Shortcuts", () => {
4950
this.timeout(DEFAULT_TIMEOUT.XL * 1000);
5051
await cleanupChat();
5152
await view.switchBack();
52-
await editor.clearText();
53+
await EditorTestUtils.clearText(editor);
5354
await new EditorView().closeAllEditors();
5455
});
5556

@@ -200,7 +201,7 @@ describe("Keyboard Shortcuts", () => {
200201
it("Should create a code block when Cmd+L is pressed with text highlighted", async () => {
201202
const text = "Hello, world!";
202203

203-
await editor.setText(text);
204+
await EditorTestUtils.setText(editor, text);
204205
await editor.selectText(text);
205206

206207
await GUIActions.executeFocusContinueInputShortcut(driver);
@@ -222,8 +223,8 @@ describe("Keyboard Shortcuts", () => {
222223
it("Should create a code block with the whole file when Cmd+L is pressed on an empty line", async () => {
223224
const text = "Hello,\n\n\nworld!";
224225

225-
await editor.setText(text);
226-
await editor.moveCursor(2, 1); //Move cursor to an empty line
226+
await EditorTestUtils.setText(editor, text);
227+
await EditorTestUtils.moveCursor(editor, 2, 1); //Move cursor to an empty line
227228

228229
await GUIActions.executeFocusContinueInputShortcut(driver);
229230

@@ -242,8 +243,8 @@ describe("Keyboard Shortcuts", () => {
242243
it("Should create a code block when Cmd+L is pressed on a non-empty line", async () => {
243244
const text = "Hello, world!";
244245

245-
await editor.setText(text);
246-
await editor.moveCursor(1, 7); //Move cursor to the 1st space
246+
await EditorTestUtils.setText(editor, text);
247+
await EditorTestUtils.moveCursor(editor, 1, 7); //Move cursor to the 1st space
247248

248249
await GUIActions.executeFocusContinueInputShortcut(driver);
249250

extensions/vscode/e2e/tests/PromptFile.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99

1010
import { GlobalActions } from "../actions/Global.actions";
1111
import { DEFAULT_TIMEOUT } from "../constants";
12+
import { EditorTestUtils } from "../EditorTestUtils";
1213

1314
describe("Prompt file", () => {
1415
let editor: TextEditor;
@@ -32,7 +33,7 @@ describe("Prompt file", () => {
3233

3334
afterEach(async function () {
3435
this.timeout(DEFAULT_TIMEOUT.XL);
35-
await editor.clearText();
36+
await EditorTestUtils.clearText(editor);
3637
await new EditorView().closeAllEditors();
3738
});
3839

@@ -66,7 +67,7 @@ describe("Prompt file", () => {
6667

6768
const text = await editor.getText();
6869
expect(text).to.include("@" + provider);
69-
await editor.clearText();
70+
await EditorTestUtils.clearText(editor);
7071
}
7172

7273
// Check that dropdown for properties in preamble works

0 commit comments

Comments
 (0)