@@ -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 ( / ^ h t t p s : \/ \/ g i t h u b \. c o m \/ a d v i s o r i e s \/ / )
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