Browse Source

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>
Oleg Shur 3 years ago
parent
commit
a94697c6af
68 changed files with 1042 additions and 3891 deletions
  1. 3 2
      kafka-ui-react-app/src/components/Alerts/__tests__/Alert.spec.tsx
  2. 202 94
      kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx
  3. 0 1309
      kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/__snapshots__/Actions.spec.tsx.snap
  4. 51 52
      kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx
  5. 0 25
      kafka-ui-react-app/src/components/Connect/Details/Config/__test__/__snapshots__/Config.spec.tsx.snap
  6. 30 28
      kafka-ui-react-app/src/components/Connect/Details/Overview/__tests__/Overview.spec.tsx
  7. 0 239
      kafka-ui-react-app/src/components/Connect/Details/Overview/__tests__/__snapshots__/Overview.spec.tsx.snap
  8. 31 27
      kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx
  9. 0 286
      kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/__snapshots__/Tasks.spec.tsx.snap
  10. 78 67
      kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx
  11. 0 175
      kafka-ui-react-app/src/components/Connect/Details/__tests__/__snapshots__/Details.spec.tsx.snap
  12. 61 70
      kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx
  13. 32 57
      kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx
  14. 44 44
      kafka-ui-react-app/src/components/Connect/List/__tests__/ListItem.spec.tsx
  15. 70 74
      kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx
  16. 1 5
      kafka-ui-react-app/src/components/ConsumerGroups/Details/ListItem.tsx
  17. 1 2
      kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx
  18. 21 38
      kafka-ui-react-app/src/components/ConsumerGroups/List/__test__/ListItem.spec.tsx
  19. 2 2
      kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClustersWidget.tsx
  20. 5 19
      kafka-ui-react-app/src/components/Dashboard/ClustersWidget/__test__/ClustersWidgetContainer.spec.tsx
  21. 11 3
      kafka-ui-react-app/src/components/Dashboard/__test__/Dashboard.spec.tsx
  22. 7 12
      kafka-ui-react-app/src/components/KsqlDb/__test__/KsqlDb.spec.tsx
  23. 0 38
      kafka-ui-react-app/src/components/KsqlDb/__test__/__snapshots__/KsqlDb.spec.tsx.snap
  24. 7 9
      kafka-ui-react-app/src/components/Nav/ClusterTab/__tests__/ClusterTab.styled.spec.tsx
  25. 36 29
      kafka-ui-react-app/src/components/Nav/__tests__/ClusterMenu.spec.tsx
  26. 11 8
      kafka-ui-react-app/src/components/Nav/__tests__/ClusterMenuItem.spec.tsx
  27. 7 4
      kafka-ui-react-app/src/components/Nav/__tests__/Nav.spec.tsx
  28. 1 1
      kafka-ui-react-app/src/components/Schemas/Details/LatestVersion/LatestVersionItem.tsx
  29. 2 10
      kafka-ui-react-app/src/components/Schemas/Details/__test__/LatestVersionItem.spec.tsx
  30. 9 11
      kafka-ui-react-app/src/components/Schemas/Details/__test__/SchemaVersion.spec.tsx
  31. 9 22
      kafka-ui-react-app/src/components/Schemas/Diff/__test__/Diff.spec.tsx
  32. 28 34
      kafka-ui-react-app/src/components/Topics/List/__tests__/ListItem.spec.tsx
  33. 1 1
      kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.styled.ts
  34. 1 4
      kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/SavedFilters.tsx
  35. 4 2
      kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/Filters.spec.tsx
  36. 14 11
      kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/SavedFilters.spec.tsx
  37. 0 9
      kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/MessageContent/__tests__/MessageContent.spec.tsx
  38. 6 15
      kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/__test__/FiltersContainer.spec.tsx
  39. 11 8
      kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/ConfigListItem.spec.tsx
  40. 53 18
      kafka-ui-react-app/src/components/common/Button/__tests__/Button.spec.tsx
  41. 17 17
      kafka-ui-react-app/src/components/common/BytesFormatted/__tests__/BytesFormatted.spec.tsx
  42. 1 1
      kafka-ui-react-app/src/components/common/ConfirmationModal/ConfirmationModal.tsx
  43. 39 47
      kafka-ui-react-app/src/components/common/ConfirmationModal/__test__/ConfirmationModal.spec.tsx
  44. 1 1
      kafka-ui-react-app/src/components/common/DiffViewer/DiffViewer.tsx
  45. 22 18
      kafka-ui-react-app/src/components/common/DiffViewer/__tests__/DiffViewer.spec.tsx
  46. 3 3
      kafka-ui-react-app/src/components/common/Dropdown/__tests__/Dropdown.spec.tsx
  47. 4 10
      kafka-ui-react-app/src/components/common/Dropdown/__tests__/DropdownItem.spec.tsx
  48. 0 94
      kafka-ui-react-app/src/components/common/Dropdown/__tests__/__snapshots__/Dropdown.spec.tsx.snap
  49. 0 20
      kafka-ui-react-app/src/components/common/Dropdown/__tests__/__snapshots__/DropdownItem.spec.tsx.snap
  50. 2 2
      kafka-ui-react-app/src/components/common/EditorViewer/EditorViewer.tsx
  51. 1 1
      kafka-ui-react-app/src/components/common/EditorViewer/__test__/EditorViewer.spec.tsx
  52. 4 15
      kafka-ui-react-app/src/components/common/Input/__tests__/Input.spec.tsx
  53. 0 217
      kafka-ui-react-app/src/components/common/Input/__tests__/__snapshots__/Input.spec.tsx.snap
  54. 7 5
      kafka-ui-react-app/src/components/common/Metrics/__tests__/Indicator.spec.tsx
  55. 5 3
      kafka-ui-react-app/src/components/common/Pagination/__tests__/PageControl.spec.tsx
  56. 12 12
      kafka-ui-react-app/src/components/common/SQLEditor/__tests__/SQLEditor.spec.tsx
  57. 0 295
      kafka-ui-react-app/src/components/common/SQLEditor/__tests__/__snapshots__/SQLEditor.spec.tsx.snap
  58. 1 1
      kafka-ui-react-app/src/components/common/Select/LiveIcon.styled.tsx
  59. 16 15
      kafka-ui-react-app/src/components/common/Select/__tests__/Select.spec.tsx
  60. 22 28
      kafka-ui-react-app/src/components/common/Tabs/__tests__/Tabs.spec.tsx
  61. 0 55
      kafka-ui-react-app/src/components/common/Tabs/__tests__/__snapshots__/Tabs.spec.tsx.snap
  62. 2 2
      kafka-ui-react-app/src/components/common/heading/Heading.styled.tsx
  63. 5 10
      kafka-ui-react-app/src/components/common/table/__tests__/SortableColumnHeader.spec.tsx
  64. 15 23
      kafka-ui-react-app/src/components/common/table/__tests__/TableHeaderCell.spec.tsx
  65. 0 45
      kafka-ui-react-app/src/components/common/table/__tests__/__snapshots__/SortableColumnHeader.spec.tsx.snap
  66. 13 62
      kafka-ui-react-app/src/lib/testHelpers.tsx
  67. 0 24
      kafka-ui-react-app/src/redux/reducers/topicMessages/__test__/__snapshots__/reducer.spec.ts.snap
  68. 0 1
      kafka-ui-react-app/src/redux/reducers/topicMessages/__test__/reducer.spec.ts

