Skip to content

Commit 9c88145

Browse files
authored
Merge pull request wso2#98 from axewilledge/ai-vscode-test
VS Code extension test changes to support AI tests
2 parents a53c1db + e51dfb8 commit 9c88145

File tree

12 files changed

+164
-89
lines changed

12 files changed

+164
-89
lines changed

common/config/rush/pnpm-lock.yaml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

workspaces/ballerina/ballerina-extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@
11131113
"@types/lodash": "^4.14.200",
11141114
"@ai-sdk/anthropic": "^1.2.12",
11151115
"ai": "^4.3.16",
1116-
"@vscode/test-electron": "^2.4.0",
1116+
"@vscode/test-electron": "^2.5.2",
11171117
"@vscode/vsce": "^2.22.0",
11181118
"@wso2/ballerina-core": "workspace:*",
11191119
"@wso2/ballerina-visualizer": "workspace:*",

workspaces/ballerina/ballerina-extension/src/features/ai/activator.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
* under the License.
1717
*/
1818

19-
import vscode from 'vscode';
19+
import { commands, window } from 'vscode';
2020
import { BallerinaExtension, ExtendedLangClient } from '../../core';
2121
import { activateCopilotLoginCommand, resetBIAuth } from './completions';
22+
import { generateCodeCore } from './service/code/code';
23+
import { GenerateCodeRequest } from '@wso2/ballerina-core';
24+
import { CopilotEventHandler } from './service/event';
2225
import { addConfigFile, getConfigFilePath } from './utils';
2326
import { StateMachine } from "../../stateMachine";
24-
import { CONFIGURE_DEFAULT_MODEL_COMMAND, DEFAULT_PROVIDER_ADDED, LOGIN_REQUIRED_WARNING_FOR_DEFAULT_MODEL, OPEN_AI_PANEL_COMMAND, SIGN_IN_BI_COPILOT } from './constants';
27+
import { CONFIGURE_DEFAULT_MODEL_COMMAND, DEFAULT_PROVIDER_ADDED, LOGIN_REQUIRED_WARNING_FOR_DEFAULT_MODEL, SIGN_IN_BI_COPILOT } from './constants';
2528
import { REFRESH_TOKEN_NOT_AVAILABLE_ERROR_MESSAGE, TOKEN_REFRESH_ONLY_SUPPORTED_FOR_BI_INTEL } from '../..//utils/ai/auth';
2629
import { AIStateMachine } from '../../views/ai-panel/aiMachine';
2730
import { AIMachineEventType } from '@wso2/ballerina-core';
@@ -32,30 +35,34 @@ export function activateAIFeatures(ballerinaExternalInstance: BallerinaExtension
3235
langClient = <ExtendedLangClient>ballerinaExternalInstance.langClient;
3336
activateCopilotLoginCommand();
3437
resetBIAuth();
38+
// Register a command in test environment to test the AI features
39+
if (process.env.AI_TEST_ENV) {
40+
commands.registerCommand('ballerina.test.ai.generateCodeCore', async (params: GenerateCodeRequest, testEventHandler: CopilotEventHandler) => {
41+
await generateCodeCore(params, testEventHandler);
42+
});
43+
}
3544

3645
const projectPath = StateMachine.context().projectUri;
3746

38-
vscode.commands.registerCommand(CONFIGURE_DEFAULT_MODEL_COMMAND, async (...args: any[]) => {
47+
commands.registerCommand(CONFIGURE_DEFAULT_MODEL_COMMAND, async (...args: any[]) => {
3948
const configPath = await getConfigFilePath(ballerinaExternalInstance, projectPath);
4049
if (configPath !== null) {
4150
try {
4251
const result = await addConfigFile(configPath);
4352
if (result) {
44-
vscode.window.showInformationMessage(DEFAULT_PROVIDER_ADDED);
53+
window.showInformationMessage(DEFAULT_PROVIDER_ADDED);
4554
}
4655
} catch (error) {
4756
if ((error as Error).message === REFRESH_TOKEN_NOT_AVAILABLE_ERROR_MESSAGE || (error as Error).message === TOKEN_REFRESH_ONLY_SUPPORTED_FOR_BI_INTEL) {
48-
vscode.window.showWarningMessage(LOGIN_REQUIRED_WARNING_FOR_DEFAULT_MODEL, SIGN_IN_BI_COPILOT).then(selection => {
57+
window.showWarningMessage(LOGIN_REQUIRED_WARNING_FOR_DEFAULT_MODEL, SIGN_IN_BI_COPILOT).then(selection => {
4958
if (selection === SIGN_IN_BI_COPILOT) {
5059
AIStateMachine.service().send(AIMachineEventType.LOGIN);
5160
}
5261
});
5362
} else {
54-
vscode.window.showErrorMessage((error as Error).message);
63+
window.showErrorMessage((error as Error).message);
5564
}
5665
}
5766
}
5867
});
5968
}
60-
61-

workspaces/ballerina/ballerina-extension/src/features/natural-programming/activator.ts

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@ import vscode from 'vscode';
2020
import { ENABLE_BACKGROUND_DRIFT_CHECK } from "../../core/preferences";
2121
import { debounce } from 'lodash';
2222
import { StateMachine } from "../../stateMachine";
23-
import { addConfigFile, getConfigFilePath, getLLMDiagnostics} from "./utils";
24-
import { NLCodeActionProvider, showTextOptions } from './nl-code-action-provider';
23+
import { addConfigFile, getConfigFilePath, getLLMDiagnostics } from "./utils";
24+
import { NLCodeActionProvider } from './nl-code-action-provider';
2525
import { BallerinaExtension } from 'src/core';
26-
import { PROGRESS_BAR_MESSAGE_FOR_DRIFT, WARNING_MESSAGE, WARNING_MESSAGE_DEFAULT,
27-
MONITERED_EXTENSIONS
28-
} from './constants';
29-
import { isSupportedSLVersion } from "../../utils";
26+
import {
27+
PROGRESS_BAR_MESSAGE_FOR_DRIFT, WARNING_MESSAGE, WARNING_MESSAGE_DEFAULT,
28+
MONITERED_EXTENSIONS,
29+
COMMAND_SHOW_TEXT
30+
} from './constants';
31+
import { isSupportedSLVersion } from "../../utils";
32+
import { CustomDiagnostic } from './custom-diagnostics';
3033

3134
let diagnosticCollection: vscode.DiagnosticCollection;
3235
const BALLERINA_UPDATE_13 = 2201130;
@@ -49,30 +52,30 @@ export function activate(ballerinaExtInstance: BallerinaExtension) {
4952
if (result == null) {
5053
return;
5154
}
52-
55+
5356
if (result > 400 && result < 500) {
5457
vscode.window.showWarningMessage(WARNING_MESSAGE);
5558
return;
5659
}
5760
vscode.window.showWarningMessage(WARNING_MESSAGE_DEFAULT);
5861
}, 600000);
59-
62+
6063
vscode.workspace.onDidChangeTextDocument(async event => {
6164
const filePath = event.document.uri.fsPath; // Get the file path
6265
const fileExtension = filePath.substring(filePath.lastIndexOf('.')); // Extract the file extension
63-
66+
6467
// Check if the file extension is in the monitoredExtensions array
6568
if (MONITERED_EXTENSIONS.includes(fileExtension)) {
6669
debouncedGetLLMDiagnostics();
6770
}
6871
}, null, ballerinaExtInstance.context.subscriptions);
69-
72+
7073
vscode.workspace.onDidDeleteFiles(async event => {
7174
let isMoniteredFileGotDeleted = false;
7275
event.files.forEach(file => {
7376
const filePath = file.fsPath; // Get the file path
7477
const fileExtension = filePath.substring(filePath.lastIndexOf('.')); // Extract the file extension
75-
78+
7679
// Check if the file extension is in the monitoredExtensions array
7780
if (MONITERED_EXTENSIONS.includes(fileExtension)) {
7881
isMoniteredFileGotDeleted = true;
@@ -92,17 +95,36 @@ export function activate(ballerinaExtInstance: BallerinaExtension) {
9295
})
9396
);
9497

95-
ballerinaExtInstance.context.subscriptions.push(showTextOptions);
98+
ballerinaExtInstance.context.subscriptions.push(
99+
vscode.commands.registerCommand(COMMAND_SHOW_TEXT, async (document: vscode.TextDocument,
100+
diagnostic: CustomDiagnostic, newText: string, range: vscode.Range) => {
101+
const editor = vscode.window.activeTextEditor;
102+
if (!editor) {
103+
vscode.window.showErrorMessage("No active editor found.");
104+
return;
105+
}
106+
107+
const textToReplace = document.getText(range);
108+
109+
// Create a Git conflict-like view with "|||||||", "HEAD" and "======="
110+
const conflictText = `<<<<<<< HEAD\n${textToReplace}\n=======\n${newText}\n>>>>>>>\n`;
111+
112+
const edit = new vscode.WorkspaceEdit();
113+
edit.replace(document.uri, range, conflictText);
114+
await vscode.workspace.applyEdit(edit);
115+
vscode.window.showInformationMessage('Changes added');
116+
})
117+
);
96118

97-
vscode.commands.registerCommand("ballerina.verifyDocs", async (...args: any[]) => {
119+
vscode.commands.registerCommand("ballerina.verifyDocs", async (...args: any[]) => {
98120
await vscode.window.withProgress(
99121
{
100122
location: vscode.ProgressLocation.Notification,
101123
title: PROGRESS_BAR_MESSAGE_FOR_DRIFT,
102124
cancellable: false,
103125
},
104126
async () => {
105-
const result: number|null = await getLLMDiagnostics(projectPath, diagnosticCollection);
127+
const result: number | null = await getLLMDiagnostics(projectPath, diagnosticCollection);
106128
if (result == null) {
107129
return;
108130
}
@@ -119,8 +141,8 @@ export function activate(ballerinaExtInstance: BallerinaExtension) {
119141
vscode.commands.registerCommand("ballerina.configureDefaultModelForNaturalFunctions", async (...args: any[]) => {
120142
const configPath = await getConfigFilePath(ballerinaExtInstance, projectPath);
121143
if (configPath != null) {
122-
const isNaturalFunctionsAvailableInBallerinaOrg =
123-
isSupportedSLVersion(ballerinaExtInstance, BALLERINA_UPDATE_13);
144+
const isNaturalFunctionsAvailableInBallerinaOrg =
145+
isSupportedSLVersion(ballerinaExtInstance, BALLERINA_UPDATE_13);
124146
addConfigFile(configPath, isNaturalFunctionsAvailableInBallerinaOrg);
125147
}
126148
});

workspaces/ballerina/ballerina-extension/src/features/natural-programming/nl-code-action-provider.ts

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import * as vscode from 'vscode';
2020
import { CustomDiagnostic } from './custom-diagnostics';
21-
import {DRIFT_DIAGNOSTIC_ID, COMMAND_SHOW_TEXT} from "./constants";
21+
import { DRIFT_DIAGNOSTIC_ID, COMMAND_SHOW_TEXT } from "./constants";
2222
import { result } from 'lodash';
2323

2424
const UPDATE_CODE_ACTION_CONTENT = "Update code to match docs";
@@ -37,7 +37,7 @@ export class NLCodeActionProvider implements vscode.CodeActionProvider {
3737
if (diagnostic instanceof CustomDiagnostic) {
3838
const customDiagnostic = diagnostic as CustomDiagnostic;
3939

40-
if (customDiagnostic.data.id == DRIFT_DIAGNOSTIC_ID){
40+
if (customDiagnostic.data.id == DRIFT_DIAGNOSTIC_ID) {
4141
const implementationChangeSolution = customDiagnostic.data.implementationChangeSolution;
4242
const docChangeSolution = customDiagnostic.data.docChangeSolution;
4343

@@ -70,22 +70,3 @@ export class NLCodeActionProvider implements vscode.CodeActionProvider {
7070
return actions;
7171
}
7272
}
73-
74-
export const showTextOptions = vscode.commands.registerCommand(COMMAND_SHOW_TEXT, async (document: vscode.TextDocument,
75-
diagnostic: CustomDiagnostic, newText: string, range: vscode.Range) => {
76-
const editor = vscode.window.activeTextEditor;
77-
if (!editor) {
78-
vscode.window.showErrorMessage("No active editor found.");
79-
return;
80-
}
81-
82-
const textToReplace = document.getText(range);
83-
84-
// Create a Git conflict-like view with "|||||||", "HEAD" and "======="
85-
const conflictText = `<<<<<<< HEAD\n${textToReplace}\n=======\n${newText}\n>>>>>>>\n`;
86-
87-
const edit = new vscode.WorkspaceEdit();
88-
edit.replace(document.uri, range, conflictText);
89-
await vscode.workspace.applyEdit(edit);
90-
vscode.window.showInformationMessage('Changes added');
91-
});

workspaces/ballerina/ballerina-extension/test/ai/evals/code/code.test.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import * as assert from "assert";
2020
import * as fs from "fs";
2121
import { ChatNotify, GenerateCodeRequest } from "@wso2/ballerina-core";
2222
import { CopilotEventHandler } from "../../../../src/features/ai/service/event";
23-
import { Uri, workspace } from "vscode";
23+
import { commands, Uri, workspace } from "vscode";
2424

2525
const RESOURCES_PATH = path.resolve(__dirname, "../../../../../test/ai/evals/code/resources");
2626

@@ -105,11 +105,14 @@ function createTestEventHandler(): { handler: CopilotEventHandler; getResult: ()
105105
}
106106

107107
suite.only("AI Code Generator Tests Suite", () => {
108-
test("basic workspace test", async function () {
109-
this.timeout(30000);
110-
//TODO: Set new langserver jar
111108

112-
const PROJECT_ROOT = "/Users/wso2/repos/ballerina-copilot/evals/project_samples/fresh_bi_package";
109+
// Close all the open workspace folders before running the test
110+
suiteSetup(async function () {
111+
await commands.executeCommand("workbench.action.closeAllEditors");
112+
});
113+
114+
test("basic workspace test", async function () {
115+
const PROJECT_ROOT = "/Users/anjanash/Desktop/Office/OpenSource/vscode-extensions/workspaces/ballerina/ballerina-extension/test/data/aiTest";
113116

114117
const success = workspace.updateWorkspaceFolders(0, 0, {
115118
uri: Uri.file(PROJECT_ROOT),
@@ -129,7 +132,7 @@ suite.only("AI Code Generator Tests Suite", () => {
129132
};
130133

131134
try {
132-
await generateCodeCore(params, testEventHandler);
135+
await commands.executeCommand('ballerina.test.ai.generateCodeCore', params, testEventHandler);
133136

134137
const result = getResult();
135138

@@ -153,7 +156,7 @@ suite.only("AI Code Generator Tests Suite", () => {
153156
});
154157
});
155158

156-
// suite.only("AI Code Generator Tests Suite", () => {
159+
// suite("AI Code Generator Tests Suite", () => {
157160
// // let langClient: ExtendedLangClient;
158161

159162
// // suiteSetup(async (done): Promise<any> => {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
org = "wso2"
3+
name = "aiTest"
4+
version = "0.1.0"
5+
distribution = "2201.13.0-m2"
6+
7+
[build-options]
8+
observabilityIncluded = true

workspaces/ballerina/ballerina-extension/test/data/aiTest/main.bal

Whitespace-only changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
strixng st = "saample giga string";
1+
string st = "saample giga string";

workspaces/ballerina/ballerina-extension/test/editor/editor-support.test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ import { assert } from "chai";
2323
const PROJECT_ROOT = join(__dirname, '..', '..', '..', 'test', 'data');
2424

2525
suite("Editor Tests", function () {
26-
suiteTeardown((done) => {
27-
commands.executeCommand('ballerina.stopLangServer');
28-
done();
29-
});
30-
3126
test("Test string splitter", function (done): void {
3227
const uri = Uri.file(join(PROJECT_ROOT, 'string.bal'));
3328

@@ -40,7 +35,10 @@ suite("Editor Tests", function () {
4035

4136
});
4237
await wait(5000);
43-
assert.strictEqual(editor.document.getText(), 'string st = "sample " +\n"giga string";\n', "Invalid string splitter");
38+
const actualText = editor.document.getText();
39+
console.log('Actual text:', JSON.stringify(actualText));
40+
console.log('Expected text:', JSON.stringify('string st = "saample" +\n" giga string";\n'));
41+
assert.strictEqual(actualText, 'string st = "saample" +\n" giga string";\n', "Invalid string splitter");
4442
done();
4543
});
4644
});

0 commit comments

Comments
 (0)