Skip to content

Commit 57445a9

Browse files
authored
Merge pull request #599 from sharma1208/venya-issue-125
Add LSP4Jakarta diagnostic + quick fix tests for Maven and Gradle (#125)
2 parents a2365e2 + ffe5a11 commit 57445a9

9 files changed

Lines changed: 516 additions & 6 deletions

File tree

src/test/GradleTestDevModeActions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright IBM Corp. 2023, 2026
44
*/
55
import { expect } from 'chai';
6-
import { DefaultTreeItem, EditorView, InputBox, SideBarView, ViewSection, VSBrowser, Workbench } from 'vscode-extension-tester';
6+
import { DefaultTreeItem, EditorView, InputBox, SideBarView, ViewSection, VSBrowser, WebDriver, Workbench } from 'vscode-extension-tester';
77
import * as utils from './utils/testUtils';
88
import * as constants from './definitions/constants';
99
import { logger } from './utils/testLogger';
@@ -18,6 +18,7 @@ describe('Devmode action tests for Gradle Project', () => {
1818
before(async function() {
1919
this.timeout(30000);
2020
// Wait for workbench to be ready
21+
await VSBrowser.instance.openResources(utils.getGradleProjectPath());
2122
await VSBrowser.instance.waitForWorkbench();
2223
sidebar = new SideBarView();
2324
});

src/test/GradleTestLSPHover.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright IBM Corp. 2026
44
*/
55
import { expect } from 'chai';
6-
import { EditorView, TextEditor, VSBrowser, Workbench } from 'vscode-extension-tester';
6+
import { EditorView, TextEditor, VSBrowser, WebDriver, Workbench } from 'vscode-extension-tester';
77
import * as utils from './utils/testUtils';
88
import { logger } from './utils/testLogger';
99
import * as path from 'path';
@@ -12,11 +12,15 @@ describe('LSP Hover tests for Gradle Project', () => {
1212
let editorView: EditorView;
1313
let editor: TextEditor;
1414
let wait: any;
15+
let driver: WebDriver;
1516

1617
before(async function() {
1718
this.timeout(60000);
1819
logger.info('Setting up Gradle LSP Hover tests');
1920

21+
driver = VSBrowser.instance.driver;
22+
await VSBrowser.instance.openResources(utils.getGradleProjectPath());
23+
2024
// Wait for workbench to be ready
2125
await VSBrowser.instance.waitForWorkbench();
2226
editorView = new EditorView();
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
2+
/*
3+
* IBM Confidential
4+
* Copyright IBM Corp. 2026
5+
*/
6+
import { expect } from 'chai';
7+
import { EditorView, TextEditor, VSBrowser, Workbench, WebDriver, BottomBarPanel, MarkerType, Key, By } from 'vscode-extension-tester';
8+
import * as utils from './utils/testUtils';
9+
import { logger } from './utils/testLogger';
10+
import * as path from 'path';
11+
12+
describe('Rest Class Snippet Test for Gradle Project', () => {
13+
let editorView: EditorView;
14+
let javaEditor: TextEditor;
15+
let wait: any;
16+
let driver: WebDriver;
17+
18+
const testRestPath = path.resolve(
19+
utils.getGradleProjectPath(),
20+
'src', 'main', 'java', 'test', 'gradle', 'liberty', 'web', 'app',
21+
'TestRest.java'
22+
);
23+
24+
before(async function() {
25+
this.timeout(60000);
26+
logger.info('Setting up rest_class snippet test');
27+
28+
driver = VSBrowser.instance.driver;
29+
await VSBrowser.instance.openResources(utils.getGradleProjectPath());
30+
31+
// Wait for workbench to be ready
32+
await VSBrowser.instance.waitForWorkbench();
33+
editorView = new EditorView();
34+
wait = utils.getWaitHelper();
35+
36+
// Open the file
37+
await VSBrowser.instance.openResources(testRestPath, async () => {
38+
await wait.sleep(3000);
39+
});
40+
javaEditor = await editorView.openEditor('TestRest.java') as TextEditor;
41+
});
42+
43+
afterEach(async function() {
44+
// Take screenshot on failure but don't close editor
45+
if (this.currentTest?.state === 'failed') {
46+
const driver = VSBrowser.instance.driver;
47+
const screenshot = await driver.takeScreenshot();
48+
logger.error(`Test failed: ${this.currentTest.title}`);
49+
}
50+
});
51+
52+
after(async function() {
53+
this.timeout(15000);
54+
try {
55+
if (javaEditor) {
56+
// Select all text first, then clear
57+
const currentText = await javaEditor.getText();
58+
try {
59+
await javaEditor.selectText(currentText);
60+
await wait.sleep(300);
61+
} catch (selectError) {
62+
// selectText may fail but setText still works
63+
}
64+
65+
await javaEditor.setText('');
66+
await wait.sleep(500);
67+
await javaEditor.save();
68+
await wait.sleep(500);
69+
logger.info('Reset TestRest.java to empty after test');
70+
}
71+
} catch (error) {
72+
logger.error('Failed to reset TestRest.java', error);
73+
}
74+
75+
try {
76+
await editorView.closeAllEditors();
77+
await wait.sleep(500);
78+
logger.info('Closed all editors after test suite');
79+
} catch (error) {
80+
logger.error('Failed to close editors in after hook', error);
81+
}
82+
83+
try {
84+
utils.copyScreenshotsToProjectFolder('maven');
85+
} catch (error) {
86+
// Ignore screenshot errors
87+
}
88+
});
89+
90+
it('LSP4Jakarta Language Server should initialize', async function() {
91+
this.timeout(60000);
92+
logger.testStart('LSP4Jakarta Language Server should initialize');
93+
94+
try {
95+
await utils.waitForLanguageServerInit(
96+
'Language Support for Jakarta EE',
97+
'Initializing Jakarta EE server',
98+
60
99+
);
100+
logger.testComplete('LSP4Jakarta Language Server initialized successfully');
101+
} catch (error) {
102+
logger.testFailed('LSP4Jakarta Language Server should initialize', error);
103+
throw error;
104+
}
105+
});
106+
107+
it('rest_class snippet populates correct REST class', async function () {
108+
this.timeout(275000);
109+
logger.testStart('rest_class snippet inserts correct REST class');
110+
111+
// at the top of the rest_class snippet test, before positioning the cursor
112+
await javaEditor.setText('');
113+
await javaEditor.save();
114+
await wait.sleep(1500); // let any auto-stub settle, then confirm
115+
const check = await javaEditor.getText();
116+
logger.info('Buffer before snippet: ' + JSON.stringify(check));
117+
118+
try {
119+
logger.step(1, 'Positioning cursor for snippet insertion');
120+
// Position cursor at end of file
121+
const lastLine = (await javaEditor.getText()).split('\n').length;
122+
await javaEditor.setCursor(lastLine - 1, 1);
123+
124+
logger.step(2, 'Typing "rest" to trigger snippet');
125+
await javaEditor.typeText('rest');
126+
logger.stepSuccess(2, 'Typed "rest"');
127+
128+
logger.step(3, 'Opening content assist');
129+
const assist = await javaEditor.toggleContentAssist(true);
130+
if (assist) {
131+
logger.step(4,'Selecting rest_class snippet');
132+
await assist.select('rest_class');
133+
await new Promise(res => setTimeout(res, 600)); // 300–800ms
134+
logger.stepSuccess(4, 'rest_class snippet selected');
135+
}
136+
await javaEditor.toggleContentAssist(false);
137+
138+
logger.step(5, 'Verifying snippet insertion');
139+
const codeInsertion = await javaEditor.getText();
140+
expect(codeInsertion).to.include('@GET')
141+
expect(codeInsertion).to.include('methodname');
142+
logger.stepSuccess(5, 'Snippet rest_class was inserted correctly');
143+
144+
logger.testComplete('rest_class snippet inserts correct REST class');
145+
} catch (error) {
146+
logger.testFailed('rest_class snippet inserts correct REST class', error);
147+
throw error;
148+
}
149+
});
150+
it('Show that private @GET method displays diagnostic and quick fix removes it ', async function () {
151+
this.timeout(90000);
152+
logger.testStart('Diagnostic for a private @GET method and quick fix clears it');
153+
try {
154+
// Find the method with @GET and change it to private
155+
let lineNum = await javaEditor.getLineOfText('methodname');
156+
if (lineNum < 1) throw new Error('Could not find the methodname line');
157+
const oldLine = await javaEditor.getTextAtLine(lineNum);
158+
const newLine = oldLine.replace("public", "private");
159+
await javaEditor.setTextAtLine(lineNum, newLine);
160+
161+
// Save file and wait for reanalysis
162+
await javaEditor.save();
163+
await wait.sleep(500);
164+
165+
// Open problems view
166+
const bottomBar = new BottomBarPanel();
167+
await bottomBar.toggle(true);
168+
let problemsView = await bottomBar.openProblemsView();
169+
let markers = await problemsView.getAllVisibleMarkers(MarkerType.Any);
170+
171+
// Check if the marker is present
172+
let found = false;
173+
for (const marker of markers) {
174+
const text = await marker.getText();
175+
// Check if text contains your diagnostic message
176+
if(text.includes('Only public methods can be exposed as resource methods.')){
177+
found = true;
178+
break;
179+
}
180+
}
181+
expect(found).to.be.true;
182+
logger.testComplete('Diagnostic shows for private @GET method');
183+
184+
// Quick fix implementation to get rid of diagnostic
185+
// Re-find line and place cursor on "methodname()"
186+
const buffer = await javaEditor.getText();
187+
logger.info('Buffer before quick fix: ' + JSON.stringify(buffer));
188+
189+
// Get column on the method name
190+
await javaEditor.selectText('methodname');
191+
await wait.sleep(300);
192+
193+
// Open the quick-fix menu with Cmd+. (Mac) / Ctrl+. (Linux/Windows)
194+
const modKey = process.platform === 'darwin' ? Key.COMMAND : Key.CONTROL;
195+
await driver.actions().keyDown(modKey).sendKeys('.').keyUp(modKey).perform();
196+
await wait.sleep(2000);
197+
198+
// Click on the option to make the method public within the quick-fixes options
199+
const options = await driver.findElements(By.css('.action-widget .action-list-item, .action-widget .monaco-list-row'));
200+
let clicked = false;
201+
for (const opt of options) {
202+
const text = await opt.getText();
203+
logger.info('OPTION: ' + JSON.stringify(text));
204+
if (text.toLowerCase().includes('make method public')) {
205+
await driver.executeScript('arguments[0].click();', opt);
206+
clicked = true;
207+
break;
208+
}
209+
}
210+
if (!clicked) {
211+
await driver.actions().sendKeys(Key.ESCAPE).perform(); // close menu cleanly
212+
throw new Error('No "make public" quick fix was offered — see OPTION logs above');
213+
}
214+
215+
await wait.sleep(3000);
216+
await javaEditor.save();
217+
await wait.sleep(5000);
218+
219+
// Check quick fix was implemented at correct line number
220+
const after = await javaEditor.getText();
221+
expect(after).to.include('public String methodname');
222+
223+
problemsView = await bottomBar.openProblemsView();
224+
markers = await problemsView.getAllVisibleMarkers(MarkerType.Any);
225+
226+
// Check if the marker is present
227+
let stillPresent = false;
228+
for (const marker of markers) {
229+
const text = await marker.getText();
230+
// Check if text contains diagnostic message
231+
if(text.includes('Only public methods can be exposed as resource methods.')){
232+
stillPresent = true;
233+
break;
234+
}
235+
}
236+
expect(stillPresent).to.be.false;
237+
logger.testComplete('Diagnostic no longer shows for public @GET method as expected');
238+
239+
} catch (error) {
240+
logger.testFailed('Diagnostic/quick-fix test flow failed', error);
241+
throw error;
242+
}
243+
244+
});
245+
});
246+

src/test/MavenTestDevModeActions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright IBM Corp. 2023, 2026
44
*/
55
import { expect } from 'chai';
6-
import { DefaultTreeItem, EditorView, SideBarView, ViewItem, ViewSection, VSBrowser, Workbench } from 'vscode-extension-tester';
6+
import { DefaultTreeItem, EditorView, SideBarView, ViewItem, ViewSection, VSBrowser, Workbench, WebDriver } from 'vscode-extension-tester';
77
import * as utils from './utils/testUtils';
88
import * as constants from './definitions/constants';
99
import { logger } from './utils/testLogger';
@@ -18,8 +18,10 @@ describe('Devmode action tests for Maven Project', () => {
1818

1919
before(async function() {
2020
this.timeout(30000);
21-
// Wait for workbench to be ready
21+
22+
await VSBrowser.instance.openResources(utils.getMvnProjectPath());
2223
await VSBrowser.instance.waitForWorkbench();
24+
2325
sidebar = new SideBarView();
2426
});
2527

src/test/MavenTestLSPHover.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright IBM Corp. 2026
44
*/
55
import { expect } from 'chai';
6-
import { EditorView, TextEditor, VSBrowser, Workbench } from 'vscode-extension-tester';
6+
import { EditorView, TextEditor, VSBrowser, Workbench, WebDriver } from 'vscode-extension-tester';
77
import * as utils from './utils/testUtils';
88
import { logger } from './utils/testLogger';
99
import * as path from 'path';
@@ -12,9 +12,13 @@ describe('LSP Hover tests for Maven Project', () => {
1212
let editorView: EditorView;
1313
let editor: TextEditor;
1414
let wait: any;
15+
let driver: WebDriver;
16+
1517

1618
before(async function() {
1719
this.timeout(60000);
20+
driver = VSBrowser.instance.driver;
21+
await VSBrowser.instance.openResources(utils.getMvnProjectPath());
1822
logger.info('Setting up Maven LSP Hover tests');
1923

2024
// Wait for workbench to be ready
@@ -214,4 +218,5 @@ describe('LSP Hover tests for Maven Project', () => {
214218

215219
});
216220

217-
// Made with Bob
221+
222+

0 commit comments

Comments
 (0)