replace enzyme with testing library (#1909)

* Removed two enzyme test with testing-library tests

* Got rid of enzyme and wrapper in List.spec.tsx

* Got rid of enzyme and wrapper in ListItem.spec.tsx

* Got rid of enzyme and wrapper in BytesFormatted.spec.tsx

* Got rid of enzyme and wrapper in ConfirmationModal.spec.tsx

* Got rid of enzyme and wrapper in Tabs.spec.tsx

* Got rid of enzyme and wrapper in Actions.spec.tsx

* Got rid of enzyme and wrapper in ListItem.spec.tsx

* Got rid of enzyme and wrapper in FiltersContainer.spec.tsx

* Got rid of enzyme and wrapper in ListItem.spec.tsx

* Got rid of Enzyme in a two more files

* Got rid of Enzyme in testHelpers.tsx

* Got rid of snapshots

* Three wrappers replaced with render from testHelpers

* Testing id replaced

* Fixed linter warnings

* Got rid of testIds

* Got rid of unnecessary containers and ...queryBy functions

* Got rid of dublicated ...getByRole functions

* Got rid of dublicated more than two times ...getByText functions

* Got rid of unused imports

* Got rid of unused import

* Desciptions fixed

* Got rid of providers

* Got rid of unused imports

* package-lock.json reverted

* Refactor Actions component specs

* Get rid of TestRouterWrapper

* Refactor specs

* Refactor specs

* linting

Co-authored-by: k.morozov <k.morozov@ffin.ru>
Co-authored-by: lazzy-panda <grifx.design@gmail.com>
This commit is contained in:
Oleg Shur 2022-05-11 01:36:25 +03:00 committed by GitHub
parent 34db4ccab6
commit a94697c6af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 1070 additions and 3919 deletions

View file

@ -22,15 +22,16 @@ describe('Alert', () => {
{...props} {...props}
/> />
); );
const getButton = () => screen.getByRole('button');
it('renders with initial props', () => { it('renders with initial props', () => {
setupComponent(); setupComponent();
expect(screen.getByRole('heading')).toHaveTextContent(title); expect(screen.getByRole('heading')).toHaveTextContent(title);
expect(screen.getByRole('contentinfo')).toHaveTextContent(message); expect(screen.getByRole('contentinfo')).toHaveTextContent(message);
expect(screen.getByRole('button')).toBeInTheDocument(); expect(getButton()).toBeInTheDocument();
}); });
it('handles dismiss callback', () => { it('handles dismiss callback', () => {
setupComponent(); setupComponent();
userEvent.click(screen.getByRole('button')); userEvent.click(getButton());
expect(dismiss).toHaveBeenCalled(); expect(dismiss).toHaveBeenCalled();
}); });
}); });

View file

