diff --git a/packages/amazonq/test/e2e/amazonq/assert.ts b/packages/amazonq/test/e2e/amazonq/assert.ts index 7bc7bb2c22e..5bcec3fc0b4 100644 --- a/packages/amazonq/test/e2e/amazonq/assert.ts +++ b/packages/amazonq/test/e2e/amazonq/assert.ts @@ -28,3 +28,14 @@ export function assertQuickActions(tab: Messenger, commands: string[]) { assert.fail(`Could not find commands: ${missingCommands.join(', ')} for ${tab.tabID}`) } } + +export function assertContextCommands(tab: Messenger, contextCommands: string[]) { + assert.deepStrictEqual( + tab + .getStore() + .contextCommands?.map((x) => x.commands) + .flat() + .map((x) => x.command), + contextCommands + ) +} diff --git a/packages/amazonq/test/e2e/amazonq/chat.test.ts b/packages/amazonq/test/e2e/amazonq/chat.test.ts new file mode 100644 index 00000000000..3021be28782 --- /dev/null +++ b/packages/amazonq/test/e2e/amazonq/chat.test.ts @@ -0,0 +1,85 @@ +/*! + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import assert from 'assert' +import { qTestingFramework } from './framework/framework' +import sinon from 'sinon' +import { Messenger } from './framework/messenger' +import { MynahUIDataModel } from '@aws/mynah-ui' +import { assertContextCommands, assertQuickActions } from './assert' +import { registerAuthHook, using } from 'aws-core-vscode/test' +import { loginToIdC } from './utils/setup' +import { webviewConstants } from 'aws-core-vscode/amazonq' + +describe('Amazon Q Chat', function () { + let framework: qTestingFramework + let tab: Messenger + let store: MynahUIDataModel + + const availableCommands: string[] = ['/dev', '/test', '/review', '/doc', '/transform'] + + before(async function () { + /** + * Login to the amazonq-test-account. When running in CI this has unlimited + * calls to the backend api + */ + await using(registerAuthHook('amazonq-test-account'), async () => { + await loginToIdC() + }) + }) + + // jscpd:ignore-start + beforeEach(() => { + // Make sure you're logged in before every test + registerAuthHook('amazonq-test-account') + framework = new qTestingFramework('cwc', true, []) + tab = framework.createTab() + store = tab.getStore() + }) + + afterEach(() => { + framework.removeTab(tab.tabID) + framework.dispose() + sinon.restore() + }) + + it(`Shows quick actions: ${availableCommands.join(', ')}`, async () => { + assertQuickActions(tab, availableCommands) + }) + + it('Shows @workspace', () => { + assertContextCommands(tab, ['@workspace']) + }) + + // jscpd:ignore-end + + it('Shows title', () => { + assert.deepStrictEqual(store.tabTitle, 'Chat') + }) + + it('Shows placeholder', () => { + assert.deepStrictEqual(store.promptInputPlaceholder, 'Ask a question or enter "/" for quick actions') + }) + + it('Sends message', async () => { + tab.addChatMessage({ + prompt: 'What is a lambda', + }) + await tab.waitForChatFinishesLoading() + const chatItems = tab.getChatItems() + // the last item should be an answer + assert.deepStrictEqual(chatItems[4].type, 'answer') + }) + + describe('Clicks examples', () => { + it('Click help', async () => { + tab.clickButton('help') + await tab.waitForText(webviewConstants.helpMessage) + const chatItems = tab.getChatItems() + assert.deepStrictEqual(chatItems[4].type, 'answer') + assert.deepStrictEqual(chatItems[4].body, webviewConstants.helpMessage) + }) + }) +}) diff --git a/packages/amazonq/test/e2e/amazonq/framework/framework.ts b/packages/amazonq/test/e2e/amazonq/framework/framework.ts index b39dbe4314b..6a29015c06f 100644 --- a/packages/amazonq/test/e2e/amazonq/framework/framework.ts +++ b/packages/amazonq/test/e2e/amazonq/framework/framework.ts @@ -29,7 +29,7 @@ export class qTestingFramework { featureName: TabType, amazonQEnabled: boolean, featureConfigsSerialized: [string, FeatureContext][], - welcomeCount = 0 + welcomeCount = Number.MAX_VALUE // by default don't show the welcome page ) { /** * Instantiate the UI and override the postMessage to publish using the app message diff --git a/packages/amazonq/test/e2e/amazonq/template.test.ts b/packages/amazonq/test/e2e/amazonq/template.test.ts new file mode 100644 index 00000000000..42857575583 --- /dev/null +++ b/packages/amazonq/test/e2e/amazonq/template.test.ts @@ -0,0 +1,67 @@ +/*! + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +// jscpd:ignore-start +import assert from 'assert' +import { qTestingFramework } from './framework/framework' +import sinon from 'sinon' +import { Messenger } from './framework/messenger' +import { MynahUIDataModel } from '@aws/mynah-ui' +import { assertQuickActions } from './assert' +import { registerAuthHook, using } from 'aws-core-vscode/test' +import { loginToIdC } from './utils/setup' + +describe.skip('Amazon Q Test Template', function () { + let framework: qTestingFramework + let tab: Messenger + let store: MynahUIDataModel + + const availableCommands: string[] = [] + + before(async function () { + /** + * Login to the amazonq-test-account. When running in CI this has unlimited + * calls to the backend api + */ + await using(registerAuthHook('amazonq-test-account'), async () => { + await loginToIdC() + }) + }) + + beforeEach(() => { + // Make sure you're logged in before every test + registerAuthHook('amazonq-test-account') + + // TODO change unknown to the tab type you want to test + framework = new qTestingFramework('unknown', true, []) + tab = framework.getTabs()[0] // use the default tab that gets created + framework.createTab() // alternatively you can create a new tab + store = tab.getStore() + }) + + afterEach(() => { + framework.removeTab(tab.tabID) + framework.dispose() + sinon.restore() + }) + + it(`Shows quick actions: ${availableCommands.join(', ')}`, async () => { + assertQuickActions(tab, availableCommands) + }) + + it('Shows title', () => { + assert.deepStrictEqual(store.tabTitle, '') + }) + + it('Shows placeholder', () => { + assert.deepStrictEqual(store.promptInputPlaceholder, '') + }) + + describe('clicks examples', () => {}) + + describe('sends message', async () => {}) +}) + +// jscpd:ignore-end diff --git a/packages/amazonq/test/e2e/amazonq/welcome.test.ts b/packages/amazonq/test/e2e/amazonq/welcome.test.ts index 3f9929cf062..d9f0ccd66bf 100644 --- a/packages/amazonq/test/e2e/amazonq/welcome.test.ts +++ b/packages/amazonq/test/e2e/amazonq/welcome.test.ts @@ -8,8 +8,8 @@ import { qTestingFramework } from './framework/framework' import sinon from 'sinon' import { Messenger } from './framework/messenger' import { MynahUIDataModel } from '@aws/mynah-ui' -import { assertQuickActions } from './assert' import { FeatureContext } from 'aws-core-vscode/shared' +import { assertContextCommands, assertQuickActions } from './assert' describe('Amazon Q Welcome page', function () { let framework: qTestingFramework @@ -42,13 +42,7 @@ describe('Amazon Q Welcome page', function () { }) it('Shows context commands', async () => { - assert.deepStrictEqual( - store.contextCommands - ?.map((x) => x.commands) - .flat() - .map((x) => x.command), - ['@workspace', '@highlight'] - ) + assertContextCommands(tab, ['@workspace', '@highlight']) }) describe('shows 3 times', async () => { diff --git a/packages/core/src/amazonq/index.ts b/packages/core/src/amazonq/index.ts index cd4ec424365..9ca9af7687c 100644 --- a/packages/core/src/amazonq/index.ts +++ b/packages/core/src/amazonq/index.ts @@ -25,6 +25,7 @@ export { init as gumbyChatAppInit } from '../amazonqGumby/app' export { init as testChatAppInit } from '../amazonqTest/app' export { init as docChatAppInit } from '../amazonqDoc/app' export { amazonQHelpUrl } from '../shared/constants' +export * as webviewConstants from './webview/ui/texts/constants' export { listCodeWhispererCommandsWalkthrough } from '../codewhisperer/ui/statusBarMenu' export { focusAmazonQPanel, focusAmazonQPanelKeybinding } from '../codewhispererChat/commands/registerCommands' export { TryChatCodeLensProvider, tryChatCodeLensCommand } from '../codewhispererChat/editor/codelens' diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 57b45d414c1..a5205be78ca 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -231,17 +231,19 @@ export class ChatController { this.openLinkInExternalBrowser(click) } - private processQuickActionCommand(quickActionCommand: ChatPromptCommandType) { + private processQuickActionCommand(message: PromptMessage) { this.editorContextExtractor .extractContextForTrigger('QuickAction') .then((context) => { const triggerID = randomUUID() + const quickActionCommand = message.command as ChatPromptCommandType + this.messenger.sendQuickActionMessage(quickActionCommand, triggerID) this.triggerEventsStorage.addTriggerEvent({ id: triggerID, - tabID: undefined, + tabID: message.tabID, message: undefined, type: 'quick_action', quickAction: quickActionCommand, @@ -484,7 +486,7 @@ export class ChatController { recordTelemetryChatRunCommand('clear') return default: - this.processQuickActionCommand(message.command) + this.processQuickActionCommand(message) } }