/* eslint-disable no-magic-numbers */ import { apiPath } from '@/redux/apiPath'; import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { HttpStatusCode } from 'axios'; import { unwrapResult } from '@reduxjs/toolkit'; import { LAYER_STATE_DEFAULT_DATA, LAYERS_STATE_INITIAL_MOCK } from '@/redux/layers/layers.mock'; import { getLayersForModel } from '@/redux/layers/layers.thunks'; import { layersFixture } from '@/models/fixtures/layersFixture'; import { layerTextsFixture } from '@/models/fixtures/layerTextsFixture'; import { layerRectsFixture } from '@/models/fixtures/layerRectsFixture'; import { layerOvalsFixture } from '@/models/fixtures/layerOvalsFixture'; import { layerLinesFixture } from '@/models/fixtures/layerLinesFixture'; import { layerImagesFixture } from '@/models/fixtures/layerImagesFixture'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { layerFixture } from '@/models/fixtures/layerFixture'; import { DEFAULT_ERROR } from '@/constants/errors'; import { layerImageFixture } from '@/models/fixtures/layerImageFixture'; import { layerTextFixture } from '@/models/fixtures/layerTextFixture'; import layersReducer, { layerAddImage, layerAddText, layerDeleteImage, layerUpdateImage, setActiveLayer, setLayerVisibility, } from './layers.slice'; import { LayersState } from './layers.types'; const mockedAxiosClient = mockNetworkNewAPIResponse(); const INITIAL_STATE: LayersState = LAYERS_STATE_INITIAL_MOCK; const layersState: LayersState = { 1: { data: { layersVisibility: { [layerFixture.id]: true, }, layers: [ { details: layerFixture, texts: {}, rects: [], ovals: [], lines: [], images: {}, }, ], activeLayer: layerFixture.id, }, loading: 'idle', error: DEFAULT_ERROR, }, }; describe('layers reducer', () => { let store = {} as ToolkitStoreWithSingleSlice<LayersState>; beforeEach(() => { store = createStoreInstanceUsingSliceReducer('layers', layersReducer); }); it('should match initial state', () => { const action = { type: 'unknown' }; expect(layersReducer(undefined, action)).toEqual(INITIAL_STATE); }); it('should update store after successful getLayers query', async () => { mockedAxiosClient.onGet(apiPath.getLayers(1)).reply(HttpStatusCode.Ok, layersFixture); mockedAxiosClient .onGet(apiPath.getLayerTexts(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerTextsFixture); mockedAxiosClient .onGet(apiPath.getLayerRects(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerRectsFixture); mockedAxiosClient .onGet(apiPath.getLayerOvals(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerOvalsFixture); mockedAxiosClient .onGet(apiPath.getLayerLines(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerLinesFixture); mockedAxiosClient .onGet(apiPath.getLayerImages(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerImagesFixture); const { type } = await store.dispatch(getLayersForModel(1)); const { data, loading, error } = store.getState().layers[1]; expect(type).toBe('vectorMap/getLayers/fulfilled'); expect(loading).toEqual('succeeded'); expect(error).toEqual({ message: '', name: '' }); expect(data).toEqual({ activeLayer: null, layers: [ { details: layersFixture.content[0], texts: { [layerTextsFixture.content[0].id]: layerTextsFixture.content[0] }, rects: layerRectsFixture.content, ovals: layerOvalsFixture.content, lines: layerLinesFixture.content, images: { [layerImagesFixture.content[0].id]: layerImagesFixture.content[0] }, }, ], layersVisibility: { [layersFixture.content[0].id]: layersFixture.content[0].visible, }, }); }); it('should update store after failed getLayers query', async () => { mockedAxiosClient.onGet(apiPath.getLayers(1)).reply(HttpStatusCode.NotFound, []); const action = await store.dispatch(getLayersForModel(1)); const { data, loading, error } = store.getState().layers[1]; expect(action.type).toBe('vectorMap/getLayers/rejected'); expect(() => unwrapResult(action)).toThrow( "Failed to fetch layers: The page you're looking for doesn't exist. Please verify the URL and try again.", ); expect(loading).toEqual('failed'); expect(error).toEqual({ message: '', name: '' }); expect(data).toEqual({ activeLayer: null, layers: [], layersVisibility: {}, }); }); it('should update store on loading getLayers query', async () => { mockedAxiosClient.onGet(apiPath.getLayers(1)).reply(HttpStatusCode.Ok, layersFixture); mockedAxiosClient .onGet(apiPath.getLayerTexts(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerTextsFixture); mockedAxiosClient .onGet(apiPath.getLayerRects(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerRectsFixture); mockedAxiosClient .onGet(apiPath.getLayerOvals(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerOvalsFixture); mockedAxiosClient .onGet(apiPath.getLayerLines(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerLinesFixture); mockedAxiosClient .onGet(apiPath.getLayerImages(1, layersFixture.content[0].id)) .reply(HttpStatusCode.Ok, layerImagesFixture); const layersPromise = store.dispatch(getLayersForModel(1)); const { data, loading } = store.getState().layers[1]; expect(data).toEqual(LAYER_STATE_DEFAULT_DATA); expect(loading).toEqual('pending'); layersPromise.then(() => { const { data: dataPromiseFulfilled, loading: promiseFulfilled } = store.getState().layers[1]; expect(dataPromiseFulfilled).toEqual({ activeLayer: null, layers: [ { details: layersFixture.content[0], texts: { [layerTextsFixture.content[0].id]: layerTextsFixture.content[0] }, rects: layerRectsFixture.content, ovals: layerOvalsFixture.content, lines: layerLinesFixture.content, images: { [layerImagesFixture.content[0].id]: layerImagesFixture.content[0] }, }, ], layersVisibility: { [layersFixture.content[0].id]: layersFixture.content[0].visible, }, }); expect(promiseFulfilled).toEqual('succeeded'); }); }); it('should handle setLayerVisibilityReducer', () => { const { store: layersStore } = getReduxWrapperWithStore({ layers: layersState, }); layersStore.dispatch( setLayerVisibility({ modelId: 1, layerId: layerFixture.id, visible: false }), ); expect(layersStore.getState().layers[1].data?.layersVisibility[layerFixture.id]).toBe(false); }); it('should handle setActiveLayerReducer', () => { const { store: layersStore } = getReduxWrapperWithStore({ layers: layersState, }); layersStore.dispatch(setActiveLayer({ modelId: 1, layerId: layerFixture.id })); expect(layersStore.getState().layers[1].data?.activeLayer).toBe(layerFixture.id); }); it('should handle layerAddImageReducer', () => { const { store: layersStore } = getReduxWrapperWithStore({ layers: layersState, }); layersStore.dispatch( layerAddImage({ modelId: 1, layerId: layerFixture.id, layerImage: layerImageFixture }), ); expect(layersStore.getState().layers[1].data?.layers[0].images[layerImageFixture.id]).toEqual( layerImageFixture, ); }); it('should handle layerUpdateImageReducer', () => { const { store: layersStore } = getReduxWrapperWithStore({ layers: layersState, }); layersStore.dispatch( layerUpdateImage({ modelId: 1, layerId: layerFixture.id, layerImage: layerImageFixture }), ); expect(layersStore.getState().layers[1].data?.layers[0].images[layerImageFixture.id]).toEqual( layerImageFixture, ); }); it('should handle layerDeleteImageReducer', () => { const { store: layersStore } = getReduxWrapperWithStore({ layers: layersState, }); layersStore.dispatch( layerDeleteImage({ modelId: 1, layerId: layerFixture.id, imageId: layerImageFixture.id }), ); expect( layersStore.getState().layers[1].data?.layers[0].images[layerImageFixture.id], ).toBeUndefined(); }); it('should handle layerAddTextReducer', () => { const { store: layersStore } = getReduxWrapperWithStore({ layers: layersState, }); layersStore.dispatch( layerAddText({ modelId: 1, layerId: layerFixture.id, layerText: layerTextFixture }), ); expect(layersStore.getState().layers[1].data?.layers[0].texts[layerTextFixture.id]).toEqual( layerTextFixture, ); }); });