import React from 'react';
import { combineReducers } from 'redux';
import { renderConnectedComponent, sleep } from '../../../test-utils/dist/js';
import {
  reduxAjaxMiddleware,
  reduxAjaxReducer,
  reduxAjaxReducerKey,
  submitFailure,
  submitPending,
  submitSuccess
} from '../index';
import { ReduxAjaxContainer } from './redux-ajax-container';

type ExampleResponse = { count: number };

enum RequestIds {
  test = 'test',
  test2 = 'test2'
}

const requestIds = [RequestIds.test, RequestIds.test2];

const Example: React.FC = () => (
  <ReduxAjaxContainer
    requestIds={requestIds}
    validateRequests={({ test, test2 }: { [requestId in RequestIds]: ExampleResponse }) =>
      test.count + test2.count > 10
    }
    success="success"
    failure="failure"
    loading="loading"
  />
);

const setupTest = () =>
  renderConnectedComponent({
    rootReducer: combineReducers({ [reduxAjaxReducerKey]: reduxAjaxReducer }),
    middlewareList: [reduxAjaxMiddleware({ fetchFn: jest.fn() })]
  })(<Example />);

describe('reduxAjaxContainer', () => {
  it('displays the resiliency component if any request fails', async () => {
    const { store, asFragment } = setupTest();
    store.dispatch(submitSuccess({ requestId: requestIds[0], response: { count: 11 } }));
    store.dispatch(submitFailure({ requestId: requestIds[1], error: {} }));
    await sleep();

    expect(asFragment()).toMatchSnapshot();
  });

  it('displays the resiliency component if the validateFunction returns false', async () => {
    const { store, asFragment } = setupTest();
    store.dispatch(submitSuccess({ requestId: requestIds[0], response: { count: 1 } }));
    store.dispatch(submitSuccess({ requestId: requestIds[1], response: { count: 2 } }));
    await sleep();

    expect(asFragment()).toMatchSnapshot();
  });

  it('displays the success component if the validateFunction returns true and all requests are successful', async () => {
    const { store, asFragment } = setupTest();
    store.dispatch(submitSuccess({ requestId: requestIds[0], response: { count: 5 } }));
    store.dispatch(submitSuccess({ requestId: requestIds[1], response: { count: 6 } }));
    await sleep();

    expect(asFragment()).toMatchSnapshot();
  });

  it('displays the loader component if not all requests are successful', async () => {
    const { store, asFragment } = setupTest();
    store.dispatch(submitPending({ requestId: requestIds[0] }));
    await sleep();

    expect(asFragment()).toMatchSnapshot();
  });
});
