diff --git a/packages/amazonq/test/e2e/amazonq/featureDev.test.ts b/packages/amazonq/test/e2e/amazonq/featureDev.test.ts index 644b6209452..a0dd92b7ac3 100644 --- a/packages/amazonq/test/e2e/amazonq/featureDev.test.ts +++ b/packages/amazonq/test/e2e/amazonq/featureDev.test.ts @@ -18,6 +18,7 @@ describe('Amazon Q Feature Dev', function () { const prompt = 'Add blank.txt file with empty content' const codegenApproachPrompt = prompt + ' and add a readme that describes the changes' + const fileLevelAcceptPrompt = prompt + ' and add a license, and a contributing file' const tooManyRequestsWaitTime = 100000 function waitForButtons(buttons: FollowUpTypes[]) { @@ -50,6 +51,11 @@ describe('Amazon Q Feature Dev', function () { ) } + async function clickActionButton(filePath: string, actionName: string) { + tab.clickFileActionButton(filePath, actionName) + await tab.waitForEvent(() => !tab.hasAction(filePath, actionName)) + } + /** * Wait for the original request to finish. * If the response has a retry button or encountered a guardrails error, continue retrying @@ -215,87 +221,111 @@ describe('Amazon Q Feature Dev', function () { tab.clickButton(FollowUpTypes.InsertCode) await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession]) }) + }) - describe('file-level accepts', async () => { - beforeEach(async () => { - await retryIfRequired(async () => { - await Promise.any([ - waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]), - waitForButtons([FollowUpTypes.Retry]), - ]) - }) + describe('file-level accepts', async () => { + beforeEach(async function () { + tab.addChatMessage({ command: '/dev', prompt: fileLevelAcceptPrompt }) + await retryIfRequired( + async () => { + await tab.waitForChatFinishesLoading() + }, + () => { + tab.addChatMessage({ prompt }) + } + ) + await retryIfRequired(async () => { + await Promise.any([ + waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]), + waitForButtons([FollowUpTypes.Retry]), + ]) }) + }) - describe('fileList', async () => { - it('has both accept-change and reject-change action buttons for file', async () => { - const filePath = tab.getFilePaths()[0] - assert.ok(tab.getActionsByFilePath(filePath).length === 2) - assert.ok(tab.hasAction(filePath, 'accept-change')) - assert.ok(tab.hasAction(filePath, 'reject-change')) - }) + describe('fileList', async () => { + it('has both accept-change and reject-change action buttons for file', async () => { + const filePath = tab.getFilePaths()[0] + assert.ok(tab.getActionsByFilePath(filePath).length === 2) + assert.ok(tab.hasAction(filePath, 'accept-change')) + assert.ok(tab.hasAction(filePath, 'reject-change')) + }) - it('has only revert-rejection action buttons for rejected file', async () => { - const filePath = tab.getFilePaths()[0] - tab.clickFileActionButton(filePath, 'reject-change') - await tab.waitForEvent(() => !tab.hasAction(filePath, 'reject-change')) + it('has only revert-rejection action button for rejected file', async () => { + const filePath = tab.getFilePaths()[0] + await clickActionButton(filePath, 'reject-change') - assert.ok(tab.getActionsByFilePath(filePath).length === 1) - assert.ok(tab.hasAction(filePath, 'revert-rejection')) - }) + assert.ok(tab.getActionsByFilePath(filePath).length === 1) + assert.ok(tab.hasAction(filePath, 'revert-rejection')) + }) - it('does not have any action buttons for accepted file', async () => { - const filePath = tab.getFilePaths()[0] - tab.clickFileActionButton(filePath, 'accept-change') - await tab.waitForEvent(() => !tab.hasAction(filePath, 'accept-change')) + it('does not have any of the action buttons for accepted file', async () => { + const filePath = tab.getFilePaths()[0] + await clickActionButton(filePath, 'accept-change') - assert.ok(tab.getActionsByFilePath(filePath).length === 0) - }) + assert.ok(tab.getActionsByFilePath(filePath).length === 0) }) - describe('accept changes button', async () => { - describe('button text', async () => { - it('shows Accept all changes when all files are neither accepted nor rejected', async () => { - const insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) - assert.ok(insertCodeButton.pillText === 'Accept all changes') - }) + it('disables all action buttons when new task is clicked', async () => { + tab.clickButton(FollowUpTypes.InsertCode) + await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession]) + tab.clickButton(FollowUpTypes.NewTask) + await waitForText('What new task would you like to work on?') + + const filePaths = tab.getFilePaths() + for (const filePath of filePaths) { + assert.ok(tab.getActionsByFilePath(filePath).length === 0) + } + }) - it('shows Accept remaining changes when one or more file is rejected', async () => { - const filePath = tab.getFilePaths()[0] - tab.clickFileActionButton(filePath, 'reject-change') - await tab.waitForEvent(() => !tab.hasAction(filePath, 'reject-change')) + it('disables all action buttons when close session is clicked', async () => { + tab.clickButton(FollowUpTypes.InsertCode) + await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession]) + tab.clickButton(FollowUpTypes.CloseSession) + await waitForText( + "Okay, I've ended this chat session. You can open a new tab to chat or start another workflow." + ) - const insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) - assert.ok(insertCodeButton.pillText === 'Accept remaining changes') - }) + const filePaths = tab.getFilePaths() + for (const filePath of filePaths) { + assert.ok(tab.getActionsByFilePath(filePath).length === 0) + } + }) + }) - it('shows Accept remaining changes when one or more file is accepted', async () => { - const filePath = tab.getFilePaths()[0] - tab.clickFileActionButton(filePath, 'accept-change') - await tab.waitForEvent(() => !tab.hasAction(filePath, 'accept-change')) + describe('accept button', async () => { + describe('button text', async () => { + it('shows "Accept all changes" when no files are accepted or rejected, and "Accept remaining changes" otherwise', async () => { + let insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) + assert.ok(insertCodeButton.pillText === 'Accept all changes') - const insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) - assert.ok(insertCodeButton.pillText === 'Accept remaining changes') - }) + const filePath = tab.getFilePaths()[0] + await clickActionButton(filePath, 'reject-change') - it('shows Accept remaining changes when a file is rejected, then shows Accept all changes again when the rejection is reverted', async () => { - let insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) - assert.ok(insertCodeButton.pillText === 'Accept all changes') + insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) + assert.ok(insertCodeButton.pillText === 'Accept remaining changes') - const filePath = tab.getFilePaths()[0] - tab.clickFileActionButton(filePath, 'reject-change') - await tab.waitForEvent(() => !tab.hasAction(filePath, 'reject-change')) + await clickActionButton(filePath, 'revert-rejection') - insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) - assert.ok(insertCodeButton.pillText === 'Accept remaining changes') + insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) + assert.ok(insertCodeButton.pillText === 'Accept all changes') - tab.clickFileActionButton(filePath, 'revert-rejection') - await tab.waitForEvent(() => !tab.hasAction(filePath, 'revert-rejection')) + await clickActionButton(filePath, 'accept-change') - insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) - assert.ok(insertCodeButton.pillText === 'Accept all changes') - }) + insertCodeButton = tab.getFollowUpButton(FollowUpTypes.InsertCode) + assert.ok(insertCodeButton.pillText === 'Accept remaining changes') }) }) + + it('disappears and automatically moves on to the next step when all changes are accepted', async () => { + const filePaths = tab.getFilePaths() + for (const filePath of filePaths) { + await clickActionButton(filePath, 'accept-change') + } + await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession]) + + assert.ok(tab.hasButton(FollowUpTypes.InsertCode) === false) + assert.ok(tab.hasButton(FollowUpTypes.ProvideFeedbackAndRegenerateCode) === false) + }) }) }) }) diff --git a/packages/amazonq/test/e2e/amazonq/framework/messenger.ts b/packages/amazonq/test/e2e/amazonq/framework/messenger.ts index f026e4366b4..28b34aa3bdb 100644 --- a/packages/amazonq/test/e2e/amazonq/framework/messenger.ts +++ b/packages/amazonq/test/e2e/amazonq/framework/messenger.ts @@ -129,10 +129,7 @@ export class Messenger { getActionsByFilePath(filePath: string) { const fileList = this.getFileList() const actions = fileList?.fileList?.actions - if (!actions) { - assert.fail('Could not find file list actions') - } - return actions[filePath] + return actions?.[filePath] ?? [] } hasButton(type: FollowUpTypes) {