1- import { execFileSync } from " node:child_process" ;
2- import { dirname , join , resolve } from " node:path" ;
3- import { fileURLToPath } from " node:url" ;
1+ import { execFileSync } from ' node:child_process' ;
2+ import { dirname , join , resolve } from ' node:path' ;
3+ import { fileURLToPath } from ' node:url' ;
44
5- import { glob } from " fast-glob" ;
6- import { describe , expect , it } from " vitest" ;
5+ import { glob } from ' fast-glob' ;
6+ import { describe , expect , it } from ' vitest' ;
77
88const __filename = fileURLToPath ( import . meta. url ) ;
99const __dirname = dirname ( __filename ) ;
1010
11- const ROOT_DIR = resolve ( __dirname , ".." ) ;
11+ const ROOT_DIR = resolve ( __dirname , '..' ) ;
1212const E2E_DIR = __dirname ;
13- const FIXTURES_DIR = join ( E2E_DIR , "fixtures" ) ;
14- const TSGOLINT_BIN = join (
15- ROOT_DIR ,
16- `tsgolint${ process . platform === "win32" ? ".exe" : "" } `
17- ) ;
13+ const FIXTURES_DIR = join ( E2E_DIR , 'fixtures' ) ;
14+ const TSGOLINT_BIN = join ( ROOT_DIR , `tsgolint${ process . platform === 'win32' ? '.exe' : '' } ` ) ;
1815
1916const ALL_RULES = [
20- " await-thenable" ,
21- " no-array-delete" ,
22- " no-base-to-string" ,
23- " no-confusing-void-expression" ,
24- " no-duplicate-type-constituents" ,
25- " no-floating-promises" ,
26- " no-for-in-array" ,
27- " no-implied-eval" ,
28- " no-meaningless-void-operator" ,
29- " no-misused-promises" ,
30- " no-misused-spread" ,
31- " no-mixed-enums" ,
32- " no-redundant-type-constituents" ,
33- " no-unnecessary-boolean-literal-compare" ,
34- " no-unnecessary-template-expression" ,
35- " no-unnecessary-type-arguments" ,
36- " no-unnecessary-type-assertion" ,
37- " no-unsafe-argument" ,
38- " no-unsafe-assignment" ,
39- " no-unsafe-call" ,
40- " no-unsafe-enum-comparison" ,
41- " no-unsafe-member-access" ,
42- " no-unsafe-return" ,
43- " no-unsafe-type-assertion" ,
44- " no-unsafe-unary-minus" ,
45- " non-nullable-type-assertion-style" ,
46- " only-throw-error" ,
47- " prefer-promise-reject-errors" ,
48- " prefer-reduce-type-parameter" ,
49- " prefer-return-this-type" ,
50- " promise-function-async" ,
51- " related-getter-setter-pairs" ,
52- " require-array-sort-compare" ,
53- " require-await" ,
54- " restrict-plus-operands" ,
55- " restrict-template-expressions" ,
56- " return-await" ,
57- " switch-exhaustiveness-check" ,
58- " unbound-method" ,
59- " use-unknown-in-catch-callback-variable" ,
17+ ' await-thenable' ,
18+ ' no-array-delete' ,
19+ ' no-base-to-string' ,
20+ ' no-confusing-void-expression' ,
21+ ' no-duplicate-type-constituents' ,
22+ ' no-floating-promises' ,
23+ ' no-for-in-array' ,
24+ ' no-implied-eval' ,
25+ ' no-meaningless-void-operator' ,
26+ ' no-misused-promises' ,
27+ ' no-misused-spread' ,
28+ ' no-mixed-enums' ,
29+ ' no-redundant-type-constituents' ,
30+ ' no-unnecessary-boolean-literal-compare' ,
31+ ' no-unnecessary-template-expression' ,
32+ ' no-unnecessary-type-arguments' ,
33+ ' no-unnecessary-type-assertion' ,
34+ ' no-unsafe-argument' ,
35+ ' no-unsafe-assignment' ,
36+ ' no-unsafe-call' ,
37+ ' no-unsafe-enum-comparison' ,
38+ ' no-unsafe-member-access' ,
39+ ' no-unsafe-return' ,
40+ ' no-unsafe-type-assertion' ,
41+ ' no-unsafe-unary-minus' ,
42+ ' non-nullable-type-assertion-style' ,
43+ ' only-throw-error' ,
44+ ' prefer-promise-reject-errors' ,
45+ ' prefer-reduce-type-parameter' ,
46+ ' prefer-return-this-type' ,
47+ ' promise-function-async' ,
48+ ' related-getter-setter-pairs' ,
49+ ' require-array-sort-compare' ,
50+ ' require-await' ,
51+ ' restrict-plus-operands' ,
52+ ' restrict-template-expressions' ,
53+ ' return-await' ,
54+ ' switch-exhaustiveness-check' ,
55+ ' unbound-method' ,
56+ ' use-unknown-in-catch-callback-variable' ,
6057] as const ;
6158
6259interface Diagnostic {
@@ -94,12 +91,11 @@ function parseHeadlessOutput(data: Buffer): Diagnostic[] {
9491 // Only process diagnostic messages (type 1)
9592 if ( msgType === 1 ) {
9693 try {
97- const diagnostic = JSON . parse ( payload . toString ( " utf-8" ) ) ;
94+ const diagnostic = JSON . parse ( payload . toString ( ' utf-8' ) ) ;
9895 // Make file paths relative to fixtures/ for deterministic snapshots
99- const filePath = diagnostic . file_path || "" ;
100- if ( filePath . includes ( "fixtures/" ) ) {
101- diagnostic . file_path =
102- "fixtures/" + filePath . split ( "fixtures/" ) . pop ( ) ;
96+ const filePath = diagnostic . file_path || '' ;
97+ if ( filePath . includes ( 'fixtures/' ) ) {
98+ diagnostic . file_path = 'fixtures/' + filePath . split ( 'fixtures/' ) . pop ( ) ;
10399 }
104100 diagnostics . push ( diagnostic ) ;
105101 } catch {
@@ -113,12 +109,12 @@ function parseHeadlessOutput(data: Buffer): Diagnostic[] {
113109
114110function sortDiagnostics ( diagnostics : Diagnostic [ ] ) : Diagnostic [ ] {
115111 diagnostics . sort ( ( a , b ) => {
116- const aFilePath = a . file_path || "" ;
117- const bFilePath = b . file_path || "" ;
112+ const aFilePath = a . file_path || '' ;
113+ const bFilePath = b . file_path || '' ;
118114 if ( aFilePath !== bFilePath ) return aFilePath . localeCompare ( bFilePath ) ;
119115
120- const aRule = a . rule || "" ;
121- const bRule = b . rule || "" ;
116+ const aRule = a . rule || '' ;
117+ const bRule = b . rule || '' ;
122118 if ( aRule !== bRule ) return aRule . localeCompare ( bRule ) ;
123119
124120 const aPos = ( a . range && a . range . pos ) || 0 ;
@@ -134,30 +130,22 @@ function sortDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] {
134130}
135131
136132async function getTestFiles ( testPath : string ) : Promise < string [ ] > {
137- const patterns = [
138- `${ testPath } /**/*.ts` ,
139- `${ testPath } /**/*.tsx` ,
140- `${ testPath } /**/*.mts` ,
141- `${ testPath } /**/*.cts` ,
142- ] ;
133+ const patterns = [ `${ testPath } /**/*.ts` , `${ testPath } /**/*.tsx` , `${ testPath } /**/*.mts` , `${ testPath } /**/*.cts` ] ;
143134 const allFiles : string [ ] = [ ] ;
144135
145136 for ( const pattern of patterns ) {
146137 const files = await glob ( pattern , {
147138 cwd : FIXTURES_DIR ,
148139 absolute : true ,
149- ignore : [ " **/node_modules/**" , " **/*.json" ] ,
140+ ignore : [ ' **/node_modules/**' , ' **/*.json' ] ,
150141 } ) ;
151142 allFiles . push ( ...files ) ;
152143 }
153144
154145 return allFiles ;
155146}
156147
157- function generateConfig (
158- files : string [ ] ,
159- rules : readonly ( typeof ALL_RULES ) [ number ] [ ] = ALL_RULES
160- ) : string {
148+ function generateConfig ( files : string [ ] , rules : readonly ( typeof ALL_RULES ) [ number ] [ ] = ALL_RULES ) : string {
161149 // Headless payload format:
162150 // ```json
163151 // {
@@ -181,26 +169,22 @@ function generateConfig(
181169 return JSON . stringify ( config ) ;
182170}
183171
184- describe ( " TSGoLint E2E Snapshot Tests" , ( ) => {
185- it ( " should generate consistent diagnostics snapshot" , async ( ) => {
186- const testFiles = await getTestFiles ( " basic" ) ;
172+ describe ( ' TSGoLint E2E Snapshot Tests' , ( ) => {
173+ it ( ' should generate consistent diagnostics snapshot' , async ( ) => {
174+ const testFiles = await getTestFiles ( ' basic' ) ;
187175 expect ( testFiles . length ) . toBeGreaterThan ( 0 ) ;
188176
189177 const config = generateConfig ( testFiles ) ;
190178
191179 // Run tsgolint in headless mode with single thread for deterministic results
192180 // Set GOMAXPROCS=1 for single-threaded execution
193- const env = { ...process . env , GOMAXPROCS : "1" } ;
181+ const env = { ...process . env , GOMAXPROCS : '1' } ;
194182
195183 let output : Buffer ;
196- output = execFileSync (
197- TSGOLINT_BIN ,
198- [ "headless" , "-fix" , "-fix-suggestions" ] ,
199- {
200- input : config ,
201- env,
202- }
203- ) ;
184+ output = execFileSync ( TSGOLINT_BIN , [ 'headless' ] , {
185+ input : config ,
186+ env,
187+ } ) ;
204188
205189 let diagnostics = parseHeadlessOutput ( output ) ;
206190 diagnostics = sortDiagnostics ( diagnostics ) ;
@@ -210,45 +194,39 @@ describe("TSGoLint E2E Snapshot Tests", () => {
210194 expect ( diagnostics ) . toMatchSnapshot ( ) ;
211195 } ) ;
212196
213- it . runIf ( process . platform === " win32" ) (
214- " should not panic with mixed forward/backslash paths from Rust (issue #143)" ,
197+ it . runIf ( process . platform === ' win32' ) (
198+ ' should not panic with mixed forward/backslash paths from Rust (issue #143)' ,
215199 async ( ) => {
216200 // Regression test for https://github.com/oxc-project/tsgolint/issues/143
217201 // This test reproduces the issue where Rust sends paths with backslashes
218202 // but TypeScript program has forward slashes, causing:
219203 // "panic: Expected file 'E:\oxc\...\index.ts' to be in program"
220204
221- const testFile = join (
222- FIXTURES_DIR ,
223- "basic" ,
224- "rules" ,
225- "no-floating-promises" ,
226- "index.ts"
227- ) ;
205+ const testFile = join ( FIXTURES_DIR , 'basic' , 'rules' , 'no-floating-promises' , 'index.ts' ) ;
228206
229207 // On Windows, convert forward slashes to backslashes to simulate Rust input
230- const rustStylePath = testFile . replace ( / \/ / g, "\\" ) ;
208+ const rustStylePath = testFile . replace ( / \/ / g, '\\' ) ;
231209
232210 expect ( ( ) => {
233- execFileSync ( TSGOLINT_BIN , [ " headless" ] , {
234- input : generateConfig ( [ rustStylePath ] , [ " no-floating-promises" ] ) ,
235- env : { ...process . env , GOMAXPROCS : "1" } ,
211+ execFileSync ( TSGOLINT_BIN , [ ' headless' ] , {
212+ input : generateConfig ( [ rustStylePath ] , [ ' no-floating-promises' ] ) ,
213+ env : { ...process . env , GOMAXPROCS : '1' } ,
236214 } ) ;
237215 } ) . not . toThrow ( ) ;
238- }
216+ } ,
239217 ) ;
240218
241- it ( " should correctly evaluate project references" , async ( ) => {
242- const testFiles = await getTestFiles ( " project-references" ) ;
219+ it ( ' should correctly evaluate project references' , async ( ) => {
220+ const testFiles = await getTestFiles ( ' project-references' ) ;
243221 expect ( testFiles . length ) . toBeGreaterThan ( 0 ) ;
244222
245- const config = generateConfig ( testFiles , [ " no-unsafe-argument" ] ) ;
223+ const config = generateConfig ( testFiles , [ ' no-unsafe-argument' ] ) ;
246224
247225 // Run tsgolint in headless mode with single thread for deterministic results
248226 // Set GOMAXPROCS=1 for single-threaded execution
249- const env = { ...process . env , GOMAXPROCS : "1" } ;
227+ const env = { ...process . env , GOMAXPROCS : '1' } ;
250228
251- const output = execFileSync ( TSGOLINT_BIN , [ " headless" ] , {
229+ const output = execFileSync ( TSGOLINT_BIN , [ ' headless' ] , {
252230 input : config ,
253231 env,
254232 } ) ;
@@ -259,15 +237,15 @@ describe("TSGoLint E2E Snapshot Tests", () => {
259237 expect ( diagnostics ) . toMatchSnapshot ( ) ;
260238 } ) ;
261239
262- it ( " should correctly lint files not inside a project" , async ( ) => {
263- const testFiles = await getTestFiles ( " with-unmatched-files" ) ;
240+ it ( ' should correctly lint files not inside a project' , async ( ) => {
241+ const testFiles = await getTestFiles ( ' with-unmatched-files' ) ;
264242 expect ( testFiles . length ) . toBeGreaterThan ( 0 ) ;
265243
266- const config = generateConfig ( testFiles , [ " no-unsafe-argument" ] ) ;
244+ const config = generateConfig ( testFiles , [ ' no-unsafe-argument' ] ) ;
267245
268- const env = { ...process . env , GOMAXPROCS : "1" } ;
246+ const env = { ...process . env , GOMAXPROCS : '1' } ;
269247
270- const output = execFileSync ( TSGOLINT_BIN , [ " headless" ] , {
248+ const output = execFileSync ( TSGOLINT_BIN , [ ' headless' ] , {
271249 input : config ,
272250 env,
273251 } ) ;
@@ -278,10 +256,10 @@ describe("TSGoLint E2E Snapshot Tests", () => {
278256 expect ( diagnostics ) . toMatchSnapshot ( ) ;
279257 } ) ;
280258
281- it ( " should work with the old version of the headless payload" , async ( ) => {
259+ it ( ' should work with the old version of the headless payload' , async ( ) => {
282260 function generateV1HeadlessPayload (
283261 files : string [ ] ,
284- rules : readonly ( typeof ALL_RULES ) [ number ] [ ] = ALL_RULES
262+ rules : readonly ( typeof ALL_RULES ) [ number ] [ ] = ALL_RULES ,
285263 ) : string {
286264 const config = {
287265 files : files . map ( ( filePath ) => ( {
@@ -294,16 +272,16 @@ describe("TSGoLint E2E Snapshot Tests", () => {
294272
295273 function getDiagnostics ( config : string ) : Diagnostic [ ] {
296274 let output : Buffer ;
297- output = execFileSync ( TSGOLINT_BIN , [ " headless" ] , {
275+ output = execFileSync ( TSGOLINT_BIN , [ ' headless' ] , {
298276 input : config ,
299- env : { ...process . env , GOMAXPROCS : "1" } ,
277+ env : { ...process . env , GOMAXPROCS : '1' } ,
300278 } ) ;
301279
302280 const diagnostics = parseHeadlessOutput ( output ) ;
303281 return sortDiagnostics ( diagnostics ) ;
304282 }
305283
306- const testFiles = await getTestFiles ( " basic" ) ;
284+ const testFiles = await getTestFiles ( ' basic' ) ;
307285 expect ( testFiles . length ) . toBeGreaterThan ( 0 ) ;
308286
309287 const v1Config = generateV1HeadlessPayload ( testFiles ) ;
0 commit comments