Skip to content

Commit 548fd14

Browse files
authored
feat(amazonq): Add Pin Context Tests and Update to pinContextHelper (#7829)
## Problem We have yet to implement the initial P0 Pin Context Tests. The pinContextHelper does not mesh well with sub menu items when clicking through different prompts to use. ## Solution I have implemented the File Context and Prompt Context Test. The Pin Context test with the @workspace was previously implemented. I have implemented the helpers: getSubMenuItems and clickSubMenuItem in the pinContextHelper. All tests still run together. Test Suite: - View Context Options - Reusable Prompt (New) - Add File as context (New) - Add Workspace as Context --- - 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.
1 parent 9db3a91 commit 548fd14

File tree

2 files changed

+127
-78
lines changed

2 files changed

+127
-78
lines changed

packages/amazonq/test/e2e_new/amazonq/helpers/pinContextHelper.ts

Lines changed: 101 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,25 @@ import { WebElement } from 'vscode-extension-tester'
99
/**
1010
* Clicks the "Pin Context" button in the chat interface
1111
* @param webview The WebviewView instance
12-
* @returns Promise<boolean> True if button was found and clicked, false otherwise
12+
* @throws Error if button is not found
1313
*/
14-
export async function clickPinContextButton(webview: WebviewView): Promise<boolean> {
15-
try {
16-
const topBar = await waitForElement(webview, By.css('.mynah-prompt-input-top-bar'))
17-
const buttons = await topBar.findElements(
18-
By.css('.mynah-button.mynah-button-secondary.fill-state-always.status-clear.mynah-ui-clickable-item')
19-
)
20-
// double check the label to make sure it says "Pin Context"
21-
for (const button of buttons) {
22-
const label = await button.findElement(By.css('.mynah-button-label'))
23-
const labelText = await label.getText()
24-
console.log('THE BUTTON TEXT LABEL IS:', labelText)
25-
if (labelText === '@Pin Context') {
26-
console.log('Found Pin Context button, clicking...')
27-
await button.click()
28-
return true
29-
}
14+
export async function clickPinContextButton(webview: WebviewView): Promise<void> {
15+
const topBar = await waitForElement(webview, By.css('.mynah-prompt-input-top-bar'))
16+
const buttons = await topBar.findElements(
17+
By.css('.mynah-button.mynah-button-secondary.fill-state-always.status-clear.mynah-ui-clickable-item')
18+
)
19+
// double check the label to make sure it says "Pin Context"
20+
for (const button of buttons) {
21+
const label = await button.findElement(By.css('.mynah-button-label'))
22+
const labelText = await label.getText()
23+
console.log('THE BUTTON TEXT LABEL IS:', labelText)
24+
if (labelText === '@Pin Context') {
25+
console.log('Found Pin Context button, clicking...')
26+
await button.click()
27+
return
3028
}
31-
console.log('Pin Context button not found')
32-
return false
33-
} catch (e) {
34-
console.error('Error clicking Pin Context button:', e)
35-
return false
3629
}
30+
throw new Error('Pin Context button not found')
3731
}
3832

3933
/**
@@ -42,65 +36,105 @@ export async function clickPinContextButton(webview: WebviewView): Promise<boole
4236
* @returns Promise<boolean> Returns the items as a WebElement List and the labels in a string array
4337
*/
4438
export async function getPinContextMenuItems(webview: WebviewView): Promise<{ items: WebElement[]; labels: string[] }> {
45-
try {
46-
const menuList = await waitForElement(webview, By.css('.mynah-detailed-list-items-block'))
47-
await sleep(3000)
48-
const menuListItems = await menuList.findElements(By.css('.mynah-detailed-list-item.mynah-ui-clickable-item'))
49-
const labels: string[] = []
39+
const menuList = await waitForElement(webview, By.css('.mynah-detailed-list-items-block'))
40+
// TODO: Fix the need for a sleep function to be required at all.
41+
await sleep(100)
42+
const menuListItems = await menuList.findElements(By.css('.mynah-detailed-list-item.mynah-ui-clickable-item'))
5043

51-
for (const item of menuListItems) {
52-
try {
53-
const textWrapper = await item.findElement(By.css('.mynah-detailed-list-item-text'))
54-
const nameElement = await textWrapper.findElement(By.css('.mynah-detailed-list-item-name'))
55-
const labelText = await nameElement.getText()
56-
labels.push(labelText)
57-
console.log('Menu item found:', labelText)
58-
} catch (e) {
59-
labels.push('')
60-
console.log('Could not get text for menu item')
61-
}
62-
}
44+
if (menuListItems.length === 0) {
45+
throw new Error('No pin context menu items found')
46+
}
6347

64-
return { items: menuListItems, labels }
65-
} catch (e) {
66-
console.error('Error getting Pin Context menu items:', e)
67-
return { items: [], labels: [] }
48+
const labels: string[] = []
49+
for (const item of menuListItems) {
50+
const textWrapper = await item.findElement(By.css('.mynah-detailed-list-item-text'))
51+
const nameElement = await textWrapper.findElement(By.css('.mynah-detailed-list-item-name'))
52+
const labelText = await nameElement.getText()
53+
labels.push(labelText)
54+
console.log('Menu item found:', labelText)
6855
}
56+
57+
return { items: menuListItems, labels }
6958
}
7059

7160
/**
7261
* Clicks a specific item in the Pin Context menu by its label text
7362
* @param webview The WebviewView instance
7463
* @param itemName The text label of the menu item to click
75-
* @returns Promise<boolean> True if the item was found and clicked, false otherwise
64+
* @throws Error if the menu item is not found or DOM structure is invalid
7665
*
7766
* NOTE: To find all possible text labels, you can call getPinContextMenuItems
7867
*/
79-
export async function clickPinContextMenuItem(webview: WebviewView, itemName: string): Promise<boolean> {
80-
try {
81-
const menuList = await waitForElement(webview, By.css('.mynah-detailed-list-items-block'))
82-
await sleep(3000)
83-
const menuListItems = await menuList.findElements(By.css('.mynah-detailed-list-item.mynah-ui-clickable-item'))
84-
for (const item of menuListItems) {
85-
try {
86-
const textWrapper = await item.findElement(By.css('.mynah-detailed-list-item-text'))
87-
const nameElement = await textWrapper.findElement(By.css('.mynah-detailed-list-item-name'))
88-
const labelText = await nameElement.getText()
68+
export async function clickPinContextMenuItem(webview: WebviewView, itemName: string): Promise<void> {
69+
const menuList = await waitForElement(webview, By.css('.mynah-detailed-list-items-block'))
70+
await sleep(100)
71+
const menuListItems = await menuList.findElements(By.css('.mynah-detailed-list-item.mynah-ui-clickable-item'))
72+
for (const item of menuListItems) {
73+
const textWrapper = await item.findElement(By.css('.mynah-detailed-list-item-text'))
74+
const nameElement = await textWrapper.findElement(By.css('.mynah-detailed-list-item-name'))
75+
const labelText = await nameElement.getText()
8976

90-
if (labelText === itemName) {
91-
console.log(`Clicking Pin Context menu item: ${itemName}`)
92-
await item.click()
93-
return true
94-
}
95-
} catch (e) {
96-
continue
97-
}
77+
if (labelText === itemName) {
78+
console.log(`Clicking Pin Context menu item: ${itemName}`)
79+
await item.click()
80+
return
9881
}
82+
}
83+
84+
throw new Error(`Pin Context menu item not found: ${itemName}`)
85+
}
86+
/**
87+
* Lists all the possible Sub-menu items in the console.
88+
* @param webview The WebviewView instance
89+
* @returns Promise<boolean> Returns the items as a WebElement List and the labels in a string array
90+
*/
91+
export async function getSubMenuItems(webview: WebviewView): Promise<{ items: WebElement[]; labels: string[] }> {
92+
const menuList = await waitForElement(webview, By.css('.mynah-detailed-list-items-block'))
93+
await sleep(100)
94+
const menuListItems = await menuList.findElements(By.css('.mynah-detailed-list-item.mynah-ui-clickable-item'))
9995

100-
console.log(`Pin Context menu item not found: ${itemName}`)
101-
return false
102-
} catch (e) {
103-
console.error(`Error clicking Pin Context menu item ${itemName}:`, e)
104-
return false
96+
if (menuListItems.length === 0) {
97+
throw new Error('No sub-menu items found')
98+
}
99+
100+
const labels: string[] = []
101+
for (const item of menuListItems) {
102+
const textWrapper = await item.findElement(
103+
By.css('.mynah-detailed-list-item-text.mynah-detailed-list-item-text-direction-row')
104+
)
105+
const nameElement = await textWrapper.findElement(By.css('.mynah-detailed-list-item-name'))
106+
const labelText = await nameElement.getText()
107+
labels.push(labelText)
108+
console.log('Menu item found:', labelText)
105109
}
110+
111+
return { items: menuListItems, labels }
112+
}
113+
/**
114+
* Clicks a specific item in the Sub-Menu by its label text
115+
* @param webview The WebviewView instance
116+
* @param itemName The text label of the menu item to click
117+
* @throws Error if the menu item is not found or DOM structure is invalid
118+
*
119+
* NOTE: To find all possible text labels, you can call getPinContextMenuItems
120+
*/
121+
export async function clickSubMenuItem(webview: WebviewView, itemName: string): Promise<void> {
122+
const menuList = await waitForElement(webview, By.css('.mynah-detailed-list-items-block'))
123+
await sleep(100)
124+
const menuListItems = await menuList.findElements(By.css('.mynah-detailed-list-item.mynah-ui-clickable-item'))
125+
for (const item of menuListItems) {
126+
const textWrapper = await item.findElement(
127+
By.css('.mynah-detailed-list-item-text.mynah-detailed-list-item-text-direction-row')
128+
)
129+
const nameElement = await textWrapper.findElement(By.css('.mynah-detailed-list-item-name'))
130+
const labelText = await nameElement.getText()
131+
132+
if (labelText === itemName) {
133+
console.log(`Clicking Pin Context menu item: ${itemName}`)
134+
await item.click()
135+
return
136+
}
137+
}
138+
139+
throw new Error(`Pin Context menu item not found: ${itemName}`)
106140
}

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

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55
import '../utils/setup'
6-
import { WebviewView } from 'vscode-extension-tester'
6+
import { WebviewView, By } from 'vscode-extension-tester'
77
import { closeAllTabs, dismissOverlayIfPresent } from '../utils/cleanupUtils'
88
import { testContext } from '../utils/testContext'
9-
import { clickPinContextButton, getPinContextMenuItems, clickPinContextMenuItem } from '../helpers/pinContextHelper'
10-
import { clearChatInput } from '../utils/generalUtils'
9+
import { clickPinContextButton, clickPinContextMenuItem, clickSubMenuItem } from '../helpers/pinContextHelper'
10+
import { waitForElement } from '../utils/generalUtils'
1111

1212
describe('Amazon Q Pin Context Functionality', function () {
1313
// this timeout is the general timeout for the entire test suite
@@ -18,18 +18,33 @@ describe('Amazon Q Pin Context Functionality', function () {
1818
webviewView = testContext.webviewView
1919
})
2020

21-
after(async function () {
22-
await closeAllTabs(webviewView)
23-
})
24-
2521
afterEach(async () => {
2622
await dismissOverlayIfPresent(webviewView)
27-
await clearChatInput(webviewView)
23+
await closeAllTabs(webviewView)
2824
})
29-
30-
it('Pin Context Test', async () => {
25+
it('Allows User to Add File Context', async () => {
26+
await clickPinContextButton(webviewView)
27+
await clickPinContextMenuItem(webviewView, 'Files')
28+
await clickPinContextMenuItem(webviewView, 'Active file')
29+
})
30+
it('Allows User to Pin Workspace Context', async () => {
3131
await clickPinContextButton(webviewView)
32-
await getPinContextMenuItems(webviewView)
3332
await clickPinContextMenuItem(webviewView, '@workspace')
3433
})
34+
it('Allows User to Add Prompt Context', async () => {
35+
await clickPinContextButton(webviewView)
36+
await clickPinContextMenuItem(webviewView, 'Prompts')
37+
const addPrompt = await waitForElement(webviewView, By.css('.mynah-ui-icon.mynah-ui-icon-list-add'))
38+
await addPrompt.click()
39+
const chatInput = await waitForElement(webviewView, By.css('[data-testid="chat-item-form-item-text-input"]'))
40+
await chatInput.sendKeys('test')
41+
const createPrompt = await waitForElement(
42+
webviewView,
43+
By.css('.mynah-button.fill-state-always.status-primary.mynah-ui-clickable-item')
44+
)
45+
await createPrompt.click()
46+
await clickPinContextButton(webviewView)
47+
await clickPinContextMenuItem(webviewView, 'Prompts')
48+
await clickSubMenuItem(webviewView, 'test')
49+
})
3550
})

0 commit comments

Comments
 (0)