1+ import { join } from 'path' ;
2+ import { NxlsWrapper } from '../nxls-wrapper' ;
3+ import {
4+ defaultVersion ,
5+ e2eCwd ,
6+ newWorkspace ,
7+ uniq ,
8+ } from '@nx-console/shared-e2e-utils' ;
9+ import {
10+ NxGeneratorOptionsRequest ,
11+ NxGeneratorOptionsRequestOptions ,
12+ } from '@nx-console/language-server-types' ;
13+
14+ let nxlsWrapper : NxlsWrapper ;
15+ const workspaceName = uniq ( 'workspace' ) ;
16+
17+ describe ( 'generator options - Windows file URI handling' , ( ) => {
18+ beforeAll ( async ( ) => {
19+ // Create a new workspace with basic React setup
20+ newWorkspace ( {
21+ name : workspaceName ,
22+ options : {
23+ preset : 'react-monorepo' ,
24+ bundler : 'vite' ,
25+ e2eTestRunner : 'cypress' ,
26+ style : 'css' ,
27+ } ,
28+ version : defaultVersion ,
29+ } ) ;
30+
31+ // Start the language server
32+ nxlsWrapper = new NxlsWrapper ( ) ;
33+ await nxlsWrapper . startNxls ( join ( e2eCwd , workspaceName ) ) ;
34+ } ) ;
35+
36+ it ( 'should handle Windows file URIs with file:// prefix correctly' , async ( ) => {
37+ const schemaPath = join (
38+ e2eCwd ,
39+ workspaceName ,
40+ 'node_modules' ,
41+ '@nx/js/src/generators/library/schema.json' ,
42+ ) ;
43+
44+ // Test with Windows-style file URI (simulating what happens on Windows)
45+ const windowsFileUri = `file:///${ schemaPath . replace ( / \\ / g, '/' ) } ` ;
46+
47+ const generatorOptions = await nxlsWrapper . sendRequest ( {
48+ ...NxGeneratorOptionsRequest ,
49+ params : {
50+ options : {
51+ collection : '@nx/js' ,
52+ name : 'library' ,
53+ path : windowsFileUri ,
54+ } satisfies NxGeneratorOptionsRequestOptions ,
55+ } ,
56+ } ) ;
57+
58+ // Verify the result is successful and contains expected options
59+ expect ( generatorOptions . result ) . toBeDefined ( ) ;
60+ expect ( generatorOptions . error ) . toBeUndefined ( ) ;
61+
62+ const options = generatorOptions . result as any [ ] ;
63+ expect ( options . length ) . toBeGreaterThan ( 0 ) ;
64+
65+ // Check for some expected options to ensure the schema was loaded correctly
66+ const optionNames = options . map ( ( o ) => o . name ) ;
67+ expect ( optionNames ) . toContain ( 'name' ) ;
68+ expect ( optionNames ) . toContain ( 'directory' ) ;
69+ expect ( optionNames ) . toContain ( 'bundler' ) ;
70+ } ) ;
71+
72+ it ( 'should handle Windows file URIs with /c:/ pattern' , async ( ) => {
73+ // Only run this test on Windows or in CI
74+ if ( process . platform !== 'win32' && ! process . env . CI ) {
75+ console . log ( 'Skipping Windows-specific path test on non-Windows platform' ) ;
76+ return ;
77+ }
78+
79+ const schemaPath = join (
80+ e2eCwd ,
81+ workspaceName ,
82+ 'node_modules' ,
83+ '@nx/js/src/generators/library/schema.json' ,
84+ ) ;
85+
86+ // Create a Windows-style path with /c:/ pattern
87+ // This simulates the exact issue that was fixed
88+ const windowsDriveLetter = schemaPath . match ( / ^ ( [ a - z A - Z ] ) : / ) ?. [ 1 ] || 'c' ;
89+ const pathWithoutDrive = schemaPath . replace ( / ^ [ a - z A - Z ] : / , '' ) ;
90+ const problematicWindowsUri = `file:///${ windowsDriveLetter } :${ pathWithoutDrive . replace ( / \\ / g, '/' ) } ` ;
91+
92+ const generatorOptions = await nxlsWrapper . sendRequest ( {
93+ ...NxGeneratorOptionsRequest ,
94+ params : {
95+ options : {
96+ collection : '@nx/js' ,
97+ name : 'library' ,
98+ path : problematicWindowsUri ,
99+ } satisfies NxGeneratorOptionsRequestOptions ,
100+ } ,
101+ } ) ;
102+
103+ // The fix should handle this correctly
104+ expect ( generatorOptions . result ) . toBeDefined ( ) ;
105+ expect ( generatorOptions . error ) . toBeUndefined ( ) ;
106+
107+ const options = generatorOptions . result as any [ ] ;
108+ expect ( options . length ) . toBeGreaterThan ( 0 ) ;
109+ } ) ;
110+
111+ it ( 'should handle regular file paths without file:// prefix' , async ( ) => {
112+ const schemaPath = join (
113+ e2eCwd ,
114+ workspaceName ,
115+ 'node_modules' ,
116+ '@nx/js/src/generators/library/schema.json' ,
117+ ) ;
118+
119+ const generatorOptions = await nxlsWrapper . sendRequest ( {
120+ ...NxGeneratorOptionsRequest ,
121+ params : {
122+ options : {
123+ collection : '@nx/js' ,
124+ name : 'library' ,
125+ path : schemaPath ,
126+ } satisfies NxGeneratorOptionsRequestOptions ,
127+ } ,
128+ } ) ;
129+
130+ // Should work with regular paths too
131+ expect ( generatorOptions . result ) . toBeDefined ( ) ;
132+ expect ( generatorOptions . error ) . toBeUndefined ( ) ;
133+
134+ const options = generatorOptions . result as any [ ] ;
135+ expect ( options . length ) . toBeGreaterThan ( 0 ) ;
136+ } ) ;
137+
138+ it ( 'should return error for non-existent schema file with file:// URI' , async ( ) => {
139+ const nonExistentPath = join (
140+ e2eCwd ,
141+ workspaceName ,
142+ 'node_modules' ,
143+ '@nx/js/src/generators/non-existent/schema.json' ,
144+ ) ;
145+
146+ const windowsFileUri = `file:///${ nonExistentPath . replace ( / \\ / g, '/' ) } ` ;
147+
148+ const generatorOptions = await nxlsWrapper . sendRequest ( {
149+ ...NxGeneratorOptionsRequest ,
150+ params : {
151+ options : {
152+ collection : '@nx/js' ,
153+ name : 'non-existent' ,
154+ path : windowsFileUri ,
155+ } satisfies NxGeneratorOptionsRequestOptions ,
156+ } ,
157+ } ) ;
158+
159+ // Should handle errors gracefully
160+ expect ( generatorOptions . error ) . toBeDefined ( ) ;
161+ } ) ;
162+
163+ afterAll ( async ( ) => {
164+ return await nxlsWrapper . stopNxls ( ) ;
165+ } ) ;
166+ } ) ;
0 commit comments