Skip to content

Commit e3aa0a6

Browse files
authored
CHANGE: @W-18279823@ Hide A4V QF Without Authed Org (#295)
1 parent 00ac8a2 commit e3aa0a6

File tree

5 files changed

+84
-7
lines changed

5 files changed

+84
-7
lines changed

src/extension.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<SFCAEx
277277
// =================================================================================================================
278278
const a4dFixAction: A4DFixAction = new A4DFixAction(externalServiceProvider, codeAnalyzer, unifiedDiffService,
279279
diagnosticManager, telemetryService, logger, display);
280-
const a4dFixActionProvider: A4DFixActionProvider = new A4DFixActionProvider(externalServiceProvider, logger);
280+
const a4dFixActionProvider: A4DFixActionProvider = new A4DFixActionProvider(externalServiceProvider, orgConnectionService, logger);
281+
281282
registerCommand(A4DFixAction.COMMAND, async (diagnostic: CodeAnalyzerDiagnostic, document: vscode.TextDocument) => {
282283
await a4dFixAction.run(diagnostic, document);
283284
});

src/lib/agentforce/a4d-fix-action-provider.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from "vscode";
22
import {messages} from "../messages";
33
import {LLMServiceProvider} from "../external-services/llm-service";
4+
import {OrgConnectionService} from "../external-services/org-connection-service";
45
import {Logger} from "../logger";
56
import {CodeAnalyzerDiagnostic} from "../diagnostics";
67
import { A4DFixAction } from "./a4d-fix-action";
@@ -13,11 +14,14 @@ export class A4DFixActionProvider implements vscode.CodeActionProvider {
1314
static readonly providedCodeActionKinds: vscode.CodeActionKind[] = [vscode.CodeActionKind.QuickFix];
1415

1516
private readonly llmServiceProvider: LLMServiceProvider;
17+
private readonly orgConnectionService: OrgConnectionService;
1618
private readonly logger: Logger;
1719
private hasWarnedAboutUnavailableLLMService: boolean = false;
20+
private hasWarnedAboutUnauthenticatedOrg: boolean = false;
1821

19-
constructor(llmServiceProvider: LLMServiceProvider, logger: Logger) {
22+
constructor(llmServiceProvider: LLMServiceProvider, orgConnectionService: OrgConnectionService, logger: Logger) {
2023
this.llmServiceProvider = llmServiceProvider;
24+
this.orgConnectionService = orgConnectionService;
2125
this.logger = logger;
2226
}
2327

@@ -33,6 +37,15 @@ export class A4DFixActionProvider implements vscode.CodeActionProvider {
3337
return [];
3438
}
3539

40+
// Do not provide quick fix code actions if user is not authenticated to an org
41+
if (!this.orgConnectionService.isAuthed()) {
42+
if (!this.hasWarnedAboutUnauthenticatedOrg) {
43+
this.logger.warn(messages.agentforce.a4dQuickFixUnauthenticatedOrg);
44+
this.hasWarnedAboutUnauthenticatedOrg = true;
45+
}
46+
return [];
47+
}
48+
3649
// Do not provide quick fix code actions if LLM service is not available. We warn once to let user know.
3750
if (!(await this.llmServiceProvider.isLLMServiceAvailable())) {
3851
if (!this.hasWarnedAboutUnavailableLLMService) {

src/lib/messages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const messages = {
1515
},
1616
agentforce: {
1717
a4dQuickFixUnavailable: "The ability to fix violations with 'Agentforce Vibes' is unavailable since a compatible 'Agentforce Vibes' extension was not found or activated. To enable this functionality, please install the 'Agentforce Vibes' extension and restart VS Code.",
18+
a4dQuickFixUnauthenticatedOrg: "The ability to fix violations with 'Agentforce Vibes' is unavailable since you are not authenticated to an org. To enable this functionality, please authenticate to an org.",
1819
failedA4DResponse: "Unable to receive code fix suggestion from Agentforce Vibes."
1920
},
2021
unifiedDiff: {

src/test/unit/lib/agentforce/agentforce-code-action-provider.test.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as vscode from "vscode"; // The vscode module is mocked out. See: scripts/setup.jest.ts
22
import {A4DFixActionProvider} from "../../../../lib/agentforce/a4d-fix-action-provider";
3-
import {SpyLLMService, SpyLogger, StubLLMServiceProvider} from "../../stubs";
3+
import {SpyLLMService, SpyLogger, StubOrgConnectionService, StubLLMServiceProvider} from "../../stubs";
44
import {StubCodeActionContext} from "../../vscode-stubs";
55
import {messages} from "../../../../lib/messages";
66
import {createTextDocument} from "jest-mock-vscode";
@@ -11,13 +11,15 @@ describe('AgentforceCodeActionProvider Tests', () => {
1111
let spyLLMService: SpyLLMService;
1212
let llmServiceProvider: StubLLMServiceProvider;
1313
let spyLogger: SpyLogger;
14+
let stubOrgConnectionService: StubOrgConnectionService;
1415
let actionProvider: A4DFixActionProvider;
1516

1617
beforeEach(() => {
1718
spyLLMService = new SpyLLMService();
1819
llmServiceProvider = new StubLLMServiceProvider(spyLLMService);
1920
spyLogger = new SpyLogger();
20-
actionProvider = new A4DFixActionProvider(llmServiceProvider, spyLogger);
21+
stubOrgConnectionService = new StubOrgConnectionService();
22+
actionProvider = new A4DFixActionProvider(llmServiceProvider, stubOrgConnectionService, spyLogger);
2123
});
2224

2325
describe('provideCodeActions Tests', () => {
@@ -68,7 +70,8 @@ describe('AgentforceCodeActionProvider Tests', () => {
6870
expect(codeActions[2].diagnostics).toEqual([supportedDiag3]);
6971
});
7072

71-
it('When the LLMService is unavailable, then warn once and return no code actions', async () => {
73+
// Authentication and LLM Service Availability Tests
74+
it('When the LLMService is unavailable, then warn once and return no code actions and warn only once', async () => {
7275
llmServiceProvider.isLLMServiceAvailableReturnValue = false;
7376
const context: vscode.CodeActionContext = new StubCodeActionContext({diagnostics: [supportedDiag1]});
7477
const codeActions: vscode.CodeAction[] = await actionProvider.provideCodeActions(sampleDocument, range, context);
@@ -78,6 +81,45 @@ describe('AgentforceCodeActionProvider Tests', () => {
7881
expect(spyLogger.warnCallHistory).toHaveLength(1);
7982
expect(spyLogger.warnCallHistory[0]).toEqual({msg: messages.agentforce.a4dQuickFixUnavailable});
8083
});
84+
85+
it('When user is not authenticated to an org, then return no code actions and warn once', async () => {
86+
stubOrgConnectionService.isAuthedReturnValue = false;
87+
const context: vscode.CodeActionContext = new StubCodeActionContext({diagnostics: [supportedDiag1]});
88+
const codeActions: vscode.CodeAction[] = await actionProvider.provideCodeActions(sampleDocument, range, context);
89+
await actionProvider.provideCodeActions(sampleDocument, range, context); // Sanity check that multiple calls do not produce additional warnings
90+
91+
expect(codeActions).toHaveLength(0);
92+
expect(spyLogger.warnCallHistory).toHaveLength(1);
93+
expect(spyLogger.warnCallHistory[0]).toEqual({msg: messages.agentforce.a4dQuickFixUnauthenticatedOrg});
94+
});
95+
96+
it('When user is authenticated and LLMService is available, then user does not see any warnings', async () => {
97+
stubOrgConnectionService.isAuthedReturnValue = true;
98+
llmServiceProvider.isLLMServiceAvailableReturnValue = true;
99+
const context: vscode.CodeActionContext = new StubCodeActionContext({diagnostics: [supportedDiag1]});
100+
const codeActions: vscode.CodeAction[] = await actionProvider.provideCodeActions(sampleDocument, range, context);
101+
102+
expect(codeActions).toHaveLength(1);
103+
expect(spyLogger.warnCallHistory).toHaveLength(0);
104+
});
105+
106+
it('When no supported diagnostics are in the context and user is not authenticated to an org, then do not warn', async () => {
107+
stubOrgConnectionService.isAuthedReturnValue = false;
108+
const context: vscode.CodeActionContext = new StubCodeActionContext({diagnostics: [unsupportedDiag1]});
109+
const codeActions: vscode.CodeAction[] = await actionProvider.provideCodeActions(sampleDocument, range, context);
110+
111+
expect(codeActions).toHaveLength(0);
112+
expect(spyLogger.warnCallHistory).toHaveLength(0);
113+
});
114+
115+
it('When no supported diagnostics are in the context and LLM Service is unavailable, then do not warn', async () => {
116+
llmServiceProvider.isLLMServiceAvailableReturnValue = false;
117+
const context: vscode.CodeActionContext = new StubCodeActionContext({diagnostics: [unsupportedDiag1]});
118+
const codeActions: vscode.CodeAction[] = await actionProvider.provideCodeActions(sampleDocument, range, context);
119+
120+
expect(codeActions).toHaveLength(0);
121+
expect(spyLogger.warnCallHistory).toHaveLength(0);
122+
});
81123
});
82124
});
83125

src/test/unit/stubs.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {FileHandler} from "../../lib/fs-utils";
1616
import {VscodeWorkspace, WindowManager} from "../../lib/vscode-api";
1717
import {Workspace} from "../../lib/workspace";
1818
import { ApexGuruAccess, ApexGuruAvailability, ApexGuruService } from "../../lib/apexguru/apex-guru-service";
19-
19+
import { HttpRequest, OrgConnectionService, OrgUserInfo } from "../../lib/external-services/org-connection-service";
2020

2121
export class SpyTelemetryService implements TelemetryService {
2222
sendExtensionActivationEventCallHistory: { hrStart: number }[] = [];
@@ -384,4 +384,24 @@ export class ThrowingScanApexGuruService extends StubApexGuruService {
384384
scan(_absFileToScan: string): Promise<Violation[]> {
385385
throw new Error("Sample error message from scan method");
386386
}
387-
}
387+
}
388+
389+
export class StubOrgConnectionService implements OrgConnectionService {
390+
isAuthedReturnValue: boolean = true;
391+
392+
isAuthed(): boolean {
393+
return this.isAuthedReturnValue;
394+
}
395+
396+
getApiVersion(): Promise<string> {
397+
return Promise.resolve('64.0');
398+
}
399+
400+
onOrgChange(_callback: (orgUserInfo: OrgUserInfo) => void): void {
401+
// No-op
402+
}
403+
404+
request<T>(requestOptions: HttpRequest): Promise<T> {
405+
throw new Error(`Not implemented:\n${JSON.stringify(requestOptions, null, 2)}`);
406+
}
407+
}

0 commit comments

Comments
 (0)