Source: app/util/testing/generalTestingUtils.js

/* eslint-disable import/no-extraneous-dependencies */
import React from 'react';
import { act, render } from '@testing-library/react';
import { renderToString } from 'react-dom/server';
import { axe, toHaveNoViolations } from 'jest-axe';
import { Form, Formik } from 'formik';
import MessageFormat from 'messageformat';

export const obtainValueFromDotStringKey = (object, string, params, mockParams) => {
  /* eslint-disable no-param-reassign, consistent-return */
  const arrayFromString = string
    .replace(/\[(\w+)\]/g, '.$1')
    .replace(/^\./, '')
    .split('.');
  for (let i = 0, n = arrayFromString.length; i < n; ++i) {
    const currentKey = arrayFromString[i];
    if (currentKey in object) {
      object = object[currentKey];
    } else {
      return;
    }
  }

  if (mockParams && params && Object.entries(params).length > 0) {
    // Replace any undefined param value with ''
    Object.keys(params).forEach(key => {
      if (params[key] === undefined) {
        params[key] = '';
      }
    });

    const regex = () => {
      const paramArr = Object.keys(params);
      const matches = paramArr
        .map((param, index) => (!(index === paramArr.length - 1) ? `{${param}}|` : `{${param}}`))
        .join('');
      return new RegExp(`${matches}`, 'gi');
    };

    const replacedObject = object.replace(regex(), matched => {
      const match = matched.replace(/{|}/g, '');
      // if react component render it other wise just return the string
      return typeof params[match] === 'object' ? renderToString(params[match]) : params[match];
    });

    const messageFormat = new MessageFormat();
    const localeMessage = messageFormat.compile(replacedObject);

    return localeMessage(params);
  }

  return object;
  /* eslint-enable */
};

export const dummy = () => {};

export const mountTest = (component, promise) => {
  describe('can mount and unmount', () => {
    it('component can be mounted without errors', async () => {
      const target = render(component);
      if (promise) await act(() => promise);

      expect(() => {
        target.unmount();
      }).not.toThrow();
    });
  });
};

export const accessibilityChecks = (component, promise, rules = {}) => {
  const axeOptions = { rules: { ...rules } };
  expect.extend(toHaveNoViolations);
  it('As no accessibility isses', async () => {
    const { container } = render(component);
    if (promise) await act(() => promise);
    const results = await axe(container, axeOptions);
    expect(results).toHaveNoViolations();
  });
};

export const formikWrapper = component => (
  <Formik>
    <Form>{component}</Form>
  </Formik>
);

/**
 * Fix the timezone issue between offices when using tests
 *
 * @param date
 * @returns {string}
 */
export const getTimeZoneIsoString = date => {
  const currentDate = new Date(date);
  return new Date(currentDate.getTime() - currentDate.getTimezoneOffset() * 60000)
    .toISOString()
    .replace('.000', '');
};