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