Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3096613
fix(amazonq): add back inline completion code files - part 1 (#7974)
leigaol Sep 2, 2025
ab57461
add telemetryHelper back
leigaol Sep 2, 2025
1f691a8
fix(amazonq): add telemetryHelper back (#7975)
leigaol Sep 3, 2025
fe9b128
setup activation separation
leigaol Sep 3, 2025
2663d8c
Merge branch 'feature/inline-rollback' into feature/inline-rollback
leigaol Sep 3, 2025
0102385
feat(amazonq): Add separate activation code path (#7980)
leigaol Sep 3, 2025
44c7da2
fix(amazonq): removing duplicate refreshStatusBar declare method (#7981)
atonaamz Sep 3, 2025
2887458
Merge branch 'feature/inline-rollback' into feature/inline-rollback
leigaol Sep 4, 2025
4742872
feat(amazonq): Get repomap from Flare directly (#7985)
leigaol Sep 5, 2025
9b9c384
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 5, 2025
e45f2c7
fix(amazonq): Wrap repomap LSP call with try catch (#7992)
leigaol Sep 6, 2025
bf50433
fix(amazonq): fix the status bar duplication (#7995)
leigaol Sep 8, 2025
e7c4ae3
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 8, 2025
604bea5
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 9, 2025
77676b3
feat(amazonq): enable pre flare experiment (#7999)
andrewyuq Sep 9, 2025
038dd0c
telemetry: register onacceptance command (#8010)
Will-ShaoHua Sep 10, 2025
4537a07
test(amazonq): add back test file for telemetryHelper.ts (#8009)
atonaamz Sep 10, 2025
d973fb7
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 10, 2025
8db9cf5
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 10, 2025
70b6101
perf: add inline debug logs (#8017)
Will-ShaoHua Sep 10, 2025
39b60a8
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 10, 2025
d39245a
test(amazonq): add back test files for inline completion codes - part…
atonaamz Sep 10, 2025
59f49b4
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 10, 2025
969ac95
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 10, 2025
af09ebe
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 11, 2025
f766ddf
test(amazonq): adding back inline tests - part 2
atonaamz Sep 11, 2025
a8b44ea
Merge branch 'feature/inline-rollback' into rollback
atonaamz Sep 11, 2025
bae74cc
Merge master into feature/inline-rollback
aws-toolkit-automation Sep 11, 2025
4a8ab5c
Merge branch 'feature/inline-rollback' into rollback
atonaamz Sep 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 64 additions & 5 deletions packages/amazonq/test/e2e/inline/inline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@

import * as vscode from 'vscode'
import assert from 'assert'
import { closeAllEditors, registerAuthHook, TestFolder, toTextEditor, using } from 'aws-core-vscode/test'
import {
closeAllEditors,
getTestWindow,
registerAuthHook,
resetCodeWhispererGlobalVariables,
TestFolder,
toTextEditor,
using,
} from 'aws-core-vscode/test'
import { RecommendationHandler, RecommendationService, session } from 'aws-core-vscode/codewhisperer'
import { Commands, globals, sleep, waitUntil, collectionUtil } from 'aws-core-vscode/shared'
import { loginToIdC } from '../amazonq/utils/setup'
import { vsCodeState } from 'aws-core-vscode/codewhisperer'

describe('Amazon Q Inline', async function () {
const retries = 3
Expand All @@ -32,6 +40,7 @@ describe('Amazon Q Inline', async function () {
const folder = await TestFolder.create()
tempFolder = folder.path
await closeAllEditors()
await resetCodeWhispererGlobalVariables()
})

afterEach(async function () {
Expand All @@ -45,6 +54,7 @@ describe('Amazon Q Inline', async function () {
const events = getUserTriggerDecision()
console.table({
'telemetry events': JSON.stringify(events),
'recommendation service status': RecommendationService.instance.isRunning,
})
}

Expand All @@ -61,6 +71,31 @@ describe('Amazon Q Inline', async function () {
})
}

async function waitForRecommendations() {
const suggestionShown = await waitUntil(async () => session.getSuggestionState(0) === 'Showed', waitOptions)
if (!suggestionShown) {
throw new Error(`Suggestion did not show. Suggestion States: ${JSON.stringify(session.suggestionStates)}`)
}
const suggestionVisible = await waitUntil(
async () => RecommendationHandler.instance.isSuggestionVisible(),
waitOptions
)
if (!suggestionVisible) {
throw new Error(
`Suggestions failed to become visible. Suggestion States: ${JSON.stringify(session.suggestionStates)}`
)
}
console.table({
'suggestions states': JSON.stringify(session.suggestionStates),
'valid recommendation': RecommendationHandler.instance.isValidResponse(),
'recommendation service status': RecommendationService.instance.isRunning,
recommendations: session.recommendations,
})
if (!RecommendationHandler.instance.isValidResponse()) {
throw new Error('Did not find a valid response')
}
}

/**
* Waits for a specific telemetry event to be emitted with the expected suggestion state.
* It looks like there might be a potential race condition in codewhisperer causing telemetry
Expand Down Expand Up @@ -114,9 +149,8 @@ describe('Amazon Q Inline', async function () {
await invokeCompletion()
originalEditorContents = vscode.window.activeTextEditor?.document.getText()

// wait until all the recommendations have finished
await waitUntil(() => Promise.resolve(vsCodeState.isRecommendationsActive === true), waitOptions)
await waitUntil(() => Promise.resolve(vsCodeState.isRecommendationsActive === false), waitOptions)
// wait until the ghost text appears
await waitForRecommendations()
}

beforeEach(async () => {
Expand All @@ -129,12 +163,14 @@ describe('Amazon Q Inline', async function () {
try {
await setup()
console.log(`test run ${attempt} succeeded`)
logUserDecisionStatus()
break
} catch (e) {
console.log(`test run ${attempt} failed`)
console.log(e)
logUserDecisionStatus()
attempt++
await resetCodeWhispererGlobalVariables()
}
}
if (attempt === retries) {
Expand Down Expand Up @@ -180,6 +216,29 @@ describe('Amazon Q Inline', async function () {
assert.deepStrictEqual(vscode.window.activeTextEditor?.document.getText(), originalEditorContents)
})
})

it(`${name} invoke on unsupported filetype`, async function () {
await setupEditor({
name: 'test.zig',
contents: `fn doSomething() void {

}`,
})

/**
* Add delay between editor loading and invoking completion
* @see beforeEach in supported filetypes for more information
*/
await sleep(1000)
await invokeCompletion()

if (name === 'automatic') {
// It should never get triggered since its not a supported file type
assert.deepStrictEqual(RecommendationService.instance.isRunning, false)
} else {
await getTestWindow().waitForMessage('currently not supported by Amazon Q inline suggestions')
}
})
})
}
})
124 changes: 124 additions & 0 deletions packages/core/src/testE2E/codewhisperer/referenceTracker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import assert from 'assert'
import * as codewhispererClient from '../../codewhisperer/client/codewhisperer'
import { ConfigurationEntry } from '../../codewhisperer/models/model'
import { setValidConnection, skipTestIfNoValidConn } from '../util/connection'
import { RecommendationHandler } from '../../codewhisperer/service/recommendationHandler'
import { createMockTextEditor, resetCodeWhispererGlobalVariables } from '../../test/codewhisperer/testUtil'
import { invokeRecommendation } from '../../codewhisperer/commands/invokeRecommendation'
import { session } from '../../codewhisperer/util/codeWhispererSession'

/*
New model deployment may impact references returned.
These tests:
1) are not required for github approval flow
2) will be auto-skipped until fix for manual runs is posted.
*/

const leftContext = `InAuto.GetContent(
InAuto.servers.auto, "vendors.json",
function (data) {
let block = '';
for(let i = 0; i < data.length; i++) {
block += '<a href="' + data`

const rightContext = `[i].title + '">' + cars[i].title + '</a>';
}
$('#cars').html(block);
});`

describe('CodeWhisperer service invocation', async function () {
let validConnection: boolean
const client = new codewhispererClient.DefaultCodeWhispererClient()
const configWithRefs: ConfigurationEntry = {
isShowMethodsEnabled: true,
isManualTriggerEnabled: true,
isAutomatedTriggerEnabled: true,
isSuggestionsWithCodeReferencesEnabled: true,
}
const configWithNoRefs: ConfigurationEntry = {
isShowMethodsEnabled: true,
isManualTriggerEnabled: true,
isAutomatedTriggerEnabled: true,
isSuggestionsWithCodeReferencesEnabled: false,
}

before(async function () {
validConnection = await setValidConnection()
})

beforeEach(function () {
void resetCodeWhispererGlobalVariables()
RecommendationHandler.instance.clearRecommendations()
// TODO: remove this line (this.skip()) when these tests no longer auto-skipped
this.skip()
// valid connection required to run tests
skipTestIfNoValidConn(validConnection, this)
})

it('trigger known to return recs with references returns rec with reference', async function () {
// check that handler is empty before invocation
const requestIdBefore = RecommendationHandler.instance.requestId
const sessionIdBefore = session.sessionId
const validRecsBefore = RecommendationHandler.instance.isValidResponse()

assert.ok(requestIdBefore.length === 0)
assert.ok(sessionIdBefore.length === 0)
assert.ok(!validRecsBefore)

const doc = leftContext + rightContext
const filename = 'test.js'
const language = 'javascript'
const line = 5
const character = 39
const mockEditor = createMockTextEditor(doc, filename, language, line, character)

await invokeRecommendation(mockEditor, client, configWithRefs)

const requestId = RecommendationHandler.instance.requestId
const sessionId = session.sessionId
const validRecs = RecommendationHandler.instance.isValidResponse()
const references = session.recommendations[0].references

assert.ok(requestId.length > 0)
assert.ok(sessionId.length > 0)
assert.ok(validRecs)
assert.ok(references !== undefined)
// TODO: uncomment this assert when this test is no longer auto-skipped
// assert.ok(references.length > 0)
})

// This test will fail if user is logged in with IAM identity center
it('trigger known to return rec with references does not return rec with references when reference tracker setting is off', async function () {
// check that handler is empty before invocation
const requestIdBefore = RecommendationHandler.instance.requestId
const sessionIdBefore = session.sessionId
const validRecsBefore = RecommendationHandler.instance.isValidResponse()

assert.ok(requestIdBefore.length === 0)
assert.ok(sessionIdBefore.length === 0)
assert.ok(!validRecsBefore)

const doc = leftContext + rightContext
const filename = 'test.js'
const language = 'javascript'
const line = 5
const character = 39
const mockEditor = createMockTextEditor(doc, filename, language, line, character)

await invokeRecommendation(mockEditor, client, configWithNoRefs)

const requestId = RecommendationHandler.instance.requestId
const sessionId = session.sessionId
const validRecs = RecommendationHandler.instance.isValidResponse()

assert.ok(requestId.length > 0)
assert.ok(sessionId.length > 0)
// no recs returned because example request returns 1 rec with reference, so no recs returned when references off
assert.ok(!validRecs)
})
})
124 changes: 124 additions & 0 deletions packages/core/src/testE2E/codewhisperer/serviceInvocations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import assert from 'assert'
import * as vscode from 'vscode'
import * as path from 'path'
import { setValidConnection, skipTestIfNoValidConn } from '../util/connection'
import { ConfigurationEntry } from '../../codewhisperer/models/model'
import * as codewhispererClient from '../../codewhisperer/client/codewhisperer'
import { RecommendationHandler } from '../../codewhisperer/service/recommendationHandler'
import {
createMockTextEditor,
createTextDocumentChangeEvent,
resetCodeWhispererGlobalVariables,
} from '../../test/codewhisperer/testUtil'
import { KeyStrokeHandler } from '../../codewhisperer/service/keyStrokeHandler'
import { sleep } from '../../shared/utilities/timeoutUtils'
import { invokeRecommendation } from '../../codewhisperer/commands/invokeRecommendation'
import { getTestWorkspaceFolder } from '../../testInteg/integrationTestsUtilities'
import { session } from '../../codewhisperer/util/codeWhispererSession'

describe('CodeWhisperer service invocation', async function () {
let validConnection: boolean
const client = new codewhispererClient.DefaultCodeWhispererClient()
const config: ConfigurationEntry = {
isShowMethodsEnabled: true,
isManualTriggerEnabled: true,
isAutomatedTriggerEnabled: true,
isSuggestionsWithCodeReferencesEnabled: true,
}

before(async function () {
validConnection = await setValidConnection()
})

beforeEach(function () {
void resetCodeWhispererGlobalVariables()
RecommendationHandler.instance.clearRecommendations()
// valid connection required to run tests
skipTestIfNoValidConn(validConnection, this)
})

it('manual trigger returns valid recommendation response', async function () {
// check that handler is empty before invocation
const requestIdBefore = RecommendationHandler.instance.requestId
const sessionIdBefore = session.sessionId
const validRecsBefore = RecommendationHandler.instance.isValidResponse()

assert.ok(requestIdBefore.length === 0)
assert.ok(sessionIdBefore.length === 0)
assert.ok(!validRecsBefore)

const mockEditor = createMockTextEditor()
await invokeRecommendation(mockEditor, client, config)

const requestId = RecommendationHandler.instance.requestId
const sessionId = session.sessionId
const validRecs = RecommendationHandler.instance.isValidResponse()

assert.ok(requestId.length > 0)
assert.ok(sessionId.length > 0)
assert.ok(validRecs)
})

it('auto trigger returns valid recommendation response', async function () {
// check that handler is empty before invocation
const requestIdBefore = RecommendationHandler.instance.requestId
const sessionIdBefore = session.sessionId
const validRecsBefore = RecommendationHandler.instance.isValidResponse()

assert.ok(requestIdBefore.length === 0)
assert.ok(sessionIdBefore.length === 0)
assert.ok(!validRecsBefore)

const mockEditor = createMockTextEditor()

const mockEvent: vscode.TextDocumentChangeEvent = createTextDocumentChangeEvent(
mockEditor.document,
new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 1)),
'\n'
)

await KeyStrokeHandler.instance.processKeyStroke(mockEvent, mockEditor, client, config)
// wait for 5 seconds to allow time for response to be generated
await sleep(5000)

const requestId = RecommendationHandler.instance.requestId
const sessionId = session.sessionId
const validRecs = RecommendationHandler.instance.isValidResponse()

assert.ok(requestId.length > 0)
assert.ok(sessionId.length > 0)
assert.ok(validRecs)
})

it('invocation in unsupported language does not generate a request', async function () {
const workspaceFolder = getTestWorkspaceFolder()
const appRoot = path.join(workspaceFolder, 'go1-plain-sam-app')
const appCodePath = path.join(appRoot, 'hello-world', 'go.mod')

// check that handler is empty before invocation
const requestIdBefore = RecommendationHandler.instance.requestId
const sessionIdBefore = session.sessionId
const validRecsBefore = RecommendationHandler.instance.isValidResponse()

assert.ok(requestIdBefore.length === 0)
assert.ok(sessionIdBefore.length === 0)
assert.ok(!validRecsBefore)

const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(appCodePath))
const editor = await vscode.window.showTextDocument(doc)
await invokeRecommendation(editor, client, config)

const requestId = RecommendationHandler.instance.requestId
const sessionId = session.sessionId
const validRecs = RecommendationHandler.instance.isValidResponse()

assert.ok(requestId.length === 0)
assert.ok(sessionId.length === 0)
assert.ok(!validRecs)
})
})
Loading