From 6e900190477e0275a4aff40dc11fa1b2bf3e11b4 Mon Sep 17 00:00:00 2001
From: mateusz-winiarczyk <mateusz.winiarczyk@appunite.com>
Date: Thu, 4 Apr 2024 18:52:55 +0200
Subject: [PATCH] fix(plugin): enter should load plugin from url (MIN-309)

---
 .../LoadPluginFromUrl.component.test.tsx      | 45 +++++++++++++++++++
 .../LoadPluginFromUrl.component.tsx           |  4 +-
 .../hooks/useLoadPluginFromUrl.ts             | 12 ++++-
 src/constants/common.ts                       |  2 +
 4 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
index 1b347d6e..1aec9dda 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
@@ -226,5 +226,50 @@ describe('LoadPluginFromUrl - component', () => {
         });
       });
     });
+    it('should load plugin from url after pressing enter key', async () => {
+      const pluginUrl = 'http://example.com/plugin.js';
+      const pluginScript = `function init() {} init()`;
+      mockedAxiosClient.onGet(pluginUrl).reply(HttpStatusCode.Ok, pluginScript);
+
+      global.URL.canParse = jest.fn().mockReturnValue(true);
+
+      const { store } = renderComponent();
+
+      const dispatchSpy = jest.spyOn(store, 'dispatch');
+
+      const input = screen.getByTestId('load-plugin-input-url');
+
+      act(() => {
+        fireEvent.change(input, { target: { value: pluginUrl } });
+        fireEvent.keyDown(input, { key: 'Enter', code: 'Enter', charCode: 13 });
+      });
+
+      await waitFor(() => {
+        expect(dispatchSpy).toHaveBeenCalledWith({
+          payload: 'e008fb2ceb97e3d6139ffe38a1b39d5d',
+          type: 'plugins/setCurrentDrawerPluginHash',
+        });
+      });
+    });
+    it('should not load plugin from url after pressing enter key if url is not correct', async () => {
+      global.URL.canParse = jest.fn().mockReturnValue(false);
+      const { store } = renderComponent();
+
+      const dispatchSpy = jest.spyOn(store, 'dispatch');
+      const input = screen.getByTestId('load-plugin-input-url');
+      expect(input).toBeVisible();
+
+      act(() => {
+        fireEvent.change(input, { target: { value: 'abcd' } });
+        fireEvent.keyDown(input, { key: 'Enter', code: 'Enter', charCode: 13 });
+      });
+
+      const button = screen.getByTestId('load-plugin-button');
+      expect(button).toBeDisabled();
+
+      await waitFor(() => {
+        expect(dispatchSpy).not.toHaveBeenCalled();
+      });
+    });
   });
 });
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.tsx b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.tsx
index f57224d0..20268f2e 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.tsx
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.tsx
@@ -3,7 +3,8 @@ import { Input } from '@/shared/Input';
 import { useLoadPluginFromUrl } from './hooks/useLoadPluginFromUrl';
 
 export const LoadPluginFromUrl = (): JSX.Element => {
-  const { handleChangePluginUrl, handleLoadPlugin, isPending, pluginUrl } = useLoadPluginFromUrl();
+  const { handleChangePluginUrl, handleLoadPlugin, isPending, pluginUrl, handleKeyPress } =
+    useLoadPluginFromUrl();
 
   return (
     <div className="flex w-full">
@@ -13,6 +14,7 @@ export const LoadPluginFromUrl = (): JSX.Element => {
           className="h-10 w-full flex-none bg-cultured p-3"
           type="url"
           value={pluginUrl}
+          onKeyDown={handleKeyPress}
           onChange={handleChangePluginUrl}
           data-testid="load-plugin-input-url"
         />
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
index 1b7c935f..bc1cf35d 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
@@ -5,8 +5,9 @@ import { setCurrentDrawerPluginHash } from '@/redux/plugins/plugins.slice';
 import { PluginsManager } from '@/services/pluginsManager';
 import { showToast } from '@/utils/showToast';
 import axios from 'axios';
-import { ChangeEvent, useMemo, useState } from 'react';
+import { ChangeEvent, useMemo, useState, KeyboardEvent } from 'react';
 import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ENTER_KEY_CODE } from '@/constants/common';
 import { PLUGIN_LOADING_ERROR_PREFIX } from '../../AvailablePluginsDrawer.constants';
 
 type UseLoadPluginReturnType = {
@@ -14,6 +15,7 @@ type UseLoadPluginReturnType = {
   handleLoadPlugin: () => Promise<void>;
   isPending: boolean;
   pluginUrl: string;
+  handleKeyPress: (event: KeyboardEvent<HTMLInputElement>) => Promise<void>;
 };
 
 export const useLoadPluginFromUrl = (): UseLoadPluginReturnType => {
@@ -64,6 +66,13 @@ export const useLoadPluginFromUrl = (): UseLoadPluginReturnType => {
       setIsLoading(false);
     }
   };
+
+  const handleKeyPress = async (event: KeyboardEvent<HTMLInputElement>): Promise<void> => {
+    if (event.code === ENTER_KEY_CODE && !isPending) {
+      await handleLoadPlugin();
+    }
+  };
+
   const handleChangePluginUrl = (event: ChangeEvent<HTMLInputElement>): void => {
     setPluginUrl(event.target.value);
   };
@@ -71,6 +80,7 @@ export const useLoadPluginFromUrl = (): UseLoadPluginReturnType => {
   return {
     handleChangePluginUrl,
     handleLoadPlugin,
+    handleKeyPress,
     isPending,
     pluginUrl,
   };
diff --git a/src/constants/common.ts b/src/constants/common.ts
index cc5db42a..33920fa6 100644
--- a/src/constants/common.ts
+++ b/src/constants/common.ts
@@ -19,3 +19,5 @@ export const ONE_HUNDRED = 100;
 
 export const EMPTY_ARRAY_STRING = '[]';
 export const ZOOM_FACTOR = 2.0; // Zoom factor indicating doubling the distance for each zoom level
+
+export const ENTER_KEY_CODE = 'Enter';
-- 
GitLab