Skip to content

Commit acabd4e

Browse files
committed
implemented the pressShortcut and switching to editor
1 parent 97397a8 commit acabd4e

File tree

6 files changed

+192
-7
lines changed

6 files changed

+192
-7
lines changed

package-lock.json

Lines changed: 23 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"testE2E": "npm run testE2E -w packages/ --if-present",
3131
"test:ui:prepare": "./node_modules/.bin/extest get-vscode -s ~/.vscode-test-resources -n && extest get-chromedriver -s ~/.vscode-test-resources -n",
3232
"test:ui:install": "cd packages/amazonq && npm run package 2>&1 | grep -o 'VSIX Version: [^ ]*' | cut -d' ' -f3 | xargs -I{} bash -c 'cd ../../ && ./node_modules/.bin/extest install-vsix -f amazon-q-vscode-{}.vsix -e packages/amazonq/test/e2e/amazonq/resources -s ~/.vscode-test-resources'",
33-
"test:ui:run": "npm run testCompile && ./node_modules/.bin/extest run-tests -s ~/.vscode-test-resources -e packages/amazonq/test/e2e/amazonq/resources packages/amazonq/dist/test/e2e/amazonq/VET.test.js",
33+
"test:ui:run": "npm run testCompile && ./node_modules/.bin/extest run-tests -s ~/.vscode-test-resources -e packages/amazonq/test/e2e/amazonq/resources packages/amazonq/dist/test/e2e_new/amazonq/tests/chat.test.js packages/amazonq/dist/test/e2e_new/amazonq/tests/pinContext.test.js packages/amazonq/dist/test/e2e_new/amazonq/tests/quickActions.test.js",
3434
"test:ui": "npm run test:ui:prepare && npm run test:ui:install && npm run test:ui:run",
3535
"testInteg": "npm run testInteg -w packages/ --if-present",
3636
"package": "npm run package -w packages/toolkit -w packages/amazonq",
@@ -83,6 +83,7 @@
8383
},
8484
"dependencies": {
8585
"@types/node": "^22.7.5",
86+
"@types/selenium-webdriver": "^4.1.28",
8687
"buffer": "^6.0.3",
8788
"jaro-winkler": "^0.2.8",
8889
"mocha": "^11.7.1",

packages/amazonq/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,5 +1420,8 @@
14201420
"engines": {
14211421
"npm": "^10.1.0",
14221422
"vscode": "^1.83.0"
1423+
},
1424+
"devDependencies": {
1425+
"@types/chai": "^5.2.2"
14231426
}
14241427
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import '../utils/setup'
6+
import { Workbench, EditorView, InputBox, TextEditor, WebviewView, Key } from 'vscode-extension-tester'
7+
import { testContext } from '../utils/testContext'
8+
import { sleep, expect } from '../utils/generalUtils'
9+
10+
function pressShortcut(element: any, key: string, platform: 'mac' | 'windows', modifier: 'cmd' | 'alt' = 'cmd') {
11+
const modifierKey = modifier === 'cmd' ? (platform === 'mac' ? Key.META : Key.CONTROL) : Key.ALT
12+
return element.sendKeys(modifierKey, key)
13+
}
14+
15+
describe('Amazon Q Inline Completion / Chat Functionality', function () {
16+
// this timeout is the general timeout for the entire test suite
17+
this.timeout(150000)
18+
let workbench: Workbench
19+
let editorView: EditorView
20+
let textEditor: TextEditor
21+
let webviewView: WebviewView
22+
23+
before(async function () {
24+
webviewView = testContext.webviewView
25+
await webviewView.switchBack()
26+
workbench = testContext.workbench
27+
28+
await workbench.executeCommand('Create: New File...')
29+
await (await InputBox.create()).selectQuickPick('Text File')
30+
await sleep(1000)
31+
editorView = new EditorView()
32+
testContext.editorView = editorView
33+
textEditor = (await editorView.openEditor('Untitled-1')) as TextEditor
34+
// or if the file we want is currently opened we can simply do
35+
// editor = new TextEditor();
36+
})
37+
38+
after(async function () {
39+
// cleanup, delete the file contents and close the editor
40+
await textEditor.clearText()
41+
await editorView.closeAllEditors()
42+
43+
// after, in order to not affect the other tests, we must switch back to the webview
44+
await webviewView.switchToFrame()
45+
})
46+
47+
it('Inline Test', async () => {
48+
// the file is currently empty, lets write something in it
49+
// note the coordinates are (1, 1) for the beginning of the file
50+
await textEditor.typeTextAt(1, 1, 'hello')
51+
52+
// now we can check if the text is correct
53+
const text = await textEditor.getText()
54+
expect(text).equals('hello')
55+
56+
// we can also replace all the text with whatever we want
57+
await textEditor.setText(`line1\nline2\nline3`)
58+
// assert how many lines there are now
59+
expect(await textEditor.getNumberOfLines()).equals(3)
60+
61+
// get text at the line with given number
62+
const line = await textEditor.getTextAtLine(2)
63+
expect(line).include('line2')
64+
65+
// get the line number of a search string
66+
const lineNum = await textEditor.getLineOfText('3')
67+
expect(lineNum).equals(3)
68+
69+
// the editor should be dirty since we haven't saved yet
70+
expect(await textEditor.isDirty()).is.true
71+
})
72+
})

packages/amazonq/test/e2e_new/amazonq/utils/generalUtils.ts

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55
import { By, WebviewView, WebElement } from 'vscode-extension-tester'
6-
import { until } from 'selenium-webdriver'
6+
import { until, WebDriver, Key } from 'selenium-webdriver'
77

88
/**
99
* General sleep function to wait for a specified amount of time
@@ -13,6 +13,30 @@ export async function sleep(timeout: number) {
1313
await new Promise((resolve) => setTimeout(resolve, timeout))
1414
}
1515

16+
/**
17+
* Expect
18+
* @param timeout Time in miliseconds
19+
*/
20+
export const expect = (actual: any) => ({
21+
equals: (expected: any) => {
22+
if (actual !== expected) {
23+
throw new Error(`Expected ${expected}, got ${actual}`)
24+
}
25+
},
26+
include: (expected: any) => {
27+
if (!actual.includes(expected)) {
28+
throw new Error(`Expected "${actual}" to include "${expected}"`)
29+
}
30+
},
31+
is: {
32+
true: () => {
33+
if (actual !== true) {
34+
throw new Error(`Expected true, got ${actual}`)
35+
}
36+
},
37+
},
38+
})
39+
1640
/**
1741
* Waits for an element to be located, if there are multiple elements with the same locator it will just return the first one
1842
* @param webview The WebviewView instance
@@ -39,6 +63,69 @@ export async function waitForElements(webview: WebviewView, locator: By, timeout
3963
return await webview.findWebElements(locator)
4064
}
4165

66+
/**
67+
* Presses a single key globally
68+
* @param driver The WebDriver instance
69+
* @param key The key to press
70+
*/
71+
export async function pressKey(driver: WebDriver, key: string): Promise<void> {
72+
await driver.actions().sendKeys(key).perform()
73+
}
74+
75+
type OSType = 'windows' | 'mac'
76+
type modifierKey = 'alt' | 'ctrl' | 'shift' | 'option' | 'command'
77+
78+
const MODIFIERKEYS: Record<OSType, Record<modifierKey, string>> = {
79+
windows: {
80+
alt: Key.ALT,
81+
ctrl: Key.CONTROL,
82+
shift: Key.SHIFT,
83+
option: Key.ALT,
84+
command: Key.COMMAND,
85+
},
86+
mac: {
87+
alt: Key.ALT,
88+
ctrl: Key.CONTROL,
89+
shift: Key.SHIFT,
90+
option: Key.ALT,
91+
command: Key.COMMAND,
92+
},
93+
}
94+
95+
/**
96+
* Presses a keyboard shortcut with modifier keys
97+
* @param driver The WebDriver instance
98+
* @param key The key to press
99+
* @param modifier The modifier key(s)
100+
* @param osType The operating system type
101+
*/
102+
export async function pressShortcut(
103+
driver: WebDriver,
104+
key: string,
105+
modifier: modifierKey | modifierKey[],
106+
osType: OSType = 'windows'
107+
): Promise<void> {
108+
const actions = driver.actions({ bridge: true })
109+
110+
try {
111+
const modifiers = Array.isArray(modifier) ? modifier : modifier ? [modifier] : []
112+
for (const mod of modifiers) {
113+
if (!(mod in MODIFIERKEYS[osType])) {
114+
throw new Error(`Invalid modifier key '${mod}' for ${osType}`)
115+
}
116+
actions.keyDown(MODIFIERKEYS[osType][mod])
117+
}
118+
actions.sendKeys(key)
119+
for (const mod of modifiers.reverse()) {
120+
actions.keyUp(MODIFIERKEYS[osType][mod])
121+
}
122+
await actions.perform()
123+
} catch (error) {
124+
console.error(`Error performing keyboard shortcut: ${error}`)
125+
throw error
126+
}
127+
}
128+
42129
/**
43130
* Writes text to the chat input and optionally sends it
44131
* @param prompt The text to write in the chat input

packages/amazonq/test/e2e_new/amazonq/utils/testContext.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5-
import { Workbench, WebviewView } from 'vscode-extension-tester'
5+
import { Workbench, WebviewView, EditorView } from 'vscode-extension-tester'
66

77
export interface TestContext {
88
workbench: Workbench
99
webviewView: WebviewView
10+
editorView: EditorView
1011
}
1112

1213
export const testContext = new Proxy<TestContext>({} as TestContext, {
@@ -24,7 +25,8 @@ export const testContext = new Proxy<TestContext>({} as TestContext, {
2425
},
2526
})
2627

27-
export function initializeTestContext(workbench: Workbench, webviewView: WebviewView): void {
28+
export function initializeTestContext(workbench: Workbench, webviewView: WebviewView, editorView: EditorView): void {
2829
testContext.workbench = workbench
2930
testContext.webviewView = webviewView
31+
testContext.editorView = editorView
3032
}

0 commit comments

Comments
 (0)