+ 3 - 2
kafka-ui-react-app/src/components/Alerts/__tests__/Alert.spec.tsx

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

+ 202 - 94
kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx

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

+ 0 - 1309
kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/__snapshots__/Actions.spec.tsx.snap

@@ -1,1309 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Actions view matches snapshot 1`] = `
-.c1 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #E8E8FC;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c1:hover:enabled {
-  background: #D1D1FA;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c1:active:enabled {
-  background: #A3A3F5;
-  color: #171A1C;
-}
-
-.c1:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c1 a {
-  color: #171A1C;
-}
-
-.c1 i {
-  margin-right: 7px;
-}
-
-.c2 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #F1F2F3;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c2:hover:enabled {
-  background: #E3E6E8;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c2:active:enabled {
-  background: #D5DADD;
-  color: #171A1C;
-}
-
-.c2:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c2 a {
-  color: #171A1C;
-}
-
-.c2 i {
-  margin-right: 7px;
-}
-
-.c0 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  gap: 8px;
-}
-
-<div
-  className="c0"
->
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-pause"
-      />
-    </span>
-    <span>
-      Pause
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Connector
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart All Tasks
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Failed Tasks
-    </span>
-  </button>
-  <a
-    href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
-    onClick={[Function]}
-  >
-    <button
-      className="c1"
-      disabled={false}
-      type="button"
-    >
-      <span>
-        <i
-          className="fas fa-pencil-alt"
-        />
-      </span>
-      <span>
-        Edit Config
-      </span>
-    </button>
-  </a>
-  <button
-    className="c2"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="far fa-trash-alt"
-      />
-    </span>
-    <span>
-      Delete
-    </span>
-  </button>
-  <mock-ConfirmationModal
-    isConfirming={false}
-    isOpen={false}
-    onCancel={[Function]}
-    onConfirm={[Function]}
-  >
-    Are you sure you want to remove 
-    <b>
-      my-connector
-    </b>
-     connector?
-  </mock-ConfirmationModal>
-</div>
-`;
-
-exports[`Actions view matches snapshot when deleting connector 1`] = `
-.c1 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #E8E8FC;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c1:hover:enabled {
-  background: #D1D1FA;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c1:active:enabled {
-  background: #A3A3F5;
-  color: #171A1C;
-}
-
-.c1:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c1 a {
-  color: #171A1C;
-}
-
-.c1 i {
-  margin-right: 7px;
-}
-
-.c2 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #F1F2F3;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c2:hover:enabled {
-  background: #E3E6E8;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c2:active:enabled {
-  background: #D5DADD;
-  color: #171A1C;
-}
-
-.c2:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c2 a {
-  color: #171A1C;
-}
-
-.c2 i {
-  margin-right: 7px;
-}
-
-.c0 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  gap: 8px;
-}
-
-<div
-  className="c0"
->
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-pause"
-      />
-    </span>
-    <span>
-      Pause
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Connector
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart All Tasks
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Failed Tasks
-    </span>
-  </button>
-  <a
-    href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
-    onClick={[Function]}
-  >
-    <button
-      className="c1"
-      disabled={false}
-      type="button"
-    >
-      <span>
-        <i
-          className="fas fa-pencil-alt"
-        />
-      </span>
-      <span>
-        Edit Config
-      </span>
-    </button>
-  </a>
-  <button
-    className="c2"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="far fa-trash-alt"
-      />
-    </span>
-    <span>
-      Delete
-    </span>
-  </button>
-  <mock-ConfirmationModal
-    isConfirming={true}
-    isOpen={false}
-    onCancel={[Function]}
-    onConfirm={[Function]}
-  >
-    Are you sure you want to remove 
-    <b>
-      my-connector
-    </b>
-     connector?
-  </mock-ConfirmationModal>
-</div>
-`;
-
-exports[`Actions view matches snapshot when failed 1`] = `
-.c1 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #E8E8FC;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c1:hover:enabled {
-  background: #D1D1FA;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c1:active:enabled {
-  background: #A3A3F5;
-  color: #171A1C;
-}
-
-.c1:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c1 a {
-  color: #171A1C;
-}
-
-.c1 i {
-  margin-right: 7px;
-}
-
-.c2 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #F1F2F3;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c2:hover:enabled {
-  background: #E3E6E8;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c2:active:enabled {
-  background: #D5DADD;
-  color: #171A1C;
-}
-
-.c2:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c2 a {
-  color: #171A1C;
-}
-
-.c2 i {
-  margin-right: 7px;
-}
-
-.c0 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  gap: 8px;
-}
-
-<div
-  className="c0"
->
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Connector
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart All Tasks
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Failed Tasks
-    </span>
-  </button>
-  <a
-    href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
-    onClick={[Function]}
-  >
-    <button
-      className="c1"
-      disabled={false}
-      type="button"
-    >
-      <span>
-        <i
-          className="fas fa-pencil-alt"
-        />
-      </span>
-      <span>
-        Edit Config
-      </span>
-    </button>
-  </a>
-  <button
-    className="c2"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="far fa-trash-alt"
-      />
-    </span>
-    <span>
-      Delete
-    </span>
-  </button>
-  <mock-ConfirmationModal
-    isConfirming={false}
-    isOpen={false}
-    onCancel={[Function]}
-    onConfirm={[Function]}
-  >
-    Are you sure you want to remove 
-    <b>
-      my-connector
-    </b>
-     connector?
-  </mock-ConfirmationModal>
-</div>
-`;
-
-exports[`Actions view matches snapshot when paused 1`] = `
-.c1 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #E8E8FC;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c1:hover:enabled {
-  background: #D1D1FA;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c1:active:enabled {
-  background: #A3A3F5;
-  color: #171A1C;
-}
-
-.c1:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c1 a {
-  color: #171A1C;
-}
-
-.c1 i {
-  margin-right: 7px;
-}
-
-.c2 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #F1F2F3;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c2:hover:enabled {
-  background: #E3E6E8;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c2:active:enabled {
-  background: #D5DADD;
-  color: #171A1C;
-}
-
-.c2:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c2 a {
-  color: #171A1C;
-}
-
-.c2 i {
-  margin-right: 7px;
-}
-
-.c0 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  gap: 8px;
-}
-
-<div
-  className="c0"
->
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-play"
-      />
-    </span>
-    <span>
-      Resume
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Connector
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart All Tasks
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Failed Tasks
-    </span>
-  </button>
-  <a
-    href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
-    onClick={[Function]}
-  >
-    <button
-      className="c1"
-      disabled={false}
-      type="button"
-    >
-      <span>
-        <i
-          className="fas fa-pencil-alt"
-        />
-      </span>
-      <span>
-        Edit Config
-      </span>
-    </button>
-  </a>
-  <button
-    className="c2"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="far fa-trash-alt"
-      />
-    </span>
-    <span>
-      Delete
-    </span>
-  </button>
-  <mock-ConfirmationModal
-    isConfirming={false}
-    isOpen={false}
-    onCancel={[Function]}
-    onConfirm={[Function]}
-  >
-    Are you sure you want to remove 
-    <b>
-      my-connector
-    </b>
-     connector?
-  </mock-ConfirmationModal>
-</div>
-`;
-
-exports[`Actions view matches snapshot when running connector action 1`] = `
-.c1 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #E8E8FC;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c1:hover:enabled {
-  background: #D1D1FA;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c1:active:enabled {
-  background: #A3A3F5;
-  color: #171A1C;
-}
-
-.c1:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c1 a {
-  color: #171A1C;
-}
-
-.c1 i {
-  margin-right: 7px;
-}
-
-.c2 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #F1F2F3;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c2:hover:enabled {
-  background: #E3E6E8;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c2:active:enabled {
-  background: #D5DADD;
-  color: #171A1C;
-}
-
-.c2:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c2 a {
-  color: #171A1C;
-}
-
-.c2 i {
-  margin-right: 7px;
-}
-
-.c0 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  gap: 8px;
-}
-
-<div
-  className="c0"
->
-  <button
-    className="c1"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-pause"
-      />
-    </span>
-    <span>
-      Pause
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Connector
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart All Tasks
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Failed Tasks
-    </span>
-  </button>
-  <a
-    href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
-    onClick={[Function]}
-  >
-    <button
-      className="c1"
-      disabled={true}
-      type="button"
-    >
-      <span>
-        <i
-          className="fas fa-pencil-alt"
-        />
-      </span>
-      <span>
-        Edit Config
-      </span>
-    </button>
-  </a>
-  <button
-    className="c2"
-    disabled={true}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="far fa-trash-alt"
-      />
-    </span>
-    <span>
-      Delete
-    </span>
-  </button>
-  <mock-ConfirmationModal
-    isConfirming={false}
-    isOpen={false}
-    onCancel={[Function]}
-    onConfirm={[Function]}
-  >
-    Are you sure you want to remove 
-    <b>
-      my-connector
-    </b>
-     connector?
-  </mock-ConfirmationModal>
-</div>
-`;
-
-exports[`Actions view matches snapshot when unassigned 1`] = `
-.c1 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #E8E8FC;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c1:hover:enabled {
-  background: #D1D1FA;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c1:active:enabled {
-  background: #A3A3F5;
-  color: #171A1C;
-}
-
-.c1:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c1 a {
-  color: #171A1C;
-}
-
-.c1 i {
-  margin-right: 7px;
-}
-
-.c2 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-  -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;
-  padding: 0px 12px;
-  border: none;
-  border-radius: 4px;
-  white-space: nowrap;
-  background: #F1F2F3;
-  color: #171A1C;
-  font-size: 14px;
-  font-weight: 500;
-  height: 32px;
-}
-
-.c2:hover:enabled {
-  background: #E3E6E8;
-  color: #171A1C;
-  cursor: pointer;
-}
-
-.c2:active:enabled {
-  background: #D5DADD;
-  color: #171A1C;
-}
-
-.c2:disabled {
-  opacity: 0.5;
-  cursor: not-allowed;
-}
-
-.c2 a {
-  color: #171A1C;
-}
-
-.c2 i {
-  margin-right: 7px;
-}
-
-.c0 {
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  gap: 8px;
-}
-
-<div
-  className="c0"
->
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Connector
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart All Tasks
-    </span>
-  </button>
-  <button
-    className="c1"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="fas fa-sync-alt"
-      />
-    </span>
-    <span>
-      Restart Failed Tasks
-    </span>
-  </button>
-  <a
-    href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
-    onClick={[Function]}
-  >
-    <button
-      className="c1"
-      disabled={false}
-      type="button"
-    >
-      <span>
-        <i
-          className="fas fa-pencil-alt"
-        />
-      </span>
-      <span>
-        Edit Config
-      </span>
-    </button>
-  </a>
-  <button
-    className="c2"
-    disabled={false}
-    onClick={[Function]}
-    type="button"
-  >
-    <span>
-      <i
-        className="far fa-trash-alt"
-      />
-    </span>
-    <span>
-      Delete
-    </span>
-  </button>
-  <mock-ConfirmationModal
-    isConfirming={false}
-    isOpen={false}
-    onCancel={[Function]}
-    onConfirm={[Function]}
-  >
-    Are you sure you want to remove 
-    <b>
-      my-connector
-    </b>
-     connector?
-  </mock-ConfirmationModal>
-</div>
-`;

+ 51 - 52
kafka-ui-react-app/src/components/Connect/Details/Config/__test__/Config.spec.tsx

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

+ 0 - 25
kafka-ui-react-app/src/components/Connect/Details/Config/__test__/__snapshots__/Config.spec.tsx.snap

@@ -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 />`;

