@@ -34,6 +34,10 @@ const failingCIChecks = [
3434 { name : 'tests' , status : 'completed' , conclusion : 'failure' } ,
3535] ;
3636
37+ const pendingCIChecks = [
38+ { name : 'tests' , status : 'in_progress' , conclusion : null } ,
39+ ] ;
40+
3741const basePRStatus = {
3842 ci_checks : successfulCIChecks ,
3943 review_status : 'approved' ,
@@ -79,11 +83,20 @@ const proofStatusWithOpenReqs = {
7983
8084// ── Helpers ───────────────────────────────────────────────────────────────────
8185
82- const setupSWRMock = ( prStatus : object , proofStatus : object ) => {
86+ const setupSWRMock = (
87+ prStatus : object | undefined ,
88+ proofStatus : object | undefined ,
89+ options ?: { proofLoading ?: boolean ; proofError ?: unknown }
90+ ) => {
8391 mockUseSWR . mockImplementation ( ( key : unknown ) => {
8492 const keyStr = typeof key === 'string' ? key : '' ;
8593 if ( keyStr . includes ( '/api/v2/proof/status' ) ) {
86- return { data : proofStatus , error : undefined , isLoading : false , mutate : jest . fn ( ) } as any ;
94+ return {
95+ data : proofStatus ,
96+ error : options ?. proofError ,
97+ isLoading : options ?. proofLoading ?? false ,
98+ mutate : jest . fn ( ) ,
99+ } as any ;
87100 }
88101 return { data : prStatus , error : undefined , isLoading : false , mutate : jest . fn ( ) } as any ;
89102 } ) ;
@@ -185,4 +198,32 @@ describe('PRStatusPanel — PROOF9-gated merge button', () => {
185198 expect ( screen . getByText ( / c i c h e c k s f a i l i n g / i) ) . toBeInTheDocument ( ) ;
186199 expect ( screen . getByText ( 'Fix critical bug' ) ) . toBeInTheDocument ( ) ;
187200 } ) ;
201+
202+ it ( 'shows "Waiting for CI checks" when CI checks are pending' , ( ) => {
203+ setupSWRMock ( { ...basePRStatus , ci_checks : pendingCIChecks } , cleanProofStatus ) ;
204+ render ( < PRStatusPanel { ...defaultProps } /> ) ;
205+ expect ( screen . getByText ( / w a i t i n g f o r c i c h e c k s / i) ) . toBeInTheDocument ( ) ;
206+ expect ( screen . getByRole ( 'button' , { name : / ^ m e r g e $ / i } ) ) . toBeDisabled ( ) ;
207+ } ) ;
208+
209+ it ( 'shows PROOF9 loading skeleton instead of "All clear" while proof data loads' , ( ) => {
210+ setupSWRMock ( basePRStatus , undefined , { proofLoading : true } ) ;
211+ render ( < PRStatusPanel { ...defaultProps } /> ) ;
212+ expect ( screen . queryByText ( / a l l c l e a r / i) ) . not . toBeInTheDocument ( ) ;
213+ expect ( screen . getByRole ( 'button' , { name : / ^ m e r g e $ / i } ) ) . toBeDisabled ( ) ;
214+ } ) ;
215+
216+ it ( 'shows PROOF9 error message when proof API fails' , ( ) => {
217+ setupSWRMock ( basePRStatus , undefined , { proofError : new Error ( 'Network error' ) } ) ;
218+ render ( < PRStatusPanel { ...defaultProps } /> ) ;
219+ expect ( screen . getByText ( / u n a b l e t o l o a d p r o o f 9 s t a t u s / i) ) . toBeInTheDocument ( ) ;
220+ expect ( screen . getByRole ( 'button' , { name : / ^ m e r g e $ / i } ) ) . toBeDisabled ( ) ;
221+ } ) ;
222+
223+ it ( 'shows success banner when PR was merged externally' , ( ) => {
224+ setupSWRMock ( { ...basePRStatus , merge_state : 'merged' } , cleanProofStatus ) ;
225+ render ( < PRStatusPanel { ...defaultProps } /> ) ;
226+ expect ( screen . getByText ( / m e r g e d s u c c e s s f u l l y / i) ) . toBeInTheDocument ( ) ;
227+ expect ( screen . queryByRole ( 'button' , { name : / m e r g e / i } ) ) . not . toBeInTheDocument ( ) ;
228+ } ) ;
188229} ) ;
0 commit comments