Skip to content

Commit 58e4aa9

Browse files
committed
add tests
1 parent 987082e commit 58e4aa9

File tree

6 files changed

+190
-22
lines changed

6 files changed

+190
-22
lines changed

packages/amazonq/test/unit/codewhisperer/models/model.test.ts

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
*/
55
import assert from 'assert'
66
import sinon from 'sinon'
7-
import { SecurityIssueFilters, SecurityTreeViewFilterState } from 'aws-core-vscode/codewhisperer'
7+
import {
8+
CodeIssueGroupingStrategy,
9+
CodeIssueGroupingStrategyState,
10+
SecurityIssueFilters,
11+
SecurityTreeViewFilterState,
12+
} from 'aws-core-vscode/codewhisperer'
813
import { globals } from 'aws-core-vscode/shared'
914

1015
describe('model', function () {
@@ -70,4 +75,113 @@ describe('model', function () {
7075
assert.deepStrictEqual(hiddenSeverities, ['High', 'Low'])
7176
})
7277
})
78+
79+
describe('CodeIssueGroupingStrategyState', function () {
80+
let sandbox: sinon.SinonSandbox
81+
let state: CodeIssueGroupingStrategyState
82+
83+
beforeEach(function () {
84+
sandbox = sinon.createSandbox()
85+
// Reset the singleton instance before each test
86+
// @ts-ignore - accessing private static for testing
87+
CodeIssueGroupingStrategyState['#instance'] = undefined
88+
state = CodeIssueGroupingStrategyState.instance
89+
})
90+
91+
afterEach(function () {
92+
sandbox.restore()
93+
})
94+
95+
describe('instance', function () {
96+
it('should return the same instance when called multiple times', function () {
97+
const instance1 = CodeIssueGroupingStrategyState.instance
98+
const instance2 = CodeIssueGroupingStrategyState.instance
99+
assert.strictEqual(instance1, instance2)
100+
})
101+
})
102+
103+
describe('getState', function () {
104+
it('should return fallback when no state is stored', function () {
105+
const tryGetStub = sandbox.stub(globals.globalState, 'tryGet').returns(undefined)
106+
const result = state.getState()
107+
108+
sinon.assert.calledWith(tryGetStub, 'aws.amazonq.codescan.groupingStrategy', String)
109+
assert.equal(result, CodeIssueGroupingStrategy.Severity)
110+
})
111+
112+
it('should return stored state when valid', function () {
113+
const validStrategy = CodeIssueGroupingStrategy.Severity
114+
const tryGetStub = sandbox.stub(globals.globalState, 'tryGet').returns(validStrategy)
115+
116+
const result = state.getState()
117+
118+
assert.equal(result, validStrategy)
119+
})
120+
121+
it('should return fallback when stored state is invalid', function () {
122+
const invalidStrategy = 'invalid'
123+
const tryGetStub = sandbox.stub(globals.globalState, 'tryGet').returns(invalidStrategy)
124+
125+
const result = state.getState()
126+
127+
assert.equal(result, CodeIssueGroupingStrategy.Severity)
128+
})
129+
})
130+
131+
describe('setState', function () {
132+
it('should update state and fire change event for valid strategy', async function () {
133+
const validStrategy = CodeIssueGroupingStrategy.FileLocation
134+
const updateStub = sandbox.stub(globals.globalState, 'update').resolves()
135+
136+
// Create a spy to watch for event emissions
137+
const eventSpy = sandbox.spy()
138+
state.onDidChangeState(eventSpy)
139+
140+
await state.setState(validStrategy)
141+
142+
sinon.assert.calledWith(updateStub, 'aws.amazonq.codescan.groupingStrategy', validStrategy)
143+
sinon.assert.calledWith(eventSpy, validStrategy)
144+
})
145+
146+
it('should use fallback and fire change event for invalid strategy', async function () {
147+
const invalidStrategy = 'invalid'
148+
const updateStub = sandbox.stub(globals.globalState, 'update').resolves()
149+
150+
// Create a spy to watch for event emissions
151+
const eventSpy = sandbox.spy()
152+
state.onDidChangeState(eventSpy)
153+
154+
await state.setState(invalidStrategy)
155+
156+
sinon.assert.calledWith(
157+
updateStub,
158+
'aws.amazonq.codescan.groupingStrategy',
159+
CodeIssueGroupingStrategy.Severity
160+
)
161+
sinon.assert.calledWith(eventSpy, CodeIssueGroupingStrategy.Severity)
162+
})
163+
})
164+
165+
describe('reset', function () {
166+
it('should set state to fallback value', async function () {
167+
const setStateStub = sandbox.stub(state, 'setState').resolves()
168+
169+
await state.reset()
170+
171+
sinon.assert.calledWith(setStateStub, CodeIssueGroupingStrategy.Severity)
172+
})
173+
})
174+
175+
describe('onDidChangeState', function () {
176+
it('should allow subscribing to state changes', async function () {
177+
const listener = sandbox.spy()
178+
const disposable = state.onDidChangeState(listener)
179+
180+
await state.setState(CodeIssueGroupingStrategy.Severity)
181+
182+
sinon.assert.calledWith(listener, CodeIssueGroupingStrategy.Severity)
183+
disposable.dispose()
184+
})
185+
})
186+
})
73187
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import { createQuickPickPrompterTester, QuickPickPrompterTester } from 'aws-core-vscode/test'
6+
import {
7+
CodeIssueGroupingStrategy,
8+
CodeIssueGroupingStrategyState,
9+
createCodeIssueGroupingStrategyPrompter,
10+
} from 'aws-core-vscode/codewhisperer'
11+
import sinon from 'sinon'
12+
13+
const severity = { label: 'Severity', data: CodeIssueGroupingStrategy.Severity }
14+
const fileLocation = { label: 'File Location', data: CodeIssueGroupingStrategy.FileLocation }
15+
16+
describe('createCodeIssueGroupingStrategyPrompter', function () {
17+
let tester: QuickPickPrompterTester<CodeIssueGroupingStrategy>
18+
19+
beforeEach(function () {
20+
tester = createQuickPickPrompterTester(createCodeIssueGroupingStrategyPrompter())
21+
})
22+
23+
it('should list grouping strategies', function () {
24+
tester.assertItems([severity, fileLocation])
25+
})
26+
27+
it('should update state on selection', async function () {
28+
const spy = sinon.spy(CodeIssueGroupingStrategyState.instance, 'setState')
29+
30+
tester.selectItems(fileLocation)
31+
tester.assertSelectedItems(fileLocation)
32+
33+
spy.calledWith(CodeIssueGroupingStrategy.FileLocation)
34+
})
35+
})

