Skip to content

Commit 4bc57e8

Browse files
jdaltonclaude
andcommitted
test: extract type-specific tests to separate file
Move npm, pub, and pypi type-specific tests (4 tests) from package-url.test.mts to purl-types.test.mts for better organization. Reduces main test file from 3439 to 3360 lines (-79 lines). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent cdccd01 commit 4bc57e8

File tree

2 files changed

+115
-87
lines changed

2 files changed

+115
-87
lines changed

test/package-url.test.mts

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ import {
2929
testValidStringParam,
3030
} from './utils/param-validation.mjs'
3131
import { createTestFunction } from './utils/test-helpers.mjs'
32-
import npmBuiltinNames from '../data/npm/builtin-names.json'
33-
import npmLegacyNames from '../data/npm/legacy-names.json'
3432
import { LOOP_SENTINEL } from '../dist/constants.js'
3533
import { PurlError, formatPurlErrorMessage } from '../dist/error.js'
3634
import { recursiveFreeze } from '../dist/objects.js'
@@ -76,11 +74,6 @@ import {
7674
validateVersion,
7775
} from '../src/validate.js'
7876

79-
function getNpmId(purl: any) {
80-
const { name, namespace } = purl
81-
return `${namespace?.length > 0 ? `${namespace}/` : ''}${name}`
82-
}
83-
8477
describe('PackageURL', () => {
8578
describe('KnownQualifierNames', () => {
8679
it.each([
@@ -518,86 +511,6 @@ describe('PackageURL', () => {
518511
})
519512
})
520513

521-
describe('npm', () => {
522-
it("should allow legacy names to be mixed case, match a builtin, or contain ~'!()* characters", () => {
523-
// Tests npm legacy package exceptions (historical packages with special names)
524-
for (const legacyName of npmLegacyNames) {
525-
let purl
526-
expect(() => {
527-
const parts = legacyName.split('/')
528-
const namespace = parts.length > 1 ? parts[0] : ''
529-
const name = parts.at(-1)
530-
purl = new PackageURL(
531-
'npm',
532-
namespace,
533-
name,
534-
undefined,
535-
undefined,
536-
undefined,
537-
)
538-
}).not.toThrow()
539-
const id = purl ? getNpmId(purl) : ''
540-
const isBuiltin = npmBuiltinNames.includes(id)
541-
const isMixedCased = /[A-Z]/.test(id)
542-
const containsIllegalCharacters = /[~'!()*]/.test(id)
543-
expect(
544-
isBuiltin || isMixedCased || containsIllegalCharacters,
545-
`assert for ${legacyName}`,
546-
)
547-
}
548-
})
549-
it('should not allow non-legacy builtin names', () => {
550-
// Tests npm builtin module validation (only legacy builtins allowed)
551-
for (const builtinName of npmBuiltinNames) {
552-
if (!npmLegacyNames.includes(builtinName)) {
553-
expect(() => {
554-
const parts = builtinName.split('/')
555-
const namespace = parts.length > 1 ? parts[0] : ''
556-
const name = parts.at(-1)
557-
558-
new PackageURL(
559-
'npm',
560-
namespace,
561-
name,
562-
undefined,
563-
undefined,
564-
undefined,
565-
)
566-
}, `assert for ${builtinName}`).toThrow()
567-
}
568-
}
569-
})
570-
})
571-
572-
describe('pub', () => {
573-
it('should normalize dashes to underscores', () => {
574-
// Tests pub-specific normalization (dashes to underscores per spec)
575-
const purlWithDashes = new PackageURL(
576-
'pub',
577-
'',
578-
'flutter-downloader',
579-
'1.0.0',
580-
undefined,
581-
undefined,
582-
)
583-
expect(purlWithDashes.toString()).toBe('pkg:pub/[email protected]')
584-
})
585-
})
586-
587-
describe('pypi', () => {
588-
it('should handle pypi package-urls per the purl-spec', () => {
589-
// Tests PyPI-specific normalizations (lowercase, underscores to dashes)
590-
const purlMixedCasing = PackageURL.fromString('pkg:pypi/[email protected]')
591-
expect(purlMixedCasing.toString()).toBe('pkg:pypi/[email protected]')
592-
const purlWithUnderscore = PackageURL.fromString(
593-
'pkg:pypi/[email protected]',
594-
)
595-
expect(purlWithUnderscore.toString()).toBe(
596-
'pkg:pypi/[email protected]',
597-
)
598-
})
599-
})
600-
601514
describe('Edge cases and additional coverage', () => {
602515
describe('URL scheme handling', () => {
603516
it('should accept pkg:// with double slash and ignore the slashes', () => {

test/purl-types.test.mts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*!
2+
Copyright (c) the purl authors
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
SOFTWARE.
21+
*/
22+
23+
import { describe, expect, it } from 'vitest'
24+
25+
import npmBuiltinNames from '../data/npm/builtin-names.json'
26+
import npmLegacyNames from '../data/npm/legacy-names.json'
27+
import { PackageURL } from '../dist/package-url.js'
28+
29+
function getNpmId(purl: any) {
30+
const { name, namespace } = purl
31+
return `${namespace?.length > 0 ? `${namespace}/` : ''}${name}`
32+
}
33+
34+
describe('PackageURL type-specific tests', () => {
35+
describe('npm', () => {
36+
it("should allow legacy names to be mixed case, match a builtin, or contain ~'!()* characters", () => {
37+
// Tests npm legacy package exceptions (historical packages with special names)
38+
for (const legacyName of npmLegacyNames) {
39+
let purl
40+
expect(() => {
41+
const parts = legacyName.split('/')
42+
const namespace = parts.length > 1 ? parts[0] : ''
43+
const name = parts.at(-1)
44+
purl = new PackageURL(
45+
'npm',
46+
namespace,
47+
name,
48+
undefined,
49+
undefined,
50+
undefined,
51+
)
52+
}).not.toThrow()
53+
const id = purl ? getNpmId(purl) : ''
54+
const isBuiltin = npmBuiltinNames.includes(id)
55+
const isMixedCased = /[A-Z]/.test(id)
56+
const containsIllegalCharacters = /[~'!()*]/.test(id)
57+
expect(
58+
isBuiltin || isMixedCased || containsIllegalCharacters,
59+
`assert for ${legacyName}`,
60+
)
61+
}
62+
})
63+
64+
it('should not allow non-legacy builtin names', () => {
65+
// Tests npm builtin module validation (only legacy builtins allowed)
66+
for (const builtinName of npmBuiltinNames) {
67+
if (!npmLegacyNames.includes(builtinName)) {
68+
expect(() => {
69+
const parts = builtinName.split('/')
70+
const namespace = parts.length > 1 ? parts[0] : ''
71+
const name = parts.at(-1)
72+
73+
new PackageURL(
74+
'npm',
75+
namespace,
76+
name,
77+
undefined,
78+
undefined,
79+
undefined,
80+
)
81+
}, `assert for ${builtinName}`).toThrow()
82+
}
83+
}
84+
})
85+
})
86+
87+
describe('pub', () => {
88+
it('should normalize dashes to underscores', () => {
89+
// Tests pub-specific normalization (dashes to underscores per spec)
90+
const purlWithDashes = new PackageURL(
91+
'pub',
92+
'',
93+
'flutter-downloader',
94+
'1.0.0',
95+
undefined,
96+
undefined,
97+
)
98+
expect(purlWithDashes.toString()).toBe('pkg:pub/[email protected]')
99+
})
100+
})
101+
102+
describe('pypi', () => {
103+
it('should handle pypi package-urls per the purl-spec', () => {
104+
// Tests PyPI-specific normalizations (lowercase, underscores to dashes)
105+
const purlMixedCasing = PackageURL.fromString('pkg:pypi/[email protected]')
106+
expect(purlMixedCasing.toString()).toBe('pkg:pypi/[email protected]')
107+
const purlWithUnderscore = PackageURL.fromString(
108+
'pkg:pypi/[email protected]',
109+
)
110+
expect(purlWithUnderscore.toString()).toBe(
111+
'pkg:pypi/[email protected]',
112+
)
113+
})
114+
})
115+
})

0 commit comments

Comments
 (0)