1- /**
2- * Copyright (c) 2025 IBM Corporation.
3- *
4- * This program and the accompanying materials are made available under the
5- * terms of the Eclipse Public License v. 2.0 which is available at
6- * http://www.eclipse.org/legal/epl-2.0.
7- *
8- * SPDX-License-Identifier: EPL-2.0
1+ /*
2+ * IBM Confidential
3+ * Copyright IBM Corp. 2025, 2026
94 */
105import { expect } from 'chai' ;
11- import { By , EditorView , TextEditor , VSBrowser , Workbench , BottomBarPanel , MarkerType , Key } from 'vscode-extension-tester' ;
6+ import { By , EditorView , TextEditor , VSBrowser , WebDriver , Workbench , BottomBarPanel , MarkerType , Key } from 'vscode-extension-tester' ;
127import * as utils from './utils/testUtils' ;
138import { logger } from './utils/testLogger' ;
149import * as path from 'path' ;
1510
16- describe ( 'Liberty Config Language Server Tests for Maven Project' , function ( ) {
11+ describe ( 'Liberty Config Language Server Tests for Maven Project' , ( ) => {
1712 let editorView : EditorView ;
1813 let editor : TextEditor ;
1914 let wait : any ;
20- let driver : any ;
15+ let driver : WebDriver ;
2116 let originalContent : string ;
2217
2318 before ( async function ( ) {
@@ -30,9 +25,7 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
3025 await VSBrowser . instance . waitForWorkbench ( ) ;
3126 editorView = new EditorView ( ) ;
3227
33- // Open the real server.xml — LCLS only activates on files under a recognised
34- // Liberty config directory name ('config'), so we edit this file directly and
35- // restore its content in afterEach.
28+ // Open the real server.xml
3629 const serverXmlPath = path . resolve (
3730 utils . getMvnProjectPath ( ) ,
3831 'src' , 'main' , 'liberty' , 'config' , 'server.xml'
@@ -54,31 +47,19 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
5447 logger . error ( `Test failed: ${ this . currentTest ?. title } ` ) ;
5548 }
5649
57- // Close the bottom bar and re-focus the editor before restoring content.
58- // Any test that opens the Output or Problems panel shifts VS Code focus,
59- // making subsequent editor operations unreliable.
50+ // Close the bottom bar and re-focus the editor
6051 await new BottomBarPanel ( ) . toggle ( false ) ;
6152 editor = await editorView . openEditor ( 'server.xml' ) as TextEditor ;
62- // Wait until getText() returns the actual server.xml content — not just any
63- // non-empty string. After the Output/Problems panel, the clipboard can still
64- // hold panel text, making getText() return stale content immediately.
65- // Checking for a known string from the file confirms the editor inputArea
66- // truly has focus and is returning its own content.
53+ // Wait until getText() returns the actual server.xml content
6754 await utils . waitForCondition ( async ( ) => {
6855 const text = await editor . getText ( ) ;
6956 return text . includes ( '<server' ) ? true : undefined ;
7057 } , 15 ) ;
7158
72- // Restore original content so each test starts from a clean slate.
73- // setText() replaces all content internally via Ctrl+A, Ctrl+V — calling
74- // clearText() first is redundant and causes a stray 'a' keystroke when
75- // focus briefly shifts between the two operations.
59+ // Restore original content
7660 if ( originalContent ) {
7761 await editor . setText ( originalContent ) ;
7862 await editor . save ( ) ;
79- // Give LCLS time to reanalyse the restored file before the next test.
80- // Avoid opening the Problems panel here — doing so steals focus from
81- // the editor and poisons the clipboard used by getText().
8263 await wait . sleep ( 3000 ) ;
8364 logger . info ( 'Restored original server.xml content' ) ;
8465 }
@@ -87,8 +68,6 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
8768 after ( async function ( ) {
8869 this . timeout ( 30000 ) ;
8970 try {
90- // Revert any unsaved changes before closing — a dirty editor causes
91- // VS Code to show a "save?" dialog which blocks closeAllEditors()
9271 await new Workbench ( ) . executeCommand ( 'revert file' ) ;
9372 await wait . sleep ( 500 ) ;
9473 await editorView . closeAllEditors ( ) ;
@@ -110,30 +89,25 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
11089 logger . testComplete ( 'Liberty Language Server initialized successfully' ) ;
11190 } ) ;
11291
113- // ========================================
114- // ISSUE #370: Diagnostic Detection
115- // ========================================
11692
117- it ( 'Should show diagnostic for invalid feature (#370)' , async function ( ) {
118- this . timeout ( 60000 ) ;
119- logger . testStart ( 'Testing diagnostic for invalid feature' ) ;
93+ // Diagnostic + Quick Fix
94+ it ( 'Should show diagnostic for invalid feature and apply quick fix' , async function ( ) {
95+ this . timeout ( 120000 ) ;
96+ logger . testStart ( 'Testing diagnostic detection and quick fix for invalid feature' ) ;
97+
12098
121- // Re-acquire editor handle at test start — afterEach may have left focus
122- // on a different panel; openEditor() clicks the tab and returns a live handle
12399 editor = await editorView . openEditor ( 'server.xml' ) as TextEditor ;
124100
125- logger . step ( 1 , 'Finding feature line' ) ;
101+ logger . step ( 1 , 'Finding feature line and replacing with invalid feature ' ) ;
126102 const lineNumber = await editor . getLineOfText ( 'jsp-2.3' ) ;
127103 logger . stepSuccess ( 1 , `Found feature at line ${ lineNumber } ` ) ;
128-
129- logger . step ( 2 , 'Replacing with invalid feature' ) ;
130104 const currentLine = await editor . getTextAtLine ( lineNumber ) ;
131105 const modifiedLine = currentLine . replace ( 'jsp-2.3' , 'jsp-100.0' ) ;
132106 await editor . setTextAtLine ( lineNumber , modifiedLine ) ;
133107 await editor . save ( ) ;
134- logger . stepSuccess ( 2 , 'Changed to invalid feature jsp-100.0' ) ;
108+ logger . stepSuccess ( 1 , 'Changed to invalid feature jsp-100.0' ) ;
135109
136- logger . step ( 3 , 'Waiting for diagnostic to appear' ) ;
110+ logger . step ( 2 , 'Waiting for diagnostic to appear' ) ;
137111 // LCLS produces: ERROR: The feature "jsp-100.0" does not exist. liberty-lemminx(incorrect_feature)
138112 await wait . forCondition ( async ( ) => {
139113 try {
@@ -144,7 +118,7 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
144118 for ( const marker of markers ) {
145119 const text = await marker . getText ( ) ;
146120 if ( text . includes ( 'does not exist' ) ) {
147- logger . stepSuccess ( 3 , `Diagnostic found: ${ text } ` ) ;
121+ logger . stepSuccess ( 2 , `Diagnostic found: ${ text } ` ) ;
148122 return true ;
149123 }
150124 }
@@ -158,58 +132,13 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
158132 message : 'Diagnostic did not appear for invalid feature'
159133 } ) ;
160134
161- logger . testComplete ( 'Diagnostic detected for invalid feature' ) ;
162- } ) ;
163-
164- // ========================================
165- // ISSUE #434: Quick Fix Application
166- // ========================================
167-
168- it ( 'Should apply quick fix for invalid feature (#434)' , async function ( ) {
169- this . timeout ( 90000 ) ;
170- logger . testStart ( 'Testing quick fix for invalid feature' ) ;
171-
172- editor = await editorView . openEditor ( 'server.xml' ) as TextEditor ;
173-
174- logger . step ( 1 , 'Adding invalid feature' ) ;
175- const lineNumber = await editor . getLineOfText ( 'jsp-2.3' ) ;
176- const currentLine = await editor . getTextAtLine ( lineNumber ) ;
177- const modifiedLine = currentLine . replace ( 'jsp-2.3' , 'jsp-100.0' ) ;
178- await editor . setTextAtLine ( lineNumber , modifiedLine ) ;
179- await editor . save ( ) ;
180- logger . stepSuccess ( 1 , 'Changed to invalid feature' ) ;
181135
182- logger . step ( 2 , 'Waiting for diagnostic to appear before triggering quick fix' ) ;
183- await wait . forCondition ( async ( ) => {
184- try {
185- const bottomBar = new BottomBarPanel ( ) ;
186- await bottomBar . toggle ( true ) ;
187- const problemsView = await bottomBar . openProblemsView ( ) ;
188- const markers = await problemsView . getAllVisibleMarkers ( MarkerType . Error ) ;
189- for ( const marker of markers ) {
190- const text = await marker . getText ( ) ;
191- if ( text . includes ( 'does not exist' ) ) {
192- return true ;
193- }
194- }
195- return undefined ;
196- } catch {
197- return undefined ;
198- }
199- } , {
200- timeout : 45000 ,
201- pollInterval : 2000 ,
202- message : 'Diagnostic did not appear before attempting quick fix'
203- } ) ;
204- // Close the bottom bar and re-acquire the editor — the Problems panel
205- // interaction in step 2 shifts focus off the editor tab
206136 await new BottomBarPanel ( ) . toggle ( false ) ;
207137 editor = await editorView . openEditor ( 'server.xml' ) as TextEditor ;
208138 await utils . waitForCondition ( async ( ) => {
209139 const text = await editor . getText ( ) ;
210140 return text . includes ( '<server' ) ? true : undefined ;
211141 } , 15 ) ;
212- logger . stepSuccess ( 2 , 'Diagnostic confirmed' ) ;
213142
214143 logger . step ( 3 , 'Selecting invalid feature text' ) ;
215144 await editor . selectText ( 'jsp-100.0' ) ;
@@ -221,7 +150,6 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
221150 // The quick-fix widget closes between polling iterations, so re-open it each time
222151 const quickFixApplied = await wait . forCondition ( async ( ) => {
223152 try {
224- // Re-select and re-open the menu on every attempt
225153 await editor . selectText ( 'jsp-100.0' ) ;
226154 await driver . actions ( ) . keyDown ( modKey ) . sendKeys ( '.' ) . keyUp ( modKey ) . perform ( ) ;
227155 await wait . sleep ( 1500 ) ;
@@ -232,8 +160,7 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
232160 for ( const opt of options ) {
233161 const text = await opt . getText ( ) ;
234162 logger . info ( `Quick fix option: ${ text } ` ) ;
235- // LCLS offers "Replace feature with jsp-2.2" and "Replace feature with jsp-2.3"
236- // Accept either — both are valid replacements for the invalid jsp-100.0
163+ // LCLS offers "Replace feature with jsp-2.2" and "Replace feature with jsp-2.3", accept either
237164 if ( text . includes ( 'Replace feature with jsp-' ) ) {
238165 await driver . executeScript ( 'arguments[0].click();' , opt ) ;
239166 logger . stepSuccess ( 4 , `Applied quick fix: ${ text } ` ) ;
@@ -255,7 +182,6 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
255182 expect ( quickFixApplied ) . to . be . true ;
256183
257184 logger . step ( 5 , 'Verifying fix was applied' ) ;
258- // Wait until the editor reflects the applied fix rather than sleeping blindly
259185 const updatedContent = await utils . waitForCondition ( async ( ) => {
260186 const text = await editor . getText ( ) ;
261187 return ! text . includes ( 'jsp-100.0' ) ? text : undefined ;
@@ -265,23 +191,19 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
265191 expect ( updatedContent ) . to . not . include ( 'jsp-100.0' ) ;
266192 logger . stepSuccess ( 5 , 'Quick fix successfully replaced invalid feature' ) ;
267193
268- logger . testComplete ( 'Quick fix applied successfully' ) ;
194+ logger . testComplete ( 'Diagnostic detected and quick fix applied successfully' ) ;
269195 } ) ;
270196
271- // ========================================
272- // ISSUE #391: Autocomplete for Features
273- // ========================================
274197
198+ // Autocomplete for Features
275199 it ( 'Should provide autocomplete for Liberty features (#391)' , async function ( ) {
276200 this . timeout ( 60000 ) ;
277201 logger . testStart ( 'Testing autocomplete for features' ) ;
278202
279203 editor = await editorView . openEditor ( 'server.xml' ) as TextEditor ;
280204
281- // The capability being tested: LCLS provides a completion list of valid
282- // Liberty feature names when the cursor is inside a <feature> tag value.
283- // We verify the list opens with items, then dismiss it and type the value
284- // directly — avoiding the fragile scroll-and-select over hundreds of entries.
205+
206+ // verify the list opens with items, then dismiss it and type the value directly
285207 logger . step ( 1 , 'Finding the closing </featureManager> line as insertion point' ) ;
286208 const featureManagerEndLine = await editor . getLineOfText ( '</featureManager>' ) ;
287209 logger . stepSuccess ( 1 , `Found </featureManager> at line ${ featureManagerEndLine } ` ) ;
@@ -290,15 +212,13 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
290212 await editor . typeTextAt ( featureManagerEndLine , 1 , ' <feature></feature>' ) ;
291213 logger . stepSuccess ( 2 , 'Typed empty feature tag' ) ;
292214
293- // Position cursor inside the empty tag — between > and <
294- // " <feature>" is 18 chars so cursor goes at col 18
295215 logger . step ( 3 , 'Positioning cursor inside the empty feature tag' ) ;
296216 await editor . setCursor ( featureManagerEndLine , 18 ) ;
297217 logger . stepSuccess ( 3 , 'Cursor positioned inside feature tag' ) ;
298218
299219 logger . step ( 4 , 'Opening content assist and verifying feature list appears' ) ;
300220 const assist = await editor . toggleContentAssist ( true ) ;
301- // Verify the list has items — confirms LCLS is providing feature completions
221+
302222 const items = await utils . waitForCondition ( async ( ) => {
303223 try {
304224 const all = await assist ! . getItems ( ) ;
@@ -329,10 +249,8 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
329249 logger . testComplete ( 'Autocomplete for features worked' ) ;
330250 } ) ;
331251
332- // ========================================
333- // ISSUE #392: Autocomplete for Config Stanzas
334- // ========================================
335252
253+ // Autocomplete for Config Stanzas
336254 describe ( 'Autocomplete for Configuration Stanzas (#392)' , ( ) => {
337255
338256 it ( 'Should autocomplete <logging> stanza' , async function ( ) {
@@ -341,9 +259,6 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
341259
342260 editor = await editorView . openEditor ( 'server.xml' ) as TextEditor ;
343261
344- // The flow: type a partial element name at server level, trigger Ctrl+Space,
345- // select from the dropdown. LCLS inserts <logging></logging>.
346- // Uses 'logging' — available with only jsp-2.3, confirmed locally.
347262 logger . step ( 1 , 'Finding </featureManager> as insertion point' ) ;
348263 const lineNumber = await editor . getLineOfText ( '</featureManager>' ) ;
349264 logger . stepSuccess ( 1 , `Found featureManager end at line ${ lineNumber } ` ) ;
@@ -378,7 +293,6 @@ describe('Liberty Config Language Server Tests for Maven Project', function () {
378293 const text = await editor . getText ( ) ;
379294 return text . includes ( '<logging>' ) ? text : undefined ;
380295 } , 10 ) ;
381- // LCLS inserts <logging></logging> (confirmed locally)
382296 expect ( updatedContent ) . to . include ( '<logging>' ) ;
383297 expect ( updatedContent ) . to . include ( '</logging>' ) ;
384298 logger . stepSuccess ( 5 , 'Logging stanza autocomplete worked' ) ;
0 commit comments