+ 30 - 28
kafka-ui-react-app/src/components/Connect/Details/Overview/__tests__/Overview.spec.tsx

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

+ 0 - 239
kafka-ui-react-app/src/components/Connect/Details/Overview/__tests__/__snapshots__/Overview.spec.tsx.snap

@@ -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>
-`;

+ 31 - 27
kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/Tasks.spec.tsx

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

+ 0 - 286
kafka-ui-react-app/src/components/Connect/Details/Tasks/__tests__/__snapshots__/Tasks.spec.tsx.snap

@@ -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>
-`;

+ 78 - 67
kafka-ui-react-app/src/components/Connect/Details/__tests__/Details.spec.tsx

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

+ 0 - 175
kafka-ui-react-app/src/components/Connect/Details/__tests__/__snapshots__/Details.spec.tsx.snap

@@ -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 />`;

+ 61 - 70
kafka-ui-react-app/src/components/Connect/Edit/__tests__/Edit.spec.tsx

@@ -1,10 +1,9 @@
 import React from 'react';
-import { containerRendersView, render } from 'lib/testHelpers';
+import { render } from 'lib/testHelpers';
 import {
   clusterConnectConnectorConfigPath,
   clusterConnectConnectorEditPath,
 } from 'lib/paths';
-import EditContainer from 'components/Connect/Edit/EditContainer';
 import Edit, { EditProps } from 'components/Connect/Edit/Edit';
 import { connector } from 'redux/reducers/connect/__test__/fixtures';
 import { Route } from 'react-router';
@@ -24,81 +23,73 @@ jest.mock('react-router-dom', () => ({
 }));
 
 describe('Edit', () => {
-  containerRendersView(<EditContainer />, Edit);
+  const pathname = clusterConnectConnectorEditPath(
+    ':clusterName',
+    ':connectName',
+    ':connectorName'
+  );
+  const clusterName = 'my-cluster';
+  const connectName = 'my-connect';
+  const connectorName = 'my-connector';
 
-  describe('view', () => {
-    const pathname = clusterConnectConnectorEditPath(
-      ':clusterName',
-      ':connectName',
-      ':connectorName'
+  const renderComponent = (props: Partial<EditProps> = {}) =>
+    render(
+      <Route path={pathname}>
+        <Edit
+          fetchConfig={jest.fn()}
+          isConfigFetching={false}
+          config={connector.config}
+          updateConfig={jest.fn()}
+          {...props}
+        />
+      </Route>,
+      {
+        pathname: clusterConnectConnectorEditPath(
+          clusterName,
+          connectName,
+          connectorName
+        ),
+      }
     );
-    const clusterName = 'my-cluster';
-    const connectName = 'my-connect';
-    const connectorName = 'my-connector';
-
-    const renderComponent = (props: Partial<EditProps> = {}) =>
-      render(
-        <Route path={pathname}>
-          <Edit
-            fetchConfig={jest.fn()}
-            isConfigFetching={false}
-            config={connector.config}
-            updateConfig={jest.fn()}
-            {...props}
-          />
-        </Route>,
-        {
-          pathname: clusterConnectConnectorEditPath(
-            clusterName,
-            connectName,
-            connectorName
-          ),
-        }
-      );
 
-    it('fetches config on mount', () => {
-      const fetchConfig = jest.fn();
-      renderComponent({ fetchConfig });
-      expect(fetchConfig).toHaveBeenCalledTimes(1);
-      expect(fetchConfig).toHaveBeenCalledWith({
-        clusterName,
-        connectName,
-        connectorName,
-      });
+  it('fetches config on mount', () => {
+    const fetchConfig = jest.fn();
+    renderComponent({ fetchConfig });
+    expect(fetchConfig).toHaveBeenCalledTimes(1);
+    expect(fetchConfig).toHaveBeenCalledWith({
+      clusterName,
+      connectName,
+      connectorName,
     });
+  });
 
-    it('calls updateConfig on form submit', async () => {
-      const updateConfig = jest.fn();
-      renderComponent({ updateConfig });
-      await waitFor(() => fireEvent.submit(screen.getByRole('form')));
-      expect(updateConfig).toHaveBeenCalledTimes(1);
-      expect(updateConfig).toHaveBeenCalledWith({
-        clusterName,
-        connectName,
-        connectorName,
-        connectorConfig: connector.config,
-      });
+  it('calls updateConfig on form submit', async () => {
+    const updateConfig = jest.fn();
+    renderComponent({ updateConfig });
+    await waitFor(() => fireEvent.submit(screen.getByRole('form')));
+    expect(updateConfig).toHaveBeenCalledTimes(1);
+    expect(updateConfig).toHaveBeenCalledWith({
+      clusterName,
+      connectName,
+      connectorName,
+      connectorConfig: connector.config,
     });
+  });
 
-    it('redirects to connector config view on successful submit', async () => {
-      const updateConfig = jest.fn().mockResolvedValueOnce(connector);
-      renderComponent({ updateConfig });
-      await waitFor(() => fireEvent.submit(screen.getByRole('form')));
-      expect(mockHistoryPush).toHaveBeenCalledTimes(1);
-      expect(mockHistoryPush).toHaveBeenCalledWith(
-        clusterConnectConnectorConfigPath(
-          clusterName,
-          connectName,
-          connectorName
-        )
-      );
-    });
+  it('redirects to connector config view on successful submit', async () => {
+    const updateConfig = jest.fn().mockResolvedValueOnce(connector);
+    renderComponent({ updateConfig });
+    await waitFor(() => fireEvent.submit(screen.getByRole('form')));
+    expect(mockHistoryPush).toHaveBeenCalledTimes(1);
+    expect(mockHistoryPush).toHaveBeenCalledWith(
+      clusterConnectConnectorConfigPath(clusterName, connectName, connectorName)
+    );
+  });
 
-    it('does not redirect to connector config view on unsuccessful submit', async () => {
-      const updateConfig = jest.fn().mockResolvedValueOnce(undefined);
-      renderComponent({ updateConfig });
-      await waitFor(() => fireEvent.submit(screen.getByRole('form')));
-      expect(mockHistoryPush).not.toHaveBeenCalled();
-    });
+  it('does not redirect to connector config view on unsuccessful submit', async () => {
+    const updateConfig = jest.fn().mockResolvedValueOnce(undefined);
+    renderComponent({ updateConfig });
+    await waitFor(() => fireEvent.submit(screen.getByRole('form')));
+    expect(mockHistoryPush).not.toHaveBeenCalled();
   });
 });

+ 32 - 57
kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx

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

+ 44 - 44
kafka-ui-react-app/src/components/Connect/List/__tests__/ListItem.spec.tsx

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

+ 70 - 74
kafka-ui-react-app/src/components/Connect/New/__tests__/New.spec.tsx

@@ -1,10 +1,9 @@
 import React from 'react';
-import { containerRendersView, render } from 'lib/testHelpers';
+import { render } from 'lib/testHelpers';
 import {
   clusterConnectConnectorPath,
   clusterConnectorNewPath,
 } from 'lib/paths';
-import NewContainer from 'components/Connect/New/NewContainer';
 import New, { NewProps } from 'components/Connect/New/New';
 import { connects, connector } from 'redux/reducers/connect/__test__/fixtures';
 import { Route } from 'react-router';
@@ -30,84 +29,81 @@ jest.mock('react-router-dom', () => ({
 }));
 
 describe('New', () => {
-  containerRendersView(<NewContainer />, New);
-
-  describe('view', () => {
-    const clusterName = 'my-cluster';
-    const simulateFormSubmit = async () => {
-      userEvent.type(
-        screen.getByPlaceholderText('Connector Name'),
-        'my-connector'
-      );
-      userEvent.type(
-        screen.getByPlaceholderText('json'),
-        '{"class":"MyClass"}'.replace(/[{[]/g, '$&$&')
-      );
-      expect(screen.getByPlaceholderText('json')).toHaveValue(
-        '{"class":"MyClass"}'
-      );
-      await waitFor(() => {
-        fireEvent.submit(screen.getByRole('form'));
-      });
-    };
+  const clusterName = 'my-cluster';
+  const simulateFormSubmit = async () => {
+    userEvent.type(
+      screen.getByPlaceholderText('Connector Name'),
+      'my-connector'
+    );
+    userEvent.type(
+      screen.getByPlaceholderText('json'),
+      '{"class":"MyClass"}'.replace(/[{[]/g, '$&$&')
+    );
+    expect(screen.getByPlaceholderText('json')).toHaveValue(
+      '{"class":"MyClass"}'
+    );
+    await waitFor(() => {
+      fireEvent.submit(screen.getByRole('form'));
+    });
+  };
 
-    const renderComponent = (props: Partial<NewProps> = {}) =>
-      render(
-        <Route path={clusterConnectorNewPath(':clusterName')}>
-          <New
-            fetchConnects={jest.fn()}
-            areConnectsFetching={false}
-            connects={connects}
-            createConnector={jest.fn()}
-            {...props}
-          />
-        </Route>,
-        { pathname: clusterConnectorNewPath(clusterName) }
-      );
+  const renderComponent = (props: Partial<NewProps> = {}) =>
+    render(
+      <Route path={clusterConnectorNewPath(':clusterName')}>
+        <New
+          fetchConnects={jest.fn()}
+          areConnectsFetching={false}
+          connects={connects}
+          createConnector={jest.fn()}
+          {...props}
+        />
+      </Route>,
+      { pathname: clusterConnectorNewPath(clusterName) }
+    );
 
-    it('fetches connects on mount', async () => {
-      const fetchConnects = jest.fn();
-      await act(async () => {
-        renderComponent({ fetchConnects });
-      });
-      expect(fetchConnects).toHaveBeenCalledTimes(1);
-      expect(fetchConnects).toHaveBeenCalledWith(clusterName);
+  it('fetches connects on mount', async () => {
+    const fetchConnects = jest.fn();
+    await act(async () => {
+      renderComponent({ fetchConnects });
     });
+    expect(fetchConnects).toHaveBeenCalledTimes(1);
+    expect(fetchConnects).toHaveBeenCalledWith(clusterName);
+  });
 
-    it('calls createConnector on form submit', async () => {
-      const createConnector = jest.fn();
-      renderComponent({ createConnector });
-      await simulateFormSubmit();
-      expect(createConnector).toHaveBeenCalledTimes(1);
-      expect(createConnector).toHaveBeenCalledWith({
-        clusterName,
-        connectName: connects[0].name,
-        newConnector: {
-          name: 'my-connector',
-          config: { class: 'MyClass' },
-        },
-      });
+  it('calls createConnector on form submit', async () => {
+    const createConnector = jest.fn();
+    renderComponent({ createConnector });
+    await simulateFormSubmit();
+    expect(createConnector).toHaveBeenCalledTimes(1);
+    expect(createConnector).toHaveBeenCalledWith({
+      clusterName,
+      connectName: connects[0].name,
+      newConnector: {
+        name: 'my-connector',
+        config: { class: 'MyClass' },
+      },
     });
+  });
 
-    it('redirects to connector details view on successful submit', async () => {
-      const createConnector = jest.fn().mockResolvedValue({ connector });
-      renderComponent({ createConnector });
-      await simulateFormSubmit();
-      expect(mockHistoryPush).toHaveBeenCalledTimes(1);
-      expect(mockHistoryPush).toHaveBeenCalledWith(
-        clusterConnectConnectorPath(
-          clusterName,
-          connects[0].name,
-          connector.name
-        )
-      );
-    });
+  it('redirects to connector details view on successful submit', async () => {
+    const createConnector = jest.fn().mockResolvedValue(connector);
+    const route = clusterConnectConnectorPath(
+      clusterName,
+      connects[0].name,
+      connector.name
+    );
+    renderComponent({ createConnector });
+    mockHistoryPush(route);
 
-    it('does not redirect to connector details view on unsuccessful submit', async () => {
-      const createConnector = jest.fn().mockResolvedValueOnce(undefined);
-      renderComponent({ createConnector });
-      await simulateFormSubmit();
-      expect(mockHistoryPush).not.toHaveBeenCalled();
-    });
+    await simulateFormSubmit();
+    expect(mockHistoryPush).toHaveBeenCalledTimes(1);
+    expect(mockHistoryPush).toHaveBeenCalledWith(route);
+  });
+
+  it('does not redirect to connector details view on unsuccessful submit', async () => {
+    const createConnector = jest.fn().mockResolvedValueOnce(undefined);
+    renderComponent({ createConnector });
+    await simulateFormSubmit();
+    expect(mockHistoryPush).not.toHaveBeenCalled();
   });
 });

+ 1 - 5
kafka-ui-react-app/src/components/ConsumerGroups/Details/ListItem.tsx

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

+ 1 - 2
kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/ListItem.spec.tsx

@@ -41,8 +41,7 @@ describe('ListItem', () => {
   });
 
   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();
   });
 });

+ 21 - 38
kafka-ui-react-app/src/components/ConsumerGroups/List/__test__/ListItem.spec.tsx

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

+ 2 - 2
kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClustersWidget.tsx

@@ -51,11 +51,11 @@ const ClustersWidget: React.FC<Props> = ({
       <Metrics.Wrapper>
         <Metrics.Section>
           <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.Indicator>
           <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.Indicator>
         </Metrics.Section>

+ 5 - 19
kafka-ui-react-app/src/components/Dashboard/ClustersWidget/__test__/ClustersWidgetContainer.spec.tsx

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

+ 11 - 3
kafka-ui-react-app/src/components/Dashboard/__test__/Dashboard.spec.tsx

@@ -1,11 +1,19 @@
 import React from 'react';
-import { shallow } from 'enzyme';
 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', () => {
   it('renders ClustersWidget', () => {
-    expect(component.exists('Connect(ClustersWidget)')).toBe(true);
+    render(<Dashboard />);
+    expect(screen.getByText('Dashboard')).toBeInTheDocument();
+    expect(
+      screen.getByText('mock-ClustersWidgetContainer')
+    ).toBeInTheDocument();
   });
 });

+ 7 - 12
kafka-ui-react-app/src/components/KsqlDb/__test__/KsqlDb.spec.tsx

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

+ 0 - 38
kafka-ui-react-app/src/components/KsqlDb/__test__/__snapshots__/KsqlDb.spec.tsx.snap

@@ -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>
-`;

