Skip to content

Commit f9ca6f5

Browse files
committed
tests
1 parent 0512189 commit f9ca6f5

9 files changed

Lines changed: 247 additions & 69 deletions

File tree

webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookTable/Components/Formatters/__tests__/__snapshots__/enabledCellFormatter.test.js.snap

Lines changed: 0 additions & 7 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
1-
import { enabledCellFormatter } from '../index';
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
5+
import enabledCellFormatter from '../enabledCellFormatter';
6+
7+
jest.mock('@patternfly/react-icons', () => ({
8+
CheckIcon: () => <span data-testid="check-icon" />,
9+
BanIcon: () => <span data-testid="ban-icon" />,
10+
}));
11+
12+
const renderCell = (value, extra) => {
13+
const formatter = enabledCellFormatter();
14+
const element = formatter(value, extra);
15+
return render(element);
16+
};
217

318
describe('enabledCellFormatter', () => {
4-
it('render', () => {
5-
expect(enabledCellFormatter()(true)).toMatchSnapshot();
19+
it('uses the cell value when row context includes rowData and value is true', () => {
20+
renderCell(true, { rowData: { id: 1, enabled: false } });
21+
expect(screen.getByTestId('check-icon')).toBeInTheDocument();
22+
});
23+
24+
it('uses the cell value when row context includes rowData and value is false', () => {
25+
renderCell(false, { rowData: { id: 1, enabled: true } });
26+
expect(screen.getByTestId('ban-icon')).toBeInTheDocument();
27+
});
28+
29+
it('uses value.enabled when rowData is not present and enabled is true', () => {
30+
renderCell({ enabled: true });
31+
expect(screen.getByTestId('check-icon')).toBeInTheDocument();
32+
});
33+
34+
it('uses value.enabled when rowData is not present and enabled is false', () => {
35+
renderCell({ enabled: false });
36+
expect(screen.getByTestId('ban-icon')).toBeInTheDocument();
637
});
738
});
Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
1-
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
25
import EnabledCell from '../EnabledCell';
36

4-
const fixtures = {
5-
'should render blank cell': {
6-
condition: false,
7-
},
8-
'should render marked cell': {
9-
condition: true,
10-
},
11-
};
12-
13-
describe('EnabledCell', () =>
14-
testComponentSnapshotsWithFixtures(EnabledCell, fixtures));
7+
jest.mock('@patternfly/react-icons', () => ({
8+
CheckIcon: () => <span data-testid="check-icon" />,
9+
BanIcon: () => <span data-testid="ban-icon" />,
10+
}));
11+
12+
describe('EnabledCell', () => {
13+
it('renders the check icon when condition is true', () => {
14+
render(<EnabledCell condition />);
15+
16+
expect(screen.getByTestId('check-icon')).toBeInTheDocument();
17+
expect(screen.queryByTestId('ban-icon')).not.toBeInTheDocument();
18+
});
19+
20+
it('renders the ban icon when condition is false', () => {
21+
render(<EnabledCell condition={false} />);
22+
23+
expect(screen.getByTestId('ban-icon')).toBeInTheDocument();
24+
expect(screen.queryByTestId('check-icon')).not.toBeInTheDocument();
25+
});
26+
});

webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookTable/Components/__tests__/__snapshots__/EnabledCell.test.js.snap

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 114 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,124 @@
11
import React from 'react';
2-
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2+
import { render, screen, fireEvent } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
34
import { Provider } from 'react-redux';
45
import { createStore } from 'redux';
56

7+
import mockForemanTableIndexPage from './mocks/MockForemanTableIndexPage';
8+
9+
import * as selectors from '../../WebhooksPageSelectors';
610
import WebhooksIndexPage from '../WebhooksIndexPage';
11+
import {
12+
spySelector,
13+
webhooks as webhooksFixture,
14+
} from './WebhooksIndexPage.fixtures';
15+
16+
jest.mock('../../Components/WebhookTable/Components/Formatters', () => ({
17+
nameToEditFormatter: () => () => null,
18+
enabledCellFormatter: () => () => null,
19+
actionCellFormatter: () => () => null,
20+
}));
21+
22+
jest.mock('foremanReact/components/PF4/TableIndexPage/TableIndexPage', () => ({
23+
__esModule: true,
24+
default: mockForemanTableIndexPage,
25+
}));
26+
27+
jest.mock('../Components/WebhookCreateModal', () => ({
28+
__esModule: true,
29+
default: ({ isOpen, onCancel }) =>
30+
isOpen ? (
31+
<div data-testid="webhook-create-modal">
32+
<button type="button" onClick={onCancel}>
33+
Close create modal
34+
</button>
35+
</div>
36+
) : null,
37+
}));
38+
39+
jest.mock('../Components/WebhookDeleteModal', () => ({
40+
__esModule: true,
41+
default: ({ modalState }) =>
42+
modalState.isOpen ? (
43+
<div data-testid="webhook-delete-modal">Delete modal</div>
44+
) : null,
45+
}));
46+
47+
jest.mock('../Components/WebhookEditModal', () => ({
48+
__esModule: true,
49+
default: ({ modalState }) =>
50+
modalState.isOpen ? (
51+
<div data-testid="webhook-edit-modal">Edit modal</div>
52+
) : null,
53+
}));
54+
55+
jest.mock('../Components/WebhookTestModal', () => ({
56+
__esModule: true,
57+
default: ({ modalState }) =>
58+
modalState.isOpen ? (
59+
<div data-testid="webhook-test-modal">Test modal</div>
60+
) : null,
61+
}));
762

8-
const fixtures = {
9-
'render with minimal props': {
10-
fetchAndPush: jest.fn(),
11-
reloadWithSearch: jest.fn(),
12-
handleCreateSubmit: jest.fn(),
13-
isLoading: false,
14-
hasError: false,
15-
hasData: false,
16-
itemCount: 0,
17-
canCreate: true,
18-
sort: {},
19-
webhooks: [],
20-
},
21-
};
63+
const store = createStore((state = {}) => state);
64+
65+
const renderPage = () =>
66+
render(
67+
<Provider store={store}>
68+
<WebhooksIndexPage />
69+
</Provider>
70+
);
2271

2372
describe('WebhooksIndexPage', () => {
24-
describe('redering', () => {
25-
const webhooksPage = () => (
26-
<Provider store={createStore((state = [], action) => state)}>
27-
<WebhooksIndexPage />
28-
</Provider>
29-
);
30-
testComponentSnapshotsWithFixtures(webhooksPage, fixtures);
73+
beforeAll(() => {
74+
spySelector(selectors);
75+
});
76+
77+
beforeEach(() => {
78+
jest.clearAllMocks();
79+
selectors.selectWebhooks.mockImplementation(() => []);
80+
});
81+
82+
it('renders the webhooks header', () => {
83+
renderPage();
84+
85+
expect(
86+
screen.getByRole('heading', { name: 'Webhooks' })
87+
).toBeInTheDocument();
88+
expect(screen.getByTestId('webhooks-table-index')).toBeInTheDocument();
89+
});
90+
91+
it('renders webhook rows from the store', () => {
92+
selectors.selectWebhooks.mockImplementation(() => webhooksFixture);
93+
94+
renderPage();
95+
96+
expect(screen.getByText('my-webhook')).toBeInTheDocument();
97+
expect(screen.getByText('your-webhook')).toBeInTheDocument();
98+
});
99+
100+
it('opens the create modal when Create new is clicked', () => {
101+
renderPage();
102+
103+
expect(
104+
screen.queryByTestId('webhook-create-modal')
105+
).not.toBeInTheDocument();
106+
107+
fireEvent.click(screen.getByRole('button', { name: 'Create new' }));
108+
109+
expect(screen.getByTestId('webhook-create-modal')).toBeInTheDocument();
110+
});
111+
112+
it('closes the create modal when cancel is triggered', () => {
113+
renderPage();
114+
115+
fireEvent.click(screen.getByRole('button', { name: 'Create new' }));
116+
expect(screen.getByTestId('webhook-create-modal')).toBeInTheDocument();
117+
118+
fireEvent.click(screen.getByRole('button', { name: 'Close create modal' }));
119+
120+
expect(
121+
screen.queryByTestId('webhook-create-modal')
122+
).not.toBeInTheDocument();
31123
});
32124
});

webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/__snapshots__/WebhooksIndexPage.test.js.snap

Lines changed: 0 additions & 17 deletions
This file was deleted.

webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/integration.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ describe('WebhooksIndexPage - Integration Test', () => {
2525
</Router>
2626
);
2727

28-
expect(component.exists('WebhooksTable')).toEqual(true);
28+
expect(component.find('[data-testid="table-index-page"]').exists()).toEqual(
29+
true
30+
);
2931
expect(component.exists('WebhookCreateModal')).toEqual(true);
3032
});
3133
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
function MockForemanTableIndexPage({ header, customCreateAction, rows = [] }) {
5+
const onCreate = customCreateAction ? customCreateAction() : undefined;
6+
return (
7+
<div data-testid="webhooks-table-index">
8+
<h1>{header}</h1>
9+
<ul aria-label="webhook-rows">
10+
{rows.map(row => (
11+
<li key={row.id}>{row.name}</li>
12+
))}
13+
</ul>
14+
{onCreate ? (
15+
<button type="button" onClick={onCreate}>
16+
Create new
17+
</button>
18+
) : null}
19+
</div>
20+
);
21+
}
22+
23+
MockForemanTableIndexPage.propTypes = {
24+
header: PropTypes.string,
25+
customCreateAction: PropTypes.func,
26+
rows: PropTypes.arrayOf(PropTypes.object),
27+
};
28+
29+
MockForemanTableIndexPage.defaultProps = {
30+
header: '',
31+
customCreateAction: null,
32+
rows: [],
33+
};
34+
35+
export default MockForemanTableIndexPage;
Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,45 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33

4-
const TableIndexPage = ({ children }) => <div>{children}</div>;
4+
/** Minimal stub — real TableIndexPage uses columns/rows, not always children. */
5+
const TableIndexPage = ({
6+
children = null,
7+
header,
8+
columns,
9+
rows,
10+
controller,
11+
apiUrl,
12+
apiOptions,
13+
customCreateAction,
14+
id,
15+
}) => (
16+
<div data-testid="table-index-page" id={id}>
17+
{header ? <h1>{header}</h1> : null}
18+
{children}
19+
{rows && rows.length > 0 ? (
20+
<ul data-testid="table-index-rows">
21+
{rows.map(row => (
22+
<li key={row.id}>{row.name}</li>
23+
))}
24+
</ul>
25+
) : null}
26+
</div>
27+
);
528

629
TableIndexPage.propTypes = {
7-
children: PropTypes.node.isRequired,
30+
children: PropTypes.node,
31+
header: PropTypes.string,
32+
columns: PropTypes.object,
33+
rows: PropTypes.array,
34+
controller: PropTypes.string,
35+
apiUrl: PropTypes.string,
36+
apiOptions: PropTypes.object,
37+
customCreateAction: PropTypes.func,
38+
id: PropTypes.string,
39+
};
40+
41+
TableIndexPage.defaultProps = {
42+
children: null,
843
};
944

1045
export default TableIndexPage;

0 commit comments

Comments
 (0)