/* eslint-disable no-magic-numbers */ import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; import { StoreType } from '@/redux/store'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; import { GLYPHS_STATE_INITIAL_MOCK } from '@/redux/glyphs/glyphs.mock'; import { apiPath } from '@/redux/apiPath'; import { HttpStatusCode } from 'axios'; import { layerImageFixture } from '@/models/fixtures/layerImageFixture'; import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { LAYER_STATE_DEFAULT_DATA, LAYERS_STATE_INITIAL_LAYER_MOCK, } from '@/redux/layers/layers.mock'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; import { overlayFixture } from '@/models/fixtures/overlaysFixture'; import { showToast } from '@/utils/showToast'; import { MapEditToolsState } from '@/redux/mapEditTools/mapEditTools.types'; import { MAP_EDIT_TOOLS_STATE_INITIAL_MOCK } from '@/redux/mapEditTools/mapEditTools.mock'; import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants'; import { Feature } from 'ol'; import Polygon from 'ol/geom/Polygon'; import { overlayGroupFixture } from '@/models/fixtures/overlayGroupsFixture'; import { LayerImageObjectEditFactoryModal } from './LayerImageObjectEditFactoryModal.component'; const mockedAxiosNewClient = mockNetworkNewAPIResponse(); const glyph = { id: 1, file: 23, filename: 'Glyph1.png' }; jest.mock('../../../../utils/showToast'); const renderComponent = ( initialMapEditToolsState: MapEditToolsState = MAP_EDIT_TOOLS_STATE_INITIAL_MOCK, ): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore({ ...INITIAL_STORE_STATE_MOCK, glyphs: { ...GLYPHS_STATE_INITIAL_MOCK, data: [glyph], }, layers: { 0: { ...LAYERS_STATE_INITIAL_LAYER_MOCK, data: { ...LAYER_STATE_DEFAULT_DATA, activeLayers: [1], }, }, }, modal: { isOpen: true, modalTitle: overlayFixture.name, modalName: 'edit-overlay', editOverlayState: overlayFixture, editOverlayGroupState: overlayGroupFixture, molArtState: {}, overviewImagesState: {}, errorReportState: {}, layerFactoryState: { id: undefined }, layerImageObjectFactoryState: { x: 1, y: 1, width: 1, height: 1, }, layerTextFactoryState: undefined, }, models: { ...MODELS_DATA_MOCK_WITH_MAIN_MAP, }, mapEditTools: initialMapEditToolsState, }); return { store, ...render( <Wrapper> <LayerImageObjectEditFactoryModal /> </Wrapper>, ), }; }; describe('LayerImageObjectEditFactoryModal - component', () => { it('should render LayerImageObjectEditFactoryModal component with initial state', () => { renderComponent({ activeAction: null, layerObject: { ...layerImageFixture, glyph: null, }, }); expect(screen.getByText(/Glyph:/i)).toBeInTheDocument(); expect(screen.getByText(/File:/i)).toBeInTheDocument(); expect(screen.getByText(/Submit/i)).toBeInTheDocument(); expect(screen.getByText(/No Image/i)).toBeInTheDocument(); }); it('should display a list of glyphs in the dropdown', async () => { renderComponent({ activeAction: null, layerObject: { ...layerImageFixture, glyph: null, }, }); const dropdown = screen.getByTestId('autocomplete'); if (!dropdown.firstChild) { throw new Error('Dropdown does not have a firstChild'); } fireEvent.keyDown(dropdown.firstChild, { key: 'ArrowDown' }); await waitFor(() => expect(screen.getByText(glyph.filename)).toBeInTheDocument()); fireEvent.click(screen.getByText(glyph.filename)); }); it('should update the selected glyph on dropdown change', async () => { renderComponent({ activeAction: null, layerObject: { ...layerImageFixture, glyph: null, }, }); const dropdown = screen.getByTestId('autocomplete'); if (!dropdown.firstChild) { throw new Error('Dropdown does not have a firstChild'); } fireEvent.keyDown(dropdown.firstChild, { key: 'ArrowDown' }); await waitFor(() => expect(screen.getByText(glyph.filename)).toBeInTheDocument()); fireEvent.click(screen.getByText(glyph.filename)); await waitFor(() => { const imgPreview: HTMLImageElement = screen.getByTestId('layer-image-preview'); const decodedSrc = decodeURIComponent(imgPreview.src); expect(decodedSrc).toContain(`glyphs/${glyph.id}/fileContent`); }); }); it('should handle form submission correctly', async () => { mockedAxiosNewClient .onPut(apiPath.updateLayerImageObject(0, 1, 1)) .reply(HttpStatusCode.Ok, layerImageFixture); const geometry = new Polygon([ [ [10, 10], [10, 10], ], ]); const layerObjectFeature = new Feature({ geometry }); const glyphData = { id: 1, x: 1, y: 1, width: 1, height: 1, layer: 1, glyph: 1, z: 1, }; const getGlyphDataMock = jest.fn(() => glyphData); jest.spyOn(layerObjectFeature, 'get').mockImplementation(key => { if (key === 'updateElement') return (): void => {}; if (key === 'getObjectData') return getGlyphDataMock; return undefined; }); renderComponent({ activeAction: MAP_EDIT_ACTIONS.TRANSFORM_IMAGE, layerObject: glyphData, }); const submitButton = screen.getByText(/Submit/i); await act(async () => { fireEvent.click(submitButton); }); expect(showToast).toHaveBeenCalledWith({ message: 'The image has been successfully updated', type: 'success', }); }); it('should display "No Image" when there is no image file', () => { const { store } = renderComponent({ activeAction: null, layerObject: { ...layerImageFixture, glyph: null, }, }); store.dispatch({ type: 'glyphs/clearGlyphData', }); expect(screen.getByText(/No Image/i)).toBeInTheDocument(); }); });