Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,62 +13,39 @@ import { sleep, waitForElements } from '../utils/generalUtils'
* @returns Promise<{items: WebElement[], texts: string[]}> Array of menu items and their text labels
*/
export async function getQuickActionsCommands(webview: WebviewView): Promise<{ items: WebElement[]; texts: string[] }> {
try {
await writeToChat('/', webview, false)
await sleep(2000)
await writeToChat('/', webview, false)
await sleep(2000)

const menuItems = await waitForElements(
webview,
By.css('.mynah-detailed-list-item.mynah-ui-clickable-item.target-command'),
10000
)
const menuItems = await waitForElements(
webview,
By.css('.mynah-detailed-list-item.mynah-ui-clickable-item.target-command'),
10000
)

const menuTexts = []
for (let i = 0; i < menuItems.length; i++) {
try {
const text = await menuItems[i].getText()
menuTexts.push(text)
console.log(`Command ${i + 1}: ${text}`)
} catch (e) {
menuTexts.push('')
console.log(`Could not get text for command ${i + 1}`)
}
}

console.log(`Found ${menuItems.length} quick action command items`)
return { items: menuItems, texts: menuTexts }
} catch (e) {
console.error('Error getting quick action commands:', e)
return { items: [], texts: [] }
const menuTexts = []
for (let i = 0; i < menuItems.length; i++) {
const text = await menuItems[i].getText()
menuTexts.push(text)
}

return { items: menuItems, texts: menuTexts }
}

/**
* Clicks a specific quick action command by name
* @param webview The WebviewView instance
* @param commandName The name of the command to click
* @returns Promise<boolean> True if command was found and clicked, false otherwise
*/
export async function clickQuickActionsCommand(webview: WebviewView, commandName: string): Promise<boolean> {
try {
const { items, texts } = await getQuickActionsCommands(webview)
if (items.length === 0) {
console.log('No quick action commands found to click')
return false
}
const indexToClick = texts.findIndex((text) => text === commandName)
export async function clickQuickActionsCommand(webview: WebviewView, commandName: string): Promise<void> {
const { items, texts } = await getQuickActionsCommands(webview)
if (items.length === 0) {
throw new Error('No quick action commands found')
}
const indexToClick = texts.findIndex((text) => text === commandName)

if (indexToClick === -1) {
console.log(`Command "${commandName}" not found`)
return false
}
console.log(`Clicking on command: ${commandName}`)
await items[indexToClick].click()
await sleep(3000)
console.log('Command clicked successfully')
return true
} catch (e) {
console.error('Error clicking quick action command:', e)
return false
if (indexToClick === -1) {
throw new Error(`Command "${commandName}" not found`)
}
await items[indexToClick].click()
await sleep(3000)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,10 @@ import { waitForElement } from '../utils/generalUtils'
* @param webviewView The WebviewView instance
*/
export async function listModels(webviewView: WebviewView): Promise<void> {
try {
const selectElement = await waitForElement(webviewView, By.css('.mynah-form-input.auto-width'))
const options = await selectElement.findElements(By.css('option'))
const optionTexts = await Promise.all(options.map(async (option) => await option.getText()))

console.log('Available model options:', optionTexts)
} catch (e) {
console.error('Error listing model options:', e)
throw e
}
const selectElement = await waitForElement(webviewView, By.css('.mynah-form-input.auto-width'))
const options = await selectElement.findElements(By.css('option'))
const optionTexts = await Promise.all(options.map(async (option) => await option.getText()))
console.log('Available model options:', optionTexts)
}

/**
Expand All @@ -28,25 +22,19 @@ export async function listModels(webviewView: WebviewView): Promise<void> {
* @param modelName The exact name of the model to select
*/
export async function selectModel(webviewView: WebviewView, modelName: string): Promise<void> {
try {
const selectElement = await waitForElement(webviewView, By.css('.mynah-form-input.auto-width'))
await selectElement.click()
const options = await selectElement.findElements(By.css('option'))
let targetOption: WebElement | undefined
for (const option of options) {
const optionText = await option.getText()
if (optionText === modelName) {
targetOption = option
break
}
const selectElement = await waitForElement(webviewView, By.css('.mynah-form-input.auto-width'))
await selectElement.click()
const options = await selectElement.findElements(By.css('option'))
let targetOption: WebElement | undefined
for (const option of options) {
const optionText = await option.getText()
if (optionText === modelName) {
targetOption = option
break
}
if (!targetOption) {
throw new Error(`Model option "${modelName}" not found`)
}
await targetOption.click()
console.log(`Selected model option: ${modelName}`)
} catch (e) {
console.error('Error selecting model option:', e)
throw e
}
if (!targetOption) {
throw new Error(`Model option "${modelName}" not found`)
}
await targetOption.click()
}
6 changes: 1 addition & 5 deletions packages/amazonq/test/e2e_new/amazonq/tests/chat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ describe('Amazon Q Chat Basic Functionality', function () {

it('Chat Prompt Test', async () => {
await writeToChat('Hello, Amazon Q!', webviewView)
const responseReceived = await waitForChatResponse(webviewView)
if (!responseReceived) {
throw new Error('Chat response not received within timeout')
}
console.log('Chat response detected successfully')
await waitForChatResponse(webviewView)
})
})
58 changes: 22 additions & 36 deletions packages/amazonq/test/e2e_new/amazonq/utils/cleanupUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,41 @@ import { sleep } from './generalUtils'
/**
* Closes all open chat tabs
* @param webview The WebviewView instance
* @returns Promise<boolean> True if all tabs were successfully closed
* @throws Error if tabs could not be closed
*/
export async function closeAllTabs(webview: WebviewView): Promise<boolean> {
try {
const closeButtons = await webview.findWebElements(By.css('.mynah-tabs-close-button'))
export async function closeAllTabs(webview: WebviewView): Promise<void> {
const closeButtons = await webview.findWebElements(By.css('.mynah-tabs-close-button'))

for (const button of closeButtons) {
await button.click()
await sleep(500)
}
for (const button of closeButtons) {
await button.click()
await sleep(500)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: look into this sleep.

}

const tabsContainer = await webview.findWebElements(By.css('.mynah-tabs-container'))
const allClosed =
tabsContainer.length === 1 ||
(await tabsContainer[0].findElements(By.css('.mynah-tab-item-label'))).length === 0
const tabsContainer = await webview.findWebElements(By.css('.mynah-tabs-container'))
const allClosed =
tabsContainer.length === 1 ||
(await tabsContainer[0].findElements(By.css('.mynah-tab-item-label'))).length === 0

if (allClosed) {
console.log('All chat tabs successfully closed')
return true
} else {
throw new Error('Failed to close all tabs')
}
} catch (error) {
console.error('Error closing tabs:', error)
throw error
if (!allClosed) {
throw new Error('Failed to close all tabs')
}
}

/**
* Attempts to dismiss any open overlays
* @param webview The WebviewView instance
* @returns Promise<boolean> True if overlay was dismissed or none was present, false if dismissal failed
* @throws Error if overlay dismissal failed
*/
export async function dismissOverlayIfPresent(webview: WebviewView): Promise<boolean> {
try {
const overlays = await webview.findWebElements(By.css('.mynah-overlay.mynah-overlay-open'))
if (overlays.length > 0) {
console.log('Overlay detected, attempting to dismiss...')
const driver = webview.getDriver()
await driver.executeScript('document.body.click()')
export async function dismissOverlayIfPresent(webview: WebviewView): Promise<void> {
const overlays = await webview.findWebElements(By.css('.mynah-overlay.mynah-overlay-open'))
if (overlays.length > 0) {
const driver = webview.getDriver()
await driver.executeScript('document.body.click()')

await sleep(1000)
const overlaysAfter = await webview.findWebElements(By.css('.mynah-overlay.mynah-overlay-open'))
return overlaysAfter.length === 0
await sleep(1000)
const overlaysAfter = await webview.findWebElements(By.css('.mynah-overlay.mynah-overlay-open'))
if (overlaysAfter.length > 0) {
throw new Error('Failed to dismiss overlay')
}
return true
} catch (e) {
console.log('Error while trying to dismiss overlay:', e)
return false
}
}
37 changes: 14 additions & 23 deletions packages/amazonq/test/e2e_new/amazonq/utils/generalUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,23 @@ export async function pressShortcut(driver: WebDriver, ...keys: (keyof typeof Ke
* @param prompt The text to write in the chat input
* @param webview The WebviewView instance
* @param send Whether to click the send button (defaults to true)
* @returns Promise<boolean> True if successful
*/
export async function writeToChat(prompt: string, webview: WebviewView, send = true): Promise<boolean> {
export async function writeToChat(prompt: string, webview: WebviewView, send = true): Promise<void> {
const chatInput = await waitForElement(webview, By.css('.mynah-chat-prompt-input'))
await chatInput.sendKeys(prompt)
if (send === true) {
if (send) {
const sendButton = await waitForElement(webview, By.css('.mynah-chat-prompt-button'))
await sendButton.click()
}
return true
}

/**
* Waits for a chat response to be generated
* @param webview The WebviewView instance
* @param timeout The timeout in milliseconds
* @returns Promise<boolean> True if a response was detected, false if timeout occurred
* @throws Error if timeout occurs before response is detected
*/
export async function waitForChatResponse(webview: WebviewView, timeout = 15000): Promise<boolean> {
export async function waitForChatResponse(webview: WebviewView, timeout = 15000): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, is there a reason we need to increase the default here?

const startTime = Date.now()

while (Date.now() - startTime < timeout) {
Expand All @@ -103,34 +101,27 @@ export async function waitForChatResponse(webview: WebviewView, timeout = 15000)
const chatItems = await latestContainer.findElements(By.css('*'))

if (chatItems.length >= 2) {
return true
return
}
}
await sleep(500)
}

return false
throw new Error('Timeout waiting for chat response')
}

/**
* Clears the text in the chat input field
* @param webview The WebviewView instance
* @returns Promise<boolean> True if successful, false if an error occurred
*/
export async function clearChat(webview: WebviewView): Promise<boolean> {
try {
const chatInput = await waitForElement(webview, By.css('.mynah-chat-prompt-input'))
await chatInput.sendKeys(
process.platform === 'darwin'
? '\uE03D\u0061' // Command+A on macOS
: '\uE009\u0061' // Ctrl+A on Windows/Linux
)
await chatInput.sendKeys('\uE003') // Backspace
return true
} catch (e) {
console.error('Error clearing chat input:', e)
return false
}
export async function clearChat(webview: WebviewView): Promise<void> {
const chatInput = await waitForElement(webview, By.css('.mynah-chat-prompt-input'))
await chatInput.sendKeys(
process.platform === 'darwin'
? '\uE03D\u0061' // Command+A on macOS
: '\uE009\u0061' // Ctrl+A on Windows/Linux
)
await chatInput.sendKeys('\uE003') // Backspace
}

/**
Expand Down
Loading