Skip to content

Commit 9b431ca

Browse files
authored
Merge pull request OpenLiberty#578 from mattbsox/hover-test
Add LSP hover tests
2 parents 6d3445f + 1dc86a0 commit 9b431ca

6 files changed

Lines changed: 665 additions & 123 deletions

File tree

src/test/GradleTestDevModeActions.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,14 @@
33
* Copyright IBM Corp. 2023, 2026
44
*/
55
import { expect } from 'chai';
6-
import { InputBox, Workbench, SideBarView, ViewSection, EditorView, DefaultTreeItem, DebugView } from 'vscode-extension-tester';
6+
import { DefaultTreeItem, EditorView, InputBox, SideBarView, ViewSection, VSBrowser, 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';
10-
import * as fs from 'fs';
11-
import { VSBrowser } from 'vscode-extension-tester';
1210
import path = require('path');
1311

1412
describe('Devmode action tests for Gradle Project', () => {
1513
let sidebar: SideBarView;
16-
let debugView: DebugView;
1714
let section: ViewSection;
1815
let item: DefaultTreeItem;
1916
let tabs: string[];
@@ -23,10 +20,10 @@ describe('Devmode action tests for Gradle Project', () => {
2320
// Wait for workbench to be ready
2421
await VSBrowser.instance.waitForWorkbench();
2522
sidebar = new SideBarView();
26-
debugView = new DebugView();
2723
});
2824

2925
afterEach(async function() {
26+
this.timeout(10000); // Increase timeout for cleanup operations
3027
// Close any open editors after each test
3128
if (this.currentTest?.state === 'failed') {
3229
const driver = VSBrowser.instance.driver;
@@ -39,6 +36,14 @@ describe('Devmode action tests for Gradle Project', () => {
3936
} catch (error) {
4037
logger.error('Failed to close editors in afterEach', error);
4138
}
39+
40+
// Clear terminal between tests to avoid confusion with old output
41+
try {
42+
const workbench = new Workbench();
43+
await workbench.executeCommand('terminal clear');
44+
} catch (error) {
45+
logger.error('Failed to clear terminal in afterEach', error);
46+
}
4247
});
4348

4449
it('Find Liberty Dashboard in sidebar', async () => {
@@ -387,10 +392,10 @@ describe('Devmode action tests for Gradle Project', () => {
387392
logger.info('Attach Debugger action completed');
388393

389394
logger.step(6, 'Waiting for debugger to attach');
390-
attachStatus = await utils.waitForDebuggerAttach(debugView);
395+
attachStatus = await utils.waitForDebuggerAttach();
391396

392397
if (!attachStatus) {
393-
logger.error('BREAKPOINTS section not found - debugger may not have attached');
398+
logger.error('DebugToolbar not found - debugger may not have attached');
394399
} else {
395400
logger.stepSuccess(6, 'Debugger attached successfully');
396401
}

src/test/GradleTestLSPHover.ts

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* IBM Confidential
3+
* Copyright IBM Corp. 2026
4+
*/
5+
import { expect } from 'chai';
6+
import { EditorView, TextEditor, VSBrowser, Workbench } from 'vscode-extension-tester';
7+
import * as utils from './utils/testUtils';
8+
import { logger } from './utils/testLogger';
9+
import * as path from 'path';
10+
11+
describe('LSP Hover tests for Gradle Project', () => {
12+
let editorView: EditorView;
13+
let editor: TextEditor;
14+
let wait: any;
15+
16+
before(async function() {
17+
this.timeout(60000);
18+
logger.info('Setting up Gradle LSP Hover tests');
19+
20+
// Wait for workbench to be ready
21+
await VSBrowser.instance.waitForWorkbench();
22+
editorView = new EditorView();
23+
wait = utils.getWaitHelper();
24+
25+
// Open server.xml file once for all tests
26+
logger.info('Opening server.xml file for all tests');
27+
const serverXmlPath = path.resolve(
28+
utils.getGradleProjectPath(),
29+
'src',
30+
'main',
31+
'liberty',
32+
'config',
33+
'server.xml'
34+
);
35+
logger.info(`Server.xml path: ${serverXmlPath}`);
36+
37+
await VSBrowser.instance.openResources(serverXmlPath, async () => {
38+
await wait.sleep(3000); // Allow time for file to load
39+
});
40+
41+
editor = await editorView.openEditor('server.xml') as TextEditor;
42+
logger.info('Server.xml file opened and editor obtained');
43+
});
44+
45+
afterEach(async function() {
46+
// Take screenshot on failure but don't close editor
47+
if (this.currentTest?.state === 'failed') {
48+
const driver = VSBrowser.instance.driver;
49+
const screenshot = await driver.takeScreenshot();
50+
logger.error(`Test failed: ${this.currentTest.title}`);
51+
}
52+
});
53+
54+
after(async function() {
55+
this.timeout(10000); // Increase timeout for cleanup operations
56+
// Close editor after all tests complete
57+
try {
58+
await editorView.closeAllEditors();
59+
logger.info('Closed all editors after test suite');
60+
} catch (error) {
61+
logger.error('Failed to close editors in after hook', error);
62+
}
63+
64+
utils.copyScreenshotsToProjectFolder('gradle');
65+
});
66+
67+
it('Liberty Language Server should initialize', async function() {
68+
this.timeout(60000);
69+
logger.testStart('Liberty Language Server should initialize');
70+
71+
try {
72+
await utils.waitForLanguageServerInit(
73+
'Language Support for Liberty',
74+
'Initialized Liberty Language server',
75+
60
76+
);
77+
logger.testComplete('Liberty Language Server initialized successfully');
78+
} catch (error) {
79+
logger.testFailed('Liberty Language Server should initialize', error);
80+
throw error;
81+
}
82+
});
83+
84+
// Test data for parameterized hover tests
85+
const hoverTestCases = [
86+
{ element: 'httpEndpoint element', line: 18, column: 10, expectedDoc: 'Configuration properties for an HTTP endpoint.' },
87+
{ element: 'feature element', line: 15, column: 16, expectedDoc: 'Specifies a feature to be used when the server runs.' },
88+
{ element: 'featureManager element', line: 14, column: 10, expectedDoc: 'Defines how the server loads features.' },
89+
{ element: 'webApplication element', line: 20, column: 10, expectedDoc: 'Defines the properties of a web application.' },
90+
{ element: 'jsp-2.3 feature value', line: 15, column: 22, expectedDoc: 'This feature enables support for Java Server Pages (JSPs) that are written to the JSP 2.3 specification.' },
91+
{ element: 'httpPort attribute', line: 18, column: 33, expectedDoc: 'The port used for client HTTP requests. Use -1 to disable this port.' }
92+
];
93+
94+
hoverTestCases.forEach(testCase => {
95+
it(`Hover over ${testCase.element} shows Liberty Language Server documentation`, async function() {
96+
this.timeout(30000);
97+
logger.testStart(`Hover over ${testCase.element} shows Liberty Language Server documentation`);
98+
99+
try {
100+
logger.step(1, `Setting cursor position on ${testCase.element}`);
101+
await editor.setCursor(testCase.line, testCase.column);
102+
logger.stepSuccess(1, `Cursor positioned on ${testCase.element} at line ${testCase.line}`);
103+
104+
logger.step(2, 'Triggering hover via command palette');
105+
await new Workbench().executeCommand('editor.action.showHover');
106+
logger.stepSuccess(2, 'Hover command executed');
107+
108+
logger.step(3, 'Verifying hover widget appears with Liberty Language Server content');
109+
const driver = VSBrowser.instance.driver;
110+
const hoverText = await utils.waitForHoverWidget(driver, testCase.element, 15000);
111+
112+
expect(hoverText).to.not.be.empty;
113+
logger.stepSuccess(3, `Hover widget displayed with Liberty Language Server content for ${testCase.element}`);
114+
115+
logger.step(4, 'Verifying hover contains expected documentation');
116+
expect(hoverText).to.include(testCase.expectedDoc);
117+
logger.stepSuccess(4, `Hover text contains expected documentation: "${testCase.expectedDoc}"`);
118+
119+
logger.testComplete(`Hover over ${testCase.element} shows Liberty Language Server documentation`);
120+
} catch (error) {
121+
logger.testFailed(`Hover over ${testCase.element} shows Liberty Language Server documentation`, error);
122+
throw error;
123+
}
124+
});
125+
});
126+
127+
describe('LSP4Jakarta Hover tests in Java file', () => {
128+
let javaEditor: TextEditor;
129+
130+
before(async function() {
131+
this.timeout(60000);
132+
logger.info('Opening HelloServlet.java file for LSP4Jakarta hover tests');
133+
134+
const javaFilePath = path.resolve(
135+
utils.getGradleProjectPath(),
136+
'src',
137+
'main',
138+
'java',
139+
'test',
140+
'gradle',
141+
'liberty',
142+
'web',
143+
'app',
144+
'HelloServlet.java'
145+
);
146+
logger.info(`Java file path: ${javaFilePath}`);
147+
148+
await VSBrowser.instance.openResources(javaFilePath, async () => {
149+
await wait.sleep(3000); // Allow time for file to load
150+
});
151+
152+
javaEditor = await editorView.openEditor('HelloServlet.java') as TextEditor;
153+
logger.info('HelloServlet.java file opened and editor obtained');
154+
});
155+
156+
it('LSP4Jakarta Language Server should initialize', async function() {
157+
this.timeout(60000);
158+
logger.testStart('LSP4Jakarta Language Server should initialize');
159+
160+
try {
161+
await utils.waitForLanguageServerInit(
162+
'Language Support for Jakarta EE',
163+
'Initializing Jakarta EE server',
164+
60
165+
);
166+
logger.testComplete('LSP4Jakarta Language Server initialized successfully');
167+
} catch (error) {
168+
logger.testFailed('LSP4Jakarta Language Server should initialize', error);
169+
throw error;
170+
}
171+
});
172+
173+
// Test data for LSP4Jakarta hover tests
174+
const jakartaHoverTestCases = [
175+
{ element: '@WebServlet annotation', line: 23, column: 2, expectedDoc: 'Annotation used to declare a servlet.' },
176+
{ element: 'HttpServlet class', line: 24, column: 35, expectedDoc: 'Provides an abstract class to be subclassed to create an HTTP servlet suitable for a Web site.' },
177+
{ element: 'HttpServletRequest type', line: 30, column: 35, expectedDoc: 'Extends the javax.servlet.ServletRequest interface to provide request information for HTTP servlets.' },
178+
{ element: 'HttpServletResponse type', line: 30, column: 70, expectedDoc: 'Extends the ServletResponse interface to provide HTTP-specific functionality in sending a response.' }
179+
];
180+
181+
jakartaHoverTestCases.forEach(testCase => {
182+
it(`Hover over ${testCase.element} shows LSP4Jakarta documentation`, async function() {
183+
this.timeout(30000);
184+
logger.testStart(`Hover over ${testCase.element} shows LSP4Jakarta documentation`);
185+
186+
try {
187+
logger.step(1, `Setting cursor position on ${testCase.element}`);
188+
await javaEditor.setCursor(testCase.line, testCase.column);
189+
logger.stepSuccess(1, `Cursor positioned on ${testCase.element} at line ${testCase.line}`);
190+
191+
logger.step(2, 'Triggering hover via command palette');
192+
await new Workbench().executeCommand('editor.action.showHover');
193+
logger.stepSuccess(2, 'Hover command executed');
194+
195+
logger.step(3, 'Verifying hover widget appears with LSP4Jakarta content');
196+
const driver = VSBrowser.instance.driver;
197+
const hoverText = await utils.waitForHoverWidget(driver, testCase.element, 15000);
198+
199+
expect(hoverText).to.not.be.empty;
200+
logger.stepSuccess(3, `Hover widget displayed with LSP4Jakarta content for ${testCase.element}`);
201+
202+
logger.step(4, 'Verifying hover contains expected documentation');
203+
expect(hoverText).to.include(testCase.expectedDoc);
204+
logger.stepSuccess(4, `Hover text contains expected documentation: "${testCase.expectedDoc}"`);
205+
206+
logger.testComplete(`Hover over ${testCase.element} shows LSP4Jakarta documentation`);
207+
} catch (error) {
208+
logger.testFailed(`Hover over ${testCase.element} shows LSP4Jakarta documentation`, error);
209+
throw error;
210+
}
211+
});
212+
});
213+
});
214+
215+
});
216+
217+
// Made with Bob

0 commit comments

Comments
 (0)