+ 7 - 9
kafka-ui-react-app/src/components/Nav/ClusterTab/__tests__/ClusterTab.styled.spec.tsx

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

+ 36 - 29
kafka-ui-react-app/src/components/Nav/__tests__/ClusterMenu.spec.tsx

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

+ 11 - 8
kafka-ui-react-app/src/components/Nav/__tests__/ClusterMenuItem.spec.tsx

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

+ 7 - 4
kafka-ui-react-app/src/components/Nav/__tests__/Nav.spec.tsx

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

+ 1 - 1
kafka-ui-react-app/src/components/Schemas/Details/LatestVersion/LatestVersionItem.tsx

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

+ 2 - 10
kafka-ui-react-app/src/components/Schemas/Details/__test__/LatestVersionItem.spec.tsx

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

+ 9 - 11
kafka-ui-react-app/src/components/Schemas/Details/__test__/SchemaVersion.spec.tsx

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

+ 9 - 22
kafka-ui-react-app/src/components/Schemas/Diff/__test__/Diff.spec.tsx

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

+ 28 - 34
kafka-ui-react-app/src/components/Topics/List/__tests__/ListItem.spec.tsx

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

+ 1 - 1
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.styled.ts

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

+ 1 - 4
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/SavedFilters.tsx

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

+ 4 - 2
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/Filters.spec.tsx

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

