huridocs/uwazi

View on GitHub
app/react/I18N/components/specs/I18NMenu.spec.tsx

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * @jest-environment jsdom
 */
import React from 'react';
import { act, fireEvent, RenderResult, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import { MockStoreEnhanced } from 'redux-mock-store';
import { Location, MemoryRouter } from 'react-router-dom';
import Immutable from 'immutable';
import { defaultState, renderConnectedContainer } from 'app/utils/test/renderConnected';
import { i18NMenuComponent as I18NMenu } from '../I18NMenu';

describe('I18NMenu', () => {
  let props: any;
  let renderResult: RenderResult;
  let store: MockStoreEnhanced;
  let location: Partial<Location>;
  const toggleInlineEditMock = jest.fn();

  Reflect.deleteProperty(global.window, 'location');
  window.location = { ...window.location, assign: jest.fn() };

  beforeEach(() => {
    jest.clearAllMocks();
    const languages = [
      { _id: '1', key: 'en', label: 'English', localized_label: 'English' },
      { _id: '2', key: 'es', label: 'Spanish', localized_label: 'Español', default: true },
    ];

    props = {
      languages: Immutable.fromJS(languages),
      toggleInlineEdit: toggleInlineEditMock,
      i18nmode: false,
      locale: 'es',
    };

    location = {
      pathname: '/templates/2452345',
      search: '?query=weneedmoreclerics',
    };
  });

  const render = (userType?: 'admin' | 'editor' | 'collaborator') => {
    const storeUser = userType
      ? Immutable.fromJS({ _id: 'user1', role: userType })
      : Immutable.fromJS({});

    props.user = userType
      ? Immutable.fromJS({ _id: 'user1', role: userType })
      : Immutable.fromJS({});

    ({ renderResult, store } = renderConnectedContainer(
      <I18NMenu.WrappedComponent {...props} />,
      () => ({
        ...defaultState,
        user: storeUser,
      }),
      'MemoryRouter',
      [location]
    ));
  };

  describe('Paths', () => {
    it.each`
      locale  | currentPath                | search                        | expectedPath
      ${'es'} | ${'/es/documents'}         | ${'?search'}                  | ${'/documents'}
      ${'en'} | ${'/en/entity/r2dzptt7ts'} | ${'?page=2'}                  | ${'/entity/r2dzptt7ts'}
      ${null} | ${'/templates/2452345'}    | ${'?query=weneedmoreclerics'} | ${'/templates/2452345?query=weneedmoreclerics'}
      ${null} | ${'/entity/2452345'}       | ${'?query=weneedmoreclerics'} | ${'/entity/2452345?query=weneedmoreclerics'}
      ${'es'} | ${'/es/templates/2452345'} | ${'?query=weneedmoreclerics'} | ${'/templates/2452345?query=weneedmoreclerics'}
    `(
      'should create the expected links for $pathName',
      async ({ locale, currentPath, search, expectedPath }) => {
        props.locale = locale;
        location.pathname = currentPath;
        location.search = search;
        render('admin');
        const links = screen.getAllByRole('link');
        expect(links.map(link => link.getAttribute('href'))).toEqual(
          expect.arrayContaining([`/en${expectedPath}`, `/es${expectedPath}`])
        );
      }
    );
  });

  it('should return empty if there are no languages', () => {
    props.languages = Immutable.fromJS([]);
    render('admin');
    expect(screen.queryByText('Live translate')).not.toBeInTheDocument();
    expect(screen.queryByText('English')).not.toBeInTheDocument();
  });

  it('should not show live transtions for not authorized user', async () => {
    render('collaborator');
    expect(screen.queryByText('Live translate')).not.toBeInTheDocument();
    expect(screen.getByText('English')).toBeInTheDocument();
  });

  it('should show live transtions for authorized user', async () => {
    render('editor');
    expect(screen.queryByText('Live translate')).toBeInTheDocument();
    const listItems = screen.getAllByRole('link');
    expect(listItems.map(item => item.textContent)).toEqual(['English', 'Español']);
  });

  it('should show as active the current locale', async () => {
    render('admin');
    const [listItem] = screen
      .getAllByRole('listitem')
      .filter(item => item.textContent === 'Español');
    expect(listItem.getAttribute('class')).toBe('menuNav-item active');
  });

  it('should not display the language section if there is only one language and no user', () => {
    props.languages = Immutable.fromJS([{ _id: '1', key: 'en', label: 'English', default: true }]);
    render();
    expect(screen.queryByText('English')).not.toBeInTheDocument();
  });

  it('should display the language section if there is only one language and a user', () => {
    props.languages = Immutable.fromJS([{ _id: '1', key: 'en', label: 'English', default: true }]);
    render('collaborator');
    expect(screen.queryByText('English')).toBeInTheDocument();
    expect(screen.getByRole('link').getAttribute('href')).toBe(
      '/en/templates/2452345?query=weneedmoreclerics'
    );
  });

  it('should change to a single button when live translating', async () => {
    props.i18nmode = true;
    render('editor');
    expect(screen.getByRole('button').parentElement!.textContent).toEqual('Live translate');
    const activeIcon = renderResult.container.getElementsByClassName('live-on');
    expect(activeIcon.length).toBe(1);
    const listItems = screen.queryAllByRole('link');
    expect(listItems).toEqual([]);
  });

  it('should active toggle translation edit mode when clicking Live translate', async () => {
    render('admin');
    await act(async () => {
      fireEvent.click(screen.getByText('Live translate').parentElement!);
    });
    expect(toggleInlineEditMock).toBeCalled();
  });

  it('should trigger a reload if the current language is deleted', async () => {
    props.locale = 'en';
    render('admin');
    props.languages = Immutable.fromJS([
      {
        _id: '2',
        key: 'es',
        label: 'Spanish',
        localized_label: 'Español',
        default: true,
      },
    ]);

    renderResult.rerender(
      <MemoryRouter initialEntries={[location]}>
        <Provider store={store}>
          <I18NMenu.WrappedComponent {...props} />
        </Provider>
      </MemoryRouter>
    );

    expect(window.location.assign).toHaveBeenCalledTimes(1);
    expect(window.location.assign).toHaveBeenCalledWith('/templates/2452345');
  });
});