@@ -31,6 +31,13 @@ import {
3131 toSortedObjectFromEntries ,
3232} from '@socketsecurity/registry/lib/objects'
3333
34+ import {
35+ testInvalidParam ,
36+ testInvalidStringParam ,
37+ testValidParam ,
38+ testValidStringParam ,
39+ } from './utils/param-validation.mjs'
40+ import { createTestFunction } from './utils/test-helpers.mjs'
3441import npmBuiltinNames from '../data/npm/builtin-names.json'
3542import npmLegacyNames from '../data/npm/legacy-names.json'
3643import { LOOP_SENTINEL } from '../dist/constants.js'
@@ -94,156 +101,20 @@ function toUrlSearchParams(search: any) {
94101 return searchParams
95102}
96103
97- // Helper functions for parameter validation tests.
98- function testInvalidParam (
99- paramName : string ,
100- paramMap : Record < string , number > ,
101- createArgs : (
102- _name : string ,
103- _value : unknown ,
104- ) => [ unknown , unknown , unknown , unknown , unknown , unknown ] ,
105- ) {
106- const paramIndex = paramMap [ paramName ]
107- ; [
108- createArgs ( paramName , 0 ) ,
109- createArgs ( paramName , false ) ,
110- createArgs ( paramName , 1 ) ,
111- createArgs ( paramName , true ) ,
112- createArgs ( paramName , { } ) ,
113- createArgs ( paramName , null ) ,
114- createArgs ( paramName , undefined ) ,
115- createArgs ( paramName , '' ) ,
116- ] . forEach ( args => {
117- const message = JSON . stringify ( args [ paramIndex ] )
118- try {
119- new PackageURL ( ...args )
120- expect ( false , message )
121- } catch {
122- expect ( true , message )
123- }
124- } )
125- }
126-
127- function testInvalidStringParam (
128- paramName : string ,
129- paramMap : Record < string , number > ,
130- createArgs : (
131- _name : string ,
132- _value : unknown ,
133- ) => [ unknown , unknown , unknown , unknown , unknown , unknown ] ,
134- ) {
135- const paramIndex = paramMap [ paramName ]
136- ; [
137- createArgs ( paramName , 0 ) ,
138- createArgs ( paramName , false ) ,
139- createArgs ( paramName , 1 ) ,
140- createArgs ( paramName , true ) ,
141- createArgs ( paramName , { } ) ,
142- ] . forEach ( args => {
143- const message = JSON . stringify ( args [ paramIndex ] )
144- try {
145- new PackageURL ( ...args )
146- expect ( false , message )
147- } catch {
148- expect ( true , message )
149- }
150- } )
151- }
152-
153- function testValidParam (
154- paramName : string ,
155- paramMap : Record < string , number > ,
156- createArgs : (
157- _name : string ,
158- _value : unknown ,
159- ) => [ unknown , unknown , unknown , unknown , unknown , unknown ] ,
160- ) {
161- const paramIndex = paramMap [ paramName ]
162- const args = createArgs ( paramName , paramName )
163- const message = JSON . stringify ( args [ paramIndex ] )
164- try {
165- new PackageURL ( ...args )
166- expect ( true , message )
167- } catch {
168- expect ( false , message )
169- }
170- }
171-
172- function testValidStringParam (
173- paramName : string ,
174- paramMap : Record < string , number > ,
175- createArgs : (
176- _name : string ,
177- _value : unknown ,
178- ) => [ unknown , unknown , unknown , unknown , unknown , unknown ] ,
179- ) {
180- const paramIndex = paramMap [ paramName ]
181- ; [
182- createArgs ( paramName , paramName ) ,
183- createArgs ( paramName , null ) ,
184- createArgs ( paramName , undefined ) ,
185- createArgs ( paramName , '' ) ,
186- ] . forEach ( args => {
187- const message = JSON . stringify ( args [ paramIndex ] )
188- try {
189- new PackageURL ( ...args )
190- expect ( true , message )
191- } catch {
192- expect ( false , message )
193- }
194- } )
195- }
196-
197- // Helper function for parameter testing.
198- const testFunction = ( ) => { }
199-
200- // Helper functions for freeze testing.
201- function createTestFunction ( ) : any {
202- return function ( ) { }
203- }
204-
205- function createTestFunctionWithReturn ( ) : any {
206- return function ( ) {
207- return 'test'
208- }
209- }
210-
211- function createTestFunction1 ( ) : any {
212- return function ( ) {
213- return 'test1'
214- }
215- }
216-
217- function createTestFunction2 ( ) : any {
218- return function ( ) {
219- return 'test2'
220- }
221- }
222-
223- function createAnotherTestFunction ( ) {
224- return function ( ) {
225- return 'another'
226- }
227- }
228-
229104describe ( 'PackageURL' , ( ) => {
230105 describe ( 'KnownQualifierNames' , ( ) => {
231- describe ( 'check access' , ( ) => {
232- ; [
233- [ 'RepositoryUrl' , 'repository_url' ] ,
234- [ 'DownloadUrl' , 'download_url' ] ,
235- [ 'VcsUrl' , 'vcs_url' ] ,
236- [ 'FileName' , 'file_name' ] ,
237- [ 'Checksum' , 'checksum' ] ,
238- ] . forEach ( function ( [ name , expectedValue ] ) {
239- it ( `maps: ${ name } => ${ expectedValue } ` , ( ) => {
240- expect (
241- PackageURL . KnownQualifierNames [
242- name as keyof typeof PackageURL . KnownQualifierNames
243- ] ,
244- ) . toBe ( expectedValue )
245- } )
246- } )
106+ it . each ( [
107+ [ 'RepositoryUrl' , 'repository_url' ] ,
108+ [ 'DownloadUrl' , 'download_url' ] ,
109+ [ 'VcsUrl' , 'vcs_url' ] ,
110+ [ 'FileName' , 'file_name' ] ,
111+ [ 'Checksum' , 'checksum' ] ,
112+ ] ) ( 'maps: %s => %s' , ( name , expectedValue ) => {
113+ expect (
114+ PackageURL . KnownQualifierNames [
115+ name as keyof typeof PackageURL . KnownQualifierNames
116+ ] ,
117+ ) . toBe ( expectedValue )
247118 } )
248119
249120 it ( 'readonly: cannot be written' , ( ) => {
@@ -378,9 +249,10 @@ describe('PackageURL', () => {
378249 } )
379250
380251 describe ( 'toString()' , ( ) => {
381- it ( 'type is validated' , ( ) => {
382- // Tests type validation rules (no special chars, can't start with number)
383- ; [ 'ty#pe' , 'ty@pe' , 'ty/pe' , '1type' ] . forEach ( type => {
252+ it . each ( [ 'ty#pe' , 'ty@pe' , 'ty/pe' , '1type' ] ) (
253+ 'type %s is validated and rejected' ,
254+ type => {
255+ // Tests type validation rules (no special chars, can't start with number)
384256 expect (
385257 ( ) =>
386258 new PackageURL (
@@ -392,8 +264,8 @@ describe('PackageURL', () => {
392264 undefined ,
393265 ) ,
394266 ) . toThrow ( / c o n t a i n s a n i l l e g a l c h a r a c t e r | c a n n o t s t a r t w i t h a n u m b e r / )
395- } )
396- } )
267+ } ,
268+ )
397269
398270 it ( 'encode #' , ( ) => {
399271 // Tests # encoding (delimiter between url and subpath, must be encoded in components)
@@ -1342,10 +1214,11 @@ describe('PackageURL', () => {
13421214
13431215 it ( 'should handle function as parameter (should reject)' , ( ) => {
13441216 // Tests parameter type validation (functions rejected)
1217+ const testFn = ( ) => { }
13451218 expect (
13461219 ( ) =>
13471220 new PackageURL (
1348- testFunction ,
1221+ testFn ,
13491222 null ,
13501223 'name' ,
13511224 undefined ,
@@ -1357,7 +1230,7 @@ describe('PackageURL', () => {
13571230 ( ) =>
13581231 new PackageURL (
13591232 'type' ,
1360- testFunction ,
1233+ testFn ,
13611234 'name' ,
13621235 undefined ,
13631236 undefined ,
@@ -1369,7 +1242,7 @@ describe('PackageURL', () => {
13691242 new PackageURL (
13701243 'type' ,
13711244 null ,
1372- testFunction ,
1245+ testFn ,
13731246 undefined ,
13741247 undefined ,
13751248 undefined ,
@@ -2412,81 +2285,40 @@ describe('PackageURL', () => {
24122285 } )
24132286
24142287 // Test purl-type.js lines 282-291 - npm name with non-URL-friendly characters
2415- it ( 'should test npm name validation with non-URL-friendly characters' , ( ) => {
2416- // Import already at top of file
2417-
2418- // Test names with non-URL-friendly characters that need encoding
2419- const testCases = [
2420- {
2421- name : 'package<>' ,
2422- expectedError :
2423- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2424- } ,
2425- {
2426- name : 'package[brackets]' ,
2427- expectedError :
2428- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2429- } ,
2430- {
2431- name : 'package{braces}' ,
2432- expectedError :
2433- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2434- } ,
2435- {
2436- name : 'package|pipe' ,
2437- expectedError :
2438- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2439- } ,
2440- {
2441- name : 'package\\backslash' ,
2442- expectedError :
2443- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2444- } ,
2445- {
2446- name : 'package^caret' ,
2447- expectedError :
2448- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2449- } ,
2450- {
2451- name : 'package space' ,
2452- expectedError :
2453- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2454- } ,
2455- {
2456- name : 'パッケージ' ,
2457- expectedError :
2458- / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s / ,
2459- // Non-ASCII characters
2460- } ,
2461- ]
2462-
2463- testCases . forEach ( ( { expectedError, name } ) => {
2464- const comp = { namespace : '' , name }
2465-
2466- // Test with throwing disabled - should return false
2467- const result = ( PurlType [ 'npm' ] as any ) . validate ( comp , false )
2468- expect ( result ) . toBe ( false )
2288+ it . each ( [
2289+ 'package<>' ,
2290+ 'package[brackets]' ,
2291+ 'package{braces}' ,
2292+ 'package|pipe' ,
2293+ 'package\\backslash' ,
2294+ 'package^caret' ,
2295+ 'package space' ,
2296+ // Non-ASCII characters
2297+ 'パッケージ' ,
2298+ ] ) ( 'should reject npm name with non-URL-friendly chars: %s' , name => {
2299+ const comp = { namespace : '' , name }
2300+ const expectedError =
2301+ / n p m " n a m e " c o m p o n e n t c a n o n l y c o n t a i n U R L - f r i e n d l y c h a r a c t e r s /
2302+
2303+ // Test with throwing disabled - should return false
2304+ const result = ( PurlType [ 'npm' ] as any ) . validate ( comp , false )
2305+ expect ( result ) . toBe ( false )
24692306
2470- // Test with throwing enabled - should throw with expected error
2471- expect ( ( ) => ( PurlType [ 'npm' ] as any ) . validate ( comp , true ) ) . toThrow (
2472- expectedError ,
2473- )
2474- } )
2307+ // Test with throwing enabled - should throw with expected error
2308+ expect ( ( ) => ( PurlType [ 'npm' ] as any ) . validate ( comp , true ) ) . toThrow (
2309+ expectedError ,
2310+ )
2311+ } )
24752312
2476- // Test that URL-friendly characters pass validation
2477- const validNames = [
2478- 'package-name' ,
2479- 'package_name' ,
2480- 'package.name' ,
2481- 'package123' ,
2482- ]
2483- validNames . forEach ( name => {
2313+ it . each ( [ 'package-name' , 'package_name' , 'package.name' , 'package123' ] ) (
2314+ 'should accept npm name with URL-friendly chars: %s' ,
2315+ name => {
24842316 const comp = { namespace : '' , name }
24852317 // Should not throw
24862318 const result = ( PurlType [ 'npm' ] as any ) . validate ( comp , true )
24872319 expect ( result ) . toBe ( true )
2488- } )
2489- } )
2320+ } ,
2321+ )
24902322
24912323 // Test encode.js line 21 - null/undefined handling
24922324 it ( 'should test encode component with falsy values' , ( ) => {
@@ -3377,13 +3209,13 @@ describe('PackageURL', () => {
33773209 // Import already at top of file
33783210
33793211 // Test freezing object with function as property
3380- const func : any = createTestFunctionWithReturn ( )
3212+ const func : any = createTestFunction ( 'test' )
33813213 ; ( func as any ) . prop = 'value'
33823214
33833215 const obj = {
33843216 fn : func ,
33853217 nested : {
3386- anotherFn : createAnotherTestFunction ( ) ,
3218+ anotherFn : createTestFunction ( 'another' ) ,
33873219 } ,
33883220 }
33893221
@@ -3443,10 +3275,10 @@ describe('PackageURL', () => {
34433275 // Import already at top of file
34443276
34453277 // Test freezing array with functions (line 33 branch for typeof item === 'function')
3446- const func1 : any = createTestFunction1 ( )
3278+ const func1 : any = createTestFunction ( 'test1' )
34473279 ; ( func1 as any ) . prop = 'value1'
34483280
3449- const func2 : any = createTestFunction2 ( )
3281+ const func2 : any = createTestFunction ( 'test2' )
34503282 ; ( func2 as any ) . nested = { data : 'nested' }
34513283
34523284 const arr = [ func1 , { method : func2 } , func2 , null , 'string' , 42 ]
0 commit comments