import { runSaga } from "redux-saga";
import {
  createScreeningTestError,
  createScreeningTestSuccess,
  fetchScreeningTestsError,
  fetchScreeningTestsSuccess,
} from "../../store/actions/screeningTests/screeningTestActions";
import {
  createScreeningTest,
  getScreeningTests,
} from "../../store/saga/screeningTestsSaga";
import * as api from "../../request/screeningTestRequest";
import * as redux from "react-redux";
import * as helper from "../../util/helpers/rejectErrorCodeHelper";

describe("screening tests saga tests", () => {
  let spyOnUseSelector;
  let spyOnUseDispatch;
  let mockDispatch;

  beforeEach(() => {
    // Mock useSelector hook
    spyOnUseSelector = jest.spyOn(redux, "useSelector");
    spyOnUseSelector.mockReturnValueOnce("anything");

    // Mock useDispatch hook
    spyOnUseDispatch = jest.spyOn(redux, "useDispatch");

    // Mock dispatch function returned from useDispatch
    mockDispatch = jest.fn();
    spyOnUseDispatch.mockReturnValue(mockDispatch);
  });

  afterEach(() => {
    jest.restoreAllMocks();
  });

  it("Should handle get tests saga with actions", async () => {
    const dispatchedActions = [];

    const mockedCall = { data: "Data" };
    api.getTests = jest.fn(() => Promise.resolve(mockedCall));

    const fakeStore = {
      getState: () => mockState.users,
      dispatch: (action) => dispatchedActions.push(action),
    };

    await runSaga(fakeStore, getScreeningTests).done;
    expect(api.getTests.mock.calls.length).toBe(1);
    expect(dispatchedActions).toContainEqual(
      fetchScreeningTestsSuccess(mockedCall.data)
    );
  });

  it("Should handle get tests saga with errors", async () => {
    const dispatchedActions = [];

    helper.rejectErrorCodeHelper = jest.fn(() => "Error");

    const mockedCall = { response: { data: { message: "Error" } } };
    api.getTests = jest.fn(() => Promise.reject(mockedCall));

    const fakeStore = {
      getState: () => mockState.users,
      dispatch: (action) => dispatchedActions.push(action),
    };

    await runSaga(fakeStore, getScreeningTests).done;
    expect(api.getTests.mock.calls.length).toBe(1);
    expect(dispatchedActions).toContainEqual(fetchScreeningTestsError("Error"));
  });

  it("Should handle create screening tests saga with actions", async () => {
    const dispatchedActions = [];

    const mockedCall = { data: "Data" };
    api.createTest = jest.fn(() => Promise.resolve(mockedCall));

    const fakeStore = {
      getState: () => mockState.users,
      dispatch: (action) => dispatchedActions.push(action),
    };

    await runSaga(fakeStore, createScreeningTest, { payload: {} }).done;
    expect(api.createTest.mock.calls.length).toBe(1);
    expect(dispatchedActions).toContainEqual(
      createScreeningTestSuccess(mockedCall.data)
    );
  });

  it("Should handle create screening tests saga with errors", async () => {
    const dispatchedActions = [];

    helper.rejectErrorCodeHelper = jest.fn(() => "Error");

    const mockedCall = { response: { data: { message: "Error" } } };
    api.createTest = jest.fn(() => Promise.reject(mockedCall));

    const fakeStore = {
      getState: () => mockState.users,
      dispatch: (action) => dispatchedActions.push(action),
    };

    await runSaga(fakeStore, createScreeningTest, { payload: {} }).done;
    expect(api.createTest.mock.calls.length).toBe(1);
    expect(dispatchedActions).toContainEqual(createScreeningTestError("Error"));
  });
});
