Browse Source

[FE] Add a warning when copying to clipboard in non-SSL envs (#3394)

* set a warning message on copyToClipboard if user use http

* Update kafka-ui-react-app/src/lib/hooks/useDataSaver.ts

* changed custom type whit warning

* added  warning title

* added test case for warning message

---------

Co-authored-by: davitbejanyan <dbejanyan@provectus.com>
Co-authored-by: Roman Zabaluev <rzabaluev@provectus.com>
Co-authored-by: Oleg Shur <workshur@gmail.com>
David 2 years ago
parent
commit
be151b4d82

+ 2 - 2
kafka-ui-react-app/src/components/common/Alert/Alert.styled.ts

@@ -1,7 +1,7 @@
-import { ToastType } from 'react-hot-toast';
 import styled from 'styled-components';
+import { ToastTypes } from 'lib/errorHandling';
 
-export const Alert = styled.div<{ $type: ToastType }>`
+export const Alert = styled.div<{ $type: ToastTypes }>`
   background-color: ${({ $type, theme }) => theme.alert.color[$type]};
   width: 500px;
   min-height: 64px;

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

@@ -1,13 +1,13 @@
 import React from 'react';
 import CloseIcon from 'components/common/Icons/CloseIcon';
 import IconButtonWrapper from 'components/common/Icons/IconButtonWrapper';
-import { ToastType } from 'react-hot-toast';
+import { ToastTypes } from 'lib/errorHandling';
 
 import * as S from './Alert.styled';
 
 export interface AlertProps {
   title: string;
-  type: ToastType;
+  type: ToastTypes;
   message: React.ReactNode;
   onDissmiss(): void;
 }

+ 2 - 1
kafka-ui-react-app/src/lib/errorHandling.tsx

@@ -9,6 +9,7 @@ interface ServerResponse {
   url?: string;
   message?: ErrorResponse['message'];
 }
+export type ToastTypes = ToastType | 'warning';
 
 export const getResponse = async (
   response: Response
@@ -34,7 +35,7 @@ interface AlertOptions {
 }
 
 export const showAlert = (
-  type: ToastType,
+  type: ToastTypes,
   { title, message, id }: AlertOptions
 ) => {
   toast.custom(

+ 30 - 1
kafka-ui-react-app/src/lib/hooks/__tests__/useDataSaver.spec.tsx

@@ -1,7 +1,12 @@
 import React, { useEffect } from 'react';
 import useDataSaver from 'lib/hooks/useDataSaver';
 import { render } from '@testing-library/react';
+import { showAlert } from 'lib/errorHandling';
 
+jest.mock('lib/errorHandling', () => ({
+  ...jest.requireActual('lib/errorHandling'),
+  showAlert: jest.fn(),
+}));
 describe('useDataSaver hook', () => {
   const content = {
     title: 'title',
@@ -38,7 +43,6 @@ describe('useDataSaver hook', () => {
       mockCreate.mockRestore();
     });
   });
-
   describe('copies the data to the clipboard', () => {
     Object.assign(navigator, {
       clipboard: {
@@ -74,4 +78,29 @@ describe('useDataSaver hook', () => {
       );
     });
   });
+  describe('navigator clipboard is undefined', () => {
+    it('calls showAlert with the correct parameters when clipboard API is unavailable', () => {
+      Object.assign(navigator, {
+        clipboard: undefined,
+      });
+
+      const HookWrapper: React.FC = () => {
+        const { copyToClipboard } = useDataSaver('topic', content);
+        useEffect(() => {
+          copyToClipboard();
+        }, [copyToClipboard]);
+        return null;
+      };
+
+      render(<HookWrapper />);
+
+      expect(showAlert).toHaveBeenCalledTimes(1);
+      expect(showAlert).toHaveBeenCalledWith('warning', {
+        id: 'topic',
+        title: 'Warning',
+        message:
+          'Copying to clipboard is unavailable due to unsecured (non-HTTPS) connection',
+      });
+    });
+  });
 });

+ 8 - 1
kafka-ui-react-app/src/lib/hooks/useDataSaver.ts

@@ -1,4 +1,4 @@
-import { showSuccessAlert } from 'lib/errorHandling';
+import { showAlert, showSuccessAlert } from 'lib/errorHandling';
 
 const useDataSaver = (
   subject: string,
@@ -14,6 +14,13 @@ const useDataSaver = (
         title: '',
         message: 'Copied successfully!',
       });
+    } else {
+      showAlert('warning', {
+        id: subject,
+        title: 'Warning',
+        message:
+          'Copying to clipboard is unavailable due to unsecured (non-HTTPS) connection',
+      });
     }
   };
   const saveFile = () => {