Skip to content

Commit 40ce504

Browse files
fix(amazonq): Addition of wait function for Amazon Q inline chat UI E2E Tests and Inline Keybind Shortcut Test (#7840)
## Problem Currently we use a `sleep(8000)` function which causes us to wait an arbitrary 8 seconds for Amazon Q to implement the fibonacci sequence. This can cause flakiness and is generally not a good practice. We also have not fully updated our inline test and our writeToTextEditor function does not work well. We also have not implemented an inline test which uses keybinds to start an inline chat suggestion. ## Solution I have implemented a function which constantly checks for a "stable" state in which we check for any new number of lines generated by Amazon Q. If this stable state is repeated more than 2 times, meaning the number of lines has stayed the same for 3 seconds (1 second wait in between), we will confirm that AmazonQ has finished generating its response. We have a maximum generate time of 15 seconds, as a fibonacci sequence should not take more than that, or something is clearly wrong with the model and we will error out. We have implemented the inline tests and the writeToTextEditor function fix. --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Co-authored-by: laura-codess <[email protected]>
1 parent 12f3a20 commit 40ce504

File tree

2 files changed

+55
-14
lines changed

2 files changed

+55
-14
lines changed

packages/amazonq/test/e2e_new/amazonq/tests/inline.test.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import '../utils/setup'
66
import { Workbench, EditorView, InputBox, TextEditor, WebviewView, Key } from 'vscode-extension-tester'
77
import { testContext } from '../utils/testContext'
8-
import { createNewTextFile, writeToTextEditor, sleep } from '../utils/generalUtils'
8+
import { createNewTextFile, writeToTextEditor, waitForInlineGeneration, pressShortcut } from '../utils/generalUtils'
99
import assert from 'assert'
1010

1111
describe('Amazon Q Inline Completion / Chat Functionality', function () {
@@ -16,35 +16,43 @@ describe('Amazon Q Inline Completion / Chat Functionality', function () {
1616
let textEditor: TextEditor
1717
let webviewView: WebviewView
1818

19-
before(async function () {
19+
beforeEach(async function () {
2020
webviewView = testContext.webviewView
2121
await webviewView.switchBack()
2222
workbench = testContext.workbench
2323
editorView = new EditorView()
2424
testContext.editorView = editorView
2525
textEditor = await createNewTextFile(workbench, editorView)
2626
})
27-
after(async function () {
28-
// Switch back to Webview Iframe when dealing with external webviews from Amazon Q.
27+
afterEach(async function () {
28+
// Switch back to iframe when dealing with external webviews from Amazon Q.
2929
await editorView.closeAllEditors()
3030
await webviewView.switchToFrame()
3131
})
32-
it('Inline Test Shortcut', async () => {
33-
await writeToTextEditor(textEditor, 'def factorial(n):')
34-
const text = await textEditor.getText()
35-
assert.equal(text, 'def factorial(n): ')
36-
await textEditor.clearText()
37-
32+
it('Inline Test Generate', async () => {
3833
const textBefore = await textEditor.getText()
3934
await workbench.executeCommand('Amazon Q: Inline Chat')
4035
const input = new InputBox()
4136
await input.sendKeys('Generate the fibonacci sequence through iteration')
4237
await input.sendKeys(Key.ENTER)
43-
// Must wait for response to be generated.
44-
await sleep(8000)
38+
// Wait for Amazon Q to finish generating code
39+
await waitForInlineGeneration(textEditor)
4540

4641
const textAfter = await textEditor.getText()
47-
assert(textAfter.length > textBefore.length, 'Amazon Q should have generated code')
42+
assert(textAfter.length > textBefore.length, 'Amazon Q generated code')
43+
await textEditor.clearText()
44+
})
45+
it('Inline Keybind Shortcut', async () => {
46+
await writeToTextEditor(textEditor, 'def fibonacci(n):')
47+
await textEditor.selectText('def fibonacci(n):')
48+
49+
const driver = webviewView.getDriver()
50+
await pressShortcut(driver, Key.COMMAND, 'i')
51+
const input = new InputBox()
52+
await input.sendKeys('Generate the fibonacci sequence through recursion')
53+
await input.sendKeys(Key.ENTER)
54+
await waitForInlineGeneration(textEditor)
55+
// Clean Up Text
4856
await textEditor.clearText()
4957
})
5058
})

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export async function pressKey(driver: WebDriver, key: keyof typeof Key): Promis
109109
* Ctrl + C | await pressShortcut(driver, Key.CONTROL, 'c')
110110
* Ctrl + Shift + T | await pressShortcut(driver, Key.CONTROL, Key.SHIFT, 't')
111111
*/
112-
export async function pressShortcut(driver: WebDriver, ...keys: (keyof typeof Key)[]): Promise<void> {
112+
export async function pressShortcut(driver: WebDriver, ...keys: (string | keyof typeof Key)[]): Promise<void> {
113113
const actions = driver.actions()
114114
for (const key of keys) {
115115
actions.keyDown(key)
@@ -215,6 +215,39 @@ export async function writeToTextEditor(textEditor: TextEditor, text: string): P
215215
const currentLines = await textEditor.getNumberOfLines()
216216
await textEditor.typeTextAt(currentLines, 1, text)
217217
}
218+
/**
219+
* Waits for Inline Generation by Amazon Q by checking if line count stops changing.
220+
* The function checks for a "stable state" by monitoring the number of lines in the editor.
221+
* A stable state is achieved when the line count remains unchanged for 3 consecutive checks (3 seconds).
222+
* Checks are performed every 1 second.
223+
* @param editor The TextEditor instance
224+
* @param timeout Maximum time to wait in milliseconds (default: 15000). Function will throw an error if generation takes longer than this timeout.
225+
* @returns Promise<void>
226+
* @throws Error if timeout is exceeded before a stable state is reached
227+
*/
228+
export async function waitForInlineGeneration(editor: TextEditor, timeout = 15000): Promise<void> {
229+
const startTime = Date.now()
230+
let previousLines = await editor.getNumberOfLines()
231+
let stableCount = 0
232+
233+
while (Date.now() - startTime < timeout) {
234+
await sleep(1000)
235+
const currentLines = await editor.getNumberOfLines()
236+
237+
if (currentLines === previousLines) {
238+
stableCount++
239+
if (stableCount >= 3) {
240+
return
241+
}
242+
} else {
243+
stableCount = 0
244+
}
245+
246+
previousLines = currentLines
247+
}
248+
249+
throw new Error(`Editor stabilization timed out after ${timeout}ms`)
250+
}
218251

219252
/**
220253
* Finds an item based on the text

0 commit comments

Comments
 (0)