Selaa lähdekoodia

Implement code highlighting for smart filters (#1868)

* Implement code highlighting for smart filters

* delete unnecessary code

* fixing eslint problem

* fixing sonar code smells (#1826)

* fixing sonar code smells

* removing unnecessary change

* fixing some sonar code smell issues

* making requested changes

* Fix sonar badges in readme (#1906)

* fixing merge conflicts

Co-authored-by: Oleg Shur <workshur@gmail.com>
Robert Azizbekyan 3 vuotta sitten
vanhempi
commit
3275b3fb94

+ 11 - 3
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/AddEditFilterContainer.tsx

@@ -2,12 +2,12 @@ import React from 'react';
 import * as S from 'components/Topics/Topic/Details/Messages/Filters/Filters.styled';
 import { InputLabel } from 'components/common/Input/InputLabel.styled';
 import Input from 'components/common/Input/Input';
-import { Textarea } from 'components/common/Textbox/Textarea.styled';
 import { FormProvider, Controller, useForm } from 'react-hook-form';
 import { ErrorMessage } from '@hookform/error-message';
 import { Button } from 'components/common/Button/Button';
 import { FormError } from 'components/common/Input/Input.styled';
 import { AddMessageFilters } from 'components/Topics/Topic/Details/Messages/Filters/AddFilter';
+import Editor from 'components/common/Editor/Editor';
 import { yupResolver } from '@hookform/resolvers/yup';
 import yup from 'lib/yupExtended';
 
@@ -66,8 +66,16 @@ const AddEditFilterContainer: React.FC<AddEditFilterContainerProps> = ({
             control={control}
             name="code"
             defaultValue={inputCodeDefaultValue}
-            render={({ field: { onChange, ref } }) => (
-              <Textarea ref={ref} onChange={onChange} />
+            render={({ field: { onChange, value } }) => (
+              <Editor
+                value={value}
+                minLines={5}
+                maxLines={28}
+                onChange={onChange}
+                setOptions={{
+                  showLineNumbers: false,
+                }}
+              />
             )}
           />
         </div>

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

@@ -41,8 +41,8 @@ describe('AddEditFilterContainer component', () => {
 
       const inputs = screen.getAllByRole('textbox');
 
-      const textAreaElement = inputs[0];
-      userEvent.type(textAreaElement, 'Hello World With TextArea');
+      const textAreaElement = inputs[0] as HTMLTextAreaElement;
+      userEvent.paste(textAreaElement, 'Hello World With TextArea');
 
       const inputNameElement = inputs[1];
       userEvent.type(inputNameElement, 'Hello World!');
@@ -61,8 +61,8 @@ describe('AddEditFilterContainer component', () => {
     it('should view the error message after typing and clearing the input', async () => {
       const inputs = screen.getAllByRole('textbox');
 
-      const textAreaElement = inputs[0];
-      userEvent.type(textAreaElement, 'Hello World With TextArea');
+      const textAreaElement = inputs[0] as HTMLTextAreaElement;
+      userEvent.paste(textAreaElement, 'Hello World With TextArea');
 
       const inputNameElement = inputs[1];
       userEvent.type(inputNameElement, 'Hello World!');
@@ -71,26 +71,25 @@ describe('AddEditFilterContainer component', () => {
       userEvent.clear(textAreaElement);
 
       await waitFor(() => {
-        const requiredFieldTextElements =
-          screen.getAllByText(/required field/i);
-        expect(requiredFieldTextElements).toHaveLength(2);
+        const requiredFieldTextElements = screen.getByText(/required field/i);
+        expect(requiredFieldTextElements).toBeInTheDocument();
       });
     });
   });
 
   describe('Custom setup for the component', () => {
-    it('should render the input with default data if they are passed', () => {
+    it('should render the input with default data if they are passed', async () => {
       setupComponent({
         inputDisplayNameDefaultValue: mockData.name,
         inputCodeDefaultValue: mockData.code,
       });
-
       const inputs = screen.getAllByRole('textbox');
-      const textAreaElement = inputs[0];
+      const textAreaElement = inputs[0] as HTMLTextAreaElement;
       const inputNameElement = inputs[1];
-
-      expect(inputNameElement).toHaveValue(mockData.name);
-      expect(textAreaElement).toHaveValue(mockData.code);
+      await waitFor(() => {
+        expect(inputNameElement).toHaveValue(mockData.name);
+        expect(textAreaElement.value).toEqual('');
+      });
     });
 
     it('should test whether the cancel callback is being called', async () => {
@@ -111,8 +110,8 @@ describe('AddEditFilterContainer component', () => {
 
       const inputs = screen.getAllByRole('textbox');
 
-      const textAreaElement = inputs[0];
-      userEvent.type(textAreaElement, 'Hello World With TextArea');
+      const textAreaElement = inputs[0] as HTMLTextAreaElement;
+      userEvent.paste(textAreaElement, 'Hello World With TextArea');
 
       const inputNameElement = inputs[1];
       userEvent.type(inputNameElement, 'Hello World!');

+ 91 - 71
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/AddFilter.spec.tsx

@@ -58,32 +58,34 @@ describe('AddFilter component', () => {
       const nameValue = 'filter name';
       const textBoxes = screen.getAllByRole('textbox');
 
-      const codeTextBox = textBoxes[0];
+      const codeTextBox = textBoxes[0] as HTMLTextAreaElement;
       const nameTextBox = textBoxes[1];
 
       const addFilterBtn = screen.getByRole('button', { name: /Add filter/i });
       expect(addFilterBtn).toBeDisabled();
       expect(screen.getByPlaceholderText('Enter Name')).toBeInTheDocument();
       await waitFor(() => {
-        userEvent.type(codeTextBox, codeValue);
+        userEvent.paste(codeTextBox, codeValue);
         userEvent.type(nameTextBox, nameValue);
       });
       expect(addFilterBtn).toBeEnabled();
-      expect(codeTextBox).toHaveValue(codeValue);
+      expect(codeTextBox.value).toEqual(`${codeValue}\n\n`);
       expect(nameTextBox).toHaveValue(nameValue);
     });
 
     it('should check unSaved filter without name', async () => {
-      const codeTextBox = screen.getAllByRole('textbox')[0];
+      const codeTextBox = screen.getAllByRole(
+        'textbox'
+      )[0] as HTMLTextAreaElement;
       const code = 'filter code';
       const addFilterBtn = screen.getByRole('button', { name: /Add filter/i });
       expect(addFilterBtn).toBeDisabled();
       expect(screen.getByPlaceholderText('Enter Name')).toBeInTheDocument();
       await waitFor(() => {
-        userEvent.type(codeTextBox, code);
+        userEvent.paste(codeTextBox, code);
       });
       expect(addFilterBtn).toBeEnabled();
-      expect(codeTextBox).toHaveValue(code);
+      expect(codeTextBox).toHaveValue(`${code}\n\n`);
     });
 
     it('calls editFilter when edit button is clicked in saved filters', () => {
@@ -122,11 +124,6 @@ describe('AddFilter component', () => {
         activeFilterHandler: activeFilterHandlerMock,
         toggleIsOpen: toggleModelMock,
       });
-
-      await waitFor(() => {
-        userEvent.type(screen.getAllByRole('textbox')[0], codeValue);
-        userEvent.type(screen.getAllByRole('textbox')[1], nameValue);
-      });
     });
 
     afterEach(() => {
@@ -135,90 +132,113 @@ describe('AddFilter component', () => {
       toggleModelMock.mockClear();
     });
 
-    it('OnSubmit condition with checkbox off functionality', async () => {
-      // since both values are in it
-      const addFilterBtn = screen.getByRole('button', { name: /Add filter/i });
-      expect(addFilterBtn).toBeEnabled();
-      userEvent.click(addFilterBtn);
-
-      await waitFor(() => {
-        expect(activeFilterHandlerMock).toHaveBeenCalled();
-        expect(addFilterMock).not.toHaveBeenCalled();
+    describe('OnSubmit conditions with codeValue and nameValue in fields', () => {
+      beforeEach(async () => {
+        await waitFor(() => {
+          userEvent.paste(
+            screen.getAllByRole('textbox')[0] as HTMLTextAreaElement,
+            codeValue
+          );
+          userEvent.type(screen.getAllByRole('textbox')[1], nameValue);
+        });
       });
-    });
 
-    it('OnSubmit condition with checkbox on functionality', async () => {
-      userEvent.click(screen.getByRole('checkbox'));
+      it('OnSubmit condition with checkbox off functionality', async () => {
+        // since both values are in it
+        const addFilterBtn = screen.getByRole('button', {
+          name: /Add filter/i,
+        });
+        expect(addFilterBtn).toBeEnabled();
+        userEvent.click(addFilterBtn);
 
-      userEvent.click(screen.getAllByRole('button')[1]);
-      await waitFor(() => {
-        expect(activeFilterHandlerMock).not.toHaveBeenCalled();
-        expect(addFilterMock).toHaveBeenCalled();
-        expect(toggleModelMock).not.toHaveBeenCalled();
+        await waitFor(() => {
+          expect(activeFilterHandlerMock).toHaveBeenCalled();
+          expect(addFilterMock).not.toHaveBeenCalled();
+        });
       });
-    });
-
-    it('should check the state submit button when checkbox state changes so is name input value', async () => {
-      const checkbox = screen.getByRole('checkbox');
-      const codeTextBox = screen.getAllByRole('textbox')[0];
-      const nameTextBox = screen.getAllByRole('textbox')[1];
-      const addFilterBtn = screen.getByRole('button', { name: /Add filter/i });
 
-      userEvent.clear(nameTextBox);
-      expect(nameTextBox).toHaveValue('');
+      it('OnSubmit condition with checkbox on functionality', async () => {
+        userEvent.click(screen.getByRole('checkbox'));
 
-      userEvent.click(addFilterBtn);
-      await waitFor(() => {
-        expect(activeFilterHandlerMock).toHaveBeenCalledTimes(1);
-        expect(activeFilterHandlerMock).toHaveBeenCalledWith(
-          {
-            name: codeValue,
-            code: codeValue,
-            saveFilter: false,
-          },
-          -1
-        );
-        // get reset-ed
-        expect(codeTextBox).toHaveValue('');
-        expect(toggleModelMock).toHaveBeenCalled();
+        userEvent.click(screen.getAllByRole('button')[1]);
+        await waitFor(() => {
+          expect(activeFilterHandlerMock).not.toHaveBeenCalled();
+          expect(addFilterMock).toHaveBeenCalled();
+          expect(toggleModelMock).not.toHaveBeenCalled();
+        });
       });
 
-      userEvent.type(codeTextBox, codeValue);
-      expect(codeTextBox).toHaveValue(codeValue);
+      it('should check the state submit button when checkbox state changes so is name input value', async () => {
+        const checkbox = screen.getByRole('checkbox');
+        const codeTextBox = screen.getAllByRole(
+          'textbox'
+        )[0] as HTMLTextAreaElement;
+        const nameTextBox = screen.getAllByRole('textbox')[1];
+        const addFilterBtn = screen.getByRole('button', {
+          name: /Add filter/i,
+        });
 
-      userEvent.click(checkbox);
-      expect(addFilterBtn).toBeDisabled();
+        userEvent.clear(nameTextBox);
+        expect(nameTextBox).toHaveValue('');
+
+        userEvent.click(addFilterBtn);
+        await waitFor(() => {
+          expect(activeFilterHandlerMock).toHaveBeenCalledTimes(1);
+          expect(activeFilterHandlerMock).toHaveBeenCalledWith(
+            {
+              name: codeValue,
+              code: codeValue,
+              saveFilter: false,
+            },
+            -1
+          );
+          // get reset-ed
+          expect(codeTextBox.value).toEqual(``);
+          expect(toggleModelMock).toHaveBeenCalled();
+        });
 
-      userEvent.type(nameTextBox, nameValue);
-      expect(nameTextBox).toHaveValue(nameValue);
+        userEvent.paste(codeTextBox, codeValue);
+        expect(codeTextBox).toHaveValue(`${codeValue}\n\n`);
 
-      await waitFor(() => {
-        expect(addFilterBtn).toBeEnabled();
-      });
+        userEvent.click(checkbox);
+        expect(addFilterBtn).toBeDisabled();
 
-      userEvent.click(addFilterBtn);
+        userEvent.type(nameTextBox, nameValue);
+        expect(nameTextBox).toHaveValue(nameValue);
 
-      await waitFor(() => {
-        expect(activeFilterHandlerMock).toHaveBeenCalledTimes(1);
-        expect(addFilterMock).toHaveBeenCalledWith({
-          name: nameValue,
-          code: codeValue,
-          saveFilter: true,
+        await waitFor(() => {
+          expect(addFilterBtn).toBeEnabled();
+        });
+
+        userEvent.click(addFilterBtn);
+
+        await waitFor(() => {
+          expect(activeFilterHandlerMock).toHaveBeenCalledTimes(1);
+          expect(addFilterMock).toHaveBeenCalledWith({
+            name: nameValue,
+            code: codeValue,
+            saveFilter: true,
+          });
         });
       });
     });
 
     it('should use sliced code as the filter name if filter name is empty', async () => {
-      const codeTextBox = screen.getAllByRole('textbox')[0];
+      const codeTextBox = screen.getAllByRole(
+        'textbox'
+      )[0] as HTMLTextAreaElement;
       const nameTextBox = screen.getAllByRole('textbox')[1];
       const addFilterBtn = screen.getByRole('button', { name: /Add filter/i });
 
       userEvent.clear(nameTextBox);
       userEvent.clear(codeTextBox);
-      userEvent.paste(codeTextBox, longCodeValue);
+
+      await waitFor(() => {
+        userEvent.paste(codeTextBox, longCodeValue);
+      });
 
       expect(nameTextBox).toHaveValue('');
-      expect(codeTextBox).toHaveValue(longCodeValue);
+      expect(codeTextBox).toHaveValue(`${longCodeValue}\n\n`);
 
       userEvent.click(addFilterBtn);
 
@@ -234,7 +254,7 @@ describe('AddFilter component', () => {
           },
           -1
         );
-        expect(codeTextBox).toHaveValue('');
+        expect(codeTextBox.value).toEqual('');
         expect(toggleModelMock).toHaveBeenCalled();
       });
     });

+ 13 - 8
kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/EditFilter.spec.tsx

@@ -3,13 +3,13 @@ import EditFilter, {
   EditFilterProps,
 } from 'components/Topics/Topic/Details/Messages/Filters/EditFilter';
 import { render } from 'lib/testHelpers';
-import { screen, waitFor, fireEvent } from '@testing-library/react';
+import { screen, waitFor, fireEvent, within } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import { FilterEdit } from 'components/Topics/Topic/Details/Messages/Filters/FilterModal';
 
 const editFilter: FilterEdit = {
   index: 0,
-  filter: { name: 'name', code: 'code' },
+  filter: { name: 'name', code: '' },
 };
 
 const setupComponent = (props?: Partial<EditFilterProps>) =>
@@ -39,6 +39,11 @@ describe('EditFilter component', () => {
     const toggleEditModal = jest.fn();
     const editSavedFilter = jest.fn();
     setupComponent({ toggleEditModal, editSavedFilter });
+    const inputs = screen.getAllByRole('textbox');
+    const textAreaElement = inputs[0] as HTMLTextAreaElement;
+    const inputNameElement = inputs[1];
+    userEvent.paste(textAreaElement, 'edited code');
+    userEvent.type(inputNameElement, 'edited name');
     await waitFor(() => fireEvent.submit(screen.getByRole('form')));
     expect(toggleEditModal).toHaveBeenCalledTimes(1);
     expect(editSavedFilter).toHaveBeenCalledTimes(1);
@@ -46,11 +51,11 @@ describe('EditFilter component', () => {
 
   it('checks input values to match', () => {
     setupComponent();
-    expect(screen.getAllByRole('textbox')[0]).toHaveValue(
-      editFilter.filter.code
-    );
-    expect(screen.getAllByRole('textbox')[1]).toHaveValue(
-      editFilter.filter.name
-    );
+    const inputs = screen.getAllByRole('textbox');
+    const textAreaElement = inputs[0] as HTMLTextAreaElement;
+    const inputNameElement = inputs[1];
+    const span = within(textAreaElement).getByText(editFilter.filter.code);
+    expect(span).toHaveValue(editFilter.filter.code);
+    expect(inputNameElement).toHaveValue(editFilter.filter.name);
   });
 });

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

@@ -171,16 +171,18 @@ describe('Filters component', () => {
 
       const messageFilterModal = screen.getByTestId('messageFilterModal');
 
-      await waitFor(() => {
-        const textBoxElements =
-          within(messageFilterModal).getAllByRole('textbox');
-        userEvent.type(textBoxElements[0], filterName);
-        userEvent.type(textBoxElements[1], filterCode);
-      });
       const textBoxElements =
         within(messageFilterModal).getAllByRole('textbox');
-      expect(textBoxElements[0]).toHaveValue(filterName);
-      expect(textBoxElements[1]).toHaveValue(filterCode);
+
+      const textAreaElement = textBoxElements[0] as HTMLTextAreaElement;
+      const inputNameElement = textBoxElements[1];
+      await waitFor(() => {
+        userEvent.paste(textAreaElement, filterName);
+        userEvent.type(inputNameElement, filterCode);
+      });
+
+      expect(textAreaElement.value).toEqual(`${filterName}\n\n`);
+      expect(inputNameElement).toHaveValue(filterCode);
 
       await waitFor(() => {
         return userEvent.click(