@@ -27,6 +27,9 @@ const mockCalendar: ContributionCalendar = {
2727 ] ,
2828} ;
2929
30+ const originalGitHubPat = process . env . GITHUB_PAT ;
31+ const originalGitHubToken = process . env . GITHUB_TOKEN ;
32+
3033function mockResponse ( body : unknown , status = 200 ) : Response {
3134 return new Response ( JSON . stringify ( body ) , {
3235 status,
@@ -36,10 +39,23 @@ function mockResponse(body: unknown, status = 200): Response {
3639
3740beforeEach ( ( ) => {
3841 clearGitHubApiCacheForTests ( ) ;
42+ process . env . GITHUB_PAT = 'test-token' ;
43+ delete process . env . GITHUB_TOKEN ;
3944} ) ;
4045
4146afterEach ( ( ) => {
4247 clearGitHubApiCacheForTests ( ) ;
48+ if ( originalGitHubPat === undefined ) {
49+ delete process . env . GITHUB_PAT ;
50+ } else {
51+ process . env . GITHUB_PAT = originalGitHubPat ;
52+ }
53+
54+ if ( originalGitHubToken === undefined ) {
55+ delete process . env . GITHUB_TOKEN ;
56+ } else {
57+ process . env . GITHUB_TOKEN = originalGitHubToken ;
58+ }
4359} ) ;
4460
4561describe ( 'fetchGitHubContributions' , ( ) => {
@@ -81,13 +97,46 @@ describe('fetchGitHubContributions', () => {
8197 const [ url , options ] = vi . mocked ( fetch ) . mock . calls [ 0 ] ;
8298 expect ( url ) . toBe ( 'https://api.github.com/graphql' ) ;
8399 expect ( options ?. method ) . toBe ( 'POST' ) ;
100+ expect ( options ?. headers ) . toMatchObject ( {
101+ Authorization : 'bearer test-token' ,
102+ 'Content-Type' : 'application/json' ,
103+ } ) ;
84104
85105 // Make sure the username is wired into the GraphQL variables, not hardcoded.
86106 const body = JSON . parse ( options ?. body as string ) ;
87107 expect ( body . variables ) . toEqual ( { login : 'octocat' } ) ;
88108 expect ( body . query ) . toContain ( 'contributionCalendar' ) ;
89109 } ) ;
90110
111+ it ( 'uses GITHUB_TOKEN when GITHUB_PAT is not configured' , async ( ) => {
112+ delete process . env . GITHUB_PAT ;
113+ process . env . GITHUB_TOKEN = 'actions-token' ;
114+ vi . mocked ( fetch ) . mockResolvedValue (
115+ mockResponse ( {
116+ data : {
117+ user : { contributionsCollection : { contributionCalendar : mockCalendar } } ,
118+ } ,
119+ } )
120+ ) ;
121+
122+ await fetchGitHubContributions ( 'octocat' ) ;
123+
124+ const [ , options ] = vi . mocked ( fetch ) . mock . calls [ 0 ] ;
125+ expect ( options ?. headers ) . toMatchObject ( {
126+ Authorization : 'bearer actions-token' ,
127+ } ) ;
128+ } ) ;
129+
130+ it ( 'throws before fetching when no GitHub token is configured' , async ( ) => {
131+ delete process . env . GITHUB_PAT ;
132+ delete process . env . GITHUB_TOKEN ;
133+
134+ await expect ( fetchGitHubContributions ( 'octocat' ) ) . rejects . toThrow (
135+ 'GitHub token is missing. Set GITHUB_PAT or GITHUB_TOKEN.'
136+ ) ;
137+ expect ( fetch ) . not . toHaveBeenCalled ( ) ;
138+ } ) ;
139+
91140 it ( 'works correctly for a brand-new user who has zero contribution weeks' , async ( ) => {
92141 const emptyCalendar : ContributionCalendar = { totalContributions : 0 , weeks : [ ] } ;
93142
0 commit comments