1- import {
2- authenticate ,
3- GITHUB_AUTH_API_KEY ,
4- GITHUB_AUTH_SERVICE_URL
5- } from '../src/auth'
1+ import { authenticate , PRODUCTION_SERVICE , STAGING_SERVICE } from '../src/auth'
62import { jest } from '@jest/globals'
3+ import core from '@actions/core'
74
85describe ( 'authenticate' , ( ) => {
96 const mockFetch = jest . spyOn ( global , 'fetch' )
107
118 beforeEach ( ( ) => {
129 process . env . GITHUB_TOKEN = 'ghp_default_token'
13- mockFetch . mockClear ( )
10+
11+ jest . clearAllMocks ( )
12+
13+ jest . spyOn ( core , 'warning' ) . mockReturnValue ( )
14+ jest . spyOn ( core , 'debug' ) . mockReturnValue ( )
1415 } )
1516
16- it ( 'should use GitHub App authentication when app is installed' , async ( ) => {
17+ it ( 'should use production GitHub App when installed' , async ( ) => {
1718 mockFetch . mockResolvedValue ( {
1819 ok : true ,
1920 status : 200 ,
20- json : async ( ) => Promise . resolve ( { token : 'ghs_app_123 ' } )
21+ json : async ( ) => Promise . resolve ( { token : 'ghs_prod_token ' } )
2122 } as Response )
2223
2324 const result = await authenticate (
2425 { owner : 'dunder-mifflin' , repo : 'website' } ,
2526 'ghp_default_token'
2627 )
2728
28- expect ( result ) . toBe ( 'ghs_app_123' )
29+ expect ( result ) . toBe ( 'ghs_prod_token' )
30+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 1 )
31+ expect ( mockFetch ) . toHaveBeenCalledWith (
32+ `${ PRODUCTION_SERVICE . url } /github/dunder-mifflin/website/installation-token` ,
33+ expect . objectContaining ( {
34+ method : 'POST' ,
35+ headers : { Authorization : `Bearer ${ PRODUCTION_SERVICE . key } ` }
36+ } )
37+ )
38+ } )
39+
40+ it ( 'should use staging GitHub App when production not installed' , async ( ) => {
41+ mockFetch
42+ . mockResolvedValueOnce ( {
43+ ok : false ,
44+ status : 404 ,
45+ json : async ( ) => ( { error : 'Not installed' } )
46+ } as Response )
47+ . mockResolvedValueOnce ( {
48+ ok : true ,
49+ status : 200 ,
50+ json : async ( ) => ( { token : 'ghs_staging_token' } )
51+ } as Response )
52+
53+ const result = await authenticate (
54+ { owner : 'dunder-mifflin' , repo : 'website' } ,
55+ 'ghp_default_token'
56+ )
57+
58+ expect ( result ) . toBe ( 'ghs_staging_token' )
59+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 2 )
2960 expect ( mockFetch ) . toHaveBeenCalledWith (
30- `${ GITHUB_AUTH_SERVICE_URL } /github/dunder-mifflin/website/installation-token` ,
61+ `${ STAGING_SERVICE . url } /github/dunder-mifflin/website/installation-token` ,
3162 expect . objectContaining ( {
3263 method : 'POST' ,
33- headers : { Authorization : `Bearer ${ GITHUB_AUTH_API_KEY } ` }
64+ headers : { Authorization : `Bearer ${ STAGING_SERVICE . key } ` }
3465 } )
3566 )
67+ expect ( core . debug ) . toHaveBeenCalledTimes ( 1 )
3668 } )
3769
3870 it ( 'should fall back to standard authentication when app is not installed' , async ( ) => {
@@ -48,6 +80,8 @@ describe('authenticate', () => {
4880 )
4981
5082 expect ( result ) . toBe ( 'ghp_default_token' )
83+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 2 )
84+ expect ( core . debug ) . toHaveBeenCalledTimes ( 2 )
5185 } )
5286
5387 it ( 'should fall back to standard authentication when service is unavailable' , async ( ) => {
@@ -65,11 +99,58 @@ describe('authenticate', () => {
6599 const customPAT = 'ghp_custom_pat'
66100
67101 const result = await authenticate (
68- { owner : 'owner ' , repo : 'repo ' } ,
102+ { owner : 'dunder-mifflin ' , repo : 'website ' } ,
69103 customPAT
70104 )
71105
72106 expect ( result ) . toBe ( customPAT )
73107 expect ( mockFetch ) . not . toHaveBeenCalled ( )
74108 } )
109+
110+ it ( 'should handle all services returning errors' , async ( ) => {
111+ mockFetch
112+ . mockResolvedValueOnce ( {
113+ ok : false ,
114+ status : 401 ,
115+ json : async ( ) => ( { error : 'Unauthorized' } )
116+ } as Response )
117+ . mockResolvedValueOnce ( {
118+ ok : false ,
119+ status : 500 ,
120+ json : async ( ) => ( { error : 'Server error' } )
121+ } as Response )
122+
123+ const result = await authenticate (
124+ { owner : 'dunder-mifflin' , repo : 'website' } ,
125+ 'ghp_default_token'
126+ )
127+
128+ expect ( result ) . toBe ( 'ghp_default_token' )
129+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 2 )
130+ expect ( core . warning ) . toHaveBeenCalledTimes ( 2 )
131+ } )
132+
133+ it ( 'should handle unexpected status codes' , async ( ) => {
134+ mockFetch
135+ . mockResolvedValueOnce ( {
136+ ok : false ,
137+ status : 403 ,
138+ json : async ( ) => ( { error : 'Forbidden' } )
139+ } as Response )
140+ . mockResolvedValueOnce ( {
141+ ok : false ,
142+ status : 403 ,
143+ json : async ( ) => ( { error : 'Forbidden' } )
144+ } as Response )
145+
146+ const result = await authenticate (
147+ { owner : 'dunder-mifflin' , repo : 'website' } ,
148+ 'ghp_default_token'
149+ )
150+
151+ expect ( result ) . toBe ( 'ghp_default_token' )
152+ expect ( core . warning ) . toHaveBeenCalledWith (
153+ expect . stringContaining ( 'returned unexpected status: 403' )
154+ )
155+ } )
75156} )
0 commit comments