1313 * Used by Socket tools for file discovery and npm package analysis.
1414 */
1515
16+ import path from 'node:path'
1617import {
1718 defaultIgnore ,
1819 getGlobMatcher ,
20+ glob ,
1921 globStreamLicenses ,
22+ globSync ,
2023} from '@socketsecurity/lib/globs'
2124import { describe , expect , it } from 'vitest'
2225
@@ -174,6 +177,18 @@ describe('globs', () => {
174177 expect ( matcher ( 'src/app.js' ) ) . toBe ( true )
175178 expect ( matcher ( 'src/utils/helper.js' ) ) . toBe ( true )
176179 } )
180+
181+ it ( 'should handle only negative patterns' , ( ) => {
182+ const matcher = getGlobMatcher ( [ '!*.test.js' , '!*.spec.js' ] )
183+ expect ( typeof matcher ) . toBe ( 'function' )
184+ } )
185+
186+ it ( 'should map negative patterns correctly' , ( ) => {
187+ const matcher = getGlobMatcher ( [ '*.js' , '!test/*.js' , '!spec/*.js' ] )
188+ expect ( matcher ( 'app.js' ) ) . toBe ( true )
189+ expect ( matcher ( 'test/app.js' ) ) . toBe ( false )
190+ expect ( matcher ( 'spec/app.js' ) ) . toBe ( false )
191+ } )
177192 } )
178193
179194 describe ( 'globStreamLicenses' , ( ) => {
@@ -184,6 +199,19 @@ describe('globs', () => {
184199 expect ( typeof stream . pipe ) . toBe ( 'function' )
185200 } )
186201
202+ it ( 'should stream license files' , async ( ) => {
203+ const files : string [ ] = [ ]
204+ const stream = globStreamLicenses ( process . cwd ( ) , { recursive : false } )
205+
206+ await new Promise < void > ( ( resolve , reject ) => {
207+ stream . on ( 'data' , ( file : string ) => files . push ( file ) )
208+ stream . on ( 'end' , ( ) => resolve ( ) )
209+ stream . on ( 'error' , reject )
210+ } )
211+
212+ expect ( Array . isArray ( files ) ) . toBe ( true )
213+ } )
214+
187215 it ( 'should accept dirname parameter' , ( ) => {
188216 expect ( ( ) => globStreamLicenses ( '.' ) ) . not . toThrow ( )
189217 expect ( ( ) => globStreamLicenses ( './src' ) ) . not . toThrow ( )
@@ -194,19 +222,50 @@ describe('globs', () => {
194222 expect ( ( ) => globStreamLicenses ( '.' , { recursive : true } ) ) . not . toThrow ( )
195223 } )
196224
197- it ( 'should handle ignoreOriginals option' , ( ) => {
198- const stream = globStreamLicenses ( '.' , { ignoreOriginals : true } )
199- expect ( stream ) . toBeDefined ( )
225+ it ( 'should handle ignoreOriginals option' , async ( ) => {
226+ const files : string [ ] = [ ]
227+ const stream = globStreamLicenses ( process . cwd ( ) , {
228+ ignoreOriginals : true ,
229+ recursive : false ,
230+ } )
231+
232+ await new Promise < void > ( ( resolve , reject ) => {
233+ stream . on ( 'data' , ( file : string ) => files . push ( file ) )
234+ stream . on ( 'end' , ( ) => resolve ( ) )
235+ stream . on ( 'error' , reject )
236+ } )
237+
238+ // Should not include files matching *.original pattern
239+ expect ( files . every ( f => ! f . includes ( '.original' ) ) ) . toBe ( true )
200240 } )
201241
202- it ( 'should handle recursive option' , ( ) => {
203- const stream = globStreamLicenses ( '.' , { recursive : false } )
204- expect ( stream ) . toBeDefined ( )
242+ it ( 'should handle recursive option' , async ( ) => {
243+ const files : string [ ] = [ ]
244+ const stream = globStreamLicenses ( process . cwd ( ) , { recursive : true } )
245+
246+ await new Promise < void > ( ( resolve , reject ) => {
247+ stream . on ( 'data' , ( file : string ) => files . push ( file ) )
248+ stream . on ( 'end' , ( ) => resolve ( ) )
249+ stream . on ( 'error' , reject )
250+ } )
251+
252+ expect ( Array . isArray ( files ) ) . toBe ( true )
205253 } )
206254
207- it ( 'should handle custom ignore patterns' , ( ) => {
208- const stream = globStreamLicenses ( '.' , { ignore : [ '**/node_modules/**' ] } )
209- expect ( stream ) . toBeDefined ( )
255+ it ( 'should handle custom ignore patterns as array' , async ( ) => {
256+ const files : string [ ] = [ ]
257+ const stream = globStreamLicenses ( process . cwd ( ) , {
258+ ignore : [ '**/test/**' , '**/node_modules/**' ] ,
259+ recursive : false ,
260+ } )
261+
262+ await new Promise < void > ( ( resolve , reject ) => {
263+ stream . on ( 'data' , ( file : string ) => files . push ( file ) )
264+ stream . on ( 'end' , ( ) => resolve ( ) )
265+ stream . on ( 'error' , reject )
266+ } )
267+
268+ expect ( Array . isArray ( files ) ) . toBe ( true )
210269 } )
211270
212271 it ( 'should handle absolute option' , ( ) => {
@@ -229,14 +288,22 @@ describe('globs', () => {
229288 expect ( stream ) . toBeDefined ( )
230289 } )
231290
232- it ( 'should handle multiple options together' , ( ) => {
233- const stream = globStreamLicenses ( '.' , {
291+ it ( 'should handle multiple options together' , async ( ) => {
292+ const files : string [ ] = [ ]
293+ const stream = globStreamLicenses ( process . cwd ( ) , {
234294 recursive : true ,
235295 ignoreOriginals : true ,
236296 dot : true ,
237297 absolute : true ,
238298 } )
239- expect ( stream ) . toBeDefined ( )
299+
300+ await new Promise < void > ( ( resolve , reject ) => {
301+ stream . on ( 'data' , ( file : string ) => files . push ( file ) )
302+ stream . on ( 'end' , ( ) => resolve ( ) )
303+ stream . on ( 'error' , reject )
304+ } )
305+
306+ expect ( Array . isArray ( files ) ) . toBe ( true )
240307 } )
241308
242309 it ( 'should be a function' , ( ) => {
@@ -250,6 +317,178 @@ describe('globs', () => {
250317 } )
251318 } )
252319
320+ describe ( 'glob' , ( ) => {
321+ it ( 'should be a function' , ( ) => {
322+ expect ( typeof glob ) . toBe ( 'function' )
323+ } )
324+
325+ it ( 'should return a promise' , ( ) => {
326+ const result = glob ( '*.js' )
327+ expect ( result ) . toBeInstanceOf ( Promise )
328+ } )
329+
330+ it ( 'should find files matching pattern' , async ( ) => {
331+ const files = await glob ( '*.json' , { cwd : process . cwd ( ) } )
332+ expect ( Array . isArray ( files ) ) . toBe ( true )
333+ expect ( files . length ) . toBeGreaterThan ( 0 )
334+ expect ( files . some ( f => f . includes ( 'package.json' ) ) ) . toBe ( true )
335+ } )
336+
337+ it ( 'should accept array of patterns' , async ( ) => {
338+ const files = await glob ( [ '*.json' , '*.md' ] , { cwd : process . cwd ( ) } )
339+ expect ( Array . isArray ( files ) ) . toBe ( true )
340+ } )
341+
342+ it ( 'should respect cwd option' , async ( ) => {
343+ const files = await glob ( '*.ts' , { cwd : 'src' } )
344+ expect ( Array . isArray ( files ) ) . toBe ( true )
345+ } )
346+
347+ it ( 'should handle ignore patterns' , async ( ) => {
348+ const files = await glob ( '**/*.ts' , {
349+ cwd : 'src' ,
350+ ignore : [ '**/paths/**' ] ,
351+ } )
352+ expect ( Array . isArray ( files ) ) . toBe ( true )
353+ expect ( files . every ( f => ! f . includes ( 'paths/' ) ) ) . toBe ( true )
354+ } )
355+
356+ it ( 'should handle absolute option' , async ( ) => {
357+ const files = await glob ( '*.json' , {
358+ cwd : process . cwd ( ) ,
359+ absolute : true ,
360+ } )
361+ expect ( Array . isArray ( files ) ) . toBe ( true )
362+ if ( files . length > 0 ) {
363+ expect ( path . isAbsolute ( files [ 0 ] ) ) . toBe ( true )
364+ }
365+ } )
366+
367+ it ( 'should handle onlyFiles option' , async ( ) => {
368+ const files = await glob ( '*' , { cwd : process . cwd ( ) , onlyFiles : true } )
369+ expect ( Array . isArray ( files ) ) . toBe ( true )
370+ } )
371+
372+ it ( 'should handle dot option' , async ( ) => {
373+ const files = await glob ( '.*' , { cwd : process . cwd ( ) , dot : true } )
374+ expect ( Array . isArray ( files ) ) . toBe ( true )
375+ } )
376+
377+ it ( 'should handle empty pattern array' , async ( ) => {
378+ const files = await glob ( [ ] , { cwd : process . cwd ( ) } )
379+ expect ( Array . isArray ( files ) ) . toBe ( true )
380+ expect ( files . length ) . toBe ( 0 )
381+ } )
382+
383+ it ( 'should handle single pattern string' , async ( ) => {
384+ const files = await glob ( 'package.json' , { cwd : process . cwd ( ) } )
385+ expect ( Array . isArray ( files ) ) . toBe ( true )
386+ expect ( files . some ( f => f . includes ( 'package.json' ) ) ) . toBe ( true )
387+ } )
388+
389+ it ( 'should handle negation patterns' , async ( ) => {
390+ const files = await glob ( [ '*.json' , '!package-lock.json' ] , {
391+ cwd : process . cwd ( ) ,
392+ } )
393+ expect ( Array . isArray ( files ) ) . toBe ( true )
394+ expect ( files . every ( f => ! f . includes ( 'package-lock.json' ) ) ) . toBe ( true )
395+ } )
396+
397+ it ( 'should work without options parameter' , async ( ) => {
398+ const files = await glob ( '*.json' )
399+ expect ( Array . isArray ( files ) ) . toBe ( true )
400+ } )
401+ } )
402+
403+ describe ( 'globSync' , ( ) => {
404+ it ( 'should be a function' , ( ) => {
405+ expect ( typeof globSync ) . toBe ( 'function' )
406+ } )
407+
408+ it ( 'should return an array' , ( ) => {
409+ const result = globSync ( '*.json' , { cwd : process . cwd ( ) } )
410+ expect ( Array . isArray ( result ) ) . toBe ( true )
411+ } )
412+
413+ it ( 'should find files matching pattern' , ( ) => {
414+ const files = globSync ( '*.json' , { cwd : process . cwd ( ) } )
415+ expect ( Array . isArray ( files ) ) . toBe ( true )
416+ expect ( files . length ) . toBeGreaterThan ( 0 )
417+ expect ( files . some ( f => f . includes ( 'package.json' ) ) ) . toBe ( true )
418+ } )
419+
420+ it ( 'should accept array of patterns' , ( ) => {
421+ const files = globSync ( [ '*.json' , '*.md' ] , { cwd : process . cwd ( ) } )
422+ expect ( Array . isArray ( files ) ) . toBe ( true )
423+ } )
424+
425+ it ( 'should respect cwd option' , ( ) => {
426+ const files = globSync ( '*.ts' , { cwd : 'src' } )
427+ expect ( Array . isArray ( files ) ) . toBe ( true )
428+ } )
429+
430+ it ( 'should handle ignore patterns' , ( ) => {
431+ const files = globSync ( '**/*.ts' , {
432+ cwd : 'src' ,
433+ ignore : [ '**/paths/**' ] ,
434+ } )
435+ expect ( Array . isArray ( files ) ) . toBe ( true )
436+ expect ( files . every ( f => ! f . includes ( 'paths/' ) ) ) . toBe ( true )
437+ } )
438+
439+ it ( 'should handle absolute option' , ( ) => {
440+ const files = globSync ( '*.json' , {
441+ cwd : process . cwd ( ) ,
442+ absolute : true ,
443+ } )
444+ expect ( Array . isArray ( files ) ) . toBe ( true )
445+ if ( files . length > 0 ) {
446+ expect ( path . isAbsolute ( files [ 0 ] ) ) . toBe ( true )
447+ }
448+ } )
449+
450+ it ( 'should handle onlyFiles option' , ( ) => {
451+ const files = globSync ( '*' , { cwd : process . cwd ( ) , onlyFiles : true } )
452+ expect ( Array . isArray ( files ) ) . toBe ( true )
453+ } )
454+
455+ it ( 'should handle dot option' , ( ) => {
456+ const files = globSync ( '.*' , { cwd : process . cwd ( ) , dot : true } )
457+ expect ( Array . isArray ( files ) ) . toBe ( true )
458+ } )
459+
460+ it ( 'should return same results as async glob' , async ( ) => {
461+ const syncFiles = globSync ( '*.json' , { cwd : process . cwd ( ) } )
462+ const asyncFiles = await glob ( '*.json' , { cwd : process . cwd ( ) } )
463+ expect ( syncFiles . sort ( ) ) . toEqual ( asyncFiles . sort ( ) )
464+ } )
465+
466+ it ( 'should handle empty pattern array' , ( ) => {
467+ const files = globSync ( [ ] , { cwd : process . cwd ( ) } )
468+ expect ( Array . isArray ( files ) ) . toBe ( true )
469+ expect ( files . length ) . toBe ( 0 )
470+ } )
471+
472+ it ( 'should handle single pattern string' , ( ) => {
473+ const files = globSync ( 'package.json' , { cwd : process . cwd ( ) } )
474+ expect ( Array . isArray ( files ) ) . toBe ( true )
475+ expect ( files . some ( f => f . includes ( 'package.json' ) ) ) . toBe ( true )
476+ } )
477+
478+ it ( 'should handle negation patterns' , ( ) => {
479+ const files = globSync ( [ '*.json' , '!package-lock.json' ] , {
480+ cwd : process . cwd ( ) ,
481+ } )
482+ expect ( Array . isArray ( files ) ) . toBe ( true )
483+ expect ( files . every ( f => ! f . includes ( 'package-lock.json' ) ) ) . toBe ( true )
484+ } )
485+
486+ it ( 'should work without options parameter' , ( ) => {
487+ const files = globSync ( '*.json' )
488+ expect ( Array . isArray ( files ) ) . toBe ( true )
489+ } )
490+ } )
491+
253492 describe ( 'integration' , ( ) => {
254493 it ( 'should have consistent behavior across calls' , ( ) => {
255494 const matcher1 = getGlobMatcher ( '*.js' )
0 commit comments