Skip to content
Snippets Groups Projects
layers.reducers.test.ts 8.91 KiB
Newer Older
/* 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: {
Miłosz Grocholewski's avatar
Miłosz Grocholewski committed
        [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: {
Miłosz Grocholewski's avatar
Miłosz Grocholewski committed
          [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,
    );
  });