From 8eb14d6ea6087bc6840654b93018b8d99e0eb614 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Sep 2025 21:07:31 +0000 Subject: [PATCH 1/4] Initial plan From 36b3660d9c342950647a6b64c541b2b0ff789176 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Sep 2025 21:21:07 +0000 Subject: [PATCH 2/4] Add CodeCatalyst showUserInfo command and tests Co-authored-by: cobbdan <103603475+cobbdan@users.noreply.github.com> --- packages/core/package.nls.json | 1 + packages/core/src/codecatalyst/commands.ts | 40 ++++++++++++ .../src/test/codecatalyst/commands.test.ts | 61 +++++++++++++++++++ packages/toolkit/package.json | 11 ++++ 4 files changed, 113 insertions(+) create mode 100644 packages/core/src/test/codecatalyst/commands.test.ts diff --git a/packages/core/package.nls.json b/packages/core/package.nls.json index 0a25550ec22..57fdaf87a4f 100644 --- a/packages/core/package.nls.json +++ b/packages/core/package.nls.json @@ -137,6 +137,7 @@ "AWS.command.codecatalyst.login": "Connect to CodeCatalyst", "AWS.command.codecatalyst.logout": "Sign out of CodeCatalyst", "AWS.command.codecatalyst.signout": "Sign Out", + "AWS.command.codecatalyst.showUserInfo": "Show User Information", "AWS.command.manageSubscription": "Manage Q Developer Pro Subscription", "AWS.command.amazonq.explainCode": "Explain", "AWS.command.amazonq.refactorCode": "Refactor", diff --git a/packages/core/src/codecatalyst/commands.ts b/packages/core/src/codecatalyst/commands.ts index 509d9b40d01..d8eae74a7d4 100644 --- a/packages/core/src/codecatalyst/commands.ts +++ b/packages/core/src/codecatalyst/commands.ts @@ -32,6 +32,41 @@ export async function listCommands(): Promise { await vscode.commands.executeCommand('workbench.action.quickOpen', '> CodeCatalyst') } +/** "Show User Info" command - displays current CodeCatalyst user details. */ +export async function showUserInfo(client: CodeCatalystClient): Promise { + try { + const userDetails = await client.verifySession() + + const userInfoMessage = [ + `**User Information**`, + ``, + `**User ID:** ${userDetails.userId}`, + `**Username:** ${userDetails.userName}`, + `**Display Name:** ${userDetails.displayName}`, + `**Email:** ${userDetails.primaryEmail}`, + ].join('\n') + + await vscode.window.showInformationMessage( + localize('aws.codecatalyst.userInfo.title', 'CodeCatalyst User Information'), + { + modal: true, + detail: userInfoMessage + } + ) + } catch (error) { + if (error instanceof ToolkitError) { + await vscode.window.showErrorMessage( + localize('aws.codecatalyst.userInfo.error', 'Failed to get user information: {0}', error.message) + ) + } else { + await vscode.window.showErrorMessage( + localize('aws.codecatalyst.userInfo.errorGeneric', 'Failed to get user information. Please ensure you are authenticated with CodeCatalyst.') + ) + } + throw error + } +} + /** "Clone CodeCatalyst Repository" command. */ export async function cloneCodeCatalystRepo(client: CodeCatalystClient, url?: vscode.Uri): Promise { let resource: { name: string; project: string; org: string } @@ -239,6 +274,10 @@ export class CodeCatalystCommands { return listCommands() } + public showUserInfo(_?: VsCodeCommandArg) { + return this.withClient(showUserInfo) + } + public cloneRepo(_?: VsCodeCommandArg, ...args: WithClient) { return this.withClient(cloneCodeCatalystRepo, ...args) } @@ -344,6 +383,7 @@ export class CodeCatalystCommands { public static readonly declared = { openResource: Commands.from(this).declareOpenResource('aws.codecatalyst.openResource'), listCommands: Commands.from(this).declareListCommands('aws.codecatalyst.listCommands'), + showUserInfo: Commands.declare('aws.codecatalyst.showUserInfo', (commands: CodeCatalystCommands) => () => commands.showUserInfo()), openSpace: Commands.from(this).declareOpenSpace('aws.codecatalyst.openOrg'), openProject: Commands.from(this).declareOpenProject('aws.codecatalyst.openProject'), openRepository: Commands.from(this).declareOpenRepository('aws.codecatalyst.openRepo'), diff --git a/packages/core/src/test/codecatalyst/commands.test.ts b/packages/core/src/test/codecatalyst/commands.test.ts new file mode 100644 index 00000000000..9e3cc320592 --- /dev/null +++ b/packages/core/src/test/codecatalyst/commands.test.ts @@ -0,0 +1,61 @@ +/*! + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import assert from 'assert' +import sinon from 'sinon' +import * as vscode from 'vscode' +import { showUserInfo } from '../../codecatalyst/commands' +import { CodeCatalystClient } from '../../shared/clients/codecatalystClient' + +describe('CodeCatalyst Commands', function () { + let sandbox: sinon.SinonSandbox + let mockClient: sinon.SinonStubbedInstance + let showInformationMessageStub: sinon.SinonStub + let showErrorMessageStub: sinon.SinonStub + + beforeEach(function () { + sandbox = sinon.createSandbox() + mockClient = sandbox.createStubInstance(Object as any) + showInformationMessageStub = sandbox.stub(vscode.window, 'showInformationMessage') + showErrorMessageStub = sandbox.stub(vscode.window, 'showErrorMessage') + }) + + afterEach(function () { + sandbox.restore() + }) + + describe('showUserInfo', function () { + it('displays user information when client returns valid data', async function () { + const mockUserDetails = { + userId: 'user-123', + userName: 'testuser', + displayName: 'Test User', + primaryEmail: 'test@example.com' + } + + mockClient.verifySession.resolves(mockUserDetails) + + await showUserInfo(mockClient as any) + + assert(showInformationMessageStub.calledOnce) + const [message, options] = showInformationMessageStub.firstCall.args + assert.strictEqual(message, 'CodeCatalyst User Information') + assert(options.modal) + assert(options.detail.includes('Test User')) + assert(options.detail.includes('test@example.com')) + }) + + it('displays error message when client fails', async function () { + mockClient.verifySession.rejects(new Error('Authentication failed')) + + try { + await showUserInfo(mockClient as any) + assert.fail('Expected error to be thrown') + } catch (error) { + assert(showErrorMessageStub.calledOnce) + } + }) + }) +}) \ No newline at end of file diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 34fb02a8bd6..5b976d6eb15 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -1424,6 +1424,11 @@ "when": "view == aws.codecatalyst && !isCloud9 && aws.codecatalyst.connected", "group": "1_codeCatalyst@1" }, + { + "command": "aws.codecatalyst.showUserInfo", + "when": "view == aws.codecatalyst && !isCloud9 && aws.codecatalyst.connected", + "group": "1_codeCatalyst@2" + }, { "command": "aws.codecatalyst.manageConnections", "when": "view == aws.codecatalyst && !isCloud9 && !aws.codecatalyst.connected", @@ -2540,6 +2545,12 @@ "icon": "$(debug-disconnect)", "enablement": "isCloud9 || !aws.isWebExtHost" }, + { + "command": "aws.codecatalyst.showUserInfo", + "title": "%AWS.command.codecatalyst.showUserInfo%", + "category": "AWS", + "enablement": "isCloud9 || !aws.isWebExtHost" + }, { "command": "aws.toolkit.auth.addConnection", "title": "%AWS.command.auth.addConnection%", From 4fb9ed5fe13fb2207f7e435d6d1e35b9c9e5e9c2 Mon Sep 17 00:00:00 2001 From: cobbdan <103603475+cobbdan@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:41:51 -0700 Subject: [PATCH 3/4] Update packages/toolkit/package.json Co-authored-by: amazon-q-developer[bot] <208079219+amazon-q-developer[bot]@users.noreply.github.com> --- packages/toolkit/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 5b976d6eb15..451d172fdd4 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -1427,6 +1427,8 @@ { "command": "aws.codecatalyst.showUserInfo", "when": "view == aws.codecatalyst && !isCloud9 && aws.codecatalyst.connected", + "group": "1_codeCatalyst@3" + }, "group": "1_codeCatalyst@2" }, { From 5bfb02a411fb15b2419f4e8b8dc1bd411c3a4a68 Mon Sep 17 00:00:00 2001 From: cobbdan <103603475+cobbdan@users.noreply.github.com> Date: Mon, 22 Sep 2025 16:13:26 -0700 Subject: [PATCH 4/4] Update packages/core/src/test/codecatalyst/commands.test.ts Co-authored-by: amazon-q-developer[bot] <208079219+amazon-q-developer[bot]@users.noreply.github.com> --- .../src/test/codecatalyst/commands.test.ts | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/core/src/test/codecatalyst/commands.test.ts b/packages/core/src/test/codecatalyst/commands.test.ts index 9e3cc320592..0547132b396 100644 --- a/packages/core/src/test/codecatalyst/commands.test.ts +++ b/packages/core/src/test/codecatalyst/commands.test.ts @@ -46,8 +46,32 @@ describe('CodeCatalyst Commands', function () { assert(options.detail.includes('Test User')) assert(options.detail.includes('test@example.com')) }) + it('displays error message when client fails with ToolkitError', async function () { + const toolkitError = new ToolkitError('Authentication failed', { code: 'NoConnectionBadState' }) + mockClient.verifySession.rejects(toolkitError) - it('displays error message when client fails', async function () { + try { + await showUserInfo(mockClient as any) + assert.fail('Expected error to be thrown') + } catch (error) { + assert(showErrorMessageStub.calledOnce) + const errorMessage = showErrorMessageStub.firstCall.args[0] + assert(errorMessage.includes('Authentication failed')) + } + }) + + it('displays generic error message when client fails with generic error', async function () { + mockClient.verifySession.rejects(new Error('Network error')) + + try { + await showUserInfo(mockClient as any) + assert.fail('Expected error to be thrown') + } catch (error) { + assert(showErrorMessageStub.calledOnce) + const errorMessage = showErrorMessageStub.firstCall.args[0] + assert(errorMessage.includes('Please ensure you are authenticated')) + } + }) mockClient.verifySession.rejects(new Error('Authentication failed')) try {