Skip to content

Commit 3fa6ded

Browse files
committed
add e2e tests for file-level accepts
1 parent b19461d commit 3fa6ded

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

packages/amazonq/test/e2e/amazonq/featureDev.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,5 +215,87 @@ describe('Amazon Q Feature Dev', function () {
215215
tab.clickButton(FollowUpTypes.InsertCode)
216216
await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
217217
})
218+
219+
describe('file-level accepts', async () => {
220+
beforeEach(async () => {
221+
await retryIfRequired(async () => {
222+
await Promise.any([
223+
waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
224+
waitForButtons([FollowUpTypes.Retry]),
225+
])
226+
})
227+
})
228+
229+
describe('fileList', async () => {
230+
it('has both accept-change and reject-change action buttons for file', async () => {
231+
const filePath = tab.getFilePaths()[0]
232+
assert.ok(tab.getActionsByFilePath(filePath).length === 2)
233+
assert.ok(tab.hasAction(filePath, 'accept-change'))
234+
assert.ok(tab.hasAction(filePath, 'reject-change'))
235+
})
236+
237+
it('has only revert-rejection action buttons for rejected file', async () => {
238+
const filePath = tab.getFilePaths()[0]
239+
tab.clickFileActionButton(filePath, 'reject-change')
240+
await tab.waitForEvent(() => !tab.hasAction(filePath, 'reject-change'))
241+
242+
assert.ok(tab.getActionsByFilePath(filePath).length === 1)
243+
assert.ok(tab.hasAction(filePath, 'revert-rejection'))
244+
})
245+
246+
it('does not have any action buttons for accepted file', async () => {
247+
const filePath = tab.getFilePaths()[0]
248+
tab.clickFileActionButton(filePath, 'accept-change')
249+
await tab.waitForEvent(() => !tab.hasAction(filePath, 'accept-change'))
250+
251+
assert.ok(tab.getActionsByFilePath(filePath).length === 0)
252+
})
253+
})
254+
255+
describe('accept changes button', async () => {
256+
describe('button text', async () => {
257+
it('shows Accept all changes when all files are neither accepted nor rejected', async () => {
258+
const insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode)
259+
assert.ok(insertCodeButton.pillText === 'Accept all changes')
260+
})
261+
262+
it('shows Accept remaining changes when one or more file is rejected', async () => {
263+
const filePath = tab.getFilePaths()[0]
264+
tab.clickFileActionButton(filePath, 'reject-change')
265+
await tab.waitForEvent(() => !tab.hasAction(filePath, 'reject-change'))
266+
267+
const insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode)
268+
assert.ok(insertCodeButton.pillText === 'Accept remaining changes')
269+
})
270+
271+
it('shows Accept remaining changes when one or more file is accepted', async () => {
272+
const filePath = tab.getFilePaths()[0]
273+
tab.clickFileActionButton(filePath, 'accept-change')
274+
await tab.waitForEvent(() => !tab.hasAction(filePath, 'accept-change'))
275+
276+
const insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode)
277+
assert.ok(insertCodeButton.pillText === 'Accept remaining changes')
278+
})
279+
280+
it('shows Accept remaining changes when a file is rejected, then shows Accept all changes again when the rejection is reverted', async () => {
281+
let insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode)
282+
assert.ok(insertCodeButton.pillText === 'Accept all changes')
283+
284+
const filePath = tab.getFilePaths()[0]
285+
tab.clickFileActionButton(filePath, 'reject-change')
286+
await tab.waitForEvent(() => !tab.hasAction(filePath, 'reject-change'))
287+
288+
insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode)
289+
assert.ok(insertCodeButton.pillText === 'Accept remaining changes')
290+
291+
tab.clickFileActionButton(filePath, 'revert-rejection')
292+
await tab.waitForEvent(() => !tab.hasAction(filePath, 'revert-rejection'))
293+
294+
insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode)
295+
assert.ok(insertCodeButton.pillText === 'Accept all changes')
296+
})
297+
})
298+
})
299+
})
218300
})
219301
})

packages/amazonq/test/e2e/amazonq/framework/messenger.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ export class Messenger {
5959
this.mynahUIProps.onFollowUpClicked(this.tabID, lastChatItem?.messageId ?? '', option[0])
6060
}
6161

62+
clickFileActionButton(filePath: string, actionName: string) {
63+
if (!this.mynahUIProps.onFileActionClick) {
64+
assert.fail('onFileActionClick must be defined to use it in the tests')
65+
}
66+
67+
this.mynahUIProps.onFileActionClick(this.tabID, this.getFileListMessageId(), filePath, actionName)
68+
}
69+
6270
findCommand(command: string) {
6371
return this.getCommands()
6472
.map((groups) => groups.commands)
@@ -78,6 +86,55 @@ export class Messenger {
7886
return this.getStore().promptInputPlaceholder
7987
}
8088

89+
getFollowUpButton(type: FollowUpTypes) {
90+
const followUpButton = this.getChatItems()
91+
.pop()
92+
?.followUp?.options?.find((action) => action.type === type)
93+
if (!followUpButton) {
94+
assert.fail(`Could not find follow up button with type ${type}`)
95+
}
96+
return followUpButton
97+
}
98+
99+
getFileList() {
100+
const chatItems = this.getChatItems()
101+
const fileList = chatItems.find((item) => 'fileList' in item)
102+
if (!fileList) {
103+
assert.fail('Could not find file list')
104+
}
105+
return fileList
106+
}
107+
108+
getFileListMessageId() {
109+
const fileList = this.getFileList()
110+
const messageId = fileList?.messageId
111+
if (!messageId) {
112+
assert.fail('Could not find file list message id')
113+
}
114+
return messageId
115+
}
116+
117+
getFilePaths() {
118+
const fileList = this.getFileList()
119+
const filePaths = fileList?.fileList?.filePaths
120+
if (!filePaths) {
121+
assert.fail('Could not find file paths')
122+
}
123+
if (filePaths.length === 0) {
124+
assert.fail('File paths list is empty')
125+
}
126+
return filePaths
127+
}
128+
129+
getActionsByFilePath(filePath: string) {
130+
const fileList = this.getFileList()
131+
const actions = fileList?.fileList?.actions
132+
if (!actions) {
133+
assert.fail('Could not find file list actions')
134+
}
135+
return actions[filePath]
136+
}
137+
81138
hasButton(type: FollowUpTypes) {
82139
return (
83140
this.getChatItems()
@@ -87,6 +144,10 @@ export class Messenger {
87144
)
88145
}
89146

147+
hasAction(filePath: string, actionName: string) {
148+
return this.getActionsByFilePath(filePath).some((action) => action.name === actionName)
149+
}
150+
90151
async waitForChatFinishesLoading() {
91152
return this.waitForEvent(() => this.getStore().loadingChat === false || this.hasButton(FollowUpTypes.Retry))
92153
}

0 commit comments

Comments
 (0)