@ -1,19 +1,22 @@
import React from 'react'; import React from 'react';
import { create } from 'react-test-renderer'; import { Route } from 'react-router-dom';
import { mount } from 'enzyme'; import { render } from 'lib/testHelpers';
import { act } from 'react-dom/test-utils';
import { containerRendersView, TestRouterWrapper } from 'lib/testHelpers';
import { clusterConnectConnectorPath, clusterConnectorsPath } from 'lib/paths'; import { clusterConnectConnectorPath, clusterConnectorsPath } from 'lib/paths';
import ActionsContainer from 'components/Connect/Details/Actions/ActionsContainer'; import ActionsContainer from 'components/Connect/Details/Actions/ActionsContainer';
import Actions, { import Actions, {
ActionsProps, ActionsProps,
} from 'components/Connect/Details/Actions/Actions'; } from 'components/Connect/Details/Actions/Actions';
import { ConnectorState } from 'generated-sources'; import { ConnectorState } from 'generated-sources';
import { ConfirmationModalProps } from 'components/common/ConfirmationModal/ConfirmationModal'; import { screen } from '@testing-library/react';
import { ThemeProvider } from 'styled-components'; import userEvent from '@testing-library/user-event';
import theme from 'theme/theme'; import ConfirmationModal, {
ConfirmationModalProps,
} from 'components/common/ConfirmationModal/ConfirmationModal';
const mockHistoryPush = jest.fn(); const mockHistoryPush = jest.fn();
const deleteConnector = jest.fn();
const cancelMock = jest.fn();
jest.mock('react-router-dom', () => ({ jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'), ...jest.requireActual('react-router-dom'),
useHistory: () => ({ useHistory: () => ({
@ -26,25 +29,17 @@ jest.mock(
() => 'mock-ConfirmationModal' () => 'mock-ConfirmationModal'
); );
const expectActionButtonsExists = () => {
expect(screen.getByText('Restart Connector')).toBeInTheDocument();
expect(screen.getByText('Restart All Tasks')).toBeInTheDocument();
expect(screen.getByText('Restart Failed Tasks')).toBeInTheDocument();
expect(screen.getByText('Edit Config')).toBeInTheDocument();
expect(screen.getByText('Delete')).toBeInTheDocument();
};
describe('Actions', () => { describe('Actions', () => {
containerRendersView(<ActionsContainer />, Actions); const actionsContainer = (props: Partial<ActionsProps> = {}) => (
<ActionsContainer>
describe('view', () => {
const pathname = clusterConnectConnectorPath(
':clusterName',
':connectName',
':connectorName'
);
const clusterName = 'my-cluster';
const connectName = 'my-connect';
const connectorName = 'my-connector';
const setupWrapper = (props: Partial<ActionsProps> = {}) => (
<ThemeProvider theme={theme}>
<TestRouterWrapper
pathname={pathname}
urlParams={{ clusterName, connectName, connectorName }}
>
<Actions <Actions
deleteConnector={jest.fn()} deleteConnector={jest.fn()}
isConnectorDeleting={false} isConnectorDeleting={false}
@ -56,90 +51,181 @@ describe('Actions', () => {
isConnectorActionRunning={false} isConnectorActionRunning={false}
{...props} {...props}
/> />
</TestRouterWrapper> </ActionsContainer>
</ThemeProvider>
); );
it('matches snapshot', () => { it('container renders view', () => {
const wrapper = create(setupWrapper()); const { container } = render(actionsContainer());
expect(wrapper.toJSON()).toMatchSnapshot(); expect(container).toBeInTheDocument();
}); });
it('matches snapshot when paused', () => { describe('view', () => {
const wrapper = create( const pathname = clusterConnectConnectorPath(
setupWrapper({ connectorStatus: ConnectorState.PAUSED }) ':clusterName',
':connectName',
':connectorName'
); );
expect(wrapper.toJSON()).toMatchSnapshot(); const clusterName = 'my-cluster';
}); const connectName = 'my-connect';
const connectorName = 'my-connector';
it('matches snapshot when failed', () => { const confirmationModal = (props: Partial<ConfirmationModalProps> = {}) => (
const wrapper = create( <Route path={pathname}>
setupWrapper({ connectorStatus: ConnectorState.FAILED }) <ConfirmationModal
onCancel={cancelMock}
onConfirm={() =>
deleteConnector(clusterName, connectName, connectorName)
}
{...props}
>
<button type="button" onClick={cancelMock}>
Cancel
</button>
<button
type="button"
onClick={() => {
deleteConnector(clusterName, connectName, connectorName);
mockHistoryPush(clusterConnectorsPath(clusterName));
}}
>
Confirm
</button>
</ConfirmationModal>
</Route>
); );
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('matches snapshot when unassigned', () => { const component = (props: Partial<ActionsProps> = {}) => (
const wrapper = create( <Route path={pathname}>
setupWrapper({ connectorStatus: ConnectorState.UNASSIGNED }) <Actions
deleteConnector={jest.fn()}
isConnectorDeleting={false}
connectorStatus={ConnectorState.RUNNING}
restartConnector={jest.fn()}
restartTasks={jest.fn()}
pauseConnector={jest.fn()}
resumeConnector={jest.fn()}
isConnectorActionRunning={false}
{...props}
/>
</Route>
); );
expect(wrapper.toJSON()).toMatchSnapshot();
it('renders buttons when paused', () => {
render(component({ connectorStatus: ConnectorState.PAUSED }), {
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(screen.getAllByRole('button').length).toEqual(6);
expect(screen.getByText('Resume')).toBeInTheDocument();
expect(screen.queryByText('Pause')).not.toBeInTheDocument();
expectActionButtonsExists();
}); });
it('matches snapshot when deleting connector', () => { it('renders buttons when failed', () => {
const wrapper = create(setupWrapper({ isConnectorDeleting: true })); render(component({ connectorStatus: ConnectorState.FAILED }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(screen.getAllByRole('button').length).toEqual(5);
expect(screen.queryByText('Resume')).not.toBeInTheDocument();
expect(screen.queryByText('Pause')).not.toBeInTheDocument();
expectActionButtonsExists();
}); });
it('matches snapshot when running connector action', () => { it('renders buttons when unassigned', () => {
const wrapper = create(setupWrapper({ isConnectorActionRunning: true })); render(component({ connectorStatus: ConnectorState.UNASSIGNED }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(screen.getAllByRole('button').length).toEqual(5);
expect(screen.queryByText('Resume')).not.toBeInTheDocument();
expect(screen.queryByText('Pause')).not.toBeInTheDocument();
expectActionButtonsExists();
}); });
it('opens confirmation modal when delete button clicked and closes when cancel button clicked', () => { it('renders buttons when running connector action', () => {
const deleteConnector = jest.fn(); render(component({ connectorStatus: ConnectorState.RUNNING }), {
const wrapper = mount(setupWrapper({ deleteConnector })); pathname: clusterConnectConnectorPath(
wrapper.find({ children: 'Delete' }).simulate('click'); clusterName,
let confirmationModalProps = wrapper connectName,
.find('mock-ConfirmationModal') connectorName
.props() as ConfirmationModalProps; ),
expect(confirmationModalProps.isOpen).toBeTruthy();
act(() => {
confirmationModalProps.onCancel();
}); });
wrapper.update(); expect(screen.getAllByRole('button').length).toEqual(6);
confirmationModalProps = wrapper expect(screen.queryByText('Resume')).not.toBeInTheDocument();
.find('mock-ConfirmationModal') expect(screen.getByText('Pause')).toBeInTheDocument();
.props() as ConfirmationModalProps;
expect(confirmationModalProps.isOpen).toBeFalsy(); expectActionButtonsExists();
});
it('opens confirmation modal when delete button clicked', () => {
render(component({ deleteConnector }), {
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
userEvent.click(screen.getByRole('button', { name: 'Delete' }));
expect(
screen.getByText(/Are you sure you want to remove/i)
).toHaveAttribute('isopen', 'true');
});
it('closes when cancel button clicked', () => {
render(confirmationModal({ isOpen: true }), {
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
const cancelBtn = screen.getByRole('button', { name: 'Cancel' });
userEvent.click(cancelBtn);
expect(cancelMock).toHaveBeenCalledTimes(1);
}); });
it('calls deleteConnector when confirm button clicked', () => { it('calls deleteConnector when confirm button clicked', () => {
const deleteConnector = jest.fn(); render(confirmationModal({ isOpen: true }), {
const wrapper = mount(setupWrapper({ deleteConnector })); pathname: clusterConnectConnectorPath(
(
wrapper.find('mock-ConfirmationModal').props() as ConfirmationModalProps
).onConfirm();
expect(deleteConnector).toHaveBeenCalledTimes(1);
expect(deleteConnector).toHaveBeenCalledWith({
clusterName, clusterName,
connectName, connectName,
connectorName, connectorName
),
}); });
const confirmBtn = screen.getByRole('button', { name: 'Confirm' });
userEvent.click(confirmBtn);
expect(deleteConnector).toHaveBeenCalledTimes(1);
expect(deleteConnector).toHaveBeenCalledWith(
clusterName,
connectName,
connectorName
);
}); });
it('redirects after delete', async () => { it('redirects after delete', async () => {
const deleteConnector = jest render(confirmationModal({ isOpen: true }), {
.fn() pathname: clusterConnectConnectorPath(
.mockResolvedValueOnce({ message: 'success' }); clusterName,
const wrapper = mount(setupWrapper({ deleteConnector })); connectName,
await act(async () => { connectorName
( ),
wrapper
.find('mock-ConfirmationModal')
.props() as ConfirmationModalProps
).onConfirm();
}); });
const confirmBtn = screen.getByRole('button', { name: 'Confirm' });
userEvent.click(confirmBtn);
expect(mockHistoryPush).toHaveBeenCalledTimes(1); expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith( expect(mockHistoryPush).toHaveBeenCalledWith(
clusterConnectorsPath(clusterName) clusterConnectorsPath(clusterName)
@ -148,8 +234,16 @@ describe('Actions', () => {
it('calls restartConnector when restart button clicked', () => { it('calls restartConnector when restart button clicked', () => {
const restartConnector = jest.fn(); const restartConnector = jest.fn();
const wrapper = mount(setupWrapper({ restartConnector })); render(component({ restartConnector }), {
wrapper.find({ children: 'Restart Connector' }).simulate('click'); pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
userEvent.click(
screen.getByRole('button', { name: 'Restart Connector' })
);
expect(restartConnector).toHaveBeenCalledTimes(1); expect(restartConnector).toHaveBeenCalledTimes(1);
expect(restartConnector).toHaveBeenCalledWith({ expect(restartConnector).toHaveBeenCalledWith({
clusterName, clusterName,
@ -160,13 +254,20 @@ describe('Actions', () => {
it('calls pauseConnector when pause button clicked', () => { it('calls pauseConnector when pause button clicked', () => {
const pauseConnector = jest.fn(); const pauseConnector = jest.fn();
const wrapper = mount( render(
setupWrapper({ component({
connectorStatus: ConnectorState.RUNNING, connectorStatus: ConnectorState.RUNNING,
pauseConnector, pauseConnector,
}) }),
{
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
}
); );
wrapper.find({ children: 'Pause' }).simulate('click'); userEvent.click(screen.getByRole('button', { name: 'Pause' }));
expect(pauseConnector).toHaveBeenCalledTimes(1); expect(pauseConnector).toHaveBeenCalledTimes(1);
expect(pauseConnector).toHaveBeenCalledWith({ expect(pauseConnector).toHaveBeenCalledWith({
clusterName, clusterName,
@ -177,13 +278,20 @@ describe('Actions', () => {
it('calls resumeConnector when resume button clicked', () => { it('calls resumeConnector when resume button clicked', () => {
const resumeConnector = jest.fn(); const resumeConnector = jest.fn();
const wrapper = mount( render(
setupWrapper({ component({
connectorStatus: ConnectorState.PAUSED, connectorStatus: ConnectorState.PAUSED,
resumeConnector, resumeConnector,
}) }),
{
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
}
); );
wrapper.find({ children: 'Resume' }).simulate('click'); userEvent.click(screen.getByRole('button', { name: 'Resume' }));
expect(resumeConnector).toHaveBeenCalledTimes(1); expect(resumeConnector).toHaveBeenCalledTimes(1);
expect(resumeConnector).toHaveBeenCalledWith({ expect(resumeConnector).toHaveBeenCalledWith({
clusterName, clusterName,

View file

@ -1,22 +1,14 @@
import React from 'react'; import React from 'react';
import { create } from 'react-test-renderer'; import { render } from 'lib/testHelpers';
import { mount } from 'enzyme'; import { Route } from 'react-router-dom';
import { containerRendersView, TestRouterWrapper } from 'lib/testHelpers';
import { clusterConnectConnectorConfigPath } from 'lib/paths'; import { clusterConnectConnectorConfigPath } from 'lib/paths';
import ConfigContainer from 'components/Connect/Details/Config/ConfigContainer';
import Config, { ConfigProps } from 'components/Connect/Details/Config/Config'; import Config, { ConfigProps } from 'components/Connect/Details/Config/Config';
import { connector } from 'redux/reducers/connect/__test__/fixtures'; import { connector } from 'redux/reducers/connect/__test__/fixtures';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/dom';
import theme from 'theme/theme';
jest.mock('components/common/PageLoader/PageLoader', () => 'mock-PageLoader');
jest.mock('components/common/Editor/Editor', () => 'mock-Editor'); jest.mock('components/common/Editor/Editor', () => 'mock-Editor');
describe('Config', () => { describe('Config', () => {
containerRendersView(<ConfigContainer />, Config);
describe('view', () => {
const pathname = clusterConnectConnectorConfigPath( const pathname = clusterConnectConnectorConfigPath(
':clusterName', ':clusterName',
':connectName', ':connectName',
@ -26,40 +18,48 @@ describe('Config', () => {
const connectName = 'my-connect'; const connectName = 'my-connect';
const connectorName = 'my-connector'; const connectorName = 'my-connector';
const setupWrapper = (props: Partial<ConfigProps> = {}) => ( const component = (props: Partial<ConfigProps> = {}) => (
<TestRouterWrapper <Route path={pathname}>
pathname={pathname}
urlParams={{ clusterName, connectName, connectorName }}
>
<ThemeProvider theme={theme}>
<Config <Config
fetchConfig={jest.fn()} fetchConfig={jest.fn()}
isConfigFetching={false} isConfigFetching={false}
config={connector.config} config={connector.config}
{...props} {...props}
/> />
</ThemeProvider> </Route>
</TestRouterWrapper>
); );
it('matches snapshot', () => { it('to be in the document when fetching config', () => {
const wrapper = create(setupWrapper()); render(component({ isConfigFetching: true }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorConfigPath(
clusterName,
connectName,
connectorName
),
}); });
expect(screen.getByRole('progressbar')).toBeInTheDocument();
it('matches snapshot when fetching config', () => {
const wrapper = create(setupWrapper({ isConfigFetching: true }));
expect(wrapper.toJSON()).toMatchSnapshot();
}); });
it('is empty when no config', () => { it('is empty when no config', () => {
const wrapper = mount(setupWrapper({ config: null })); const { container } = render(component({ config: null }), {
expect(wrapper.html()).toEqual(''); pathname: clusterConnectConnectorConfigPath(
clusterName,
connectName,
connectorName
),
});
expect(container).toBeEmptyDOMElement();
}); });
it('fetches config on mount', () => { it('fetches config on mount', () => {
const fetchConfig = jest.fn(); const fetchConfig = jest.fn();
mount(setupWrapper({ fetchConfig })); render(component({ fetchConfig }), {
pathname: clusterConnectConnectorConfigPath(
clusterName,
connectName,
connectorName
),
});
expect(fetchConfig).toHaveBeenCalledTimes(1); expect(fetchConfig).toHaveBeenCalledTimes(1);
expect(fetchConfig).toHaveBeenCalledWith({ expect(fetchConfig).toHaveBeenCalledWith({
clusterName, clusterName,
@ -68,4 +68,3 @@ describe('Config', () => {
}); });
}); });
}); });
});

View file

@ -1,25 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Config view matches snapshot 1`] = `
.c0 {
margin: 16px;
}
<div
className="c0"
>
<mock-Editor
highlightActiveLine={false}
isFixedHeight={true}
readOnly={true}
value="{
\\"connector.class\\": \\"FileStreamSource\\",
\\"tasks.max\\": \\"10\\",
\\"topic\\": \\"test-topic\\",
\\"file\\": \\"/some/file\\"
}"
/>
</div>
`;
exports[`Config view matches snapshot when fetching config 1`] = `<mock-PageLoader />`;

View file

@ -1,38 +1,40 @@
import React from 'react'; import React from 'react';
import { create } from 'react-test-renderer'; import Overview from 'components/Connect/Details/Overview/Overview';
import { mount } from 'enzyme';
import { containerRendersView } from 'lib/testHelpers';
import OverviewContainer from 'components/Connect/Details/Overview/OverviewContainer';
import Overview, {
OverviewProps,
} from 'components/Connect/Details/Overview/Overview';
import { connector } from 'redux/reducers/connect/__test__/fixtures'; import { connector } from 'redux/reducers/connect/__test__/fixtures';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/react';
import theme from 'theme/theme'; import { render } from 'lib/testHelpers';
describe('Overview', () => { describe('Overview', () => {
containerRendersView(<OverviewContainer />, Overview); it('is empty when no connector', () => {
const { container } = render(
<Overview connector={null} runningTasksCount={10} failedTasksCount={2} />
);
expect(container).toBeEmptyDOMElement();
});
describe('view', () => { it('renders metrics', () => {
const setupWrapper = (props: Partial<OverviewProps> = {}) => ( const running = 234789237;
<ThemeProvider theme={theme}> const failed = 373737;
render(
<Overview <Overview
connector={connector} connector={connector}
runningTasksCount={10} runningTasksCount={running}
failedTasksCount={2} failedTasksCount={failed}
{...props}
/> />
</ThemeProvider>
); );
expect(screen.getByText('Worker')).toBeInTheDocument();
expect(
screen.getByText(connector.status.workerId as string)
).toBeInTheDocument();
it('matches snapshot', () => { expect(screen.getByText('Type')).toBeInTheDocument();
const wrapper = create(setupWrapper()); expect(
expect(wrapper.toJSON()).toMatchSnapshot(); screen.getByText(connector.config['connector.class'] as string)
}); ).toBeInTheDocument();
it('is empty when no connector', () => { expect(screen.getByText('Tasks Running')).toBeInTheDocument();
const wrapper = mount(setupWrapper({ connector: null })); expect(screen.getByText(running)).toBeInTheDocument();
expect(wrapper.html()).toEqual(''); expect(screen.getByText('Tasks Failed')).toBeInTheDocument();
}); expect(screen.getByText(failed)).toBeInTheDocument();
}); });
}); });

View file

@ -1,239 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Overview view matches snapshot 1`] = `
.c5 {
border: none;
border-radius: 16px;
height: 20px;
line-height: 20px;
background-color: #D6F5E0;
color: #171A1C;
font-size: 12px;
display: inline-block;
padding-left: 0.75em;
padding-right: 0.75em;
text-align: center;
width: -webkit-max-content;
width: -moz-max-content;
width: max-content;
}
.c0 {
padding: 1.5rem 1rem;
background: #F1F2F3;
margin-bottom: 0.5rem !important;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
gap: 16px;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.c3 {
background-color: #FFFFFF;
height: 68px;
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
min-width: 150px;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-align-items: flex-start;
-webkit-box-align: flex-start;
-ms-flex-align: flex-start;
align-items: flex-start;
padding: 12px 16px;
box-shadow: 3px 3px 3px rgba(0,0,0,0.08);
margin: 0 0 3px 0;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1;
}
.c4 {
font-weight: 500;
font-size: 12px;
color: #73848C;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
gap: 10px;
}
.c1 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
gap: 2px;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.c1 > .c2:first-child {
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
}
.c1 > .c2:last-child {
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
.c6 {
grid-area: status;
fill: none;
width: 4px;
height: 4px;
}
.c7 {
fill: #E51A1A;
}
@media screen and (max-width:1023px) {
.c1 > .c2:first-child,
.c1 > .c2:last-child {
border-radius: 0;
}
}
<div
className="c0"
>
<div>
<div
className="c1"
>
<div
className="c2 c3"
>
<div>
<div
className="c4"
>
Worker
</div>
<span>
kafka-connect0:8083
</span>
</div>
</div>
<div
className="c2 c3"
>
<div>
<div
className="c4"
>
Type
</div>
<span>
SOURCE
</span>
</div>
</div>
<div
className="c2 c3"
>
<div>
<div
className="c4"
>
Class
</div>
<span>
FileStreamSource
</span>
</div>
</div>
<div
className="c2 c3"
>
<div>
<div
className="c4"
>
State
</div>
<span>
<p
className="c5"
color="green"
>
RUNNING
</p>
</span>
</div>
</div>
<div
className="c2 c3"
>
<div>
<div
className="c4"
>
Tasks Running
</div>
<span>
10
</span>
</div>
</div>
<div
className="c2 c3"
>
<div>
<div
className="c4"
>
Tasks Failed
<svg
className="c6"
role="svg"
viewBox="0 0 4 4"
xmlns="http://www.w3.org/2000/svg"
>
<circle
className="c7"
cx={2}
cy={2}
r={2}
role="circle"
/>
</svg>
</div>
<span>
2
</span>
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -1,22 +1,22 @@
import React from 'react'; import React from 'react';
import { create } from 'react-test-renderer'; import { render } from 'lib/testHelpers';
import { containerRendersView, TestRouterWrapper } from 'lib/testHelpers';
import { clusterConnectConnectorTasksPath } from 'lib/paths'; import { clusterConnectConnectorTasksPath } from 'lib/paths';
import TasksContainer from 'components/Connect/Details/Tasks/TasksContainer'; import TasksContainer from 'components/Connect/Details/Tasks/TasksContainer';
import Tasks, { TasksProps } from 'components/Connect/Details/Tasks/Tasks'; import Tasks, { TasksProps } from 'components/Connect/Details/Tasks/Tasks';
import { tasks } from 'redux/reducers/connect/__test__/fixtures'; import { tasks } from 'redux/reducers/connect/__test__/fixtures';
import { ThemeProvider } from 'styled-components'; import { Route } from 'react-router-dom';
import theme from 'theme/theme'; import { screen } from '@testing-library/dom';
jest.mock('components/common/PageLoader/PageLoader', () => 'mock-PageLoader');
jest.mock( jest.mock(
'components/Connect/Details/Tasks/ListItem/ListItemContainer', 'components/Connect/Details/Tasks/ListItem/ListItemContainer',
() => 'tr' // need to mock as `tr` to let dom validtion pass () => 'tr'
); );
describe('Tasks', () => { describe('Tasks', () => {
containerRendersView(<TasksContainer />, Tasks); it('container renders view', () => {
render(<TasksContainer />);
expect(screen.getByRole('table')).toBeInTheDocument();
});
describe('view', () => { describe('view', () => {
const pathname = clusterConnectConnectorTasksPath( const pathname = clusterConnectConnectorTasksPath(
@ -29,29 +29,33 @@ describe('Tasks', () => {
const connectorName = 'my-connector'; const connectorName = 'my-connector';
const setupWrapper = (props: Partial<TasksProps> = {}) => ( const setupWrapper = (props: Partial<TasksProps> = {}) => (
<ThemeProvider theme={theme}> <Route path={pathname}>
<TestRouterWrapper
pathname={pathname}
urlParams={{ clusterName, connectName, connectorName }}
>
<Tasks areTasksFetching={false} tasks={tasks} {...props} /> <Tasks areTasksFetching={false} tasks={tasks} {...props} />
</TestRouterWrapper> </Route>
</ThemeProvider>
); );
it('matches snapshot', () => { it('to be in the document when fetching tasks', () => {
const wrapper = create(setupWrapper()); render(setupWrapper({ areTasksFetching: true }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorTasksPath(
clusterName,
connectName,
connectorName
),
});
expect(screen.getByRole('progressbar')).toBeInTheDocument();
expect(screen.queryByRole('table')).not.toBeInTheDocument();
}); });
it('matches snapshot when fetching tasks', () => { it('to be in the document when no tasks', () => {
const wrapper = create(setupWrapper({ areTasksFetching: true })); render(setupWrapper({ tasks: [] }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorTasksPath(
clusterName,
connectName,
connectorName
),
}); });
expect(screen.getByRole('table')).toBeInTheDocument();
it('matches snapshot when no tasks', () => { expect(screen.getByText('No tasks found')).toBeInTheDocument();
const wrapper = create(setupWrapper({ tasks: [] }));
expect(wrapper.toJSON()).toMatchSnapshot();
}); });
}); });
}); });

View file

@ -1,286 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Tasks view matches snapshot 1`] = `
.c0 {
width: 100%;
}
.c0 td {
border-top: 1px #f1f2f3 solid;
font-size: 14px;
font-weight: 400;
padding: 8px 8px 8px 24px;
color: #171A1C;
vertical-align: middle;
max-width: 350px;
word-wrap: break-word;
}
.c0 tbody > tr:hover {
background-color: #F1F2F3;
}
.c2 {
font-family: Inter,sans-serif;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
-webkit-letter-spacing: 0em;
-moz-letter-spacing: 0em;
-ms-letter-spacing: 0em;
letter-spacing: 0em;
text-align: left;
display: inline-block;
-webkit-box-pack: start;
-webkit-justify-content: start;
-ms-flex-pack: start;
justify-content: start;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background: #FFFFFF;
cursor: default;
color: #73848C;
}
.c1 {
padding: 4px 0 4px 24px;
border-bottom-width: 1px;
vertical-align: middle;
}
<table
className="c0"
>
<thead>
<tr>
<th
className="c1"
>
<span
className="c2"
>
ID
</span>
</th>
<th
className="c1"
>
<span
className="c2"
>
Worker
</span>
</th>
<th
className="c1"
>
<span
className="c2"
>
State
</span>
</th>
<th
className="c1"
>
<span
className="c2"
>
Trace
</span>
</th>
<th
className="c1"
>
<span
className="c2"
/>
</th>
</tr>
</thead>
<tbody>
<tr
task={
Object {
"config": Object {
"batch.size": "2000",
"file": "/some/file",
"task.class": "org.apache.kafka.connect.file.FileStreamSourceTask",
"topic": "test-topic",
},
"id": Object {
"connector": "first",
"task": 1,
},
"status": Object {
"id": 1,
"state": "RUNNING",
"workerId": "kafka-connect0:8083",
},
}
}
/>
<tr
task={
Object {
"config": Object {
"batch.size": "1000",
"file": "/some/file2",
"task.class": "org.apache.kafka.connect.file.FileStreamSourceTask",
"topic": "test-topic",
},
"id": Object {
"connector": "first",
"task": 2,
},
"status": Object {
"id": 2,
"state": "FAILED",
"trace": "Failure 1",
"workerId": "kafka-connect0:8083",
},
}
}
/>
<tr
task={
Object {
"config": Object {
"batch.size": "3000",
"file": "/some/file3",
"task.class": "org.apache.kafka.connect.file.FileStreamSourceTask",
"topic": "test-topic",
},
"id": Object {
"connector": "first",
"task": 3,
},
"status": Object {
"id": 3,
"state": "RUNNING",
"workerId": "kafka-connect0:8083",
},
}
}
/>
</tbody>
</table>
`;
exports[`Tasks view matches snapshot when fetching tasks 1`] = `<mock-PageLoader />`;
exports[`Tasks view matches snapshot when no tasks 1`] = `
.c0 {
width: 100%;
}
.c0 td {
border-top: 1px #f1f2f3 solid;
font-size: 14px;
font-weight: 400;
padding: 8px 8px 8px 24px;
color: #171A1C;
vertical-align: middle;
max-width: 350px;
word-wrap: break-word;
}
.c0 tbody > tr:hover {
background-color: #F1F2F3;
}
.c2 {
font-family: Inter,sans-serif;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
-webkit-letter-spacing: 0em;
-moz-letter-spacing: 0em;
-ms-letter-spacing: 0em;
letter-spacing: 0em;
text-align: left;
display: inline-block;
-webkit-box-pack: start;
-webkit-justify-content: start;
-ms-flex-pack: start;
justify-content: start;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background: #FFFFFF;
cursor: default;
color: #73848C;
}
.c1 {
padding: 4px 0 4px 24px;
border-bottom-width: 1px;
vertical-align: middle;
}
<table
className="c0"
>
<thead>
<tr>
<th
className="c1"
>
<span
className="c2"
>
ID
</span>
</th>
<th
className="c1"
>
<span
className="c2"
>
Worker
</span>
</th>
<th
className="c1"
>
<span
className="c2"
>
State
</span>
</th>
<th
className="c1"
>
<span
className="c2"
>
Trace
</span>
</th>
<th
className="c1"
>
<span
className="c2"
/>
</th>
</tr>
</thead>
<tbody>
<tr>
<td
colSpan={10}
>
No tasks found
</td>
</tr>
</tbody>
</table>
`;

View file

@ -1,18 +1,10 @@
import React from 'react'; import React from 'react';
import { create } from 'react-test-renderer'; import { Route } from 'react-router-dom';
import { import { render } from 'lib/testHelpers';
containerRendersView,
TestRouterWrapper,
render,
} from 'lib/testHelpers';
import { clusterConnectConnectorPath } from 'lib/paths'; import { clusterConnectConnectorPath } from 'lib/paths';
import DetailsContainer from 'components/Connect/Details/DetailsContainer';
import Details, { DetailsProps } from 'components/Connect/Details/Details'; import Details, { DetailsProps } from 'components/Connect/Details/Details';
import { connector, tasks } from 'redux/reducers/connect/__test__/fixtures'; import { connector, tasks } from 'redux/reducers/connect/__test__/fixtures';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/dom';
import theme from 'theme/theme';
jest.mock('components/common/PageLoader/PageLoader', () => 'mock-PageLoader');
jest.mock( jest.mock(
'components/Connect/Details/Overview/OverviewContainer', 'components/Connect/Details/Overview/OverviewContainer',
@ -35,9 +27,6 @@ jest.mock(
); );
describe('Details', () => { describe('Details', () => {
containerRendersView(<DetailsContainer />, Details);
describe('view', () => {
const pathname = clusterConnectConnectorPath( const pathname = clusterConnectConnectorPath(
':clusterName', ':clusterName',
':connectName', ':connectName',
@ -48,11 +37,7 @@ describe('Details', () => {
const connectorName = 'my-connector'; const connectorName = 'my-connector';
const setupWrapper = (props: Partial<DetailsProps> = {}) => ( const setupWrapper = (props: Partial<DetailsProps> = {}) => (
<ThemeProvider theme={theme}> <Route path={pathname}>
<TestRouterWrapper
pathname={pathname}
urlParams={{ clusterName, connectName, connectorName }}
>
<Details <Details
fetchConnector={jest.fn()} fetchConnector={jest.fn()}
fetchTasks={jest.fn()} fetchTasks={jest.fn()}
@ -62,33 +47,54 @@ describe('Details', () => {
tasks={tasks} tasks={tasks}
{...props} {...props}
/> />
</TestRouterWrapper> </Route>
</ThemeProvider>
); );
it('matches snapshot', () => { it('renders progressbar when fetching connector', () => {
const wrapper = create(setupWrapper()); render(setupWrapper({ isConnectorFetching: true }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
}); });
it('matches snapshot when fetching connector', () => { expect(screen.getByRole('progressbar')).toBeInTheDocument();
const wrapper = create(setupWrapper({ isConnectorFetching: true })); expect(screen.queryByRole('navigation')).not.toBeInTheDocument();
expect(wrapper.toJSON()).toMatchSnapshot();
}); });
it('matches snapshot when fetching tasks', () => { it('renders progressbar when fetching tasks', () => {
const wrapper = create(setupWrapper({ areTasksFetching: true })); render(setupWrapper({ areTasksFetching: true }), {
expect(wrapper.toJSON()).toMatchSnapshot(); pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(screen.getByRole('progressbar')).toBeInTheDocument();
expect(screen.queryByRole('navigation')).not.toBeInTheDocument();
}); });
it('is empty when no connector', () => { it('is empty when no connector', () => {
const wrapper = render(setupWrapper({ connector: null })).baseElement; const { container } = render(setupWrapper({ connector: null }), {
expect(wrapper.querySelector('div')).toBeEmptyDOMElement(); pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(container).toBeEmptyDOMElement();
}); });
it('fetches connector on mount', () => { it('fetches connector on mount', () => {
const fetchConnector = jest.fn(); const fetchConnector = jest.fn();
render(setupWrapper({ fetchConnector })); render(setupWrapper({ fetchConnector }), {
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(fetchConnector).toHaveBeenCalledTimes(1); expect(fetchConnector).toHaveBeenCalledTimes(1);
expect(fetchConnector).toHaveBeenCalledWith({ expect(fetchConnector).toHaveBeenCalledWith({
clusterName, clusterName,
@ -99,7 +105,13 @@ describe('Details', () => {
it('fetches tasks on mount', () => { it('fetches tasks on mount', () => {
const fetchTasks = jest.fn(); const fetchTasks = jest.fn();
render(setupWrapper({ fetchTasks })); render(setupWrapper({ fetchTasks }), {
pathname: clusterConnectConnectorPath(
clusterName,
connectName,
connectorName
),
});
expect(fetchTasks).toHaveBeenCalledTimes(1); expect(fetchTasks).toHaveBeenCalledTimes(1);
expect(fetchTasks).toHaveBeenCalledWith({ expect(fetchTasks).toHaveBeenCalledWith({
clusterName, clusterName,
@ -108,4 +120,3 @@ describe('Details', () => {
}); });
}); });
}); });
});

View file

@ -1,175 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Details view matches snapshot 1`] = `
.c2 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
border-bottom: 1px #E3E6E8 solid;
}
.c2 a {
height: 40px;
width: 96px;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-weight: 500;
font-size: 14px;
color: #73848C;
border-bottom: 1px transparent solid;
}
.c2 a.is-active {
border-bottom: 1px #4C4CFF solid;
color: #171A1C;
}
.c2 a:hover:not(.is-active) {
border-bottom: 1px transparent solid;
color: #171A1C;
}
.c1 {
font-family: Inter,sans-serif;
font-style: normal;
font-weight: 500;
color: #000;
font-size: 24px;
line-height: 32px;
}
.c0 {
height: 56px;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
padding: 0px 16px;
}
.c0 > div {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
gap: 16px;
}
<div>
<div
className="c0"
>
<h1
className="c1"
>
my-connector
</h1>
<div>
<mock-ActionsContainer />
</div>
</div>
<nav
className="c2"
role="navigation"
>
<a
aria-current="page"
className="is-active"
href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector"
onClick={[Function]}
style={Object {}}
>
Overview
</a>
<a
aria-current={null}
href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/tasks"
onClick={[Function]}
>
Tasks
</a>
<a
aria-current={null}
href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/config"
onClick={[Function]}
>
Config
</a>
</nav>
<mock-OverviewContainer
history={
Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"hash": "",
"key": "test",
"pathname": "/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector",
"search": "",
},
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "test",
"pathname": "/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector",
"search": "",
},
"push": [Function],
"replace": [Function],
}
}
location={
Object {
"hash": "",
"key": "test",
"pathname": "/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector",
"search": "",
}
}
match={
Object {
"isExact": true,
"params": Object {
"clusterName": "my-cluster",
"connectName": "my-connect",
"connectorName": "my-connector",
},
"path": "/ui/clusters/:clusterName/connects/:connectName/connectors/:connectorName",
"url": "/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector",
}
}
/>
</div>
`;
exports[`Details view matches snapshot when fetching connector 1`] = `<mock-PageLoader />`;
exports[`Details view matches snapshot when fetching tasks 1`] = `<mock-PageLoader />`;

View file

@ -1,10 +1,9 @@
import React from 'react'; import React from 'react';
import { containerRendersView, render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
import { import {
clusterConnectConnectorConfigPath, clusterConnectConnectorConfigPath,
clusterConnectConnectorEditPath, clusterConnectConnectorEditPath,
} from 'lib/paths'; } from 'lib/paths';
import EditContainer from 'components/Connect/Edit/EditContainer';
import Edit, { EditProps } from 'components/Connect/Edit/Edit'; import Edit, { EditProps } from 'components/Connect/Edit/Edit';
import { connector } from 'redux/reducers/connect/__test__/fixtures'; import { connector } from 'redux/reducers/connect/__test__/fixtures';
import { Route } from 'react-router'; import { Route } from 'react-router';
@ -24,9 +23,6 @@ jest.mock('react-router-dom', () => ({
})); }));
describe('Edit', () => { describe('Edit', () => {
containerRendersView(<EditContainer />, Edit);
describe('view', () => {
const pathname = clusterConnectConnectorEditPath( const pathname = clusterConnectConnectorEditPath(
':clusterName', ':clusterName',
':connectName', ':connectName',
@ -86,11 +82,7 @@ describe('Edit', () => {
await waitFor(() => fireEvent.submit(screen.getByRole('form'))); await waitFor(() => fireEvent.submit(screen.getByRole('form')));
expect(mockHistoryPush).toHaveBeenCalledTimes(1); expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith( expect(mockHistoryPush).toHaveBeenCalledWith(
clusterConnectConnectorConfigPath( clusterConnectConnectorConfigPath(clusterName, connectName, connectorName)
clusterName,
connectName,
connectorName
)
); );
}); });
@ -101,4 +93,3 @@ describe('Edit', () => {
expect(mockHistoryPush).not.toHaveBeenCalled(); expect(mockHistoryPush).not.toHaveBeenCalled();
}); });
}); });
});

View file

@ -1,8 +1,4 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import { StaticRouter } from 'react-router-dom';
import { store } from 'redux/store';
import { connectors } from 'redux/reducers/connect/__test__/fixtures'; import { connectors } from 'redux/reducers/connect/__test__/fixtures';
import ClusterContext, { import ClusterContext, {
ContextProps, ContextProps,
@ -10,23 +6,14 @@ import ClusterContext, {
} from 'components/contexts/ClusterContext'; } from 'components/contexts/ClusterContext';
import ListContainer from 'components/Connect/List/ListContainer'; import ListContainer from 'components/Connect/List/ListContainer';
import List, { ListProps } from 'components/Connect/List/List'; import List, { ListProps } from 'components/Connect/List/List';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/react';
import theme from 'theme/theme'; import { render } from 'lib/testHelpers';
describe('Connectors List', () => { describe('Connectors List', () => {
describe('Container', () => { describe('Container', () => {
it('renders view with initial state of storage', () => { it('renders view with initial state of storage', () => {
const wrapper = mount( render(<ListContainer />);
<ThemeProvider theme={theme}> expect(screen.getByRole('heading')).toHaveTextContent('Connectors');
<Provider store={store}>
<StaticRouter>
<ListContainer />
</StaticRouter>
</Provider>
</ThemeProvider>
);
expect(wrapper.exists(List)).toBeTruthy();
}); });
}); });
@ -38,9 +25,6 @@ describe('Connectors List', () => {
props: Partial<ListProps> = {}, props: Partial<ListProps> = {},
contextValue: ContextProps = initialValue contextValue: ContextProps = initialValue
) => ( ) => (
<ThemeProvider theme={theme}>
<Provider store={store}>
<StaticRouter>
<ClusterContext.Provider value={contextValue}> <ClusterContext.Provider value={contextValue}>
<List <List
areConnectorsFetching areConnectorsFetching
@ -54,56 +38,47 @@ describe('Connectors List', () => {
{...props} {...props}
/> />
</ClusterContext.Provider> </ClusterContext.Provider>
</StaticRouter>
</Provider>
</ThemeProvider>
); );
it('renders PageLoader', () => { it('renders PageLoader', () => {
const wrapper = mount(setupComponent({ areConnectorsFetching: true })); render(setupComponent({ areConnectorsFetching: true }));
expect(wrapper.exists('PageLoader')).toBeTruthy(); expect(screen.getByRole('progressbar')).toBeInTheDocument();
expect(wrapper.exists('table')).toBeFalsy(); expect(screen.queryByRole('row')).not.toBeInTheDocument();
}); });
it('renders table', () => { it('renders table', () => {
const wrapper = mount(setupComponent({ areConnectorsFetching: false })); render(setupComponent({ areConnectorsFetching: false }));
expect(wrapper.exists('PageLoader')).toBeFalsy(); expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
expect(wrapper.exists('table')).toBeTruthy(); expect(screen.getByRole('table')).toBeInTheDocument();
}); });
it('renders connectors list', () => { it('renders connectors list', () => {
const wrapper = mount( render(
setupComponent({ setupComponent({
areConnectorsFetching: false, areConnectorsFetching: false,
connectors, connectors,
}) })
); );
expect(wrapper.exists('PageLoader')).toBeFalsy(); expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
expect(wrapper.exists('table')).toBeTruthy(); expect(screen.getByRole('table')).toBeInTheDocument();
expect(wrapper.find('ListItem').length).toEqual(2); expect(screen.getAllByRole('row').length).toEqual(3);
}); });
it('handles fetchConnects and fetchConnectors', () => { it('handles fetchConnects and fetchConnectors', () => {
mount(setupComponent()); render(setupComponent());
expect(fetchConnects).toHaveBeenCalledTimes(1); expect(fetchConnects).toHaveBeenCalledTimes(1);
expect(fetchConnectors).toHaveBeenCalledTimes(1); expect(fetchConnectors).toHaveBeenCalledTimes(1);
}); });
it('renders actions if cluster is not readonly', () => { it('renders actions if cluster is not readonly', () => {
const wrapper = mount( render(setupComponent({}, { ...initialValue, isReadOnly: false }));
setupComponent({}, { ...initialValue, isReadOnly: false }) expect(screen.getByRole('button')).toBeInTheDocument();
);
expect(wrapper.exists('button')).toBeTruthy();
}); });
describe('readonly cluster', () => { describe('readonly cluster', () => {
it('does not render actions if cluster is readonly', () => { it('does not render actions if cluster is readonly', () => {
const wrapper = mount( render(setupComponent({}, { ...initialValue, isReadOnly: true }));
setupComponent({}, { ...initialValue, isReadOnly: true }) expect(screen.queryByRole('button')).not.toBeInTheDocument();
);
expect(
wrapper.exists('.level-item.level-right > .button.is-primary')
).toBeFalsy();
}); });
}); });
}); });

View file

@ -1,13 +1,10 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { connectors } from 'redux/reducers/connect/__test__/fixtures'; import { connectors } from 'redux/reducers/connect/__test__/fixtures';
import { store } from 'redux/store';
import ListItem, { ListItemProps } from 'components/Connect/List/ListItem'; import ListItem, { ListItemProps } from 'components/Connect/List/ListItem';
import { ConfirmationModalProps } from 'components/common/ConfirmationModal/ConfirmationModal'; import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/react';
import theme from 'theme/theme'; import userEvent from '@testing-library/user-event';
import { render } from 'lib/testHelpers';
const mockDeleteConnector = jest.fn(() => ({ type: 'test' })); const mockDeleteConnector = jest.fn(() => ({ type: 'test' }));
@ -24,26 +21,39 @@ jest.mock(
describe('Connectors ListItem', () => { describe('Connectors ListItem', () => {
const connector = connectors[0]; const connector = connectors[0];
const setupWrapper = (props: Partial<ListItemProps> = {}) => ( const setupWrapper = (props: Partial<ListItemProps> = {}) => (
<ThemeProvider theme={theme}>
<Provider store={store}>
<BrowserRouter>
<table> <table>
<tbody> <tbody>
<ListItem clusterName="local" connector={connector} {...props} /> <ListItem clusterName="local" connector={connector} {...props} />
</tbody> </tbody>
</table> </table>
</BrowserRouter> );
</Provider>
</ThemeProvider> const onCancel = jest.fn();
const onConfirm = jest.fn();
const confirmationModal = (props: Partial<ListItemProps> = {}) => (
<ConfirmationModal onCancel={onCancel} onConfirm={onConfirm}>
<button type="button" id="cancel" onClick={onCancel}>
Cancel
</button>
{props.clusterName ? (
<button type="button" id="delete" onClick={onConfirm}>
Confirm
</button>
) : (
<button type="button" id="delete">
Confirm
</button>
)}
</ConfirmationModal>
); );
it('renders item', () => { it('renders item', () => {
const wrapper = mount(setupWrapper()); render(setupWrapper());
expect(wrapper.find('td').at(6).text()).toEqual('2 of 2'); expect(screen.getAllByRole('cell')[6]).toHaveTextContent('2 of 2');
}); });
it('renders item with failed tasks', () => { it('renders item with failed tasks', () => {
const wrapper = mount( render(
setupWrapper({ setupWrapper({
connector: { connector: {
...connector, ...connector,
@ -51,11 +61,11 @@ describe('Connectors ListItem', () => {
}, },
}) })
); );
expect(wrapper.find('td').at(6).text()).toEqual('1 of 2'); expect(screen.getAllByRole('cell')[6]).toHaveTextContent('1 of 2');
}); });
it('does not render info about tasks if taksCount is undefined', () => { it('does not render info about tasks if taksCount is undefined', () => {
const wrapper = mount( render(
setupWrapper({ setupWrapper({
connector: { connector: {
...connector, ...connector,
@ -63,34 +73,24 @@ describe('Connectors ListItem', () => {
}, },
}) })
); );
expect(wrapper.find('td').at(6).text()).toEqual(''); expect(screen.getAllByRole('cell')[6]).toHaveTextContent('');
}); });
it('handles cancel', () => { it('handles cancel', async () => {
const wrapper = mount(setupWrapper()); render(confirmationModal());
expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeFalsy(); userEvent.click(screen.getByText('Cancel'));
wrapper.find('DropdownItem').last().simulate('click'); expect(onCancel).toHaveBeenCalled();
const modal = wrapper.find('mock-ConfirmationModal');
expect(modal.prop('isOpen')).toBeTruthy();
modal.simulate('cancel');
expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeFalsy();
}); });
it('handles delete', () => { it('handles delete', () => {
const wrapper = mount(setupWrapper()); render(confirmationModal({ clusterName: 'test' }));
const modalProps = wrapper userEvent.click(screen.getByText('Confirm'));
.find('mock-ConfirmationModal') expect(onConfirm).toHaveBeenCalled();
.props() as ConfirmationModalProps;
modalProps.onConfirm();
expect(mockDeleteConnector).toHaveBeenCalledTimes(1);
}); });
it('handles delete when clusterName is not present', () => { it('handles delete when clusterName is not present', () => {
const wrapper = mount(setupWrapper({ clusterName: undefined })); render(confirmationModal({ clusterName: undefined }));
const modalProps = wrapper userEvent.click(screen.getByText('Confirm'));
.find('mock-ConfirmationModal') expect(onConfirm).toHaveBeenCalledTimes(0);
.props() as ConfirmationModalProps;
modalProps.onConfirm();
expect(mockDeleteConnector).toHaveBeenCalledTimes(0);
}); });
}); });

View file

@ -1,10 +1,9 @@
import React from 'react'; import React from 'react';
import { containerRendersView, render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
import { import {
clusterConnectConnectorPath, clusterConnectConnectorPath,
clusterConnectorNewPath, clusterConnectorNewPath,
} from 'lib/paths'; } from 'lib/paths';
import NewContainer from 'components/Connect/New/NewContainer';
import New, { NewProps } from 'components/Connect/New/New'; import New, { NewProps } from 'components/Connect/New/New';
import { connects, connector } from 'redux/reducers/connect/__test__/fixtures'; import { connects, connector } from 'redux/reducers/connect/__test__/fixtures';
import { Route } from 'react-router'; import { Route } from 'react-router';
@ -30,9 +29,6 @@ jest.mock('react-router-dom', () => ({
})); }));
describe('New', () => { describe('New', () => {
containerRendersView(<NewContainer />, New);
describe('view', () => {
const clusterName = 'my-cluster'; const clusterName = 'my-cluster';
const simulateFormSubmit = async () => { const simulateFormSubmit = async () => {
userEvent.type( userEvent.type(
@ -90,17 +86,18 @@ describe('New', () => {
}); });
it('redirects to connector details view on successful submit', async () => { it('redirects to connector details view on successful submit', async () => {
const createConnector = jest.fn().mockResolvedValue({ connector }); const createConnector = jest.fn().mockResolvedValue(connector);
renderComponent({ createConnector }); const route = clusterConnectConnectorPath(
await simulateFormSubmit();
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith(
clusterConnectConnectorPath(
clusterName, clusterName,
connects[0].name, connects[0].name,
connector.name connector.name
)
); );
renderComponent({ createConnector });
mockHistoryPush(route);
await simulateFormSubmit();
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith(route);
}); });
it('does not redirect to connector details view on unsuccessful submit', async () => { it('does not redirect to connector details view on unsuccessful submit', async () => {
@ -110,4 +107,3 @@ describe('New', () => {
expect(mockHistoryPush).not.toHaveBeenCalled(); expect(mockHistoryPush).not.toHaveBeenCalled();
}); });
}); });
});

View file

@ -22,11 +22,7 @@ const ListItem: React.FC<Props> = ({ clusterName, name, consumers }) => {
<> <>
<tr> <tr>
<ToggleButton> <ToggleButton>
<IconButtonWrapper <IconButtonWrapper onClick={() => setIsOpen(!isOpen)} aria-hidden>
onClick={() => setIsOpen(!isOpen)}
aria-hidden
data-testid="consumer-group-list-item-toggle"
>
<MessageToggleIcon isOpen={isOpen} /> <MessageToggleIcon isOpen={isOpen} />
</IconButtonWrapper> </IconButtonWrapper>
</ToggleButton> </ToggleButton>

View file

@ -41,8 +41,7 @@ describe('ListItem', () => {
}); });
it('should renders list item with topic content open', () => { it('should renders list item with topic content open', () => {
userEvent.click(screen.getByTestId('consumer-group-list-item-toggle')); userEvent.click(screen.getAllByRole('cell')[0].children[0]);
expect(screen.getByText('Consumer ID')).toBeInTheDocument(); expect(screen.getByText('Consumer ID')).toBeInTheDocument();
}); });
}); });

View file

@ -1,10 +1,8 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import ListItem from 'components/ConsumerGroups/List/ListItem'; import ListItem from 'components/ConsumerGroups/List/ListItem';
import { ThemeProvider } from 'styled-components';
import theme from 'theme/theme';
import { StaticRouter } from 'react-router';
import { ConsumerGroupState, ConsumerGroup } from 'generated-sources'; import { ConsumerGroupState, ConsumerGroup } from 'generated-sources';
import { screen } from '@testing-library/react';
import { render } from 'lib/testHelpers';
describe('List', () => { describe('List', () => {
const mockConsumerGroup = { const mockConsumerGroup = {
@ -29,75 +27,60 @@ describe('List', () => {
}, },
], ],
}; };
const component = mount(
<StaticRouter>
<ThemeProvider theme={theme}>
<table>
<tbody>
<ListItem consumerGroup={mockConsumerGroup} />
</tbody>
</table>
</ThemeProvider>
</StaticRouter>
);
const setupWrapper = (consumerGroup: ConsumerGroup) => ( const setupWrapper = (consumerGroup: ConsumerGroup) => (
<StaticRouter>
<ThemeProvider theme={theme}>
<table> <table>
<tbody> <tbody>
<ListItem consumerGroup={consumerGroup} /> <ListItem consumerGroup={consumerGroup} />
</tbody> </tbody>
</table> </table>
</ThemeProvider>
</StaticRouter>
); );
const getCell = () => screen.getAllByRole('cell')[5];
it('render empty ListItem', () => { it('render empty ListItem', () => {
expect(component.exists('tr')).toBeTruthy(); render(setupWrapper(mockConsumerGroup));
expect(screen.getByRole('row')).toBeInTheDocument();
}); });
it('renders item with stable status', () => { it('renders item with stable status', () => {
const wrapper = mount( render(
setupWrapper({ setupWrapper({
...mockConsumerGroup, ...mockConsumerGroup,
state: ConsumerGroupState.STABLE, state: ConsumerGroupState.STABLE,
}) })
); );
expect(screen.getByRole('row')).toHaveTextContent(
expect(wrapper.find('td').at(5).text()).toBe(ConsumerGroupState.STABLE); ConsumerGroupState.STABLE
);
}); });
it('renders item with dead status', () => { it('renders item with dead status', () => {
const wrapper = mount( render(
setupWrapper({ setupWrapper({
...mockConsumerGroup, ...mockConsumerGroup,
state: ConsumerGroupState.DEAD, state: ConsumerGroupState.DEAD,
}) })
); );
expect(getCell()).toHaveTextContent(ConsumerGroupState.DEAD);
expect(wrapper.find('td').at(5).text()).toBe(ConsumerGroupState.DEAD);
}); });
it('renders item with empty status', () => { it('renders item with empty status', () => {
const wrapper = mount( render(
setupWrapper({ setupWrapper({
...mockConsumerGroup, ...mockConsumerGroup,
state: ConsumerGroupState.EMPTY, state: ConsumerGroupState.EMPTY,
}) })
); );
expect(getCell()).toHaveTextContent(ConsumerGroupState.EMPTY);
expect(wrapper.find('td').at(5).text()).toBe(ConsumerGroupState.EMPTY);
}); });
it('renders item with empty-string status', () => { it('renders item with empty-string status', () => {
const wrapper = mount( render(
setupWrapper({ setupWrapper({
...mockConsumerGroup, ...mockConsumerGroup,
state: ConsumerGroupState.UNKNOWN, state: ConsumerGroupState.UNKNOWN,
}) })
); );
expect(getCell()).toHaveTextContent(ConsumerGroupState.UNKNOWN);
expect(wrapper.find('td').at(5).text()).toBe(ConsumerGroupState.UNKNOWN);
}); });
}); });

View file

@ -51,11 +51,11 @@ const ClustersWidget: React.FC<Props> = ({
<Metrics.Wrapper> <Metrics.Wrapper>
<Metrics.Section> <Metrics.Section>
<Metrics.Indicator label={<Tag color="green">Online</Tag>}> <Metrics.Indicator label={<Tag color="green">Online</Tag>}>
<span data-testid="onlineCount">{onlineClusters.length}</span>{' '} <span>{onlineClusters.length}</span>{' '}
<Metrics.LightText>clusters</Metrics.LightText> <Metrics.LightText>clusters</Metrics.LightText>
</Metrics.Indicator> </Metrics.Indicator>
<Metrics.Indicator label={<Tag color="gray">Offline</Tag>}> <Metrics.Indicator label={<Tag color="gray">Offline</Tag>}>
<span data-testid="offlineCount">{offlineClusters.length}</span>{' '} <span>{offlineClusters.length}</span>{' '}
<Metrics.LightText>clusters</Metrics.LightText> <Metrics.LightText>clusters</Metrics.LightText>
</Metrics.Indicator> </Metrics.Indicator>
</Metrics.Section> </Metrics.Section>

View file

@ -1,26 +1,12 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import { containerRendersView } from 'lib/testHelpers';
import ClustersWidget from 'components/Dashboard/ClustersWidget/ClustersWidget'; import ClustersWidget from 'components/Dashboard/ClustersWidget/ClustersWidget';
import ClustersWidgetContainer from 'components/Dashboard/ClustersWidget/ClustersWidgetContainer'; import { getByTextContent, render } from 'lib/testHelpers';
import theme from 'theme/theme';
import { ThemeProvider } from 'styled-components';
describe('ClustersWidgetContainer', () => { describe('ClustersWidgetContainer', () => {
containerRendersView(<ClustersWidgetContainer />, ClustersWidget); it('renders ClustersWidget', () => {
describe('view empty ClusterWidget', () => { render(
const setupEmptyWrapper = () => ( <ClustersWidget clusters={[]} onlineClusters={[]} offlineClusters={[]} />
<ThemeProvider theme={theme}>
<ClustersWidget
clusters={[]}
onlineClusters={[]}
offlineClusters={[]}
/>
</ThemeProvider>
); );
it(' is empty when no online clusters', () => { expect(getByTextContent('Online 0 clusters')).toBeInTheDocument();
const wrapper = mount(setupEmptyWrapper());
expect(wrapper.find('[data-testid="onlineCount"]').text()).toBe('0');
});
}); });
}); });

View file

@ -1,11 +1,19 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme';
import Dashboard from 'components/Dashboard/Dashboard'; import Dashboard from 'components/Dashboard/Dashboard';
import { render } from 'lib/testHelpers';
import { screen } from '@testing-library/dom';
const component = shallow(<Dashboard />); jest.mock(
'components/Dashboard/ClustersWidget/ClustersWidgetContainer.ts',
() => () => <div>mock-ClustersWidgetContainer</div>
);
describe('Dashboard', () => { describe('Dashboard', () => {
it('renders ClustersWidget', () => { it('renders ClustersWidget', () => {
expect(component.exists('Connect(ClustersWidget)')).toBe(true); render(<Dashboard />);
expect(screen.getByText('Dashboard')).toBeInTheDocument();
expect(
screen.getByText('mock-ClustersWidgetContainer')
).toBeInTheDocument();
}); });
}); });

View file

@ -1,20 +1,15 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import KsqlDb from 'components/KsqlDb/KsqlDb'; import KsqlDb from 'components/KsqlDb/KsqlDb';
import { StaticRouter } from 'react-router'; import { render } from 'lib/testHelpers';
import { screen } from '@testing-library/dom';
import { clusterKsqlDbPath } from 'lib/paths';
describe('KsqlDb Component', () => { describe('KsqlDb Component', () => {
const pathname = `ui/clusters/local/ksql-db`;
describe('KsqlDb', () => { describe('KsqlDb', () => {
const setupComponent = () => ( it('to be in the document', () => {
<StaticRouter location={{ pathname }} context={{}}> render(<KsqlDb />, { pathname: clusterKsqlDbPath() });
<KsqlDb /> expect(screen.getByText('KSQL DB')).toBeInTheDocument();
</StaticRouter> expect(screen.getByText('Execute KSQL Request')).toBeInTheDocument();
);
it('matches snapshot', () => {
expect(mount(setupComponent())).toMatchSnapshot();
}); });
}); });
}); });

View file

@ -1,38 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`KsqlDb Component KsqlDb matches snapshot 1`] = `
<StaticRouter
context={Object {}}
location={
Object {
"pathname": "ui/clusters/local/ksql-db",
}
}
>
<Router
history={
Object {
"action": "POP",
"block": [Function],
"createHref": [Function],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"listen": [Function],
"location": Object {
"hash": "",
"pathname": "ui/clusters/local/ksql-db",
"search": "",
},
"push": [Function],
"replace": [Function],
}
}
staticContext={Object {}}
>
<KsqlDb>
<Switch />
</KsqlDb>
</Router>
</StaticRouter>
`;

View file

@ -6,40 +6,38 @@ import * as S from 'components/Nav/ClusterTab/ClusterTab.styled';
import { ServerStatus } from 'generated-sources'; import { ServerStatus } from 'generated-sources';
describe('Cluster Styled Components', () => { describe('Cluster Styled Components', () => {
const getMenuItem = () => screen.getByRole('menuitem');
describe('Wrapper Component', () => { describe('Wrapper Component', () => {
it('should check the rendering and correct Styling when it is open', () => { it('should check the rendering and correct Styling when it is open', () => {
render(<S.Wrapper isOpen />); render(<S.Wrapper isOpen />);
expect(screen.getByRole('menuitem')).toHaveStyle( expect(getMenuItem()).toHaveStyle(`color:${theme.menu.color.isOpen}`);
`color:${theme.menu.color.isOpen}`
);
}); });
it('should check the rendering and correct Styling when it is Not open', () => { it('should check the rendering and correct Styling when it is Not open', () => {
render(<S.Wrapper isOpen={false} />); render(<S.Wrapper isOpen={false} />);
expect(screen.getByRole('menuitem')).toHaveStyle( expect(getMenuItem()).toHaveStyle(`color:${theme.menu.color.normal}`);
`color:${theme.menu.color.normal}`
);
}); });
}); });
describe('StatusIcon Component', () => { describe('StatusIcon Component', () => {
const getStatusCircle = () => screen.getByRole('status-circle');
it('should check the rendering and correct Styling when it is online', () => { it('should check the rendering and correct Styling when it is online', () => {
render(<S.StatusIcon status={ServerStatus.ONLINE} />); render(<S.StatusIcon status={ServerStatus.ONLINE} />);
expect(screen.getByRole('status-circle')).toHaveStyle( expect(getStatusCircle()).toHaveStyle(
`fill:${theme.menu.statusIconColor.online}` `fill:${theme.menu.statusIconColor.online}`
); );
}); });
it('should check the rendering and correct Styling when it is offline', () => { it('should check the rendering and correct Styling when it is offline', () => {
render(<S.StatusIcon status={ServerStatus.OFFLINE} />); render(<S.StatusIcon status={ServerStatus.OFFLINE} />);
expect(screen.getByRole('status-circle')).toHaveStyle( expect(getStatusCircle()).toHaveStyle(
`fill:${theme.menu.statusIconColor.offline}` `fill:${theme.menu.statusIconColor.offline}`
); );
}); });
it('should check the rendering and correct Styling when it is Initializing', () => { it('should check the rendering and correct Styling when it is Initializing', () => {
render(<S.StatusIcon status={ServerStatus.INITIALIZING} />); render(<S.StatusIcon status={ServerStatus.INITIALIZING} />);
expect(screen.getByRole('status-circle')).toHaveStyle( expect(getStatusCircle()).toHaveStyle(
`fill:${theme.menu.statusIconColor.initializing}` `fill:${theme.menu.statusIconColor.initializing}`
); );
}); });

View file

@ -11,18 +11,25 @@ describe('ClusterMenu', () => {
const setupComponent = (cluster: Cluster, singleMode?: boolean) => ( const setupComponent = (cluster: Cluster, singleMode?: boolean) => (
<ClusterMenu cluster={cluster} singleMode={singleMode} /> <ClusterMenu cluster={cluster} singleMode={singleMode} />
); );
const getMenuItems = () => screen.getAllByRole('menuitem');
const getMenuItem = () => screen.getByRole('menuitem');
const getBrokers = () => screen.getByTitle('Brokers');
const getTopics = () => screen.getByTitle('Brokers');
const getConsumers = () => screen.getByTitle('Brokers');
const getKafkaConnect = () => screen.getByTitle('Kafka Connect');
const getCluster = () => screen.getByText(onlineClusterPayload.name);
it('renders cluster menu with default set of features', () => { it('renders cluster menu with default set of features', () => {
render(setupComponent(onlineClusterPayload)); render(setupComponent(onlineClusterPayload));
expect(screen.getByText(onlineClusterPayload.name)).toBeInTheDocument(); expect(getCluster()).toBeInTheDocument();
expect(screen.getAllByRole('menuitem').length).toEqual(1); expect(getMenuItems().length).toEqual(1);
userEvent.click(screen.getByRole('menuitem')); userEvent.click(getMenuItem());
expect(screen.getAllByRole('menuitem').length).toEqual(4); expect(getMenuItems().length).toEqual(4);
expect(screen.getByTitle('Brokers')).toBeInTheDocument(); expect(getBrokers()).toBeInTheDocument();
expect(screen.getByTitle('Topics')).toBeInTheDocument(); expect(getTopics()).toBeInTheDocument();
expect(screen.getByTitle('Consumers')).toBeInTheDocument(); expect(getConsumers()).toBeInTheDocument();
}); });
it('renders cluster menu with correct set of features', () => { it('renders cluster menu with correct set of features', () => {
render( render(
@ -35,15 +42,15 @@ describe('ClusterMenu', () => {
], ],
}) })
); );
expect(screen.getAllByRole('menuitem').length).toEqual(1); expect(getMenuItems().length).toEqual(1);
userEvent.click(screen.getByRole('menuitem')); userEvent.click(getMenuItem());
expect(screen.getAllByRole('menuitem').length).toEqual(7); expect(getMenuItems().length).toEqual(7);
expect(screen.getByTitle('Brokers')).toBeInTheDocument(); expect(getBrokers()).toBeInTheDocument();
expect(screen.getByTitle('Topics')).toBeInTheDocument(); expect(getTopics()).toBeInTheDocument();
expect(screen.getByTitle('Consumers')).toBeInTheDocument(); expect(getConsumers()).toBeInTheDocument();
expect(screen.getByTitle('Schema Registry')).toBeInTheDocument(); expect(screen.getByTitle('Schema Registry')).toBeInTheDocument();
expect(screen.getByTitle('Kafka Connect')).toBeInTheDocument(); expect(getKafkaConnect()).toBeInTheDocument();
expect(screen.getByTitle('KSQL DB')).toBeInTheDocument(); expect(screen.getByTitle('KSQL DB')).toBeInTheDocument();
}); });
it('renders open cluster menu', () => { it('renders open cluster menu', () => {
@ -51,11 +58,11 @@ describe('ClusterMenu', () => {
pathname: clusterConnectorsPath(onlineClusterPayload.name), pathname: clusterConnectorsPath(onlineClusterPayload.name),
}); });
expect(screen.getAllByRole('menuitem').length).toEqual(4); expect(getMenuItems().length).toEqual(4);
expect(screen.getByText(onlineClusterPayload.name)).toBeInTheDocument(); expect(getCluster()).toBeInTheDocument();
expect(screen.getByTitle('Brokers')).toBeInTheDocument(); expect(getBrokers()).toBeInTheDocument();
expect(screen.getByTitle('Topics')).toBeInTheDocument(); expect(getTopics()).toBeInTheDocument();
expect(screen.getByTitle('Consumers')).toBeInTheDocument(); expect(getConsumers()).toBeInTheDocument();
}); });
it('makes Kafka Connect link active', () => { it('makes Kafka Connect link active', () => {
render( render(
@ -65,12 +72,12 @@ describe('ClusterMenu', () => {
}), }),
{ pathname: clusterConnectorsPath(onlineClusterPayload.name) } { pathname: clusterConnectorsPath(onlineClusterPayload.name) }
); );
expect(screen.getAllByRole('menuitem').length).toEqual(1); expect(getMenuItems().length).toEqual(1);
userEvent.click(screen.getByRole('menuitem')); userEvent.click(getMenuItem());
expect(screen.getAllByRole('menuitem').length).toEqual(5); expect(getMenuItems().length).toEqual(5);
expect(screen.getByText('Kafka Connect')).toBeInTheDocument(); expect(getKafkaConnect()).toBeInTheDocument();
expect(screen.getByText('Kafka Connect')).toHaveClass('is-active'); expect(getKafkaConnect()).toHaveClass('is-active');
}); });
it('makes Kafka Connect link active', () => { it('makes Kafka Connect link active', () => {
render( render(
@ -80,11 +87,11 @@ describe('ClusterMenu', () => {
}), }),
{ pathname: clusterConnectsPath(onlineClusterPayload.name) } { pathname: clusterConnectsPath(onlineClusterPayload.name) }
); );
expect(screen.getAllByRole('menuitem').length).toEqual(1); expect(getMenuItems().length).toEqual(1);
userEvent.click(screen.getByRole('menuitem')); userEvent.click(getMenuItem());
expect(screen.getAllByRole('menuitem').length).toEqual(5); expect(getMenuItems().length).toEqual(5);
expect(screen.getByText('Kafka Connect')).toBeInTheDocument(); expect(getKafkaConnect()).toBeInTheDocument();
expect(screen.getByText('Kafka Connect')).toHaveClass('is-active'); expect(getKafkaConnect()).toHaveClass('is-active');
}); });
}); });

View file

@ -12,6 +12,9 @@ describe('ClusterMenuItem', () => {
</ul> </ul>
); );
const getMenuItem = () => screen.getByRole('menuitem');
const getLink = () => screen.queryByRole('link');
it('renders component with correct title', () => { it('renders component with correct title', () => {
const testTitle = 'My Test Title'; const testTitle = 'My Test Title';
render(setupComponent({ title: testTitle })); render(setupComponent({ title: testTitle }));
@ -20,24 +23,24 @@ describe('ClusterMenuItem', () => {
it('renders top level component with correct styles', () => { it('renders top level component with correct styles', () => {
render(setupComponent({ isTopLevel: true })); render(setupComponent({ isTopLevel: true }));
expect(screen.getByRole('menuitem')).toHaveStyle({ fontWeight: '500' }); expect(getMenuItem()).toHaveStyle({ fontWeight: '500' });
}); });
it('renders non-top level component with correct styles', () => { it('renders non-top level component with correct styles', () => {
render(setupComponent({ isTopLevel: false })); render(setupComponent({ isTopLevel: false }));
expect(screen.getByRole('menuitem')).toHaveStyle({ fontWeight: 'normal' }); expect(getMenuItem()).toHaveStyle({ fontWeight: 'normal' });
}); });
it('renders list item with link inside', () => { it('renders list item with link inside', () => {
render(setupComponent({ to: '/my-cluster' })); render(setupComponent({ to: '/my-cluster' }));
expect(screen.getByRole('menuitem')).toBeInTheDocument(); expect(getMenuItem()).toBeInTheDocument();
expect(screen.queryByRole('link')).toBeInTheDocument(); expect(getLink()).toBeInTheDocument();
}); });
it('renders list item without link inside', () => { it('renders list item without link inside', () => {
render(setupComponent({ to: '' })); render(setupComponent({ to: '' }));
expect(screen.getByRole('menuitem')).toBeInTheDocument(); expect(getMenuItem()).toBeInTheDocument();
expect(screen.queryByRole('link')).not.toBeInTheDocument(); expect(getLink()).not.toBeInTheDocument();
}); });
it('renders list item with children', () => { it('renders list item with children', () => {
@ -46,8 +49,8 @@ describe('ClusterMenuItem', () => {
<ClusterMenuItem to="/test">Test Text Box</ClusterMenuItem> <ClusterMenuItem to="/test">Test Text Box</ClusterMenuItem>
</ul> </ul>
); );
expect(screen.getByRole('menuitem')).toBeInTheDocument(); expect(getMenuItem()).toBeInTheDocument();
expect(screen.queryByRole('link')).toBeInTheDocument(); expect(getLink()).toBeInTheDocument();
expect(screen.getByText('Test Text Box')).toBeInTheDocument(); expect(screen.getByText('Test Text Box')).toBeInTheDocument();
}); });
}); });

View file

@ -8,10 +8,13 @@ import { screen } from '@testing-library/react';
import { render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
describe('Nav', () => { describe('Nav', () => {
const getDashboard = () => screen.getByText('Dashboard');
const getMenuItemsCount = () => screen.getAllByRole('menuitem').length;
it('renders loader', () => { it('renders loader', () => {
render(<Nav clusters={[]} />); render(<Nav clusters={[]} />);
expect(screen.getAllByRole('menuitem').length).toEqual(1); expect(getMenuItemsCount()).toEqual(1);
expect(screen.getByText('Dashboard')).toBeInTheDocument(); expect(getDashboard()).toBeInTheDocument();
}); });
it('renders ClusterMenu', () => { it('renders ClusterMenu', () => {
@ -22,8 +25,8 @@ describe('Nav', () => {
/> />
); );
expect(screen.getAllByRole('menu').length).toEqual(3); expect(screen.getAllByRole('menu').length).toEqual(3);
expect(screen.getAllByRole('menuitem').length).toEqual(3); expect(getMenuItemsCount()).toEqual(3);
expect(screen.getByText('Dashboard')).toBeInTheDocument(); expect(getDashboard()).toBeInTheDocument();
expect(screen.getByText(onlineClusterPayload.name)).toBeInTheDocument(); expect(screen.getByText(onlineClusterPayload.name)).toBeInTheDocument();
expect(screen.getByText(offlineClusterPayload.name)).toBeInTheDocument(); expect(screen.getByText(offlineClusterPayload.name)).toBeInTheDocument();
}); });

View file

@ -17,7 +17,7 @@ const LatestVersionItem: React.FC<LatestVersionProps> = ({
<Heading level={3}>Relevant version</Heading> <Heading level={3}>Relevant version</Heading>
<EditorViewer data={schema} schemaType={schemaType} maxLines={28} /> <EditorViewer data={schema} schemaType={schemaType} maxLines={28} />
</div> </div>
<div data-testid="meta-data"> <div>
<div> <div>
<S.MetaDataLabel>Latest version</S.MetaDataLabel> <S.MetaDataLabel>Latest version</S.MetaDataLabel>
<p>{version}</p> <p>{version}</p>

View file

@ -1,36 +1,28 @@
import React from 'react'; import React from 'react';
import LatestVersionItem from 'components/Schemas/Details/LatestVersion/LatestVersionItem'; import LatestVersionItem from 'components/Schemas/Details/LatestVersion/LatestVersionItem';
import { SchemaSubject } from 'generated-sources';
import { render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
import { screen } from '@testing-library/react'; import { screen } from '@testing-library/react';
import { jsonSchema, protoSchema } from './fixtures'; import { jsonSchema, protoSchema } from './fixtures';
const renderComponent = (schema: SchemaSubject) => {
render(<LatestVersionItem schema={schema} />);
};
describe('LatestVersionItem', () => { describe('LatestVersionItem', () => {
it('renders latest version of json schema', () => { it('renders latest version of json schema', () => {
renderComponent(jsonSchema); render(<LatestVersionItem schema={jsonSchema} />);
expect(screen.getByText('Relevant version')).toBeInTheDocument(); expect(screen.getByText('Relevant version')).toBeInTheDocument();
expect(screen.getByText('Latest version')).toBeInTheDocument(); expect(screen.getByText('Latest version')).toBeInTheDocument();
expect(screen.getByText('ID')).toBeInTheDocument(); expect(screen.getByText('ID')).toBeInTheDocument();
expect(screen.getByText('Subject')).toBeInTheDocument(); expect(screen.getByText('Subject')).toBeInTheDocument();
expect(screen.getByText('Compatibility')).toBeInTheDocument(); expect(screen.getByText('Compatibility')).toBeInTheDocument();
expect(screen.getByText('15')).toBeInTheDocument(); expect(screen.getByText('15')).toBeInTheDocument();
expect(screen.getByTestId('json-viewer')).toBeInTheDocument();
}); });
it('renders latest version of compatibility', () => { it('renders latest version of compatibility', () => {
renderComponent(protoSchema); render(<LatestVersionItem schema={protoSchema} />);
expect(screen.getByText('Relevant version')).toBeInTheDocument(); expect(screen.getByText('Relevant version')).toBeInTheDocument();
expect(screen.getByText('Latest version')).toBeInTheDocument(); expect(screen.getByText('Latest version')).toBeInTheDocument();
expect(screen.getByText('ID')).toBeInTheDocument(); expect(screen.getByText('ID')).toBeInTheDocument();
expect(screen.getByText('Subject')).toBeInTheDocument(); expect(screen.getByText('Subject')).toBeInTheDocument();
expect(screen.getByText('Compatibility')).toBeInTheDocument(); expect(screen.getByText('Compatibility')).toBeInTheDocument();
expect(screen.getByText('BACKWARD')).toBeInTheDocument(); expect(screen.getByText('BACKWARD')).toBeInTheDocument();
expect(screen.getByTestId('json-viewer')).toBeInTheDocument();
}); });
}); });

View file

@ -6,21 +6,19 @@ import userEvent from '@testing-library/user-event';
import { versions } from './fixtures'; import { versions } from './fixtures';
const renderComponent = () => { const component = (
render(
<table> <table>
<tbody> <tbody>
<SchemaVersion version={versions[0]} /> <SchemaVersion version={versions[0]} />
</tbody> </tbody>
</table> </table>
); );
};
describe('SchemaVersion', () => { describe('SchemaVersion', () => {
it('renders versions', () => { it('renders versions', () => {
renderComponent(); render(component);
expect(screen.getAllByRole('cell')).toHaveLength(3); expect(screen.getAllByRole('cell')).toHaveLength(3);
expect(screen.queryByTestId('json-viewer')).not.toBeInTheDocument(); expect(screen.queryByTestId('json-viewer')).not.toBeInTheDocument();
userEvent.click(screen.getByRole('button')); userEvent.click(screen.getByRole('button'));
expect(screen.getByTestId('json-viewer')).toBeInTheDocument();
}); });
}); });

View file

@ -1,40 +1,28 @@
import React from 'react'; import React from 'react';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { StaticRouter } from 'react-router';
import Diff, { DiffProps } from 'components/Schemas/Diff/Diff'; import Diff, { DiffProps } from 'components/Schemas/Diff/Diff';
import { render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
import { screen } from '@testing-library/react'; import { screen } from '@testing-library/react';
import thunk from 'redux-thunk';
import { versions } from './fixtures'; import { versions } from './fixtures';
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
describe('Diff', () => { describe('Diff', () => {
const initialState: Partial<DiffProps> = {};
const store = mockStore(initialState);
const setupComponent = (props: DiffProps) => const setupComponent = (props: DiffProps) =>
render( render(
<Provider store={store}>
<StaticRouter>
<Diff <Diff
versions={props.versions} versions={props.versions}
leftVersionInPath={props.leftVersionInPath} leftVersionInPath={props.leftVersionInPath}
rightVersionInPath={props.rightVersionInPath} rightVersionInPath={props.rightVersionInPath}
areVersionsFetched={props.areVersionsFetched} areVersionsFetched={props.areVersionsFetched}
/> />
</StaticRouter>
</Provider>
); );
describe('Container', () => { describe('Container', () => {
it('renders view', () => { it('renders view', () => {
setupComponent({ setupComponent({
areVersionsFetched: true, areVersionsFetched: true,
versions, versions,
}); });
expect(screen.getAllByText('Version 3').length).toEqual(4);
}); });
}); });
@ -65,8 +53,7 @@ describe('Diff', () => {
}); });
it('renders all options', () => { it('renders all options', () => {
const selectedOption = screen.getAllByRole('option'); expect(screen.getAllByRole('option').length).toEqual(2);
expect(selectedOption.length).toEqual(2);
}); });
it('renders left select with empty value', () => { it('renders left select with empty value', () => {
const select = screen.getAllByRole('listbox')[0]; const select = screen.getAllByRole('listbox')[0];

View file

@ -1,13 +1,12 @@
import React from 'react'; import React from 'react';
import { StaticRouter } from 'react-router';
import { mount } from 'enzyme';
import { import {
externalTopicPayload, externalTopicPayload,
internalTopicPayload, internalTopicPayload,
} from 'redux/reducers/topics/__test__/fixtures'; } from 'redux/reducers/topics/__test__/fixtures';
import ListItem, { ListItemProps } from 'components/Topics/List/ListItem'; import ListItem, { ListItemProps } from 'components/Topics/List/ListItem';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/react';
import theme from 'theme/theme'; import userEvent from '@testing-library/user-event';
import { render } from 'lib/testHelpers';
const mockDelete = jest.fn(); const mockDelete = jest.fn();
const clusterName = 'local'; const clusterName = 'local';
@ -26,8 +25,6 @@ jest.mock('react-redux', () => ({
describe('ListItem', () => { describe('ListItem', () => {
const setupComponent = (props: Partial<ListItemProps> = {}) => ( const setupComponent = (props: Partial<ListItemProps> = {}) => (
<StaticRouter>
<ThemeProvider theme={theme}>
<table> <table>
<tbody> <tbody>
<ListItem <ListItem
@ -42,39 +39,36 @@ describe('ListItem', () => {
/> />
</tbody> </tbody>
</table> </table>
</ThemeProvider>
</StaticRouter>
); );
it('renders without checkbox for internal topic', () => { const getCheckbox = () => screen.getByRole('checkbox');
const wrapper = mount(setupComponent());
expect(wrapper.find('td').at(0).html()).toEqual('<td></td>'); it('renders without checkbox for internal topic', () => {
render(setupComponent({ topic: internalTopicPayload }));
expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();
}); });
it('renders with checkbox for external topic', () => { it('renders with checkbox for external topic', () => {
const wrapper = mount(setupComponent({ topic: externalTopicPayload })); render(setupComponent({ topic: externalTopicPayload }));
expect(wrapper.find('td').at(0).html()).toEqual( expect(getCheckbox()).toBeInTheDocument();
'<td><input type="checkbox"></td>'
);
}); });
it('triggers the toggleTopicSelected when clicked on the checkbox input', () => { it('triggers the toggleTopicSelected when clicked on the checkbox input', () => {
const wrapper = mount(setupComponent({ topic: externalTopicPayload })); render(setupComponent({ topic: externalTopicPayload }));
expect(wrapper.exists('input')).toBeTruthy(); expect(getCheckbox()).toBeInTheDocument();
wrapper.find('input[type="checkbox"]').at(0).simulate('change'); userEvent.click(getCheckbox());
expect(mockToggleTopicSelected).toBeCalledTimes(1); expect(mockToggleTopicSelected).toBeCalledTimes(1);
expect(mockToggleTopicSelected).toBeCalledWith(externalTopicPayload.name); expect(mockToggleTopicSelected).toBeCalledWith(externalTopicPayload.name);
}); });
it('renders correct out of sync replicas number', () => { it('renders correct out of sync replicas number', () => {
const wrapper = mount( render(
setupComponent({ setupComponent({
topic: { ...externalTopicPayload, partitions: undefined }, topic: { ...externalTopicPayload, partitions: undefined },
}) })
); );
expect(wrapper.find('td').at(3).text()).toEqual('0'); expect(screen.getAllByRole('cell', { name: '0' }).length).toBeTruthy();
}); });
}); });

View file

@ -181,7 +181,7 @@ export const ActiveSmartFilterWrapper = styled.div`
justify-content: flex-start; justify-content: flex-start;
`; `;
export const DeleteSavedFilter = styled.div` export const DeleteSavedFilter = styled.div.attrs({ role: 'deleteIcon' })`
color: ${({ theme }) => theme.breadcrumb}; color: ${({ theme }) => theme.breadcrumb};
cursor: pointer; cursor: pointer;
`; `;

View file

@ -72,10 +72,7 @@ const SavedFilters: FC<Props> = ({
<S.FilterEdit onClick={() => onEdit(index, filter)}> <S.FilterEdit onClick={() => onEdit(index, filter)}>
Edit Edit
</S.FilterEdit> </S.FilterEdit>
<S.DeleteSavedFilter <S.DeleteSavedFilter onClick={() => deleteFilterHandler(index)}>
data-testid="deleteIcon"
onClick={() => deleteFilterHandler(index)}
>
<i className="fas fa-times" /> <i className="fas fa-times" />
</S.DeleteSavedFilter> </S.DeleteSavedFilter>
</S.FilterOptions> </S.FilterOptions>

View file

@ -41,6 +41,8 @@ const setupWrapper = (
</TopicMessagesContext.Provider> </TopicMessagesContext.Provider>
); );
}; };
const getSubmit = () => screen.getByText('Submit');
describe('Filters component', () => { describe('Filters component', () => {
it('renders component', () => { it('renders component', () => {
setupWrapper(); setupWrapper();
@ -56,7 +58,7 @@ describe('Filters component', () => {
describe('when fetching is over', () => { describe('when fetching is over', () => {
it('shows submit button while fetching is over', () => { it('shows submit button while fetching is over', () => {
setupWrapper(); setupWrapper();
expect(screen.getByText('Submit')).toBeInTheDocument(); expect(getSubmit()).toBeInTheDocument();
}); });
}); });
@ -138,7 +140,7 @@ describe('Filters component', () => {
userEvent.click(StopLoading); userEvent.click(StopLoading);
const option = screen.getAllByRole('option'); const option = screen.getAllByRole('option');
expect(option[1]).toHaveTextContent('Oldest First'); expect(option[1]).toHaveTextContent('Oldest First');
expect(screen.getByText('Submit')).toBeInTheDocument(); expect(getSubmit()).toBeInTheDocument();
}); });
}); });

View file

@ -26,6 +26,8 @@ describe('SavedFilter Component', () => {
); );
}; };
const getSavedFilters = () => screen.getAllByRole('savedFilter');
it('should check the Cancel button click', () => { it('should check the Cancel button click', () => {
const cancelMock = jest.fn(); const cancelMock = jest.fn();
setUpComponent({ closeModal: cancelMock }); setUpComponent({ closeModal: cancelMock });
@ -70,15 +72,13 @@ describe('SavedFilter Component', () => {
}); });
it('should check the normal data rendering', () => { it('should check the normal data rendering', () => {
expect(screen.getAllByRole('savedFilter')).toHaveLength( expect(getSavedFilters()).toHaveLength(mockFilters.length);
mockFilters.length
);
expect(screen.getByText(mockFilters[0].name)).toBeInTheDocument(); expect(screen.getByText(mockFilters[0].name)).toBeInTheDocument();
expect(screen.getByText(mockFilters[1].name)).toBeInTheDocument(); expect(screen.getByText(mockFilters[1].name)).toBeInTheDocument();
}); });
it('should check the Filter edit Button works', () => { it('should check the Filter edit Button works', () => {
const savedFilters = screen.getAllByRole('savedFilter'); const savedFilters = getSavedFilters();
userEvent.hover(savedFilters[0]); userEvent.hover(savedFilters[0]);
userEvent.click(within(savedFilters[0]).getByText(/edit/i)); userEvent.click(within(savedFilters[0]).getByText(/edit/i));
expect(onEditMock).toHaveBeenCalled(); expect(onEditMock).toHaveBeenCalled();
@ -94,7 +94,7 @@ describe('SavedFilter Component', () => {
userEvent.click(selectFilterButton); userEvent.click(selectFilterButton);
expect(activeFilterMock).not.toHaveBeenCalled(); expect(activeFilterMock).not.toHaveBeenCalled();
const savedFilterElement = screen.getAllByRole('savedFilter'); const savedFilterElement = getSavedFilters();
userEvent.click(savedFilterElement[0]); userEvent.click(savedFilterElement[0]);
userEvent.click(selectFilterButton); userEvent.click(selectFilterButton);
@ -115,8 +115,9 @@ describe('SavedFilter Component', () => {
}); });
it('Open Confirmation for the deletion modal', () => { it('Open Confirmation for the deletion modal', () => {
const savedFilters = screen.getAllByRole('savedFilter'); const { container } = setUpComponent({ deleteFilter: deleteMock });
const deleteIcons = screen.getAllByTestId('deleteIcon'); const savedFilters = getSavedFilters();
const deleteIcons = container.getElementsByTagName('i');
userEvent.hover(savedFilters[0]); userEvent.hover(savedFilters[0]);
userEvent.click(deleteIcons[0]); userEvent.click(deleteIcons[0]);
const modelDialog = screen.getByRole('dialog'); const modelDialog = screen.getByRole('dialog');
@ -127,8 +128,9 @@ describe('SavedFilter Component', () => {
}); });
it('Close Confirmations deletion modal with button', () => { it('Close Confirmations deletion modal with button', () => {
const savedFilters = screen.getAllByRole('savedFilter'); const { container } = setUpComponent({ deleteFilter: deleteMock });
const deleteIcons = screen.getAllByTestId('deleteIcon'); const savedFilters = getSavedFilters();
const deleteIcons = container.getElementsByTagName('i');
userEvent.hover(savedFilters[0]); userEvent.hover(savedFilters[0]);
userEvent.click(deleteIcons[0]); userEvent.click(deleteIcons[0]);
@ -143,8 +145,9 @@ describe('SavedFilter Component', () => {
}); });
it('Delete the saved filter', () => { it('Delete the saved filter', () => {
const savedFilters = screen.getAllByRole('savedFilter'); const { container } = setUpComponent({ deleteFilter: deleteMock });
const deleteIcons = screen.getAllByTestId('deleteIcon'); const savedFilters = getSavedFilters();
const deleteIcons = container.getElementsByTagName('i');
userEvent.hover(savedFilters[0]); userEvent.hover(savedFilters[0]);
userEvent.click(deleteIcons[0]); userEvent.click(deleteIcons[0]);

View file

@ -54,11 +54,6 @@ describe('MessageContent screen', () => {
userEvent.click(keyTab[0]); userEvent.click(keyTab[0]);
expect(keyTab[0]).toHaveClass('is-active'); expect(keyTab[0]).toHaveClass('is-active');
}); });
it('displays the key in the EditorViewer', () => {
const keyTab = screen.getAllByText('Key');
userEvent.click(keyTab[0]);
expect(screen.getByTestId('json-viewer')).toBeInTheDocument();
});
}); });
describe('when switched to display the headers', () => { describe('when switched to display the headers', () => {
@ -66,10 +61,6 @@ describe('MessageContent screen', () => {
userEvent.click(screen.getByText('Headers')); userEvent.click(screen.getByText('Headers'));
expect(screen.getByText('Headers')).toHaveClass('is-active'); expect(screen.getByText('Headers')).toHaveClass('is-active');
}); });
it('displays the key in the EditorViewer', () => {
userEvent.click(screen.getByText('Headers'));
expect(screen.getByTestId('json-viewer')).toBeInTheDocument();
});
}); });
describe('when switched to display the content', () => { describe('when switched to display the content', () => {

View file

@ -1,25 +1,16 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import { StaticRouter } from 'react-router-dom';
import { store } from 'redux/store';
import FiltersContainer from 'components/Topics/Topic/Details/Messages/Filters/FiltersContainer'; import FiltersContainer from 'components/Topics/Topic/Details/Messages/Filters/FiltersContainer';
import { screen } from '@testing-library/react';
import { render } from 'lib/testHelpers';
jest.mock( jest.mock(
'components/Topics/Topic/Details/Messages/Filters/Filters', 'components/Topics/Topic/Details/Messages/Filters/Filters',
() => 'mock-Filters' () => () => <div>mock-Filters</div>
); );
describe('FiltersContainer', () => { describe('FiltersContainer', () => {
it('renders view with initial state of storage', () => { it('renders Filters component', () => {
const wrapper = mount( render(<FiltersContainer />);
<Provider store={store}> expect(screen.getByText('mock-Filters')).toBeInTheDocument();
<StaticRouter>
<FiltersContainer />
</StaticRouter>
</Provider>
);
expect(wrapper.exists('mock-Filters')).toBeTruthy();
}); });
}); });

View file

@ -15,6 +15,9 @@ const setupComponent = (props: ListItemProps) => {
); );
}; };
const getName = () => screen.getByText('someName');
const getValue = () => screen.getByText('someValue');
it('renders with CustomValue', () => { it('renders with CustomValue', () => {
setupComponent({ setupComponent({
config: { config: {
@ -23,10 +26,10 @@ it('renders with CustomValue', () => {
defaultValue: 'someDefaultValue', defaultValue: 'someDefaultValue',
}, },
}); });
expect(screen.getByText('someName')).toBeInTheDocument(); expect(getName()).toBeInTheDocument();
expect(screen.getByText('someName')).toHaveStyle('font-weight: 500'); expect(getName()).toHaveStyle('font-weight: 500');
expect(screen.getByText('someValue')).toBeInTheDocument(); expect(getValue()).toBeInTheDocument();
expect(screen.getByText('someValue')).toHaveStyle('font-weight: 500'); expect(getValue()).toHaveStyle('font-weight: 500');
expect(screen.getByText('someDefaultValue')).toBeInTheDocument(); expect(screen.getByText('someDefaultValue')).toBeInTheDocument();
}); });
@ -34,9 +37,9 @@ it('renders without CustomValue', () => {
setupComponent({ setupComponent({
config: { name: 'someName', value: 'someValue', defaultValue: 'someValue' }, config: { name: 'someName', value: 'someValue', defaultValue: 'someValue' },
}); });
expect(screen.getByText('someName')).toBeInTheDocument(); expect(getName()).toBeInTheDocument();
expect(screen.getByText('someName')).toHaveStyle('font-weight: 400'); expect(getName()).toHaveStyle('font-weight: 400');
expect(screen.getByText('someValue')).toBeInTheDocument(); expect(getValue()).toBeInTheDocument();
expect(screen.getByText('someValue')).toHaveStyle('font-weight: 400'); expect(getValue()).toHaveStyle('font-weight: 400');
expect(screen.getByTitle('Default Value')).toHaveTextContent(''); expect(screen.getByTitle('Default Value')).toHaveTextContent('');
}); });

View file

@ -1,26 +1,61 @@
import React from 'react'; import React from 'react';
import { Button } from 'components/common/Button/Button'; import { Button } from 'components/common/Button/Button';
import { ButtonProps } from 'components/common/Button/Button.styled'; import { screen } from '@testing-library/react';
import { mountWithTheme } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
import theme from 'theme/theme';
describe('StyledButton', () => { describe('Button', () => {
const setupComponent = (props: ButtonProps) => it('renders small primary Button', () => {
mountWithTheme(<Button {...props} />); render(<Button buttonType="primary" buttonSize="S" />);
expect(screen.getByRole('button')).toBeInTheDocument();
it('should render with props S and Primary', () => { expect(screen.getByRole('button')).toHaveStyleRule(
const wrapper = setupComponent({ 'color',
buttonSize: 'S', theme.button.primary.color
buttonType: 'primary', );
}); expect(screen.getByRole('button')).toHaveStyleRule(
expect(wrapper.exists()).toBeTruthy(); 'font-size',
theme.button.fontSize.S
);
}); });
it('should render with inverted theme colors', () => { it('renders medium size secondary Button', () => {
const wrapper = setupComponent({ render(<Button buttonType="secondary" buttonSize="M" />);
buttonSize: 'S', expect(screen.getByRole('button')).toBeInTheDocument();
buttonType: 'primary', expect(screen.getByRole('button')).toHaveStyleRule(
isInverted: true, 'color',
theme.button.secondary.color
);
expect(screen.getByRole('button')).toHaveStyleRule(
'font-size',
theme.button.fontSize.M
);
}); });
expect(wrapper.exists()).toBeTruthy();
it('renders small Button', () => {
render(<Button buttonType="secondary" buttonSize="S" />);
expect(screen.getByRole('button')).toBeInTheDocument();
expect(screen.getByRole('button')).toHaveStyleRule(
'color',
theme.button.secondary.color
);
});
it('renders link with large primary button inside', () => {
render(<Button isLink to="/my-link" buttonType="primary" buttonSize="L" />);
expect(screen.getByRole('link')).toBeInTheDocument();
expect(screen.getByRole('button')).toBeInTheDocument();
expect(screen.getByRole('button')).toHaveStyleRule(
'font-size',
theme.button.fontSize.L
);
});
it('renders inverted color Button', () => {
render(<Button buttonType="primary" buttonSize="S" isInverted />);
expect(screen.getByRole('button')).toBeInTheDocument();
expect(screen.getByRole('button')).toHaveStyleRule(
'color',
theme.button.primary.invertedColors.normal
);
}); });
}); });

View file

@ -1,43 +1,43 @@
import { shallow } from 'enzyme';
import React from 'react'; import React from 'react';
import BytesFormatted, { import BytesFormatted, {
sizes, sizes,
} from 'components/common/BytesFormatted/BytesFormatted'; } from 'components/common/BytesFormatted/BytesFormatted';
import { render, screen } from '@testing-library/react';
describe('BytesFormatted', () => { describe('BytesFormatted', () => {
it('renders Bytes correctly', () => { it('renders Bytes correctly', () => {
const component = shallow(<BytesFormatted value={666} />); render(<BytesFormatted value={666} />);
expect(component.text()).toEqual('666Bytes'); expect(screen.getByText('666Bytes')).toBeInTheDocument();
}); });
it('renders correct units', () => { it('renders correct units', () => {
let value = 1; let value = 1;
sizes.forEach((unit) => { sizes.forEach((unit) => {
const component = shallow(<BytesFormatted value={value} />); render(<BytesFormatted value={value} />);
expect(component.text()).toEqual(`1${unit}`); expect(screen.getByText(`1${unit}`)).toBeInTheDocument();
value *= 1024; value *= 1024;
}); });
}); });
it('renders correct precision', () => { it('renders correct precision', () => {
let component = shallow(<BytesFormatted value={2000} precision={100} />); render(<BytesFormatted value={2000} precision={100} />);
expect(component.text()).toEqual(`1.953125${sizes[1]}`); expect(screen.getByText(`1.953125${sizes[1]}`)).toBeInTheDocument();
component = shallow(<BytesFormatted value={10000} precision={5} />); render(<BytesFormatted value={10000} precision={5} />);
expect(component.text()).toEqual(`9.76563${sizes[1]}`); expect(screen.getByText(`9.76563${sizes[1]}`)).toBeInTheDocument();
}); });
it('correctly handles invalid props', () => { it('correctly handles invalid props', () => {
let component = shallow(<BytesFormatted value={10000} precision={-1} />); render(<BytesFormatted value={10000} precision={-1} />);
expect(component.text()).toEqual(`10${sizes[1]}`); expect(screen.getByText(`10${sizes[1]}`)).toBeInTheDocument();
component = shallow(<BytesFormatted value="some string" />); render(<BytesFormatted value="some string" />);
expect(component.text()).toEqual(`-${sizes[0]}`); expect(screen.getAllByText(`-${sizes[0]}`).length).toBeTruthy();
component = shallow(<BytesFormatted value={-100000} />); render(<BytesFormatted value={-100000} />);
expect(component.text()).toEqual(`-${sizes[0]}`); expect(screen.getAllByText(`-${sizes[0]}`).length).toBeTruthy();
component = shallow(<BytesFormatted value={undefined} />); render(<BytesFormatted value={undefined} />);
expect(component.text()).toEqual(`0${sizes[0]}`); expect(screen.getByText(`0${sizes[0]}`)).toBeInTheDocument();
}); });
}); });

View file

@ -29,7 +29,7 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = ({
return isOpen ? ( return isOpen ? (
<ConfirmationModalWrapper> <ConfirmationModalWrapper>
<div onClick={cancelHandler} aria-hidden="true" /> <div onClick={cancelHandler} aria-hidden="true" role="button" />
<div> <div>
<header> <header>
<p>{title}</p> <p>{title}</p>

View file

@ -1,89 +1,80 @@
import { mount, ReactWrapper } from 'enzyme';
import React from 'react'; import React from 'react';
import ConfirmationModal, { import ConfirmationModal, {
ConfirmationModalProps, ConfirmationModalProps,
} from 'components/common/ConfirmationModal/ConfirmationModal'; } from 'components/common/ConfirmationModal/ConfirmationModal';
import { ThemeProvider } from 'styled-components'; import { screen } from '@testing-library/react';
import theme from 'theme/theme'; import userEvent from '@testing-library/user-event';
import { render } from 'lib/testHelpers';
const confirmMock = jest.fn(); const confirmMock = jest.fn();
const cancelMock = jest.fn(); const cancelMock = jest.fn();
const body = 'Please Confirm the action!'; const body = 'Please Confirm the action!';
describe('ConfirmationModal', () => { describe('ConfirmationModal', () => {
const setupWrapper = (props: Partial<ConfirmationModalProps> = {}) => ( const setupWrapper = (props: Partial<ConfirmationModalProps> = {}) => (
<ThemeProvider theme={theme}> <ConfirmationModal onCancel={cancelMock} onConfirm={confirmMock} {...props}>
<ConfirmationModal
onCancel={cancelMock}
onConfirm={confirmMock}
{...props}
>
{body} {body}
</ConfirmationModal> </ConfirmationModal>
</ThemeProvider>
); );
it('renders nothing', () => { it('renders nothing', () => {
const wrapper = mount(setupWrapper({ isOpen: false })); render(setupWrapper({ isOpen: false }));
expect(wrapper.exists(ConfirmationModal)).toBeTruthy(); expect(screen.queryByText(body)).not.toBeInTheDocument();
expect(wrapper.exists('ConfirmationModal > div')).toBeFalsy();
}); });
it('renders modal', () => { it('renders modal', () => {
const wrapper = mount(setupWrapper({ isOpen: true })); render(setupWrapper({ isOpen: true }));
expect(wrapper.exists(ConfirmationModal)).toBeTruthy(); expect(screen.getByRole('dialog')).toHaveTextContent(body);
expect(wrapper.exists('div')).toBeTruthy(); expect(screen.getAllByRole('button').length).toEqual(2);
expect(wrapper.find('div > div:last-child > section').text()).toEqual(body);
expect(wrapper.find('div > div:last-child > footer button').length).toEqual(
2
);
}); });
it('renders modal with default header', () => { it('renders modal with default header', () => {
const wrapper = mount(setupWrapper({ isOpen: true })); render(setupWrapper({ isOpen: true }));
expect(wrapper.find('div > div:last-child > header > p').text()).toEqual( expect(screen.getByText('Confirm the action')).toBeInTheDocument();
'Confirm the action'
);
}); });
it('renders modal with custom header', () => { it('renders modal with custom header', () => {
const title = 'My Custom Header'; const title = 'My Custom Header';
const wrapper = mount(setupWrapper({ isOpen: true, title })); render(setupWrapper({ isOpen: true, title }));
expect(wrapper.find('div > div:last-child > header > p').text()).toEqual( expect(screen.getByText(title)).toBeInTheDocument();
title
);
}); });
it('Check the text on the submit button default behavior', () => { it('Check the text on the submit button default behavior', () => {
const wrapper = mount(setupWrapper({ isOpen: true })); render(setupWrapper({ isOpen: true }));
expect(wrapper.exists({ children: 'Submit' })).toBeTruthy(); expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument();
}); });
it('handles onConfirm when user clicks confirm button', () => { it('handles onConfirm when user clicks confirm button', () => {
const wrapper = mount(setupWrapper({ isOpen: true })); render(setupWrapper({ isOpen: true }));
const confirmBtn = wrapper.find({ children: 'Submit' }); const confirmBtn = screen.getByRole('button', { name: 'Submit' });
confirmBtn.at(2).simulate('click'); userEvent.click(confirmBtn);
expect(cancelMock).toHaveBeenCalledTimes(0); expect(cancelMock).toHaveBeenCalledTimes(0);
expect(confirmMock).toHaveBeenCalledTimes(1); expect(confirmMock).toHaveBeenCalledTimes(1);
}); });
it('Check the text on the submit button', () => { it('Check the text on the submit button', () => {
const submitBtnText = 'Submit btn Text'; const submitBtnText = 'Submit btn Text';
const wrapper = mount(setupWrapper({ isOpen: true, submitBtnText })); render(setupWrapper({ isOpen: true, submitBtnText }));
expect(wrapper.exists({ children: submitBtnText })).toBeTruthy(); expect(
screen.getByRole('button', { name: submitBtnText })
).toBeInTheDocument();
}); });
describe('cancellation', () => { describe('cancellation', () => {
let wrapper: ReactWrapper;
describe('when not confirming', () => { describe('when not confirming', () => {
beforeEach(() => { beforeEach(() => {
wrapper = mount(setupWrapper({ isOpen: true })); render(setupWrapper({ isOpen: true }));
}); });
it('handles onCancel when user clicks on modal-background', () => { it('handles onCancel when user clicks on modal-background', () => {
wrapper.find('div > div:first-child').simulate('click'); const { container } = render(setupWrapper({ isOpen: true }));
userEvent.click(container.children[0].children[0]);
expect(cancelMock).toHaveBeenCalledTimes(1); expect(cancelMock).toHaveBeenCalledTimes(1);
expect(confirmMock).toHaveBeenCalledTimes(0); expect(confirmMock).toHaveBeenCalledTimes(0);
}); });
it('handles onCancel when user clicks on Cancel button', () => { it('handles onCancel when user clicks on Cancel button', () => {
const cancelBtn = wrapper.find({ children: 'Cancel' }); const cancelBtn = screen.getByRole('button', { name: 'Cancel' });
cancelBtn.at(2).simulate('click');
userEvent.click(cancelBtn);
expect(cancelMock).toHaveBeenCalledTimes(1); expect(cancelMock).toHaveBeenCalledTimes(1);
expect(confirmMock).toHaveBeenCalledTimes(0); expect(confirmMock).toHaveBeenCalledTimes(0);
}); });
@ -91,16 +82,17 @@ describe('ConfirmationModal', () => {
describe('when confirming', () => { describe('when confirming', () => {
beforeEach(() => { beforeEach(() => {
wrapper = mount(setupWrapper({ isOpen: true, isConfirming: true })); render(setupWrapper({ isOpen: true, isConfirming: true }));
}); });
it('does not call onCancel when user clicks on modal-background', () => { it('does not call onCancel when user clicks on modal-background', () => {
wrapper.find('div > div:first-child').simulate('click'); userEvent.click(screen.getByRole('dialog'));
expect(cancelMock).toHaveBeenCalledTimes(0); expect(cancelMock).toHaveBeenCalledTimes(0);
expect(confirmMock).toHaveBeenCalledTimes(0); expect(confirmMock).toHaveBeenCalledTimes(0);
}); });
it('does not call onCancel when user clicks on Cancel button', () => { it('does not call onCancel when user clicks on Cancel button', () => {
const cancelBtn = wrapper.find({ children: 'Cancel' }); const cancelBtn = screen.getByRole('button', { name: 'Cancel' });
cancelBtn.at(2).simulate('click'); userEvent.click(cancelBtn);
expect(cancelMock).toHaveBeenCalledTimes(0); expect(cancelMock).toHaveBeenCalledTimes(0);
expect(confirmMock).toHaveBeenCalledTimes(0); expect(confirmMock).toHaveBeenCalledTimes(0);
}); });

View file

@ -22,7 +22,7 @@ const DiffViewer = React.forwardRef<DiffEditor | null, DiffViewerProps>(
) * 16 ) * 16
: 500; : 500;
return ( return (
<div data-testid="diffviewer"> <div>
<DiffEditor <DiffEditor
name="diff-editor" name="diff-editor"
ref={ref} ref={ref}

View file

@ -1,17 +1,17 @@
import React from 'react'; import React from 'react';
import { render } from 'lib/testHelpers';
import DiffViewer from 'components/common/DiffViewer/DiffViewer'; import DiffViewer from 'components/common/DiffViewer/DiffViewer';
import { screen } from '@testing-library/react'; import { render } from '@testing-library/react';
describe('Editor component', () => { describe('Editor component', () => {
const left = '{\n}'; const left = '{\n}';
const right = '{\ntest: true\n}'; const right = '{\ntest: true\n}';
const renderComponent = (props: { const renderComponent = (props: {
leftVersion?: string; leftVersion?: string;
rightVersion?: string; rightVersion?: string;
isFixedHeight?: boolean; isFixedHeight?: boolean;
}) => { }) => {
render( const { container } = render(
<DiffViewer <DiffViewer
value={[props.leftVersion ?? '', props.rightVersion ?? '']} value={[props.leftVersion ?? '', props.rightVersion ?? '']}
name="name" name="name"
@ -19,38 +19,42 @@ describe('Editor component', () => {
isFixedHeight={props.isFixedHeight} isFixedHeight={props.isFixedHeight}
/> />
); );
return container;
}; };
it('renders', () => { it('renders', () => {
renderComponent({ leftVersion: left, rightVersion: right }); const component = renderComponent({
expect(screen.getByTestId('diffviewer')).toBeInTheDocument(); leftVersion: left,
rightVersion: right,
});
expect(component).toBeInTheDocument();
}); });
it('renders with fixed height', () => { it('renders with fixed height', () => {
renderComponent({ const component = renderComponent({
leftVersion: left, leftVersion: left,
rightVersion: right, rightVersion: right,
isFixedHeight: true, isFixedHeight: true,
}); }).children[0].children[0];
const wrapper = screen.getByTestId('diffviewer'); expect(component).toHaveStyle('height: 500px;');
expect(wrapper.firstChild).toHaveStyle('height: 500px');
}); });
it('renders with fixed height with no value', () => { it('renders with fixed height with no value', () => {
renderComponent({ isFixedHeight: true }); const component = renderComponent({
const wrapper = screen.getByTestId('diffviewer'); isFixedHeight: true,
expect(wrapper.firstChild).toHaveStyle('height: 500px'); }).children[0].children[0];
expect(component).toHaveStyle('height: 500px;');
}); });
it('renders without fixed height with no value', () => { it('renders without fixed height with no value', () => {
renderComponent({}); const component = renderComponent({}).children[0].children[0];
const wrapper = screen.getByTestId('diffviewer'); expect(component).toHaveStyle('height: 32px;');
expect(wrapper.firstChild).toHaveStyle('height: 32px');
}); });
it('renders without fixed height with one value', () => { it('renders without fixed height with one value', () => {
renderComponent({ leftVersion: left }); const component = renderComponent({
const wrapper = screen.getByTestId('diffviewer'); leftVersion: left,
expect(wrapper.firstChild).toHaveStyle('height: 48px'); }).children[0].children[0];
expect(component).toHaveStyle('height: 48px;');
}); });
}); });

View file

@ -66,8 +66,8 @@ describe('Dropdown', () => {
expect(wrapper.querySelector('.dropdown.is-active')).toBeTruthy(); expect(wrapper.querySelector('.dropdown.is-active')).toBeTruthy();
}); });
it('matches snapshot', () => { it('to be in the document', () => {
const { baseElement } = render( render(
setupWrapper( setupWrapper(
{ {
right: true, right: true,
@ -76,6 +76,6 @@ describe('Dropdown', () => {
dummyChildren dummyChildren
) )
); );
expect(baseElement).toMatchSnapshot(); expect(screen.getByRole('menu')).toBeInTheDocument();
}); });
}); });

View file

@ -7,20 +7,14 @@ import { screen } from '@testing-library/react';
const onClick = jest.fn(); const onClick = jest.fn();
describe('DropdownItem', () => { describe('DropdownItem', () => {
it('matches snapshot', () => { it('to be in the document', () => {
const { baseElement } = render( render(<DropdownItem onClick={jest.fn()}>Item 1</DropdownItem>);
<DropdownItem onClick={jest.fn()}>Item 1</DropdownItem> expect(screen.getByText('Item 1')).toBeInTheDocument();
);
expect(onClick).not.toHaveBeenCalled();
expect(baseElement).toMatchSnapshot();
}); });
it('handles Click', () => { it('handles Click', () => {
render(<DropdownItem onClick={onClick}>Item 1</DropdownItem>); render(<DropdownItem onClick={onClick}>Item 1</DropdownItem>);
userEvent.click(screen.getByText('Item 1'));
const dropDown = screen.getByText('Item 1');
userEvent.click(dropDown);
expect(onClick).toHaveBeenCalled(); expect(onClick).toHaveBeenCalled();
}); });
}); });

View file

@ -1,94 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Dropdown matches snapshot 1`] = `
.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-self: center;
-ms-flex-item-align: center;
align-self: center;
}
.c1 {
background: transparent;
border: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: 'center';
-webkit-box-align: 'center';
-ms-flex-align: 'center';
align-items: 'center';
-webkit-box-pack: 'center';
-webkit-justify-content: 'center';
-ms-flex-pack: 'center';
justify-content: 'center';
}
.c1:hover {
cursor: pointer;
}
.c2 {
color: initial;
}
<body>
<div>
<div
class="dropdown is-right is-up"
>
<div
class="c0"
>
<button
class="c1"
type="button"
>
My Test Label
</button>
</div>
<div
class="dropdown-menu"
id="dropdown-menu"
role="menu"
>
<div
class="dropdown-content has-text-left"
>
<a
class="c2 dropdown-item is-link"
href="#end"
role="menuitem"
type="button"
>
Child 1
</a>
<a
class="c2 dropdown-item is-link"
href="#end"
role="menuitem"
type="button"
>
Child 2
</a>
<hr
class="dropdown-divider"
/>
<a
class="c2 dropdown-item is-link"
href="#end"
role="menuitem"
type="button"
>
Child 3
</a>
</div>
</div>
</div>
</div>
</body>
`;

View file

@ -1,20 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DropdownItem matches snapshot 1`] = `
.c0 {
color: initial;
}
<body>
<div>
<a
class="c0 dropdown-item is-link"
href="#end"
role="menuitem"
type="button"
>
Item 1
</a>
</div>
</body>
`;

View file

@ -23,7 +23,7 @@ const EditorViewer: React.FC<FullMessageProps> = ({
}) => { }) => {
try { try {
return ( return (
<StyledWrapper data-testid="json-viewer"> <StyledWrapper>
<Editor <Editor
isFixedHeight isFixedHeight
schemaType={schemaType} schemaType={schemaType}
@ -40,7 +40,7 @@ const EditorViewer: React.FC<FullMessageProps> = ({
); );
} catch (e) { } catch (e) {
return ( return (
<StyledWrapper data-testid="json-viewer"> <StyledWrapper>
<p>{data}</p> <p>{data}</p>
</StyledWrapper> </StyledWrapper>
); );

View file

@ -22,7 +22,7 @@ describe('EditorViewer component', () => {
expect(screen.getByRole('textbox')).toBeInTheDocument(); expect(screen.getByRole('textbox')).toBeInTheDocument();
}); });
it('matches the snapshot with fixed height with no value', () => { it('to be in the document with fixed height with no value', () => {
setupComponent({ setupComponent({
data: '', data: '',
maxLines, maxLines,

View file

@ -1,5 +1,6 @@
import Input, { InputProps } from 'components/common/Input/Input'; import Input, { InputProps } from 'components/common/Input/Input';
import React from 'react'; import React from 'react';
import { screen } from '@testing-library/react';
import { render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
const setupWrapper = (props?: Partial<InputProps>) => ( const setupWrapper = (props?: Partial<InputProps>) => (
@ -12,21 +13,9 @@ jest.mock('react-hook-form', () => ({
})); }));
describe('Custom Input', () => { describe('Custom Input', () => {
describe('with no icons', () => { describe('with no icons', () => {
it('matches the snapshot', () => { it('to be in the document', () => {
const component = render(setupWrapper()); render(setupWrapper());
expect(component.baseElement).toMatchSnapshot(); expect(screen.getByRole('textbox')).toBeInTheDocument();
});
});
describe('with icons', () => {
it('matches the snapshot', () => {
const component = render(
setupWrapper({
leftIcon: 'fas fa-address-book',
rightIcon: 'fas fa-address-book',
})
);
expect(component.baseElement).toMatchSnapshot();
}); });
}); });
}); });

View file

@ -1,217 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Custom Input with icons matches the snapshot 1`] = `
<body>
.c1 {
position: absolute;
top: 50%;
line-height: 0;
z-index: 1;
left: 12px;
right: unset;
height: 11px;
width: 11px;
color: #454F54;
}
.c3 {
position: absolute;
top: 50%;
line-height: 0;
z-index: 1;
left: unset;
right: 15px;
height: 11px;
width: 11px;
color: #454F54;
}
.c2 {
border: 1px #ABB5BA solid;
border-radius: 4px;
height: 40px;
width: 100%;
padding-left: 36px;
font-size: 14px;
}
.c2::-webkit-input-placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c2::-moz-placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c2:-ms-input-placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c2::placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c2:hover {
border-color: #73848C;
}
.c2:focus {
outline: none;
border-color: #454F54;
}
.c2:focus::-webkit-input-placeholder {
color: transparent;
}
.c2:focus::-moz-placeholder {
color: transparent;
}
.c2:focus:-ms-input-placeholder {
color: transparent;
}
.c2:focus::placeholder {
color: transparent;
}
.c2:disabled {
color: #ABB5BA;
border-color: #E3E6E8;
cursor: not-allowed;
}
.c2:read-only {
color: #171A1C;
border: none;
background-color: #F1F2F3;
cursor: not-allowed;
}
.c2:-moz-read-only:focus::placeholder {
color: #ABB5BA;
}
.c2:read-only:focus::placeholder {
color: #ABB5BA;
}
.c0 {
position: relative;
}
<div>
<div
class="c0"
>
<i
class="c1 fas fa-address-book"
/>
<input
class="c2 c0"
/>
<i
class="c3 fas fa-address-book"
/>
</div>
</div>
</body>
`;
exports[`Custom Input with no icons matches the snapshot 1`] = `
.c1 {
border: 1px #ABB5BA solid;
border-radius: 4px;
height: 40px;
width: 100%;
padding-left: 12px;
font-size: 14px;
}
.c1::-webkit-input-placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c1::-moz-placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c1:-ms-input-placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c1::placeholder {
color: #ABB5BA;
font-size: 14px;
}
.c1:hover {
border-color: #73848C;
}
.c1:focus {
outline: none;
border-color: #454F54;
}
.c1:focus::-webkit-input-placeholder {
color: transparent;
}
.c1:focus::-moz-placeholder {
color: transparent;
}
.c1:focus:-ms-input-placeholder {
color: transparent;
}
.c1:focus::placeholder {
color: transparent;
}
.c1:disabled {
color: #ABB5BA;
border-color: #E3E6E8;
cursor: not-allowed;
}
.c1:read-only {
color: #171A1C;
border: none;
background-color: #F1F2F3;
cursor: not-allowed;
}
.c1:-moz-read-only:focus::placeholder {
color: #ABB5BA;
}
.c1:read-only:focus::placeholder {
color: #ABB5BA;
}
.c0 {
position: relative;
}
<body>
<div>
<div
class="c0"
>
<input
class="c1 c0"
/>
</div>
</div>
</body>
`;

View file

@ -25,36 +25,38 @@ describe('Indicator', () => {
}); });
describe('should render circular alert', () => { describe('should render circular alert', () => {
const getCircle = () => screen.getByRole('circle');
it('should be in document', () => { it('should be in document', () => {
setupComponent({ title, label, isAlert: true }); setupComponent({ title, label, isAlert: true });
expect(screen.getByRole('svg')).toBeInTheDocument(); expect(screen.getByRole('svg')).toBeInTheDocument();
expect(screen.getByRole('circle')).toBeInTheDocument(); expect(getCircle()).toBeInTheDocument();
}); });
it('success alert', () => { it('success alert', () => {
setupComponent({ title, label, isAlert: true, alertType: 'success' }); setupComponent({ title, label, isAlert: true, alertType: 'success' });
expect(screen.getByRole('circle')).toHaveStyle( expect(getCircle()).toHaveStyle(
`fill: ${theme.circularAlert.color.success}` `fill: ${theme.circularAlert.color.success}`
); );
}); });
it('error alert', () => { it('error alert', () => {
setupComponent({ title, label, isAlert: true, alertType: 'error' }); setupComponent({ title, label, isAlert: true, alertType: 'error' });
expect(screen.getByRole('circle')).toHaveStyle( expect(getCircle()).toHaveStyle(
`fill: ${theme.circularAlert.color.error}` `fill: ${theme.circularAlert.color.error}`
); );
}); });
it('warning alert', () => { it('warning alert', () => {
setupComponent({ title, label, isAlert: true, alertType: 'warning' }); setupComponent({ title, label, isAlert: true, alertType: 'warning' });
expect(screen.getByRole('circle')).toHaveStyle( expect(getCircle()).toHaveStyle(
`fill: ${theme.circularAlert.color.warning}` `fill: ${theme.circularAlert.color.warning}`
); );
}); });
it('info alert', () => { it('info alert', () => {
setupComponent({ title, label, isAlert: true, alertType: 'info' }); setupComponent({ title, label, isAlert: true, alertType: 'info' });
expect(screen.getByRole('circle')).toHaveStyle( expect(getCircle()).toHaveStyle(
`fill: ${theme.circularAlert.color.info}` `fill: ${theme.circularAlert.color.info}`
); );
}); });

View file

@ -12,22 +12,24 @@ describe('PageControl', () => {
const setupComponent = (props: Partial<PageControlProps> = {}) => const setupComponent = (props: Partial<PageControlProps> = {}) =>
render(<PageControl url="/test" page={page} current {...props} />); render(<PageControl url="/test" page={page} current {...props} />);
const getButton = () => screen.getByRole('button');
it('renders current page', () => { it('renders current page', () => {
setupComponent({ current: true }); setupComponent({ current: true });
expect(screen.getByRole('button')).toHaveStyle( expect(getButton()).toHaveStyle(
`background-color: ${theme.pagination.currentPage}` `background-color: ${theme.pagination.currentPage}`
); );
}); });
it('renders non-current page', () => { it('renders non-current page', () => {
setupComponent({ current: false }); setupComponent({ current: false });
expect(screen.getByRole('button')).toHaveStyle( expect(getButton()).toHaveStyle(
`background-color: ${theme.pagination.backgroundColor}` `background-color: ${theme.pagination.backgroundColor}`
); );
}); });
it('renders page number', () => { it('renders page number', () => {
setupComponent({ current: false }); setupComponent({ current: false });
expect(screen.getByRole('button')).toHaveTextContent(String(page)); expect(getButton()).toHaveTextContent(String(page));
}); });
}); });

View file

@ -1,22 +1,22 @@
import React from 'react'; import React from 'react';
import SQLEditor from 'components/common/SQLEditor/SQLEditor'; import SQLEditor from 'components/common/SQLEditor/SQLEditor';
import { render } from 'lib/testHelpers'; import { render } from 'lib/testHelpers';
import { screen } from '@testing-library/react';
describe('SQLEditor component', () => { describe('SQLEditor component', () => {
it('matches the snapshot', () => { it('to be in the document with fixed height', () => {
const { baseElement } = render(<SQLEditor value="" name="name" />); render(<SQLEditor value="" name="name" isFixedHeight />);
expect(baseElement).toMatchSnapshot(); expect(
}); screen.getByRole('textbox').parentElement?.getAttribute('style') !==
'16px'
it('matches the snapshot with fixed height', () => {
const { baseElement } = render(
<SQLEditor value="" name="name" isFixedHeight />
); );
expect(baseElement).toMatchSnapshot();
}); });
it('matches the snapshot with fixed height with no value', () => { it('to be in the document with fixed height with no value', () => {
const { baseElement } = render(<SQLEditor name="name" isFixedHeight />); render(<SQLEditor value="" name="name" />);
expect(baseElement).toMatchSnapshot(); expect(
screen.getByRole('textbox').parentElement?.getAttribute('style') ===
'16px'
);
}); });
}); });

View file

@ -1,295 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SQLEditor component matches the snapshot 1`] = `
<body>
<div>
<div
class=" ace_editor ace_hidpi ace-tm"
id="name"
style="width: 100%; height: 372px; font-size: 12px;"
>
<textarea
autocapitalize="off"
autocorrect="off"
class="ace_text-input"
spellcheck="false"
style="opacity: 0; font-size: 1px;"
wrap="off"
/>
<div
aria-hidden="true"
class="ace_gutter"
>
<div
class="ace_layer ace_gutter-layer ace_folding-enabled"
style="height: 1000000px;"
/>
</div>
<div
class="ace_scroller"
style="line-height: 0px;"
>
<div
class="ace_content"
>
<div
class="ace_layer ace_print-margin-layer"
>
<div
class="ace_print-margin"
style="left: 4px; visibility: visible;"
/>
</div>
<div
class="ace_layer ace_marker-layer"
/>
<div
class="ace_layer ace_text-layer"
style="height: 1000000px; margin: 0px 4px;"
/>
<div
class="ace_layer ace_marker-layer"
/>
<div
class="ace_layer ace_cursor-layer ace_hidden-cursors"
>
<div
class="ace_cursor"
/>
</div>
</div>
</div>
<div
class="ace_scrollbar ace_scrollbar-v"
style="display: none; width: 20px;"
>
<div
class="ace_scrollbar-inner"
style="width: 20px;"
>
 
</div>
</div>
<div
class="ace_scrollbar ace_scrollbar-h"
style="display: none; height: 20px;"
>
<div
class="ace_scrollbar-inner"
style="height: 20px;"
>
 
</div>
</div>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
/>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</div>
</div>
</div>
</div>
</body>
`;
exports[`SQLEditor component matches the snapshot with fixed height 1`] = `
<body>
<div>
<div
class=" ace_editor ace_hidpi ace-tm"
id="name"
style="width: 100%; height: 16px; font-size: 12px;"
>
<textarea
autocapitalize="off"
autocorrect="off"
class="ace_text-input"
spellcheck="false"
style="opacity: 0; font-size: 1px;"
wrap="off"
/>
<div
aria-hidden="true"
class="ace_gutter"
>
<div
class="ace_layer ace_gutter-layer ace_folding-enabled"
style="height: 1000000px;"
/>
</div>
<div
class="ace_scroller"
style="line-height: 0px;"
>
<div
class="ace_content"
>
<div
class="ace_layer ace_print-margin-layer"
>
<div
class="ace_print-margin"
style="left: 4px; visibility: visible;"
/>
</div>
<div
class="ace_layer ace_marker-layer"
/>
<div
class="ace_layer ace_text-layer"
style="height: 1000000px; margin: 0px 4px;"
/>
<div
class="ace_layer ace_marker-layer"
/>
<div
class="ace_layer ace_cursor-layer ace_hidden-cursors"
>
<div
class="ace_cursor"
/>
</div>
</div>
</div>
<div
class="ace_scrollbar ace_scrollbar-v"
style="display: none; width: 20px;"
>
<div
class="ace_scrollbar-inner"
style="width: 20px;"
>
 
</div>
</div>
<div
class="ace_scrollbar ace_scrollbar-h"
style="display: none; height: 20px;"
>
<div
class="ace_scrollbar-inner"
style="height: 20px;"
>
 
</div>
</div>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
/>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</div>
</div>
</div>
</div>
</body>
`;
exports[`SQLEditor component matches the snapshot with fixed height with no value 1`] = `
<body>
<div>
<div
class=" ace_editor ace_hidpi ace-tm"
id="name"
style="width: 100%; height: 512px; font-size: 12px;"
>
<textarea
autocapitalize="off"
autocorrect="off"
class="ace_text-input"
spellcheck="false"
style="opacity: 0; font-size: 1px;"
wrap="off"
/>
<div
aria-hidden="true"
class="ace_gutter"
>
<div
class="ace_layer ace_gutter-layer ace_folding-enabled"
style="height: 1000000px;"
/>
</div>
<div
class="ace_scroller"
style="line-height: 0px;"
>
<div
class="ace_content"
>
<div
class="ace_layer ace_print-margin-layer"
>
<div
class="ace_print-margin"
style="left: 4px; visibility: visible;"
/>
</div>
<div
class="ace_layer ace_marker-layer"
/>
<div
class="ace_layer ace_text-layer"
style="height: 1000000px; margin: 0px 4px;"
/>
<div
class="ace_layer ace_marker-layer"
/>
<div
class="ace_layer ace_cursor-layer ace_hidden-cursors"
>
<div
class="ace_cursor"
/>
</div>
</div>
</div>
<div
class="ace_scrollbar ace_scrollbar-v"
style="display: none; width: 20px;"
>
<div
class="ace_scrollbar-inner"
style="width: 20px;"
>
 
</div>
</div>
<div
class="ace_scrollbar ace_scrollbar-h"
style="display: none; height: 20px;"
>
<div
class="ace_scrollbar-inner"
style="height: 20px;"
>
 
</div>
</div>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
/>
<div
style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</div>
</div>
</div>
</div>
</body>
`;

View file

@ -12,7 +12,7 @@ const SVGWrapper = styled.i`
const LiveIcon: React.FC<Props> = () => { const LiveIcon: React.FC<Props> = () => {
const theme = useTheme(); const theme = useTheme();
return ( return (
<SVGWrapper data-testid="liveIcon"> <SVGWrapper>
<svg <svg
width="16" width="16"
height="16" height="16"

View file

@ -29,37 +29,38 @@ describe('Custom Select', () => {
}); });
}); });
const getListbox = () => screen.getByRole('listbox');
const getOption = () => screen.getByRole('option');
it('renders component', () => { it('renders component', () => {
expect(screen.getByRole('listbox')).toBeInTheDocument(); expect(getListbox()).toBeInTheDocument();
}); });
it('show select options when select is being clicked', () => { it('show select options when select is being clicked', () => {
expect(screen.getByRole('option')).toBeInTheDocument(); expect(getOption()).toBeInTheDocument();
userEvent.click(screen.getByRole('listbox')); userEvent.click(getListbox());
expect(screen.getAllByRole('option')).toHaveLength(3); expect(screen.getAllByRole('option')).toHaveLength(3);
}); });
it('checking select option change', () => { it('checking select option change', () => {
const listbox = screen.getByRole('listbox');
const optionLabel = 'test-label1'; const optionLabel = 'test-label1';
userEvent.click(listbox); userEvent.click(getListbox());
userEvent.selectOptions(listbox, [optionLabel]); userEvent.selectOptions(getListbox(), [optionLabel]);
expect(screen.getByRole('option')).toHaveTextContent(optionLabel); expect(getOption()).toHaveTextContent(optionLabel);
}); });
it('trying to select disabled option does not trigger change', () => { it('trying to select disabled option does not trigger change', () => {
const listbox = screen.getByRole('listbox');
const normalOptionLabel = 'test-label1'; const normalOptionLabel = 'test-label1';
const disabledOptionLabel = 'test-label2'; const disabledOptionLabel = 'test-label2';
userEvent.click(listbox); userEvent.click(getListbox());
userEvent.selectOptions(listbox, [normalOptionLabel]); userEvent.selectOptions(getListbox(), [normalOptionLabel]);
userEvent.click(listbox); userEvent.click(getListbox());
userEvent.selectOptions(listbox, [disabledOptionLabel]); userEvent.selectOptions(getListbox(), [disabledOptionLabel]);
expect(screen.getByRole('option')).toHaveTextContent(normalOptionLabel); expect(getOption()).toHaveTextContent(normalOptionLabel);
}); });
}); });
@ -72,8 +73,8 @@ describe('Custom Select', () => {
describe('when live', () => { describe('when live', () => {
it('there is live icon', () => { it('there is live icon', () => {
renderComponent({ isLive: true }); render(<Select name="test" {...{ isLive: true }} />);
expect(screen.getByTestId('liveIcon')).toBeInTheDocument(); expect(screen.getByRole('listbox')).toBeInTheDocument();
}); });
}); });
}); });

View file

@ -1,43 +1,37 @@
import { mount, shallow } from 'enzyme';
import React from 'react'; import React from 'react';
import Tabs from 'components/common/Tabs/Tabs'; import Tabs from 'components/common/Tabs/Tabs';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('Tabs component', () => { describe('Tabs component', () => {
const tabs: string[] = ['Tab 1', 'Tab 2', 'Tab 3']; const tabs: string[] = ['Tab 1', 'Tab 2', 'Tab 3'];
const child1 = <div className="child_1" />; const child1 = <div data-testid="child_1" />;
const child2 = <div className="child_2" />; const child2 = <div data-testid="child_2" />;
const child3 = <div className="child_3" />; const child3 = <div data-testid="child_3" />;
const component = mount( beforeEach(() =>
render(
<Tabs tabs={tabs}> <Tabs tabs={tabs}>
{child1} {child1}
{child2} {child2}
{child3} {child3}
</Tabs> </Tabs>
)
); );
it('renders the tabs with default index 0', () => it('renders the tabs with default index 0', () => {
expect(component.find(`li`).at(0).hasClass('is-active')).toBeTruthy()); expect(screen.getAllByRole('listitem')[0]).toHaveClass('is-active');
});
it('renders the list of tabs', () => { it('renders the list of tabs', () => {
component.find(`a`).forEach((link, idx) => { screen.queryAllByRole('button').forEach((link, idx) => {
expect(link.contains(tabs[idx])).toBeTruthy(); expect(link).toHaveTextContent(tabs[idx]);
}); });
}); });
it('renders the children', () => { it('expects list items to be in the document', () => {
component.find(`a`).forEach((link, idx) => { screen.queryAllByRole('button').forEach((link, idx) => {
link.simulate('click'); userEvent.click(link);
expect(component.find(`.child_${idx + 1}`).exists()).toBeTruthy(); expect(screen.getByTestId(`child_${idx + 1}`)).toBeInTheDocument();
}); });
}); });
it('matches the snapshot', () => {
const shallowComponent = shallow(
<Tabs tabs={tabs}>
{child1}
{child2}
{child3}
</Tabs>
);
expect(shallowComponent).toMatchSnapshot();
});
}); });

View file

@ -1,55 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Tabs component matches the snapshot 1`] = `
<Fragment>
<div
className="tabs"
>
<ul>
<li
className="is-active"
key="Tab 1"
>
<a
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex={0}
>
Tab 1
</a>
</li>
<li
className=""
key="Tab 2"
>
<a
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex={1}
>
Tab 2
</a>
</li>
<li
className=""
key="Tab 3"
>
<a
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex={2}
>
Tab 3
</a>
</li>
</ul>
</div>
<div
className="child_1"
key=".0"
/>
</Fragment>
`;

View file

@ -6,8 +6,8 @@ interface HeadingBaseProps {
$level: HeadingLevel; $level: HeadingLevel;
} }
const HeadingBase = styled.h1<HeadingBaseProps>` const HeadingBase = styled.h1<HeadingBaseProps>`
${({ theme }) => theme.heading.base} ${({ theme }) => theme.heading?.base}
${({ theme, $level }) => theme.heading.variants[$level]} ${({ theme, $level }) => theme.heading?.variants[$level]}
`; `;
export interface Props { export interface Props {

View file

@ -1,11 +1,12 @@
import SortableColumnHeader from 'components/common/table/SortableCulumnHeader/SortableColumnHeader'; import SortableColumnHeader from 'components/common/table/SortableCulumnHeader/SortableColumnHeader';
import { mount } from 'enzyme';
import { TopicColumnsToSort } from 'generated-sources'; import { TopicColumnsToSort } from 'generated-sources';
import React from 'react'; import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('ListHeader', () => { describe('ListHeader', () => {
const setOrderBy = jest.fn(); const setOrderBy = jest.fn();
const component = mount( const component = (
<table> <table>
<thead> <thead>
<tr> <tr>
@ -19,19 +20,13 @@ describe('ListHeader', () => {
</thead> </thead>
</table> </table>
); );
it('matches the snapshot', () => {
expect(component).toMatchSnapshot();
});
describe('on column click', () => { describe('on column click', () => {
it('calls setOrderBy', () => { it('calls setOrderBy', () => {
component.find('th').simulate('click'); render(component);
userEvent.click(screen.getByRole('columnheader'));
expect(setOrderBy).toHaveBeenCalledTimes(1); expect(setOrderBy).toHaveBeenCalledTimes(1);
expect(setOrderBy).toHaveBeenCalledWith(TopicColumnsToSort.NAME); expect(setOrderBy).toHaveBeenCalledWith(TopicColumnsToSort.NAME);
}); });
it('matches the snapshot', () => {
expect(component).toMatchSnapshot();
});
}); });
}); });

View file

@ -28,10 +28,11 @@ describe('TableHeaderCell', () => {
</thead> </thead>
</table> </table>
); );
const getColumnHeader = () => screen.getByRole('columnheader');
it('renders without props', () => { it('renders without props', () => {
setupComponent(); setupComponent();
expect(screen.getByRole('columnheader')).toBeInTheDocument(); expect(getColumnHeader()).toBeInTheDocument();
}); });
it('renders with title & preview text', () => { it('renders with title & preview text', () => {
@ -40,9 +41,10 @@ describe('TableHeaderCell', () => {
previewText: testPreviewText, previewText: testPreviewText,
}); });
const columnheader = screen.getByRole('columnheader'); expect(within(getColumnHeader()).getByText(testTitle)).toBeInTheDocument();
expect(within(columnheader).getByText(testTitle)).toBeInTheDocument(); expect(
expect(within(columnheader).getByText(testPreviewText)).toBeInTheDocument(); within(getColumnHeader()).getByText(testPreviewText)
).toBeInTheDocument();
}); });
it('renders with orderable props', () => { it('renders with orderable props', () => {
@ -53,8 +55,7 @@ describe('TableHeaderCell', () => {
sortOrder: SortOrder.ASC, sortOrder: SortOrder.ASC,
handleOrderBy, handleOrderBy,
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByRole('button');
const title = within(columnheader).getByRole('button');
expect(title).toBeInTheDocument(); expect(title).toBeInTheDocument();
expect(title).toHaveTextContent(testTitle); expect(title).toHaveTextContent(testTitle);
expect(title).toHaveStyle(`color: ${theme.table.th.color.active};`); expect(title).toHaveStyle(`color: ${theme.table.th.color.active};`);
@ -67,8 +68,7 @@ describe('TableHeaderCell', () => {
orderValue: TopicColumnsToSort.NAME, orderValue: TopicColumnsToSort.NAME,
handleOrderBy, handleOrderBy,
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByRole('button');
const title = within(columnheader).getByRole('button');
userEvent.click(title); userEvent.click(title);
expect(handleOrderBy.mock.calls.length).toBe(1); expect(handleOrderBy.mock.calls.length).toBe(1);
}); });
@ -80,8 +80,7 @@ describe('TableHeaderCell', () => {
orderValue: TopicColumnsToSort.NAME, orderValue: TopicColumnsToSort.NAME,
handleOrderBy, handleOrderBy,
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByRole('button');
const title = within(columnheader).getByRole('button');
userEvent.type(title, SPACE_KEY); userEvent.type(title, SPACE_KEY);
// userEvent.type clicks and only then presses space // userEvent.type clicks and only then presses space
expect(handleOrderBy.mock.calls.length).toBe(2); expect(handleOrderBy.mock.calls.length).toBe(2);
@ -93,8 +92,7 @@ describe('TableHeaderCell', () => {
previewText: testPreviewText, previewText: testPreviewText,
onPreview, onPreview,
}); });
const columnheader = screen.getByRole('columnheader'); const preview = within(getColumnHeader()).getByRole('button');
const preview = within(columnheader).getByRole('button');
userEvent.click(preview); userEvent.click(preview);
expect(onPreview.mock.calls.length).toBe(1); expect(onPreview.mock.calls.length).toBe(1);
}); });
@ -105,10 +103,8 @@ describe('TableHeaderCell', () => {
previewText: testPreviewText, previewText: testPreviewText,
onPreview, onPreview,
}); });
const columnheader = screen.getByRole('columnheader'); const preview = within(getColumnHeader()).getByRole('button');
const preview = within(columnheader).getByRole('button');
userEvent.type(preview, SPACE_KEY); userEvent.type(preview, SPACE_KEY);
// userEvent.type clicks and only then presses space
expect(onPreview.mock.calls.length).toBe(2); expect(onPreview.mock.calls.length).toBe(2);
}); });
@ -118,8 +114,7 @@ describe('TableHeaderCell', () => {
orderBy: TopicColumnsToSort.NAME, orderBy: TopicColumnsToSort.NAME,
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByText(testTitle);
const title = within(columnheader).getByText(testTitle);
expect(within(title).queryByTitle(sortIconTitle)).not.toBeInTheDocument(); expect(within(title).queryByTitle(sortIconTitle)).not.toBeInTheDocument();
expect(title).toHaveStyle('cursor: default;'); expect(title).toHaveStyle('cursor: default;');
}); });
@ -132,8 +127,7 @@ describe('TableHeaderCell', () => {
sortOrder: SortOrder.ASC, sortOrder: SortOrder.ASC,
handleOrderBy: jest.fn(), handleOrderBy: jest.fn(),
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByText(testTitle);
const title = within(columnheader).getByText(testTitle);
expect(title).toHaveStyle(`color: ${theme.table.th.color.active};`); expect(title).toHaveStyle(`color: ${theme.table.th.color.active};`);
}); });
@ -144,8 +138,7 @@ describe('TableHeaderCell', () => {
orderValue: TopicColumnsToSort.OUT_OF_SYNC_REPLICAS, orderValue: TopicColumnsToSort.OUT_OF_SYNC_REPLICAS,
handleOrderBy: jest.fn(), handleOrderBy: jest.fn(),
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByText(testTitle);
const title = within(columnheader).getByText(testTitle);
expect(title).toHaveStyle(`color: ${theme.table.th.color.normal}`); expect(title).toHaveStyle(`color: ${theme.table.th.color.normal}`);
}); });
@ -154,8 +147,7 @@ describe('TableHeaderCell', () => {
title: testTitle, title: testTitle,
}); });
const columnheader = screen.getByRole('columnheader'); const title = within(getColumnHeader()).getByText(testTitle);
const title = within(columnheader).getByText(testTitle);
expect(title).toHaveStyle( expect(title).toHaveStyle(
`background: ${theme.table.th.backgroundColor.normal};` `background: ${theme.table.th.backgroundColor.normal};`
); );

View file

@ -1,45 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ListHeader matches the snapshot 1`] = `
<table>
<thead>
<tr>
<ListHeaderCell
orderBy={null}
setOrderBy={[MockFunction]}
title="Name"
value="NAME"
>
<th
className="is-clickable"
onClick={[Function]}
>
Name
</th>
</ListHeaderCell>
</tr>
</thead>
</table>
`;
exports[`ListHeader on column click matches the snapshot 1`] = `
<table>
<thead>
<tr>
<ListHeaderCell
orderBy={null}
setOrderBy={[MockFunction]}
title="Name"
value="NAME"
>
<th
className="is-clickable"
onClick={[Function]}
>
Name
</th>
</ListHeaderCell>
</tr>
</thead>
</table>
`;

View file

@ -1,81 +1,32 @@
import React, { ReactElement } from 'react'; import React, { ReactElement } from 'react';
import { MemoryRouter, Route, StaticRouter } from 'react-router-dom'; import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { store as appStore } from 'redux/store';
import { ThemeProvider } from 'styled-components'; import { ThemeProvider } from 'styled-components';
import theme from 'theme/theme'; import theme from 'theme/theme';
import { render, RenderOptions } from '@testing-library/react'; import { render, RenderOptions, screen } from '@testing-library/react';
import { AnyAction, Store } from 'redux'; import { AnyAction, Store } from 'redux';
import { RootState } from 'redux/interfaces'; import { RootState } from 'redux/interfaces';
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import rootReducer from 'redux/reducers'; import rootReducer from 'redux/reducers';
import mockStoreCreator from 'redux/store/configureStore/mockStoreCreator'; import mockStoreCreator from 'redux/store/configureStore/mockStoreCreator';
interface TestRouterWrapperProps {
pathname: string;
urlParams: {
[key: string]: string;
};
}
export const TestRouterWrapper: React.FC<TestRouterWrapperProps> = ({
children,
pathname,
urlParams,
}) => (
<MemoryRouter
initialEntries={[
{
key: 'test',
pathname: Object.keys(urlParams).reduce(
(acc, param) => acc.replace(`:${param}`, urlParams[param]),
pathname
),
},
]}
>
<Route path={pathname}>{children}</Route>
</MemoryRouter>
);
export const containerRendersView = (
container: React.ReactElement,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
view: React.FC<any>
) => {
describe('container', () => {
it('renders view', async () => {
let wrapper = mount(<div />);
await act(async () => {
wrapper = mount(
<Provider store={appStore}>
<StaticRouter>
<ThemeProvider theme={theme}>{container}</ThemeProvider>
</StaticRouter>
</Provider>
);
});
expect(wrapper.exists(view)).toBeTruthy();
});
});
};
export function mountWithTheme(child: ReactElement) {
return mount(child, {
wrappingComponent: ({ children }) => (
<ThemeProvider theme={theme}>{children}</ThemeProvider>
),
});
}
interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> { interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
preloadedState?: Partial<RootState>; preloadedState?: Partial<RootState>;
store?: Store<Partial<RootState>, AnyAction>; store?: Store<Partial<RootState>, AnyAction>;
pathname?: string; pathname?: string;
} }
export function getByTextContent(textMatch: string | RegExp): HTMLElement {
return screen.getByText((content, node) => {
const hasText = (nod: Element) => nod.textContent === textMatch;
const nodeHasText = hasText(node as Element);
const childrenDontHaveText = Array.from(node?.children || []).every(
(child) => !hasText(child)
);
return nodeHasText && childrenDontHaveText;
});
}
const customRender = ( const customRender = (
ui: ReactElement, ui: ReactElement,
{ {

View file

@ -1,24 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TopicMessages reducer Adds new message 1`] = `
Object {
"isFetching": false,
"messages": Array [
Object {
"content": "{\\"host\\":\\"schemaregistry1\\",\\"port\\":8085,\\"master_eligibility\\":true,\\"scheme\\":\\"http\\",\\"version\\":1}",
"headers": Object {},
"key": "schema-registry",
"offset": 14,
"partition": 29,
"timestamp": 2021-07-21T23:25:14.865Z,
"timestampType": "CREATE_TIME",
},
],
"meta": Object {
"bytesConsumed": 0,
"elapsedMs": 0,
"isCancelled": false,
"messagesConsumed": 0,
},
}
`;

View file

@ -19,7 +19,6 @@ describe('TopicMessages reducer', () => {
addTopicMessage({ message: topicMessagePayload }) addTopicMessage({ message: topicMessagePayload })
); );
expect(state.messages.length).toEqual(1); expect(state.messages.length).toEqual(1);
expect(state).toMatchSnapshot();
}); });
it('Adds new message with live tailing one', () => { it('Adds new message with live tailing one', () => {