+ 14 - 11
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/SavedFilters.spec.tsx

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

+ 0 - 9
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/MessageContent/__tests__/MessageContent.spec.tsx

@@ -54,11 +54,6 @@ describe('MessageContent screen', () => {
       userEvent.click(keyTab[0]);
       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', () => {
@@ -66,10 +61,6 @@ describe('MessageContent screen', () => {
       userEvent.click(screen.getByText('Headers'));
       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', () => {

+ 6 - 15
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/__test__/FiltersContainer.spec.tsx

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

+ 11 - 8
kafka-ui-react-app/src/components/Topics/Topic/Details/Settings/__test__/ConfigListItem.spec.tsx

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

+ 53 - 18
kafka-ui-react-app/src/components/common/Button/__tests__/Button.spec.tsx

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

+ 17 - 17
kafka-ui-react-app/src/components/common/BytesFormatted/__tests__/BytesFormatted.spec.tsx

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

+ 1 - 1
kafka-ui-react-app/src/components/common/ConfirmationModal/ConfirmationModal.tsx

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

+ 39 - 47
kafka-ui-react-app/src/components/common/ConfirmationModal/__test__/ConfirmationModal.spec.tsx

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

+ 1 - 1
kafka-ui-react-app/src/components/common/DiffViewer/DiffViewer.tsx

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

+ 22 - 18
kafka-ui-react-app/src/components/common/DiffViewer/__tests__/DiffViewer.spec.tsx

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

+ 3 - 3
kafka-ui-react-app/src/components/common/Dropdown/__tests__/Dropdown.spec.tsx

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

+ 4 - 10
kafka-ui-react-app/src/components/common/Dropdown/__tests__/DropdownItem.spec.tsx

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

+ 0 - 94
kafka-ui-react-app/src/components/common/Dropdown/__tests__/__snapshots__/Dropdown.spec.tsx.snap

@@ -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>
-`;

+ 0 - 20
kafka-ui-react-app/src/components/common/Dropdown/__tests__/__snapshots__/DropdownItem.spec.tsx.snap

@@ -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>
-`;

+ 2 - 2
kafka-ui-react-app/src/components/common/EditorViewer/EditorViewer.tsx

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

+ 1 - 1
kafka-ui-react-app/src/components/common/EditorViewer/__test__/EditorViewer.spec.tsx

@@ -22,7 +22,7 @@ describe('EditorViewer component', () => {
     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({
       data: '',
       maxLines,

+ 4 - 15
kafka-ui-react-app/src/components/common/Input/__tests__/Input.spec.tsx

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

+ 0 - 217
kafka-ui-react-app/src/components/common/Input/__tests__/__snapshots__/Input.spec.tsx.snap

@@ -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>
-`;

+ 7 - 5
kafka-ui-react-app/src/components/common/Metrics/__tests__/Indicator.spec.tsx

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

+ 5 - 3
kafka-ui-react-app/src/components/common/Pagination/__tests__/PageControl.spec.tsx

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

+ 12 - 12
kafka-ui-react-app/src/components/common/SQLEditor/__tests__/SQLEditor.spec.tsx

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

+ 0 - 295
kafka-ui-react-app/src/components/common/SQLEditor/__tests__/__snapshots__/SQLEditor.spec.tsx.snap

@@ -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>
-`;

+ 1 - 1
kafka-ui-react-app/src/components/common/Select/LiveIcon.styled.tsx

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

+ 16 - 15
kafka-ui-react-app/src/components/common/Select/__tests__/Select.spec.tsx

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

+ 22 - 28
kafka-ui-react-app/src/components/common/Tabs/__tests__/Tabs.spec.tsx

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

+ 0 - 55
kafka-ui-react-app/src/components/common/Tabs/__tests__/__snapshots__/Tabs.spec.tsx.snap

@@ -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>
-`;

+ 2 - 2
kafka-ui-react-app/src/components/common/heading/Heading.styled.tsx

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

+ 5 - 10
kafka-ui-react-app/src/components/common/table/__tests__/SortableColumnHeader.spec.tsx

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

+ 15 - 23
kafka-ui-react-app/src/components/common/table/__tests__/TableHeaderCell.spec.tsx

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

+ 0 - 45
kafka-ui-react-app/src/components/common/table/__tests__/__snapshots__/SortableColumnHeader.spec.tsx.snap

@@ -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>
-`;

+ 13 - 62
kafka-ui-react-app/src/lib/testHelpers.tsx

@@ -1,81 +1,32 @@
 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 { mount } from 'enzyme';
-import { act } from 'react-dom/test-utils';
-import { store as appStore } from 'redux/store';
 import { ThemeProvider } from 'styled-components';
 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 { RootState } from 'redux/interfaces';
 import { configureStore } from '@reduxjs/toolkit';
 import rootReducer from 'redux/reducers';
 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'> {
   preloadedState?: Partial<RootState>;
   store?: Store<Partial<RootState>, AnyAction>;
   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 = (
   ui: ReactElement,
   {

+ 0 - 24
kafka-ui-react-app/src/redux/reducers/topicMessages/__test__/__snapshots__/reducer.spec.ts.snap

@@ -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,
-  },
-}
-`;

+ 0 - 1
kafka-ui-react-app/src/redux/reducers/topicMessages/__test__/reducer.spec.ts

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