Skip to content

Commit 9dfb3be

Browse files
committed
fix "Fix Selected" with no fixable entries + replace redux-mock-store
1 parent a51d9dd commit 9dfb3be

2 files changed

Lines changed: 60 additions & 21 deletions

File tree

webpack/components/PreupgradeReportsTable/__tests__/PreupgradeReportsTable.test.js

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
import React from 'react';
2-
import {
3-
render,
4-
screen,
5-
waitFor,
6-
fireEvent,
7-
within,
8-
cleanup,
9-
} from '@testing-library/react';
10-
import '@testing-library/jest-dom/extend-expect';
112
import { Provider } from 'react-redux';
12-
import configureMockStore from 'redux-mock-store';
13-
import thunk from 'redux-thunk';
3+
import { configureStore } from '@reduxjs/toolkit';
4+
import Immutable from 'seamless-immutable';
5+
import { render, screen, waitFor, fireEvent, within, cleanup } from '@testing-library/react';
6+
import '@testing-library/jest-dom';
147
import { APIActions } from 'foremanReact/redux/API';
158
import PreupgradeReportsTable from '../index';
169

1710
jest.mock('foremanReact/redux/API');
1811

12+
const mockReducer = (state = Immutable({ API: {} })) => state;
13+
1914
jest.mock('foremanReact/constants', () => ({
2015
...jest.requireActual('foremanReact/constants'),
2116
getControllerSearchProps: jest.fn(() => ({
@@ -33,6 +28,7 @@ jest.mock('foremanReact/components/SearchBar', () => {
3328
const MockSearchBar = ({ onSearch, onChange }) => (
3429
<input
3530
data-testid="search-input"
31+
aria-label="Search preupgrade report entries"
3632
onChange={e => onChange && onChange(e.target.value)}
3733
onKeyDown={e => {
3834
if (e.key === 'Enter') onSearch(e.target.value);
@@ -42,7 +38,6 @@ jest.mock('foremanReact/components/SearchBar', () => {
4238
return MockSearchBar;
4339
});
4440

45-
const mockStore = configureMockStore([thunk]);
4641
const mockJobId = 42;
4742
const mockReportId = 999;
4843
const mockJobData = {
@@ -72,14 +67,11 @@ const mockEntries = Array.from({ length: 12 }, (_, i) => ({
7267
}));
7368

7469
describe('PreupgradeReportsTable', () => {
75-
let store;
76-
7770
beforeEach(() => {
78-
store = mockStore({ API: {} });
7971
jest.clearAllMocks();
8072

8173
APIActions.get.mockImplementation(({ key, handleSuccess }) => {
82-
return dispatch => {
74+
return () => {
8375
if (key.includes('GET_LEAPP_REPORT_LIST')) {
8476
handleSuccess({ results: [{ id: mockReportId }] });
8577
}
@@ -101,12 +93,16 @@ describe('PreupgradeReportsTable', () => {
10193
cleanup();
10294
});
10395

104-
const renderComponent = (data = mockJobData) =>
105-
render(
96+
const renderComponent = (data = mockJobData) => {
97+
const store = configureStore({
98+
reducer: mockReducer,
99+
});
100+
return render(
106101
<Provider store={store}>
107102
<PreupgradeReportsTable data={data} />
108103
</Provider>
109104
);
105+
};
110106

111107
const expandSection = () => {
112108
fireEvent.click(screen.getByText('Leapp preupgrade report'));
@@ -132,6 +128,9 @@ describe('PreupgradeReportsTable', () => {
132128
});
133129

134130
it('refetches when status_label transitions (e.g. Running → Succeeded)', async () => {
131+
const store = configureStore({
132+
reducer: mockReducer,
133+
});
135134
const { rerender } = render(
136135
<Provider store={store}>
137136
<PreupgradeReportsTable
@@ -420,6 +419,43 @@ describe('PreupgradeReportsTable', () => {
420419
expect(screen.getByRole('button', { name: 'Fix Selected' })).toBeDisabled();
421420
});
422421

422+
it('disables Fix Selected when selecting all on page with no fixable entries', async () => {
423+
APIActions.get.mockImplementation(({ key, handleSuccess }) => {
424+
return () => {
425+
if (key.includes('GET_LEAPP_REPORT_LIST')) {
426+
handleSuccess({ results: [{ id: mockReportId }] });
427+
}
428+
if (key.includes('GET_LEAPP_REPORT_ENTRIES')) {
429+
handleSuccess({
430+
id: mockReportId,
431+
results: [
432+
{
433+
id: 999,
434+
title: 'Non-fixable Entry',
435+
hostname: 'test.com',
436+
host_id: 200,
437+
severity: 'low',
438+
summary: 'This has no command remediation',
439+
detail: {
440+
remediations: [{ type: 'hint', context: 'Manual fix only' }],
441+
},
442+
},
443+
],
444+
total: 1,
445+
});
446+
}
447+
return { type: 'MOCK_API_SUCCESS' };
448+
};
449+
});
450+
451+
renderComponent();
452+
expandSection();
453+
await waitFor(() => screen.getByText('Non-fixable Entry', { selector: 'td' }));
454+
455+
fireEvent.click(screen.getByLabelText('Select all'));
456+
expect(screen.getByRole('button', { name: 'Fix Selected' })).toBeDisabled();
457+
});
458+
423459
it('renders Run Upgrade button enabled when entries are present', async () => {
424460
renderComponent();
425461
expandSection();

webpack/components/PreupgradeReportsTable/index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,15 @@ const PreupgradeReportsTable = ({ data = {} }) => {
331331

332332
if (!isLeappJob) return null;
333333

334+
const hasAnySelection =
335+
areAllRowsSelected() || exclusionSet.size > 0 || selectedIds.length > 0;
336+
334337
const isFixSelectedDisabled =
335338
status === STATUS.PENDING ||
336339
isSubmitting ||
337-
(!areAllRowsSelected() &&
338-
exclusionSet.size === 0 &&
339-
selectedIds.length === 0);
340+
!hasAnySelection ||
341+
// When using select-all, check if any fixable entries exist on current page
342+
(areAllRowsSelected() && pagedFixableEntries.length === 0);
340343

341344
const isRunUpgradeDisabled =
342345
status === STATUS.PENDING ||

0 commit comments

Comments
 (0)