Browse Source

Merge pull request #167 from provectus/i154/tests

[ISSUE-154] Update test config. Add first tests
Guzel738 4 năm trước cách đây
mục cha
commit
cc097e9327

+ 9 - 2
kafka-ui-react-app/.eslintrc.json

@@ -1,7 +1,8 @@
 {
   "env": {
     "browser": true,
-    "es6": true
+    "es6": true,
+    "jest": true
   },
   "globals": {
     "Atomics": "readonly",
@@ -14,7 +15,7 @@
     },
     "ecmaVersion": 2018,
     "sourceType": "module",
-    "project": "./tsconfig.json"
+    "project": ["./tsconfig.json", "./src/setupTests.ts"]
   },
   "plugins": ["@typescript-eslint", "prettier"],
   "extends": [
@@ -37,6 +38,12 @@
       "rules": {
         "react/prop-types": "off"
       }
+    },
+    {
+      "files": ["*.spec.tsx"],
+      "rules": {
+        "react/jsx-props-no-spreading": "off"
+      }
     }
   ]
 }

+ 8 - 0
kafka-ui-react-app/jest.config.js

@@ -0,0 +1,8 @@
+module.exports = {
+  roots: ['<rootDir>/src'],
+  transform: {
+    '^.+\\.tsx?$': 'ts-jest',
+  },
+  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
+  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
+};

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 144 - 684
kafka-ui-react-app/package-lock.json


+ 8 - 3
kafka-ui-react-app/package.json

