Skip to content

Commit 484abc0

Browse files
committed
Add tests for backward compatibility in validation functions
Adds comprehensive test coverage for legacy boolean parameter support and undefined parameter handling in validation functions. Tests cover: - validateEmptyByType, validateName, validateNamespace - validateQualifierKey, validateRequired, validateRequiredByType - validateStartsWithoutNumber, validateStrings, validateType, validateVersion - validateQualifiers with various parameter types - npm namespace validation non-throws mode Increases branch coverage from 97.23% to 100%.
1 parent 97cefb2 commit 484abc0

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

test/package-url.test.mts

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ import {
6565
} from '../src/purl-component.js'
6666
import {
6767
validateEmptyByType,
68+
validateName,
69+
validateNamespace,
6870
validateQualifierKey,
6971
validateQualifiers,
7072
validateRequired,
@@ -73,6 +75,7 @@ import {
7375
validateStrings,
7476
validateSubpath,
7577
validateType,
78+
validateVersion,
7679
} from '../src/validate.js'
7780

7881
function getNpmId(purl: any) {
@@ -1745,6 +1748,15 @@ describe('PackageURL', () => {
17451748
)
17461749
expect(validateRequired('field', null, { throws: false })).toBe(false)
17471750
expect(validateRequired('field', '', { throws: false })).toBe(false)
1751+
// Test with undefined parameter (line 160)
1752+
expect(validateRequired('field', null, undefined)).toBe(false)
1753+
expect(validateRequired('field', 'value', undefined)).toBe(true)
1754+
// Test with legacy boolean parameter
1755+
expect(validateRequired('field', null, false)).toBe(false)
1756+
expect(validateRequired('field', 'value', false)).toBe(true)
1757+
expect(() => validateRequired('field', null, true)).toThrow(
1758+
'"field" is a required component',
1759+
)
17481760

17491761
// validateRequiredByType
17501762
expect(() =>
@@ -1756,6 +1768,18 @@ describe('PackageURL', () => {
17561768
expect(
17571769
validateRequiredByType('npm', 'name', null, { throws: false }),
17581770
).toBe(false)
1771+
// Test with undefined parameter (line 182)
1772+
expect(validateRequiredByType('npm', 'name', null, undefined)).toBe(
1773+
false,
1774+
)
1775+
expect(validateRequiredByType('npm', 'name', 'value', undefined)).toBe(
1776+
true,
1777+
)
1778+
// Test with legacy boolean parameter
1779+
expect(validateRequiredByType('npm', 'name', null, false)).toBe(false)
1780+
expect(() => validateRequiredByType('npm', 'name', null, true)).toThrow(
1781+
'npm requires a "name" component',
1782+
)
17591783

17601784
// validateStartsWithoutNumber
17611785
expect(() =>
@@ -1764,6 +1788,128 @@ describe('PackageURL', () => {
17641788
expect(
17651789
validateStartsWithoutNumber('field', '1test', { throws: false }),
17661790
).toBe(false)
1791+
// Test with undefined parameter (line 203)
1792+
expect(validateStartsWithoutNumber('field', '1test', undefined)).toBe(
1793+
false,
1794+
)
1795+
expect(validateStartsWithoutNumber('field', 'test', undefined)).toBe(
1796+
true,
1797+
)
1798+
// Test with legacy boolean parameter
1799+
expect(validateStartsWithoutNumber('field', '1test', false)).toBe(false)
1800+
expect(() =>
1801+
validateStartsWithoutNumber('field', '1test', true),
1802+
).toThrow('field "1test" cannot start with a number')
1803+
1804+
// validateQualifiers with undefined parameter (line 123)
1805+
expect(validateQualifiers({ key: 'value' }, undefined)).toBe(true)
1806+
expect(validateQualifiers(null, undefined)).toBe(true)
1807+
expect(validateQualifiers([], undefined)).toBe(false)
1808+
// Test with legacy boolean parameter
1809+
expect(validateQualifiers({ key: 'value' }, false)).toBe(true)
1810+
expect(validateQualifiers([], false)).toBe(false)
1811+
expect(() => validateQualifiers([], true)).toThrow(
1812+
'"qualifiers" must be a plain object',
1813+
)
1814+
})
1815+
1816+
// Test legacy boolean parameter support for backward compatibility
1817+
it('should support legacy boolean parameter in validation functions', () => {
1818+
// validateEmptyByType with legacy boolean parameter (line 28)
1819+
expect(() =>
1820+
validateEmptyByType('swift', 'namespace', 'not-empty', true),
1821+
).toThrow(/swift "namespace" component must be empty/)
1822+
expect(
1823+
validateEmptyByType('swift', 'namespace', 'not-empty', false),
1824+
).toBe(false)
1825+
expect(validateEmptyByType('swift', 'namespace', '', false)).toBe(true)
1826+
expect(validateEmptyByType('swift', 'namespace', null, false)).toBe(
1827+
true,
1828+
)
1829+
// Test with undefined parameter
1830+
expect(validateEmptyByType('swift', 'namespace', '', undefined)).toBe(
1831+
true,
1832+
)
1833+
expect(
1834+
validateEmptyByType('swift', 'namespace', 'not-empty', undefined),
1835+
).toBe(false)
1836+
1837+
// validateName with legacy boolean parameter (line 47)
1838+
expect(() => validateName(null, true)).toThrow(
1839+
/"name" is a required component/,
1840+
)
1841+
expect(validateName(null, false)).toBe(false)
1842+
expect(validateName('valid', false)).toBe(true)
1843+
// Test with undefined parameter
1844+
expect(validateName('valid', undefined)).toBe(true)
1845+
expect(validateName(null, undefined)).toBe(false)
1846+
1847+
// validateNamespace with legacy boolean parameter (line 62)
1848+
expect(() => validateNamespace(123, true)).toThrow(
1849+
/"namespace" must be a string/,
1850+
)
1851+
expect(validateNamespace(123, false)).toBe(false)
1852+
expect(validateNamespace('valid', false)).toBe(true)
1853+
expect(validateNamespace(null, false)).toBe(true)
1854+
// Test with undefined parameter
1855+
expect(validateNamespace('valid', undefined)).toBe(true)
1856+
expect(validateNamespace(123, undefined)).toBe(false)
1857+
1858+
// validateQualifierKey with legacy boolean parameter (line 75)
1859+
expect(() => validateQualifierKey('key!invalid', true)).toThrow(
1860+
/qualifier "key!invalid" contains an illegal character/,
1861+
)
1862+
expect(validateQualifierKey('key!invalid', false)).toBe(false)
1863+
expect(validateQualifierKey('validkey', false)).toBe(true)
1864+
// Test with undefined parameter
1865+
expect(validateQualifierKey('validkey', undefined)).toBe(true)
1866+
expect(validateQualifierKey('key!invalid', undefined)).toBe(false)
1867+
1868+
// validateStrings with legacy boolean parameter (line 227)
1869+
expect(() => validateStrings('test', 123, true)).toThrow(
1870+
/"test" must be a string/,
1871+
)
1872+
expect(validateStrings('test', 123, false)).toBe(false)
1873+
expect(validateStrings('test', 'valid', false)).toBe(true)
1874+
expect(validateStrings('test', null, false)).toBe(true)
1875+
// Test with undefined parameter
1876+
expect(validateStrings('test', 'valid', undefined)).toBe(true)
1877+
expect(validateStrings('test', 123, undefined)).toBe(false)
1878+
1879+
// validateType with legacy boolean parameter (line 260)
1880+
expect(() => validateType('type$illegal', true)).toThrow(
1881+
/type "type\$illegal" contains an illegal character/,
1882+
)
1883+
expect(validateType('type$illegal', false)).toBe(false)
1884+
expect(validateType('validtype', false)).toBe(true)
1885+
// Test with undefined parameter
1886+
expect(validateType('validtype', undefined)).toBe(true)
1887+
expect(validateType('type$illegal', undefined)).toBe(false)
1888+
1889+
// validateVersion with legacy boolean parameter (line 309)
1890+
expect(validateVersion('1.0.0', false)).toBe(true)
1891+
expect(validateVersion(123, false)).toBe(false)
1892+
expect(() => validateVersion(123, true)).toThrow(
1893+
/"version" must be a string/,
1894+
)
1895+
expect(validateVersion(null, false)).toBe(true)
1896+
expect(validateVersion(undefined, false)).toBe(true)
1897+
// Test with undefined parameter
1898+
expect(validateVersion('1.0.0', undefined)).toBe(true)
1899+
expect(validateVersion(123, undefined)).toBe(false)
1900+
})
1901+
1902+
// Test npm namespace validation non-throws mode
1903+
it('should validate npm namespace without @ character in non-throws mode', () => {
1904+
// Test purl-type.ts lines 428-429 - return false path
1905+
const comp = { namespace: 'namespace', name: 'test' }
1906+
const result = (PurlType['npm'] as any).validate(comp, false)
1907+
expect(result).toBe(false)
1908+
1909+
// Also verify throws mode works
1910+
expect(() => (PurlType['npm'] as any).validate(comp, true)).toThrow(
1911+
/npm "namespace" component must start with an "@" character/,
1912+
)
17671913
})
17681914

17691915
// Test index.js exports

0 commit comments

Comments
 (0)