Skip to content

Commit 64906a2

Browse files
committed
test: improve code coverage from 94.49% to 99.20%
Add comprehensive tests for injection validation, PurlBuilder factory methods, and edge cases across validate/strings/url-converter/compare. - Add purl-injection-nothrow.test.mts: 78 tests covering per-type validate() with throws=false for injection chars, empty namespace validation, required field validation, and throw path verification - Add purl-builder-types.test.mts: 26 tests covering all PurlBuilder static factory methods - Add edge-case tests for Docker Hub/MetaCPAN unrecognized paths, encodeQualifiers non-object input - Convert c8 ignore comments to v8 ignore across 24 source files (vitest v8 provider uses v8 ignore, not c8 ignore) - Add v8 ignore for unreachable npm validation branches where injection validator catches characters before type-specific checks
1 parent 6e71847 commit 64906a2

27 files changed

Lines changed: 798 additions & 54 deletions

src/compare.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function _registerPackageURL(ctor: typeof PackageURL): void {
2929

3030
function toCanonicalString(input: PurlInput): string {
3131
if (typeof input === 'string') {
32-
/* c8 ignore next 5 -- PackageURL is always registered at module load time. */
32+
/* v8 ignore next 5 -- PackageURL is always registered at module load time. */
3333
if (!_PackageURL) {
3434
throw new Error(
3535
'PackageURL not registered. Import PackageURL before using string comparison.',

src/exists.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* ```
1212
*/
1313

14-
/* c8 ignore start - Re-export only file, no logic to test */
14+
/* v8 ignore start - Re-export only file, no logic to test */
1515

1616
export { cargoExists } from './purl-types/cargo.js'
1717
export { cocoapodsExists } from './purl-types/cocoapods.js'
@@ -33,4 +33,4 @@ export { pypiExists } from './purl-types/pypi.js'
3333
export { vscodeExtensionExists } from './purl-types/vscode-extension.js'
3434
export type { ExistsOptions, ExistsResult } from './purl-types/npm.js'
3535

36-
/* c8 ignore stop */
36+
/* v8 ignore stop */

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ SOFTWARE.
4040
* - Parsers: Modular parsers for ecosystem-specific package specifiers
4141
*/
4242

43-
/* c8 ignore start - Re-export only file, no logic to test */
43+
/* v8 ignore start - Re-export only file, no logic to test */
4444

4545
export type { PURLString } from '@socketsecurity/lib/types'
4646
// ============================================================================
@@ -105,4 +105,4 @@ export { stringify, stringifySpec } from './stringify.js'
105105
export { Vers } from './vers.js'
106106
export type { VersComparator, VersConstraint, VersWildcard } from './vers.js'
107107

108-
/* c8 ignore stop */
108+
/* v8 ignore stop */

src/package-url.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ class PackageURL {
655655
// Split the remainder once from left on ':'
656656
const colonIndex = StringPrototypeIndexOf(purlStr, ':')
657657
// Use WHATWG URL to split up the purl string
658-
/* c8 ignore next 3 -- Comment lines don't need coverage. */
658+
/* v8 ignore next 3 -- Comment lines don't need coverage. */
659659
// - Split the purl string once from right on '#'
660660
// - Split the remainder once from right on '?'
661661
// - Split the remainder once from left on ':'
@@ -675,7 +675,7 @@ class PackageURL {
675675
// When leading slashes were trimmed, the original string had an authority
676676
// section (e.g., pkg://user:pass@host/...). Detect `@` in the authority
677677
// by checking between the `//` and the next `/`.
678-
/* c8 ignore next 8 -- V8 coverage sees multiple branch paths that can't all be tested. */
678+
/* v8 ignore next 8 -- V8 coverage sees multiple branch paths that can't all be tested. */
679679
if (afterColon.length !== trimmedAfterColon.length) {
680680
// afterColon starts with slashes — find the authority section
681681
const authorityStart = StringPrototypeIndexOf(afterColon, '//') + 2
@@ -697,11 +697,11 @@ class PackageURL {
697697
}
698698
}
699699
// The scheme is a constant with the value "pkg"
700-
/* c8 ignore next -- Tested: colonIndex === -1 (url undefined) case, but V8 can't see both branches. */ if (
700+
/* v8 ignore next -- Tested: colonIndex === -1 (url undefined) case, but V8 can't see both branches. */ if (
701701
url?.protocol !== 'pkg:'
702702
) {
703703
throw new PurlError('missing required "pkg" scheme component')
704-
/* c8 ignore next -- Unreachable code after throw. */
704+
/* v8 ignore next -- Unreachable code after throw. */
705705
}
706706
// A purl must NOT contain a URL Authority i.e. there is no support for
707707
// username, password, host and port components
@@ -723,14 +723,14 @@ class PackageURL {
723723

724724
let rawVersion: string | undefined
725725
// Both branches of this ternary are tested, but V8 reports phantom branch combinations
726-
/* c8 ignore start -- npm vs non-npm path logic both tested but V8 sees extra branches. */
726+
/* v8 ignore start -- npm vs non-npm path logic both tested but V8 sees extra branches. */
727727
// Deviate from the specification to handle a special npm purl type case for
728728
// pnpm ids such as 'pkg:npm/next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
729729
let atSignIndex =
730730
rawType === 'npm'
731731
? StringPrototypeIndexOf(pathname, '@', firstSlashIndex + 2)
732732
: StringPrototypeLastIndexOf(pathname, '@')
733-
/* c8 ignore stop */
733+
/* v8 ignore stop */
734734
// When a forward slash ('/') is directly preceding an '@' symbol,
735735
// then the '@' symbol is NOT considered a version separator
736736
if (
@@ -790,7 +790,7 @@ class PackageURL {
790790
)
791791
// Use URLSearchParams#append to preserve plus signs
792792
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams#preserving_plus_signs
793-
/* c8 ignore next -- URLSearchParams.append has internal V8 branches we can't control. */ searchParams.append(
793+
/* v8 ignore next -- URLSearchParams.append has internal V8 branches we can't control. */ searchParams.append(
794794
key,
795795
value,
796796
)

src/purl-types/cargo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ export async function cargoExists(
117117
}
118118
return result
119119
} catch (e) {
120-
/* c8 ignore start */
120+
/* v8 ignore start */
121121
const error = e instanceof Error ? e.message : String(e)
122-
/* c8 ignore stop */
122+
/* v8 ignore stop */
123123
return {
124124
exists: false,
125125
error: StringPrototypeIncludes(error, '404')

src/purl-types/cocoapods.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export async function cocoapodsExists(
105105
}
106106
return result
107107
} catch (e) {
108-
/* c8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
108+
/* v8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
109109
const error = e instanceof Error ? e.message : String(e)
110110
return {
111111
exists: false,

src/purl-types/composer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function packagistExists(
131131
}
132132
return result
133133
} catch (e) {
134-
/* c8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
134+
/* v8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
135135
const error = e instanceof Error ? e.message : String(e)
136136
return {
137137
exists: false,

src/purl-types/conda.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ export async function condaExists(
149149
}
150150
return result
151151
} catch (e) {
152-
/* c8 ignore start */
152+
/* v8 ignore start */
153153
const error = e instanceof Error ? e.message : String(e)
154-
/* c8 ignore stop */
154+
/* v8 ignore stop */
155155
return {
156156
exists: false,
157157
error: StringPrototypeIncludes(error, '404')

src/purl-types/cpan.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export async function cpanExists(
9898
}
9999
return result
100100
} catch (e) {
101-
/* c8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
101+
/* v8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
102102
const error = e instanceof Error ? e.message : String(e)
103103
return {
104104
exists: false,

src/purl-types/cran.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export async function cranExists(
100100
}
101101
return result
102102
} catch (e) {
103-
/* c8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
103+
/* v8 ignore next - httpJson typically throws Error; String(e) is defensive programming */
104104
const error = e instanceof Error ? e.message : String(e)
105105
return {
106106
exists: false,

0 commit comments

Comments
 (0)