@@ -32,7 +32,8 @@
   "lint-staged": {
     "*.{js,ts,jsx,tsx}": [
       "eslint -c .eslintrc.json --fix",
-      "git add"
+      "git add",
+      "jest --bail --findRelatedTests"
     ]
   },
   "scripts": {
@@ -65,11 +66,12 @@
     ]
   },
   "devDependencies": {
-    "@testing-library/jest-dom": "^4.2.4",
+    "@testing-library/jest-dom": "^5.11.9",
     "@testing-library/react": "^9.5.0",
     "@testing-library/user-event": "^7.1.2",
     "@types/classnames": "^2.2.11",
-    "@types/jest": "^24.9.1",
+    "@types/enzyme": "^3.10.8",
+    "@types/jest": "^26.0.20",
     "@types/lodash": "^4.14.165",
     "@types/node": "^12.19.8",
     "@types/react": "^17.0.0",
@@ -80,7 +82,9 @@
     "@types/redux-thunk": "^2.1.0",
     "@typescript-eslint/eslint-plugin": "^4.9.0",
     "@typescript-eslint/parser": "^4.9.0",
+    "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1",
     "dotenv": "^8.2.0",
+    "enzyme": "^3.11.0",
     "eslint": "^7.14.0",
     "eslint-config-airbnb": "^18.2.1",
     "eslint-config-airbnb-typescript": "^12.0.0",
@@ -96,6 +100,7 @@
     "node-sass": "^4.14.1",
     "prettier": "^2.2.1",
     "react-scripts": "4.0.1",
+    "ts-jest": "^26.4.4",
     "typescript": "~4.1.2"
   },
   "engines": {

+ 1 - 2
kafka-ui-react-app/src/components/Topics/Details/Messages/Messages.tsx

@@ -20,7 +20,7 @@ import * as _ from 'lodash';
 import { useDebouncedCallback } from 'use-debounce';
 import { Option } from 'react-multi-select-component/dist/lib/interfaces';
 
-interface Props {
+export interface Props {
   clusterName: ClusterName;
   topicName: TopicName;
   isFetched: boolean;
@@ -309,7 +309,6 @@ const Messages: React.FC<Props> = ({
               id="selectSeekType"
               name="selectSeekType"
               onChange={handleSeekTypeChange}
-              defaultValue={SeekType.OFFSET}
               value={selectedSeekType}
             >
               <option value={SeekType.OFFSET}>Offset</option>

+ 5 - 5
kafka-ui-react-app/src/setupTests.ts

@@ -1,6 +1,6 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-// eslint-disable-next-line import/no-extraneous-dependencies
+/* eslint-disable */
+import * as Enzyme from 'enzyme';
+import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
 import '@testing-library/jest-dom/extend-expect';
+
+Enzyme.configure({ adapter: new Adapter() });

+ 156 - 0
kafka-ui-react-app/src/tests/Topics/Details/Messages/Messages.spec.tsx

@@ -0,0 +1,156 @@
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+import JSONTree from 'react-json-tree';
+import * as useDebounce from 'use-debounce';
+import DatePicker from 'react-datepicker';
+import Messages, { Props } from 'components/Topics/Details/Messages/Messages';
+import PageLoader from 'components/common/PageLoader/PageLoader';
+
+describe('Messages component', () => {
+  beforeEach(() => {
+    jest.restoreAllMocks();
+  });
+
+  const setupWrapper = (props: Partial<Props> = {}) => (
+    <Messages
+      clusterName="Test cluster"
+      topicName="Cluster topic"
+      isFetched
+      fetchTopicMessages={jest.fn()}
+      messages={[]}
+      partitions={[]}
+      {...props}
+    />
+  );
+
+  describe('Initial state', () => {
+    it('renders PageLoader', () => {
+      expect(
+        shallow(setupWrapper({ isFetched: false })).exists(PageLoader)
+      ).toBeTruthy();
+    });
+  });
+
+  describe('Messages table', () => {
+    describe('With messages', () => {
+      const messagesWrapper = mount(
+        setupWrapper({
+          messages: [
+            {
+              partition: 1,
+              offset: 2,
+              timestamp: new Date('05-05-1994'),
+              content: [1, 2, 3],
+            },
+          ],
+        })
+      );
+      it('renders table', () => {
+        expect(
+          messagesWrapper.exists('[className="table is-striped is-fullwidth"]')
+        ).toBeTruthy();
+      });
+      it('renders JSONTree', () => {
+        expect(messagesWrapper.find(JSONTree).length).toEqual(1);
+      });
+      it('parses message content correctly', () => {
+        const messages = [
+          {
+            partition: 1,
+            offset: 2,
+            timestamp: new Date('05-05-1994'),
+            content: [1, 2, 3],
+          },
+        ];
+        const content = JSON.stringify(messages[0].content);
+        expect(JSON.parse(content)).toEqual(messages[0].content);
+      });
+    });
+    describe('Without messages', () => {
+      it('renders string', () => {
+        const wrapper = mount(setupWrapper());
+        expect(wrapper.text()).toContain('No messages at selected topic');
+      });
+    });
+  });
+
+  describe('Offset field', () => {
+    describe('Seek Type dependency', () => {
+      const wrapper = mount(setupWrapper());
+
+      it('renders DatePicker', () => {
+        wrapper
+          .find('[id="selectSeekType"]')
+          .simulate('change', { target: { value: 'TIMESTAMP' } });
+
+        expect(
+          wrapper.find('[id="selectSeekType"]').first().props().value
+        ).toEqual('TIMESTAMP');
+
+        expect(wrapper.exists(DatePicker)).toBeTruthy();
+      });
+    });
+
+    describe('With defined offset value', () => {
+      const wrapper = shallow(setupWrapper());
+
+      it('shows offset value in input', () => {
+        const offset = '10';
+
+        wrapper
+          .find('#searchOffset')
+          .simulate('change', { target: { value: offset } });
+
+        expect(wrapper.find('#searchOffset').first().props().value).toEqual(
+          offset
+        );
+      });
+    });
+    describe('With invalid offset value', () => {
+      const wrapper = shallow(setupWrapper());
+
+      it('shows 0 in input', () => {
+        wrapper
+          .find('#searchOffset')
+          .simulate('change', { target: { value: null } });
+
+        expect(wrapper.find('#searchOffset').first().props().value).toBe('0');
+      });
+    });
+  });
+
+  describe('Search field', () => {
+    it('renders input correctly', () => {
+      const query = 20;
+      const mockedUseDebouncedCallback = jest.fn();
+      jest
+        .spyOn(useDebounce, 'useDebouncedCallback')
+        .mockImplementationOnce(() => [
+          mockedUseDebouncedCallback,
+          jest.fn(),
+          jest.fn(),
+        ]);
+
+      const wrapper = shallow(setupWrapper());
+
+      wrapper
+        .find('#searchText')
+        .simulate('change', { target: { value: query } });
+
+      expect(wrapper.find('#searchText').first().props().value).toEqual(query);
+      expect(mockedUseDebouncedCallback).toHaveBeenCalledWith({ q: query });
+    });
+  });
+
+  describe('Submit button', () => {
+    it('fetches topic messages', () => {
+      const mockedfetchTopicMessages = jest.fn();
+      const wrapper = mount(
+        setupWrapper({ fetchTopicMessages: mockedfetchTopicMessages })
+      );
+
+      wrapper.find('[type="submit"]').simulate('click');
+      expect(mockedfetchTopicMessages).toHaveBeenCalled();
+    });
+  });
+});

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác