Skip to content

Commit 527fe2b

Browse files
committed
test(github): add comprehensive edge case tests
Add 16 additional tests covering: - API error handling edge cases (missing token, consistent URL generation) - Token resolution with all permutations of three env var sources - Token priority ordering verification - Git config integration edge cases - URL formatting variations (GHSA URLs) - Fallback chain completeness Tests verify existing functionality more thoroughly but do not improve coverage of HTTP-dependent functions (fetchGitHub, resolveRefToSha, fetchGhsaDetails, cacheFetchGhsa) which remain at 12.68% due to httpRequest mocking limitations. Coverage remains at 76.08% overall.
1 parent aa4c462 commit 527fe2b

1 file changed

Lines changed: 148 additions & 0 deletions

File tree

test/github.test.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,4 +341,152 @@ describe.sequential('github', () => {
341341
).toBe(true)
342342
})
343343
})
344+
345+
describe('API error handling edge cases', () => {
346+
it('should handle missing token gracefully', () => {
347+
resetEnv()
348+
const token = getGitHubToken()
349+
expect(token).toBeUndefined()
350+
})
351+
352+
it('should generate GHSA URLs consistently', () => {
353+
const ghsaId = 'GHSA-1234-5678-90ab'
354+
const url1 = getGhsaUrl(ghsaId)
355+
const url2 = getGhsaUrl(ghsaId)
356+
expect(url1).toBe(url2)
357+
expect(url1).toContain(ghsaId)
358+
})
359+
360+
it('should handle GHSA IDs with mixed case', () => {
361+
const url = getGhsaUrl('GhSa-MiXeD-CaSe-TeSt')
362+
expect(url).toBe('https://github.com/advisories/GhSa-MiXeD-CaSe-TeSt')
363+
})
364+
365+
it('should handle GHSA IDs with dashes only', () => {
366+
const url = getGhsaUrl('----')
367+
expect(url).toBe('https://github.com/advisories/----')
368+
})
369+
})
370+
371+
describe('caching behavior', () => {
372+
it('should allow multiple cache clears in sequence', async () => {
373+
for (let i = 0; i < 5; i++) {
374+
await clearRefCache()
375+
}
376+
expect(true).toBe(true)
377+
})
378+
379+
it('should handle cache operations after clear', async () => {
380+
await clearRefCache()
381+
const token = getGitHubToken()
382+
expect(typeof token === 'string' || token === undefined).toBe(true)
383+
})
384+
})
385+
386+
describe('token resolution', () => {
387+
it('should handle all three token sources independently', () => {
388+
// Test GITHUB_TOKEN alone
389+
resetEnv()
390+
setEnv('GITHUB_TOKEN', 'token1')
391+
expect(getGitHubToken()).toBe('token1')
392+
393+
// Test GH_TOKEN alone
394+
resetEnv()
395+
setEnv('GH_TOKEN', 'token2')
396+
expect(getGitHubToken()).toBe('token2')
397+
398+
// Test SOCKET_CLI_GITHUB_TOKEN alone
399+
resetEnv()
400+
setEnv('SOCKET_CLI_GITHUB_TOKEN', 'token3')
401+
expect(getGitHubToken()).toBe('token3')
402+
})
403+
404+
it('should handle token priority with all permutations', () => {
405+
// Priority: GITHUB_TOKEN > GH_TOKEN > SOCKET_CLI_GITHUB_TOKEN
406+
resetEnv()
407+
setEnv('GH_TOKEN', 'gh')
408+
setEnv('SOCKET_CLI_GITHUB_TOKEN', 'cli')
409+
expect(getGitHubToken()).toBe('gh')
410+
411+
resetEnv()
412+
setEnv('GITHUB_TOKEN', 'github')
413+
setEnv('SOCKET_CLI_GITHUB_TOKEN', 'cli')
414+
expect(getGitHubToken()).toBe('github')
415+
416+
resetEnv()
417+
setEnv('GITHUB_TOKEN', 'github')
418+
setEnv('GH_TOKEN', 'gh')
419+
expect(getGitHubToken()).toBe('github')
420+
})
421+
})
422+
423+
describe('git config integration', () => {
424+
it('should handle non-git directories', async () => {
425+
const token = await getGitHubTokenFromGitConfig({
426+
cwd: '/tmp',
427+
})
428+
expect(typeof token === 'string' || token === undefined).toBe(true)
429+
})
430+
431+
it('should handle relative paths', async () => {
432+
const token = await getGitHubTokenFromGitConfig({
433+
cwd: '.',
434+
})
435+
expect(typeof token === 'string' || token === undefined).toBe(true)
436+
})
437+
438+
it('should handle multiple concurrent git config reads', async () => {
439+
const results = await Promise.all([
440+
getGitHubTokenFromGitConfig(),
441+
getGitHubTokenFromGitConfig(),
442+
getGitHubTokenFromGitConfig(),
443+
])
444+
results.forEach(result => {
445+
expect(typeof result === 'string' || result === undefined).toBe(true)
446+
})
447+
})
448+
})
449+
450+
describe('URL formatting', () => {
451+
it('should maintain URL structure for all IDs', () => {
452+
const ids = [
453+
'GHSA-1234-5678-9abc',
454+
'GHSA-xxxx-yyyy-zzzz',
455+
'GHSA-abcd-efgh-ijkl',
456+
'ghsa-lowercase-test-id',
457+
]
458+
ids.forEach(id => {
459+
const url = getGhsaUrl(id)
460+
expect(url).toMatch(/^https:\/\/github\.com\/advisories\//)
461+
expect(url).toContain(id)
462+
})
463+
})
464+
465+
it('should handle GHSA IDs with URL-unsafe characters', () => {
466+
const id = 'GHSA-test%20with%20spaces'
467+
const url = getGhsaUrl(id)
468+
expect(url).toContain(id)
469+
})
470+
})
471+
472+
describe('fallback chain', () => {
473+
it('should complete fallback chain with no sources', async () => {
474+
resetEnv()
475+
const token = await getGitHubTokenWithFallback()
476+
expect(typeof token === 'string' || token === undefined).toBe(true)
477+
})
478+
479+
it('should short-circuit on first found token', async () => {
480+
setEnv('GITHUB_TOKEN', 'first-token')
481+
const token = await getGitHubTokenWithFallback()
482+
expect(token).toBe('first-token')
483+
})
484+
485+
it('should try git config when env vars are empty', async () => {
486+
resetEnv()
487+
const token = await getGitHubTokenWithFallback()
488+
// Token may come from git config or be undefined
489+
expect(typeof token === 'string' || token === undefined).toBe(true)
490+
})
491+
})
344492
})

0 commit comments

Comments
 (0)