Skip to content

Commit 28a5032

Browse files
committed
feat(q-featuredev): skip registering run command log file, minor fix of feature dev sessionState unit test
1 parent 7333d71 commit 28a5032

File tree

3 files changed

+168
-2
lines changed

3 files changed

+168
-2
lines changed

packages/core/src/amazonqFeatureDev/client/featureDev.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ export class FeatureDevClient implements FeatureClient {
264264

265265
const newFileContents: { zipFilePath: string; fileContent: string }[] = []
266266
for (const [filePath, fileContent] of Object.entries(newFiles)) {
267+
if (filePath === '.amazonq/dev/run_command_log.txt') {
268+
continue
269+
}
267270
newFileContents.push({ zipFilePath: filePath, fileContent })
268271
}
269272

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as assert from 'assert'
7+
import sinon from 'sinon'
8+
9+
import * as codewhispererChatClient from '../../../shared/clients/codewhispererChatClient'
10+
import * as logger from '../../../shared/logger/logger'
11+
12+
import { FeatureDevClient } from '../../../amazonqFeatureDev/client/featureDev'
13+
import { ToolkitError } from '../../../shared/errors'
14+
import { UserWrittenCodeTracker } from '../../../codewhisperer/tracker/userWrittenCodeTracker'
15+
16+
describe('FeatureDev', () => {
17+
describe('exportResultArchive', () => {
18+
const conversationId = 'fake-conversation-id'
19+
let mockLogger: any
20+
let mockStreamingClient: any
21+
let featureDevClient: FeatureDevClient
22+
23+
beforeEach(() => {
24+
mockLogger = {
25+
debug: sinon.stub(),
26+
error: sinon.stub(),
27+
}
28+
sinon.stub(logger, 'getLogger').returns(mockLogger)
29+
30+
mockStreamingClient = {
31+
exportResultArchive: sinon.stub(),
32+
}
33+
sinon.stub(codewhispererChatClient, 'createCodeWhispererChatStreamingClient').resolves(mockStreamingClient)
34+
35+
featureDevClient = new FeatureDevClient()
36+
})
37+
38+
afterEach(() => {
39+
sinon.restore()
40+
})
41+
42+
it('successfully exports and parses archive result', async () => {
43+
const mockResponse = {
44+
body: {
45+
async *[Symbol.asyncIterator]() {
46+
yield {
47+
binaryPayloadEvent: {
48+
bytes: Buffer.from(
49+
JSON.stringify({
50+
code_generation_result: {
51+
new_file_contents: {
52+
'file1.ts': 'content1',
53+
'file2.ts': 'content2',
54+
'.amazonq/dev/run_command_log.txt': 'should be filtered',
55+
},
56+
deleted_files: ['deleted1.ts'],
57+
references: [
58+
{
59+
licenseName: 'MIT',
60+
repository: 'test-repo',
61+
url: 'http://example.com',
62+
},
63+
],
64+
},
65+
})
66+
),
67+
},
68+
}
69+
},
70+
},
71+
}
72+
73+
mockStreamingClient.exportResultArchive.resolves(mockResponse)
74+
const trackSpy = sinon.stub(UserWrittenCodeTracker.instance, 'onQFeatureInvoked')
75+
const result = await featureDevClient.exportResultArchive(conversationId)
76+
77+
assert.strictEqual(mockStreamingClient.exportResultArchive.callCount, 1)
78+
assert.deepStrictEqual(mockStreamingClient.exportResultArchive.getCall(0).args[0], {
79+
exportId: conversationId,
80+
exportIntent: 'TASK_ASSIST',
81+
})
82+
83+
assert.strictEqual(trackSpy.callCount, 1)
84+
85+
assert.deepStrictEqual(result.newFileContents, [
86+
{ zipFilePath: 'file1.ts', fileContent: 'content1' },
87+
{ zipFilePath: 'file2.ts', fileContent: 'content2' },
88+
])
89+
assert.deepStrictEqual(result.deletedFiles, ['deleted1.ts'])
90+
assert.ok(result.references)
91+
})
92+
93+
it('throws error when response body is undefined', async () => {
94+
mockStreamingClient.exportResultArchive.resolves({ body: undefined })
95+
96+
await assert.rejects(
97+
async () => await featureDevClient.exportResultArchive(conversationId),
98+
new ToolkitError('Empty response from CodeWhisperer Streaming service.', {
99+
code: 'ExportResultArchiveFailed',
100+
})
101+
)
102+
})
103+
104+
it('throws error when internal server exception occurs', async () => {
105+
const mockResponse = {
106+
body: {
107+
async *[Symbol.asyncIterator]() {
108+
yield {
109+
internalServerException: new Error('Internal server error'),
110+
}
111+
},
112+
},
113+
}
114+
115+
mockStreamingClient.exportResultArchive.resolves(mockResponse)
116+
117+
await assert.rejects(
118+
async () => await featureDevClient.exportResultArchive(conversationId),
119+
/Internal server error/
120+
)
121+
})
122+
123+
it('handles empty result fields gracefully', async () => {
124+
const mockResponse = {
125+
body: {
126+
async *[Symbol.asyncIterator]() {
127+
yield {
128+
binaryPayloadEvent: {
129+
bytes: Buffer.from(
130+
JSON.stringify({
131+
code_generation_result: {},
132+
})
133+
),
134+
},
135+
}
136+
},
137+
},
138+
}
139+
140+
mockStreamingClient.exportResultArchive.resolves(mockResponse)
141+
142+
const result = await featureDevClient.exportResultArchive(conversationId)
143+
144+
assert.deepStrictEqual(result.newFileContents, [])
145+
assert.deepStrictEqual(result.deletedFiles, [])
146+
assert.deepStrictEqual(result.references, [])
147+
})
148+
149+
it('wraps and logs errors appropriately', async () => {
150+
const testError = new Error('Test error')
151+
;(testError as any).requestId = 'test-request-id'
152+
mockStreamingClient.exportResultArchive.rejects(testError)
153+
154+
await assert.rejects(
155+
async () => await featureDevClient.exportResultArchive(conversationId),
156+
new ToolkitError('Test error', { code: 'ExportResultArchiveFailed' })
157+
)
158+
159+
assert.strictEqual(mockLogger.error.callCount, 1)
160+
assert.ok(mockLogger.error.getCall(0).args[0].includes('test-request-id'))
161+
})
162+
})
163+
})

packages/core/src/test/amazonqFeatureDev/session/sessionState.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ describe('sessionStateFeatureDev', () => {
7676
)
7777

7878
assert.deepStrictEqual(result.nextState?.deletedFiles, nextState.deletedFiles)
79-
assert.deepStrictEqual(result.nextState?.filePaths, result.nextState?.filePaths)
80-
assert.deepStrictEqual(result.nextState?.references, result.nextState?.references)
79+
assert.deepStrictEqual(result.nextState?.filePaths, nextState.filePaths)
80+
assert.deepStrictEqual(result.nextState?.references, nextState.references)
8181
})
8282

8383
it('fails when codeGenerationStatus failed ', async () => {

0 commit comments

Comments
 (0)