import { renderHook } from "@testing-library/react-hooks"; import MockAdapter from "axios-mock-adapter"; import React from "react"; import { Provider, useStore } from "react-redux"; import { ApiActionCreator, RequestMethod, StateHelper } from "../"; import { useGet } from "../hooks"; import { carActionHandler } from "../test-utils/CarActionHandler"; import { configureStore } from "../test-utils/configureStore"; import { ApiActionType } from "../services/ApiActionCreator/enums/ApiActionType"; import { END } from "redux-saga"; import { RootState } from "../interfaces/RootState"; describe("StateHelper", () => { const ReduxProvider = ({ children, reduxStore, }: { children: any; reduxStore: any; }) => {children}; const { store: mockStore, apiSaga } = configureStore(); afterEach(() => { jest.resetAllMocks(); }); const wrapper = ({ children }: { children: any }) => ( {children} ); it("should correctly fetch request meta with passed id", async () => { const mock = new MockAdapter(apiSaga.apiService.httpAdapter); mock.onGet("/cars/1").reply(200, { data: { id: "1", type: "car", attributes: { brand: "GetCar", model: "GLL", year: "2020", }, }, }); const { waitForNextUpdate } = renderHook( () => useGet(carActionHandler, "1"), { wrapper, }, ); const { result: storeResult } = renderHook( () => useStore(), { wrapper, }, ); const state = storeResult.current.getState(); await waitForNextUpdate(); const meta = StateHelper.getMeta( state, "GET_CAR", RequestMethod.Get, "1", ); expect(meta).toEqual({ loading: true, status: "begin", endpoint: "/cars/1", entityIds: [], }); }); it("should correctly fetch request meta with passed id", async () => { const mock = new MockAdapter(apiSaga.apiService.httpAdapter); mock.onGet("/cars/1").reply(200, { data: { id: "1", type: "car", attributes: { brand: "GetCar", model: "GLL", year: "2020", }, }, }); const { waitForNextUpdate } = renderHook( () => useGet(carActionHandler, "1"), { wrapper, }, ); const { result: storeResult } = renderHook( () => useStore(), { wrapper, }, ); const state = storeResult.current.getState(); await waitForNextUpdate(); const meta = StateHelper.getMeta( state, "GET_CAR", RequestMethod.Get, "1", ); expect(meta).toEqual({ loading: true, status: "begin", endpoint: "/cars/1", entityIds: ["1"], entities: [{ id: "1", type: "car" }], error: undefined, dataMeta: undefined, }); }); it("should retrieve request meta with arbitrary operation", async () => { const getCarOperation = "FETCH_CAR"; const { store: mockStore, apiSaga } = configureStore({ /** * saga "END" callback * this is where we can test the final outcome of the saga along with the mocks */ onSagaEnd: () => { const state = mockStore.getState(); const meta = StateHelper.getMeta( state, getCarOperation, RequestMethod.Get, "1", ); expect(meta?.loading).toEqual(false); expect(meta).toEqual({ loading: false, status: "success", endpoint: "/cars/1", entities: [{ id: "1", type: "car" }], error: undefined, dataMeta: undefined, entityIds: ["1"], }); }, }); const mock = new MockAdapter(apiSaga.apiService.httpAdapter); mock.onGet("/cars/1").reply(200, { data: { id: "1", type: "car", attributes: { brand: "GetCar", model: "GLL", year: "2020", }, }, }); const getCarAction = ApiActionCreator.createActionSync({ operation: getCarOperation, endpoint: "/cars", method: RequestMethod.Get, apiActionType: ApiActionType.JsonApiRequest, id: "1", }); mockStore.dispatch(getCarAction); const state = mockStore.getState(); const meta = StateHelper.getMeta( state, getCarOperation, RequestMethod.Get, "1", ); /** * initial saga dispatch */ expect(meta).toEqual({ loading: true, status: "begin", endpoint: "/cars/1", entityIds: [], }); /** * simulate saga END */ mockStore.dispatch(END); }); it("should retrieve correct identifiers with arbitrary operation - single record", async () => { const getCarOperation = "FETCH_CAR"; const { store: mockStore, apiSaga } = configureStore({ /** * saga "END" callback * this is where we can test the final outcome of the saga along with the mocks */ onSagaEnd: () => { const state = mockStore.getState(); const identifiers = StateHelper.getIdentifiers( state, getCarOperation, RequestMethod.Get, "1", ); expect(identifiers).toEqual(["1"]); }, }); const mock = new MockAdapter(apiSaga.apiService.httpAdapter); mock.onGet("/cars/1").reply(200, { data: { id: "1", type: "car", attributes: { brand: "GetCar", model: "GLL", year: "2020", }, }, }); const getCarAction = ApiActionCreator.createActionSync({ operation: getCarOperation, endpoint: "/cars", method: RequestMethod.Get, apiActionType: ApiActionType.JsonApiRequest, id: "1", }); mockStore.dispatch(getCarAction); const state = mockStore.getState(); const identifiers = StateHelper.getIdentifiers( state, getCarOperation, RequestMethod.Get, "1", ); /** * initial saga dispatch */ expect(identifiers).toEqual([]); /** * simulate saga END */ mockStore.dispatch(END); }); it("should retrieve correct identifiers with arbitrary operation - multiple records", async () => { const getCarsOperation = "FETCH_CARS"; const { store: mockStore, apiSaga } = configureStore({ /** * saga "END" callback * this is where we can test the final outcome of the saga along with the mocks */ onSagaEnd: () => { const state = mockStore.getState(); const identifiers = StateHelper.getIdentifiers( state, getCarsOperation, RequestMethod.Get, ); expect(identifiers).toEqual(["1", "2"]); }, }); const mock = new MockAdapter(apiSaga.apiService.httpAdapter); mock.onGet("/cars").reply(200, { data: [ { id: "1", type: "car", attributes: { brand: "GetCar", model: "GLL", year: "2020", }, }, { id: "2", type: "car", attributes: { brand: "GetCar2", model: "GLL", year: "2020", }, }, ], }); const getCarAction = ApiActionCreator.createActionSync({ operation: getCarsOperation, endpoint: "/cars", method: RequestMethod.Get, apiActionType: ApiActionType.JsonApiRequest, }); mockStore.dispatch(getCarAction); const state = mockStore.getState(); const identifiers = StateHelper.getIdentifiers( state, getCarsOperation, RequestMethod.Get, ); /** * initial saga dispatch */ expect(identifiers).toEqual([]); /** * simulate saga END */ mockStore.dispatch(END); }); });