Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
LoadPluginFromUrl.component.test.tsx 5.15 KiB
/* eslint-disable no-magic-numbers */
import { pluginFixture } from '@/models/fixtures/pluginFixture';
import { apiPath } from '@/redux/apiPath';
import { StoreType } from '@/redux/store';
import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
import { InitialStoreState } from '@/utils/testing/getReduxStoreActionsListener';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import axios, { HttpStatusCode } from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { act } from 'react-dom/test-utils';
import { handleError } from '@/utils/error-report/errorReporting';
import { LoadPluginFromUrl } from './LoadPluginFromUrl.component';

const mockedAxiosApiClient = mockNetworkResponse();
const mockedAxiosClient = new MockAdapter(axios);

jest.mock('../../../../../utils/error-report/errorReporting');

const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } => {
  const { Wrapper, store } = getReduxWrapperWithStore(initialStore);
  return (
    render(
      <Wrapper>
        <LoadPluginFromUrl />
      </Wrapper>,
    ),
    {
      store,
    }
  );
};

describe('LoadPluginFromUrl - component', () => {
  global.URL.canParse = jest.fn();

  afterEach(() => {
    jest.restoreAllMocks();
  });
  describe('when always', () => {
    it('renders plugin input label', () => {
      renderComponent();

      const pluginInputLabel = screen.getByLabelText('URL:');
      expect(pluginInputLabel).toBeInTheDocument();
    });

    it('renders plugin input', () => {
      renderComponent();

      const pluginInput = screen.getByTestId('load-plugin-input-url');
      expect(pluginInput).toBeInTheDocument();
    });

    it('renders plugin load button', () => {
      renderComponent();

      const loadButton = screen.getByText('Load');
      expect(loadButton.tagName).toBe('BUTTON');
      expect(loadButton).toBeInTheDocument();
    });
    it('should unload plugin after click', async () => {
      mockedAxiosApiClient.onPost(apiPath.registerPluign()).reply(HttpStatusCode.Ok, pluginFixture);
      mockedAxiosApiClient
        .onGet(apiPath.getPlugin(pluginFixture.hash))
        .reply(HttpStatusCode.Ok, pluginFixture);
      mockedAxiosClient.onGet(pluginFixture.urls[0]).reply(HttpStatusCode.Ok, '');

      renderComponent();
      const input = screen.getByTestId('load-plugin-input-url');
      expect(input).toBeVisible();

      await act(() => {
        fireEvent.change(input, { target: { value: pluginFixture.urls[0] } });
      });

      expect(input).toHaveValue(pluginFixture.urls[0]);

      const button = screen.queryByTestId('load-plugin-button');
      expect(button).toBeVisible();

      await act(() => {
        button?.click();
      });

      expect(button).toBeDisabled();
    });

    it('should disable url input if url is empty', async () => {
      renderComponent();
      const input = screen.getByTestId('load-plugin-input-url');
      expect(input).toBeVisible();

      act(() => {
        fireEvent.change(input, { target: { value: '' } });
      });

      expect(input).toHaveValue('');

      const button = screen.getByTestId('load-plugin-button');
      expect(button).toBeDisabled();
    });

    it('should disable url input if url is not correct', async () => {
      global.URL.canParse = jest.fn().mockReturnValue(false);
      renderComponent();
      const input = screen.getByTestId('load-plugin-input-url');
      expect(input).toBeVisible();

      act(() => {
        fireEvent.change(input, { target: { value: 'abcd' } });
      });

      expect(input).toHaveValue('abcd');

      const button = screen.getByTestId('load-plugin-button');
      expect(button).toBeDisabled();
    });
    it('should handle error if plugin failed to load', async () => {
      const pluginUrl = 'http://example.com/plugin.js';
      mockedAxiosClient.onGet(pluginUrl).reply(HttpStatusCode.Unauthorized, null);

      global.URL.canParse = jest.fn().mockReturnValue(true);

      renderComponent();
      const input = screen.getByTestId('load-plugin-input-url');
      expect(input).toBeVisible();

      act(() => {
        fireEvent.change(input, { target: { value: pluginUrl } });
      });

      const button = screen.getByTestId('load-plugin-button');

      act(() => {
        button.click();
      });

      await waitFor(() => {
        expect(handleError).toHaveBeenCalled();
      });
    });

    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();
      });
    });
  });
});