@@ -56,7 +56,7 @@ const mockEntries = Array.from({ length: 12 }, (_, i) => ({
5656 flags : i === 0 ? [ 'inhibitor' ] : [ ] ,
5757 detail : {
5858 remediations :
59- i === 0
59+ i === 0 || i === 3 || i === 4
6060 ? [ { type : 'command' , context : [ 'echo' , 'fix_command' ] } ]
6161 : i === 1
6262 ? [ { type : 'hint' , context : 'Do something manually' } ]
@@ -76,10 +76,14 @@ describe('PreupgradeReportsTable', () => {
7676 handleSuccess ( { results : [ { id : mockReportId } ] } ) ;
7777 }
7878 if ( key . includes ( 'GET_LEAPP_REPORT_ENTRIES' ) ) {
79+ const fixableCount = mockEntries . filter (
80+ e => e . detail ?. remediations ?. some ( r => r . type === 'command' )
81+ ) . length ;
7982 handleSuccess ( {
8083 id : mockReportId ,
8184 results : mockEntries ,
8285 total : mockEntries . length ,
86+ fixable_count : fixableCount ,
8387 } ) ;
8488 }
8589 return { type : 'MOCK_API_SUCCESS' } ;
@@ -560,4 +564,140 @@ describe('PreupgradeReportsTable', () => {
560564 } )
561565 ) ;
562566 } ) ;
567+
568+ it ( 'fetches and displays fixableCount from API response' , async ( ) => {
569+ const mockFixableCount = 3 ;
570+ APIActions . get . mockImplementation ( ( { key, handleSuccess } ) => {
571+ return ( ) => {
572+ if ( key . includes ( 'GET_LEAPP_REPORT_LIST' ) ) {
573+ handleSuccess ( { results : [ { id : mockReportId } ] } ) ;
574+ }
575+ if ( key . includes ( 'GET_LEAPP_REPORT_ENTRIES' ) ) {
576+ handleSuccess ( {
577+ id : mockReportId ,
578+ results : mockEntries ,
579+ total : mockEntries . length ,
580+ subtotal : mockEntries . length ,
581+ fixable_count : mockFixableCount ,
582+ } ) ;
583+ }
584+ return { type : 'MOCK_API_SUCCESS' } ;
585+ } ;
586+ } ) ;
587+
588+ renderComponent ( ) ;
589+ expandSection ( ) ;
590+ await waitForTable ( ) ;
591+
592+ const selectDropdown = screen . getByRole ( 'button' , { name : 'Select' } ) ;
593+ fireEvent . click ( selectDropdown ) ;
594+
595+ await waitFor ( ( ) => {
596+ const selectAllText = screen . getByText ( / S e l e c t a l l \( 3 / i) ;
597+ expect ( selectAllText ) . toBeInTheDocument ( ) ;
598+ } ) ;
599+ } ) ;
600+
601+ it ( 'displays correct fixableCount when search filters are applied' , async ( ) => {
602+ const mockFilteredFixableCount = 1 ;
603+ APIActions . get . mockImplementation ( ( { key, handleSuccess, params } ) => {
604+ return ( ) => {
605+ if ( key . includes ( 'GET_LEAPP_REPORT_LIST' ) ) {
606+ handleSuccess ( { results : [ { id : mockReportId } ] } ) ;
607+ }
608+ if ( key . includes ( 'GET_LEAPP_REPORT_ENTRIES' ) ) {
609+ if ( params ?. search ) {
610+ handleSuccess ( {
611+ id : mockReportId ,
612+ results : [ mockEntries [ 0 ] ] , // Only one filtered result
613+ total : mockEntries . length ,
614+ subtotal : 1 ,
615+ fixable_count : mockFilteredFixableCount ,
616+ } ) ;
617+ } else {
618+ handleSuccess ( {
619+ id : mockReportId ,
620+ results : mockEntries ,
621+ total : mockEntries . length ,
622+ subtotal : mockEntries . length ,
623+ fixable_count : 3 ,
624+ } ) ;
625+ }
626+ }
627+ return { type : 'MOCK_API_SUCCESS' } ;
628+ } ;
629+ } ) ;
630+
631+ renderComponent ( ) ;
632+ expandSection ( ) ;
633+ await waitForTable ( ) ;
634+
635+ const input = screen . getByTestId ( 'search-input' ) ;
636+ fireEvent . change ( input , { target : { value : 'title = "Report Entry 1"' } } ) ;
637+ fireEvent . keyDown ( input , { key : 'Enter' } ) ;
638+
639+ await waitFor ( ( ) => screen . getByText ( 'Report Entry 1' , { selector : 'td' } ) ) ;
640+
641+ const selectDropdown = screen . getByRole ( 'button' , { name : 'Select' } ) ;
642+ fireEvent . click ( selectDropdown ) ;
643+
644+ await waitFor ( ( ) => {
645+ const selectAllText = screen . getByText ( / S e l e c t a l l \( 1 / i) ;
646+ expect ( selectAllText ) . toBeInTheDocument ( ) ;
647+ } ) ;
648+ } ) ;
649+
650+ it ( 'shows 0 fixable items when all entries are non-fixable (hint-only)' , async ( ) => {
651+ APIActions . get . mockImplementation ( ( { key, handleSuccess } ) => {
652+ return ( ) => {
653+ if ( key . includes ( 'GET_LEAPP_REPORT_LIST' ) ) {
654+ handleSuccess ( { results : [ { id : mockReportId } ] } ) ;
655+ }
656+ if ( key . includes ( 'GET_LEAPP_REPORT_ENTRIES' ) ) {
657+ handleSuccess ( {
658+ id : mockReportId ,
659+ results : [
660+ {
661+ id : 1 ,
662+ title : 'Hint-only Entry 1' ,
663+ hostname : 'test.com' ,
664+ host_id : 100 ,
665+ severity : 'low' ,
666+ summary : 'Summary' ,
667+ detail : {
668+ remediations : [ { type : 'hint' , context : 'Manual fix required' } ] ,
669+ } ,
670+ } ,
671+ {
672+ id : 2 ,
673+ title : 'Hint-only Entry 2' ,
674+ hostname : 'test.com' ,
675+ host_id : 101 ,
676+ severity : 'low' ,
677+ summary : 'Summary' ,
678+ detail : {
679+ remediations : [ { type : 'hint' , context : 'Manual fix required' } ] ,
680+ } ,
681+ } ,
682+ ] ,
683+ total : 2 ,
684+ subtotal : 2 ,
685+ fixable_count : 0 ,
686+ } ) ;
687+ }
688+ return { type : 'MOCK_API_SUCCESS' } ;
689+ } ;
690+ } ) ;
691+
692+ renderComponent ( ) ;
693+ expandSection ( ) ;
694+ await waitFor ( ( ) => screen . getByText ( 'Hint-only Entry 1' , { selector : 'td' } ) ) ;
695+
696+ const checkboxes = screen . getAllByRole ( 'checkbox' ) ;
697+ checkboxes . forEach ( checkbox => {
698+ expect ( checkbox ) . toBeDisabled ( ) ;
699+ } ) ;
700+
701+ expect ( screen . getByRole ( 'button' , { name : 'Fix Selected' } ) ) . toBeDisabled ( ) ;
702+ } ) ;
563703} ) ;
0 commit comments