Skip to content

Commit 5ed7415

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 28c5f97 commit 5ed7415

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) {
@@ -1756,6 +1759,15 @@ describe('PackageURL', () => {
17561759
)
17571760
expect(validateRequired('field', null, { throws: false })).toBe(false)
17581761
expect(validateRequired('field', '', { throws: false })).toBe(false)
1762+
// Test with undefined parameter (line 160)
1763+
expect(validateRequired('field', null, undefined)).toBe(false)
1764+
expect(validateRequired('field', 'value', undefined)).toBe(true)
1765+
// Test with legacy boolean parameter
1766+
expect(validateRequired('field', null, false)).toBe(false)
1767+
expect(validateRequired('field', 'value', false)).toBe(true)
1768+
expect(() => validateRequired('field', null, true)).toThrow(
1769+
'"field" is a required component',
1770+
)
17591771

17601772
// validateRequiredByType
17611773
expect(() =>
@@ -1767,6 +1779,18 @@ describe('PackageURL', () => {
17671779
expect(
17681780
validateRequiredByType('npm', 'name', null, { throws: false }),
17691781
).toBe(false)
1782+
// Test with undefined parameter (line 182)
1783+
expect(validateRequiredByType('npm', 'name', null, undefined)).toBe(
1784+
false,
1785+
)
1786+
expect(validateRequiredByType('npm', 'name', 'value', undefined)).toBe(
1787+
true,
1788+
)
1789+
// Test with legacy boolean parameter
1790+
expect(validateRequiredByType('npm', 'name', null, false)).toBe(false)
1791+
expect(() => validateRequiredByType('npm', 'name', null, true)).toThrow(
1792+
'npm requires a "name" component',
1793+
)
17701794

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

17801926
// Test index.js exports

0 commit comments

Comments
 (0)