Skip to content

Commit 1bc5bdc

Browse files
committed
Merge branch 'master' into ec2/commentkeys
2 parents 37d64ae + f988458 commit 1bc5bdc

34 files changed

+2705
-261
lines changed

package-lock.json

Lines changed: 916 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"generateNonCodeFiles": "npm run generateNonCodeFiles -w packages/ --if-present"
4040
},
4141
"devDependencies": {
42-
"@aws-toolkits/telemetry": "^1.0.284",
42+
"@aws-toolkits/telemetry": "^1.0.287",
4343
"@playwright/browser-chromium": "^1.43.1",
4444
"@stylistic/eslint-plugin": "^2.11.0",
4545
"@types/he": "^1.2.3",
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Auth: SSO session was bad, but no reauth prompt given"
4+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import assert from 'assert'
7+
import { qTestingFramework } from './framework/framework'
8+
import sinon from 'sinon'
9+
import { registerAuthHook, using } from 'aws-core-vscode/test'
10+
import { loginToIdC } from './utils/setup'
11+
import { Messenger } from './framework/messenger'
12+
import { FollowUpTypes } from 'aws-core-vscode/amazonq'
13+
import { i18n } from 'aws-core-vscode/shared'
14+
import { docGenerationProgressMessage, DocGenerationStep, Mode } from 'aws-core-vscode/amazonqDoc'
15+
16+
describe('Amazon Q Doc', async function () {
17+
let framework: qTestingFramework
18+
let tab: Messenger
19+
20+
before(async function () {
21+
/**
22+
* The tests are getting throttled, only run them on stable for now
23+
*
24+
* TODO: Re-enable for all versions once the backend can handle them
25+
*/
26+
const testVersion = process.env['VSCODE_TEST_VERSION']
27+
if (testVersion && testVersion !== 'stable') {
28+
this.skip()
29+
}
30+
31+
await using(registerAuthHook('amazonq-test-account'), async () => {
32+
await loginToIdC()
33+
})
34+
})
35+
36+
beforeEach(() => {
37+
registerAuthHook('amazonq-test-account')
38+
framework = new qTestingFramework('doc', true, [])
39+
tab = framework.createTab()
40+
})
41+
42+
afterEach(() => {
43+
framework.removeTab(tab.tabID)
44+
framework.dispose()
45+
sinon.restore()
46+
})
47+
48+
describe('Quick action availability', () => {
49+
it('Shows /doc when doc generation is enabled', async () => {
50+
const command = tab.findCommand('/doc')
51+
if (!command.length) {
52+
assert.fail('Could not find command')
53+
}
54+
55+
if (command.length > 1) {
56+
assert.fail('Found too many commands with the name /doc')
57+
}
58+
})
59+
60+
it('Does NOT show /doc when doc generation is NOT enabled', () => {
61+
// The beforeEach registers a framework which accepts requests. If we don't dispose before building a new one we have duplicate messages
62+
framework.dispose()
63+
framework = new qTestingFramework('doc', false, [])
64+
const tab = framework.createTab()
65+
const command = tab.findCommand('/doc')
66+
if (command.length > 0) {
67+
assert.fail('Found command when it should not have been found')
68+
}
69+
})
70+
})
71+
72+
describe('/doc entry', () => {
73+
beforeEach(async function () {
74+
tab.addChatMessage({ command: '/doc' })
75+
await tab.waitForChatFinishesLoading()
76+
})
77+
78+
it('Checks for initial follow ups', async () => {
79+
await tab.waitForButtons([FollowUpTypes.CreateDocumentation, FollowUpTypes.UpdateDocumentation])
80+
})
81+
})
82+
83+
describe('Creates a README', () => {
84+
beforeEach(async function () {
85+
tab.addChatMessage({ command: '/doc' })
86+
await tab.waitForChatFinishesLoading()
87+
})
88+
89+
it('Creates a README for root folder', async () => {
90+
await tab.waitForButtons([FollowUpTypes.CreateDocumentation])
91+
92+
tab.clickButton(FollowUpTypes.CreateDocumentation)
93+
94+
await tab.waitForText(i18n('AWS.amazonq.doc.answer.createReadme'))
95+
96+
await tab.waitForButtons([FollowUpTypes.ProceedFolderSelection])
97+
98+
tab.clickButton(FollowUpTypes.ProceedFolderSelection)
99+
100+
await tab.waitForText(docGenerationProgressMessage(DocGenerationStep.SUMMARIZING_FILES, Mode.CREATE))
101+
102+
await tab.waitForText(
103+
`${i18n('AWS.amazonq.doc.answer.readmeCreated')} ${i18n('AWS.amazonq.doc.answer.codeResult')}`
104+
)
105+
106+
await tab.waitForButtons([
107+
FollowUpTypes.AcceptChanges,
108+
FollowUpTypes.MakeChanges,
109+
FollowUpTypes.RejectChanges,
110+
])
111+
})
112+
})
113+
})

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

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,11 @@ describe('Amazon Q Feature Dev', function () {
2222
const fileLevelAcceptPrompt = `${prompt} and add a license, and a contributing file`
2323
const tooManyRequestsWaitTime = 100000
2424

25-
function waitForButtons(buttons: FollowUpTypes[]) {
26-
return tab.waitForEvent(() => {
27-
return buttons.every((value) => tab.hasButton(value))
28-
})
29-
}
30-
3125
async function waitForText(text: string) {
32-
await tab.waitForEvent(
33-
() => {
34-
return tab.getChatItems().some((chatItem) => chatItem.body === text)
35-
},
36-
{
37-
waitIntervalInMs: 250,
38-
waitTimeoutInMs: 2000,
39-
}
40-
)
26+
await tab.waitForText(text, {
27+
waitIntervalInMs: 250,
28+
waitTimeoutInMs: 2000,
29+
})
4130
}
4231

4332
async function iterate(prompt: string) {
@@ -201,12 +190,12 @@ describe('Amazon Q Feature Dev', function () {
201190
it('Clicks accept code and click new task', async () => {
202191
await retryIfRequired(async () => {
203192
await Promise.any([
204-
waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
205-
waitForButtons([FollowUpTypes.Retry]),
193+
tab.waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
194+
tab.waitForButtons([FollowUpTypes.Retry]),
206195
])
207196
})
208197
tab.clickButton(FollowUpTypes.InsertCode)
209-
await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
198+
await tab.waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
210199
tab.clickButton(FollowUpTypes.NewTask)
211200
await waitForText('What new task would you like to work on?')
212201
assert.deepStrictEqual(tab.getChatItems().pop()?.body, 'What new task would you like to work on?')
@@ -215,15 +204,15 @@ describe('Amazon Q Feature Dev', function () {
215204
it('Iterates on codegen', async () => {
216205
await retryIfRequired(async () => {
217206
await Promise.any([
218-
waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
219-
waitForButtons([FollowUpTypes.Retry]),
207+
tab.waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
208+
tab.waitForButtons([FollowUpTypes.Retry]),
220209
])
221210
})
222211
tab.clickButton(FollowUpTypes.ProvideFeedbackAndRegenerateCode)
223212
await tab.waitForChatFinishesLoading()
224213
await iterate(codegenApproachPrompt)
225214
tab.clickButton(FollowUpTypes.InsertCode)
226-
await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
215+
await tab.waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
227216
})
228217
})
229218

@@ -240,8 +229,8 @@ describe('Amazon Q Feature Dev', function () {
240229
)
241230
await retryIfRequired(async () => {
242231
await Promise.any([
243-
waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
244-
waitForButtons([FollowUpTypes.Retry]),
232+
tab.waitForButtons([FollowUpTypes.InsertCode, FollowUpTypes.ProvideFeedbackAndRegenerateCode]),
233+
tab.waitForButtons([FollowUpTypes.Retry]),
245234
])
246235
})
247236
})
@@ -271,7 +260,7 @@ describe('Amazon Q Feature Dev', function () {
271260

272261
it('disables all action buttons when new task is clicked', async () => {
273262
tab.clickButton(FollowUpTypes.InsertCode)
274-
await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
263+
await tab.waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
275264
tab.clickButton(FollowUpTypes.NewTask)
276265
await waitForText('What new task would you like to work on?')
277266

@@ -283,7 +272,7 @@ describe('Amazon Q Feature Dev', function () {
283272

284273
it('disables all action buttons when close session is clicked', async () => {
285274
tab.clickButton(FollowUpTypes.InsertCode)
286-
await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
275+
await tab.waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
287276
tab.clickButton(FollowUpTypes.CloseSession)
288277
await waitForText(
289278
"Okay, I've ended this chat session. You can open a new tab to chat or start another workflow."
@@ -335,7 +324,7 @@ describe('Amazon Q Feature Dev', function () {
335324
for (const filePath of filePaths) {
336325
await clickActionButton(filePath, 'accept-change')
337326
}
338-
await waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
327+
await tab.waitForButtons([FollowUpTypes.NewTask, FollowUpTypes.CloseSession])
339328

340329
assert.ok(tab.hasButton(FollowUpTypes.InsertCode) === false)
341330
assert.ok(tab.hasButton(FollowUpTypes.ProvideFeedbackAndRegenerateCode) === false)

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class Messenger {
5252

5353
const lastChatItem = this.getChatItems().pop()
5454
const option = lastChatItem?.followUp?.options?.filter((option) => option.type === type)
55-
if (!option || option.length > 1) {
55+
if (!option?.length || option.length > 1) {
5656
assert.fail('Could not find follow up option')
5757
}
5858

@@ -153,17 +153,23 @@ export class Messenger {
153153
return this.getActionsByFilePath(filePath).some((action) => action.name === actionName)
154154
}
155155

156+
async waitForText(text: string, waitOverrides?: MessengerOptions) {
157+
await this.waitForEvent(() => {
158+
return this.getChatItems().some((chatItem) => chatItem.body === text)
159+
}, waitOverrides)
160+
}
161+
162+
async waitForButtons(buttons: FollowUpTypes[]) {
163+
return this.waitForEvent(() => {
164+
return buttons.every((value) => this.hasButton(value))
165+
})
166+
}
167+
156168
async waitForChatFinishesLoading() {
157169
return this.waitForEvent(() => this.getStore().loadingChat === false || this.hasButton(FollowUpTypes.Retry))
158170
}
159171

160-
async waitForEvent(
161-
event: () => boolean,
162-
waitOverrides?: {
163-
waitIntervalInMs: number
164-
waitTimeoutInMs: number
165-
}
166-
) {
172+
async waitForEvent(event: () => boolean, waitOverrides?: MessengerOptions) {
167173
/**
168174
* Wait until the chat has finished loading. This happens when a backend request
169175
* has finished and responded in the chat

packages/core/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"./auth": "./dist/src/auth/index.js",
2121
"./amazonqGumby": "./dist/src/amazonqGumby/index.js",
2222
"./amazonqFeatureDev": "./dist/src/amazonqFeatureDev/index.js",
23+
"./amazonqDoc": "./dist/src/amazonqDoc/index.js",
2324
"./amazonqScan": "./dist/src/amazonqScan/index.js",
2425
"./amazonqTest": "./dist/src/amazonqTest/index.js",
2526
"./codewhispererChat": "./dist/src/codewhispererChat/index.js",
@@ -495,6 +496,7 @@
495496
"dependencies": {
496497
"@amzn/amazon-q-developer-streaming-client": "file:../../src.gen/@amzn/amazon-q-developer-streaming-client",
497498
"@amzn/codewhisperer-streaming": "file:../../src.gen/@amzn/codewhisperer-streaming",
499+
"@aws-sdk/client-cloudwatch-logs": "^3.666.0",
498500
"@aws-sdk/client-cloudformation": "^3.667.0",
499501
"@aws-sdk/client-cognito-identity": "^3.637.0",
500502
"@aws-sdk/client-lambda": "^3.637.0",

packages/core/package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@
177177
"AWS.command.downloadSchemaItemCode": "Download Code Bindings",
178178
"AWS.command.viewLogs": "View Logs",
179179
"AWS.command.cloudWatchLogs.searchLogGroup": "Search Log Group",
180+
"AWS.command.cloudWatchLogs.tailLogGroup": "Tail Log Group",
180181
"AWS.command.sam.newTemplate": "Create new SAM Template",
181182
"AWS.command.cloudFormation.newTemplate": "Create new CloudFormation Template",
182183
"AWS.command.quickStart": "View Quick Start",
@@ -253,7 +254,7 @@
253254
"AWS.appcomposer.explorerTitle": "Infrastructure Composer",
254255
"AWS.cdk.explorerTitle": "CDK",
255256
"AWS.codecatalyst.explorerTitle": "CodeCatalyst",
256-
"AWS.cwl.limit.desc": "Maximum amount of log entries pulled per request from CloudWatch Logs (max 10000)",
257+
"AWS.cwl.limit.desc": "Maximum amount of log entries pulled per request from CloudWatch Logs. For LiveTail, when the limit is reached, the oldest events will be removed to accomodate new events. (max 10000)",
257258
"AWS.samcli.deploy.bucket.recentlyUsed": "Buckets recently used for SAM deployments",
258259
"AWS.submenu.amazonqEditorContextSubmenu.title": "Amazon Q",
259260
"AWS.submenu.auth.title": "Authentication",

0 commit comments

Comments
 (0)