packages/core/src/codewhisperer/commands/basicCommands.ts

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ import { startCodeFixGeneration } from './startCodeFixGeneration'
7070
import { DefaultAmazonQAppInitContext } from '../../amazonq/apps/initContext'
7171
import path from 'path'
7272
import { parsePatch } from 'diff'
73+
import { createQuickPick } from '../../shared/ui/pickerPrompter'
74+
import { createCodeIssueGroupingStrategyPrompter } from '../ui/prompters'
7375

7476
const MessageTimeOut = 5_000
7577

@@ -890,27 +892,8 @@ export const showSecurityIssueFilters = Commands.declare({ id: 'aws.amazonq.secu
890892
export const showCodeIssueGroupingQuickPick = Commands.declare(
891893
{ id: 'aws.amazonq.codescan.showGroupingStrategy' },
892894
() => async () => {
893-
const quickPick = vscode.window.createQuickPick()
894-
quickPick.title = localize('aws.commands.amazonq.groupIssues', 'Group Issues')
895-
quickPick.placeholder = localize(
896-
'aws.amazonq.codescan.groupIssues.placeholder',
897-
'Select how to group code issues'
898-
)
899-
quickPick.items = codeIssueGroupingStrategies.map((strategy) => ({
900-
label: codeIssueGroupingStrategyLabel[strategy],
901-
}))
902-
const groupingStrategy = CodeIssueGroupingStrategyState.instance.getState()
903-
quickPick.activeItems = quickPick.items.filter(
904-
(item) => item.label === codeIssueGroupingStrategyLabel[groupingStrategy]
905-
)
906-
quickPick.show()
907-
quickPick.onDidChangeSelection(async (items) => {
908-
const [item] = items
909-
await CodeIssueGroupingStrategyState.instance.setState(
910-
Object.entries(codeIssueGroupingStrategyLabel).find(([, label]) => label === item.label)?.[0]
911-
)
912-
quickPick.hide()
913-
})
895+
const prompter = createCodeIssueGroupingStrategyPrompter()
896+
await prompter.prompt()
914897
}
915898
)
916899

packages/core/src/codewhisperer/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,4 @@ export * as CodeWhispererConstants from '../codewhisperer/models/constants'
101101
export { getSelectedCustomization } from './util/customizationUtil'
102102
export { Container } from './service/serviceContainer'
103103
export * from './util/gitUtil'
104+
export * from './ui/prompters'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import {
7+
codeIssueGroupingStrategies,
8+
CodeIssueGroupingStrategy,
9+
codeIssueGroupingStrategyLabel,
10+
CodeIssueGroupingStrategyState,
11+
} from '../models/model'
12+
import { createQuickPick, QuickPickPrompter } from '../../shared/ui/pickerPrompter'
13+
import { localize } from '../../shared/utilities/vsCodeUtils'
14+
15+
export function createCodeIssueGroupingStrategyPrompter(): QuickPickPrompter<CodeIssueGroupingStrategy> {
16+
const groupingStrategy = CodeIssueGroupingStrategyState.instance.getState()
17+
const prompter = createQuickPick(
18+
codeIssueGroupingStrategies.map((strategy) => ({
19+
data: strategy,
20+
label: codeIssueGroupingStrategyLabel[strategy],
21+
})),
22+
{
23+
title: localize('aws.commands.amazonq.groupIssues', 'Group Issues'),
24+
placeholder: localize('aws.amazonq.codescan.groupIssues.placeholder', 'Select how to group code issues'),
25+
}
26+
)
27+
prompter.quickPick.activeItems = prompter.quickPick.items.filter((item) => item.data === groupingStrategy)
28+
prompter.quickPick.onDidChangeSelection(async (items) => {
29+
const [item] = items
30+
await CodeIssueGroupingStrategyState.instance.setState(item.data)
31+
prompter.quickPick.hide()
32+
})
33+
return prompter
34+
}

packages/core/src/test/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ export * from './credentials/testUtil'
2424
export * from './testUtil'
2525
export * from './amazonqFeatureDev/utils'
2626
export * from './fake/mockFeatureConfigData'
27+
export * from './shared/ui/testUtils'

0 commit comments

Comments
 (0)