Spaces:
Running
Running
| import { fabric } from 'fabric'; | |
| import ImageEditor from '@/imageEditor'; | |
| import '@/command/loadImage'; | |
| describe('UI', () => { | |
| let actions, imageEditorMock, mockImage; | |
| beforeEach(() => { | |
| imageEditorMock = new ImageEditor(document.createElement('div'), { | |
| includeUI: { | |
| loadImage: false, | |
| initMenu: 'flip', | |
| menuBarPosition: 'bottom', | |
| applyCropSelectionStyle: true, | |
| }, | |
| }); | |
| actions = imageEditorMock.getActions(); | |
| mockImage = new fabric.Image(); | |
| imageEditorMock._graphics.setCanvasImage('mockImage', mockImage); | |
| }); | |
| describe('mainAction', () => { | |
| let mainAction; | |
| beforeEach(() => { | |
| mainAction = actions.main; | |
| }); | |
| it('should be executed When the initLoadImage action occurs', async () => { | |
| const loadImageFromURLSpy = jest | |
| .spyOn(imageEditorMock, 'loadImageFromURL') | |
| .mockReturnValue(Promise.resolve(300)); | |
| const clearUndoStackSpy = jest.spyOn(imageEditorMock, 'clearUndoStack'); | |
| const resizeEditorSpy = jest.spyOn(imageEditorMock.ui, 'resizeEditor'); | |
| await mainAction.initLoadImage('path', 'imageName'); | |
| expect(loadImageFromURLSpy).toHaveBeenCalled(); | |
| expect(clearUndoStackSpy).toHaveBeenCalled(); | |
| expect(resizeEditorSpy).toHaveBeenCalled(); | |
| }); | |
| it('should be executed When the undo action occurs', () => { | |
| jest.spyOn(imageEditorMock, 'isEmptyUndoStack').mockReturnValue(false); | |
| const undoSpy = jest.spyOn(imageEditorMock, 'undo').mockReturnValue({ then: () => {} }); | |
| mainAction.undo(); | |
| expect(undoSpy).toHaveBeenCalled(); | |
| }); | |
| it('should be executed When the redo action occurs', () => { | |
| jest.spyOn(imageEditorMock, 'isEmptyRedoStack').mockReturnValue(false); | |
| const redoSpy = jest.spyOn(imageEditorMock, 'redo').mockReturnValue({ then: () => {} }); | |
| mainAction.redo(); | |
| expect(redoSpy).toHaveBeenCalled(); | |
| }); | |
| it('should be executed When the delete action occurs', () => { | |
| imageEditorMock.activeObjectId = 10; | |
| imageEditorMock.removeActiveObject = jest.fn(); | |
| mainAction.delete(); | |
| expect(imageEditorMock.removeActiveObject).toHaveBeenCalled(); | |
| expect(imageEditorMock.activeObjectId).toBeNull(); | |
| }); | |
| it('should be run and the enabled state should be changed When the deleteAll action occurs', () => { | |
| imageEditorMock.clearObjects = jest.fn(); | |
| const changeHelpButtonEnabledSpy = jest.spyOn(imageEditorMock.ui, 'changeHelpButtonEnabled'); | |
| mainAction.deleteAll(); | |
| expect(imageEditorMock.clearObjects).toHaveBeenCalled(); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(1, 'delete', false); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(2, 'deleteAll', false); | |
| }); | |
| it('should be executed When the load action occurs', async () => { | |
| const loadImageFromFileSpy = jest | |
| .spyOn(imageEditorMock, 'loadImageFromFile') | |
| .mockReturnValue(Promise.resolve()); | |
| const clearUndoStackSpy = jest.spyOn(imageEditorMock, 'clearUndoStack'); | |
| const resizeEditorSpy = jest.spyOn(imageEditorMock.ui, 'resizeEditor'); | |
| global.URL.createObjectURL = jest.fn(); | |
| await mainAction.load(); | |
| expect(loadImageFromFileSpy).toHaveBeenCalled(); | |
| expect(clearUndoStackSpy).toHaveBeenCalled(); | |
| expect(resizeEditorSpy).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('shapeAction', () => { | |
| let shapeAction; | |
| beforeEach(() => { | |
| shapeAction = actions.shape; | |
| }); | |
| it('should be executed When the changeShape action occurs', () => { | |
| imageEditorMock.activeObjectId = 10; | |
| imageEditorMock.changeShape = jest.fn(); | |
| shapeAction.changeShape({ strokeWidth: '#000000' }); | |
| expect(imageEditorMock.changeShape).toHaveBeenCalledWith( | |
| 10, | |
| { strokeWidth: '#000000' }, | |
| undefined | |
| ); | |
| }); | |
| it('should be executed When the setDrawingShape action occurs', () => { | |
| imageEditorMock.setDrawingShape = jest.fn(); | |
| shapeAction.setDrawingShape(); | |
| expect(imageEditorMock.setDrawingShape).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('cropAction', () => { | |
| let cropAction; | |
| beforeEach(() => { | |
| cropAction = actions.crop; | |
| }); | |
| it('should be executed when the crop action occurs', async () => { | |
| const getCropzoneRectSpy = jest | |
| .spyOn(imageEditorMock, 'getCropzoneRect') | |
| .mockReturnValue(true); | |
| const cropSpy = jest.spyOn(imageEditorMock, 'crop').mockReturnValue(Promise.resolve()); | |
| const stopDrawingModeSpy = jest.spyOn(imageEditorMock, 'stopDrawingMode'); | |
| imageEditorMock.ui.changeMenu = jest.fn(); | |
| await cropAction.crop(); | |
| expect(getCropzoneRectSpy).toHaveBeenCalled(); | |
| expect(cropSpy).toHaveBeenCalled(); | |
| expect(stopDrawingModeSpy).toHaveBeenCalled(); | |
| }); | |
| it('should be executed When the cancel action occurs', () => { | |
| const stopDrawingModeSpy = jest.spyOn(imageEditorMock, 'stopDrawingMode'); | |
| imageEditorMock.ui.changeMenu = jest.fn(); | |
| cropAction.cancel(); | |
| expect(stopDrawingModeSpy).toHaveBeenCalled(); | |
| expect(imageEditorMock.ui.changeMenu).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('flipAction', () => { | |
| let flipAction; | |
| beforeEach(() => { | |
| flipAction = actions.flip; | |
| }); | |
| it('should be executed When the flip(flipType) action occurs', () => { | |
| imageEditorMock.flipX = jest.fn(); | |
| imageEditorMock.flipY = jest.fn(); | |
| flipAction.flip('flipX'); | |
| expect(imageEditorMock.flipX).toHaveBeenCalled(); | |
| flipAction.flip('flipY'); | |
| expect(imageEditorMock.flipY).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('rotateAction', () => { | |
| let rotateAction; | |
| beforeEach(() => { | |
| rotateAction = actions.rotate; | |
| }); | |
| it('should be executed When the rotate action occurs', () => { | |
| const resizeEditorSpy = jest.spyOn(imageEditorMock.ui, 'resizeEditor'); | |
| imageEditorMock.rotate = jest.fn(); | |
| rotateAction.rotate(30); | |
| expect(imageEditorMock.rotate).toHaveBeenCalledWith(30, undefined); | |
| expect(resizeEditorSpy).toHaveBeenCalled(); | |
| }); | |
| it('should be executed When the setAngle action occurs', () => { | |
| const resizeEditorSpy = jest.spyOn(imageEditorMock.ui, 'resizeEditor'); | |
| imageEditorMock.setAngle = jest.fn(); | |
| rotateAction.setAngle(30); | |
| expect(imageEditorMock.setAngle).toHaveBeenCalledWith(30, undefined); | |
| expect(resizeEditorSpy).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('textAction', () => { | |
| let textAction; | |
| beforeEach(() => { | |
| textAction = actions.text; | |
| }); | |
| it('should be executed When the changeTextStyle action occurs', () => { | |
| imageEditorMock.activeObjectId = 10; | |
| imageEditorMock.changeTextStyle = jest.fn(); | |
| textAction.changeTextStyle({ fontSize: 10 }); | |
| expect(imageEditorMock.changeTextStyle).toHaveBeenCalledWith(10, { fontSize: 10 }, undefined); | |
| }); | |
| }); | |
| describe('maskAction', () => { | |
| let maskAction; | |
| beforeEach(() => { | |
| maskAction = actions.mask; | |
| }); | |
| it('should be executed When the applyFilter action occurs', () => { | |
| imageEditorMock.activeObjectId = 10; | |
| imageEditorMock.applyFilter = jest.fn(); | |
| jest.spyOn(imageEditorMock, 'applyFilter'); | |
| maskAction.applyFilter(); | |
| expect(imageEditorMock.applyFilter).toHaveBeenCalledWith('mask', { maskObjId: 10 }); | |
| }); | |
| }); | |
| describe('drawAction', () => { | |
| let drawAction; | |
| beforeEach(() => { | |
| drawAction = actions.draw; | |
| }); | |
| it('should be executed When the setDrawMode("free") action occurs', () => { | |
| imageEditorMock.startDrawingMode = jest.fn(); | |
| drawAction.setDrawMode('free'); | |
| expect(imageEditorMock.startDrawingMode).toHaveBeenCalledWith('FREE_DRAWING', undefined); | |
| }); | |
| it('should be executed When the setColor() action occurs', () => { | |
| imageEditorMock.setBrush = jest.fn(); | |
| drawAction.setColor('#000000'); | |
| expect(imageEditorMock.setBrush).toBeCalledWith({ color: '#000000' }); | |
| }); | |
| }); | |
| describe('iconAction', () => { | |
| let iconAction; | |
| beforeEach(() => { | |
| iconAction = actions.icon; | |
| }); | |
| it('should run drawing mode when the add icon occurs', () => { | |
| const startDrawingModeSpy = jest.spyOn(imageEditorMock, 'startDrawingMode'); | |
| const setDrawingIconSpy = jest.spyOn(imageEditorMock, 'setDrawingIcon'); | |
| iconAction.addIcon('iconTypeA', '#fff'); | |
| expect(startDrawingModeSpy).toHaveBeenCalledWith('ICON'); | |
| expect(setDrawingIconSpy).toHaveBeenCalledWith('iconTypeA', '#fff'); | |
| }); | |
| }); | |
| describe('filterAction', () => { | |
| let filterAction; | |
| beforeEach(() => { | |
| filterAction = actions.filter; | |
| }); | |
| it('should be executed When the type of applyFilter is false', () => { | |
| imageEditorMock.removeFilter = jest.fn(); | |
| jest.spyOn(imageEditorMock, 'hasFilter').mockReturnValue(true); | |
| filterAction.applyFilter(false, {}); | |
| expect(imageEditorMock.removeFilter).toHaveBeenCalled(); | |
| }); | |
| it('should be executed When the type of applyFilter is true', () => { | |
| imageEditorMock.applyFilter = jest.fn(); | |
| filterAction.applyFilter(true, {}); | |
| expect(imageEditorMock.applyFilter).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('commonAction', () => { | |
| it('should return to the getActions method must contain commonAction.', () => { | |
| ['shape', 'crop', 'flip', 'rotate', 'text', 'mask', 'draw', 'icon', 'filter'].forEach( | |
| (submenu) => { | |
| expect(actions[submenu].modeChange).toBeDefined(); | |
| expect(actions[submenu].deactivateAll).toBeDefined(); | |
| expect(actions[submenu].changeSelectableAll).toBeDefined(); | |
| expect(actions[submenu].discardSelection).toBeDefined(); | |
| expect(actions[submenu].stopDrawingMode).toBeDefined(); | |
| } | |
| ); | |
| }); | |
| describe('modeChange()', () => { | |
| let commonAction; | |
| beforeEach(() => { | |
| commonAction = actions.main; | |
| }); | |
| it('should be executed When the modeChange("text") action occurs', () => { | |
| const changeActivateModeSpy = jest.spyOn(imageEditorMock, '_changeActivateMode'); | |
| commonAction.modeChange('text'); | |
| expect(changeActivateModeSpy).toHaveBeenCalledWith('TEXT'); | |
| }); | |
| it('should be executed When the modeChange("crop") action occurs', () => { | |
| const startDrawingModeSpy = jest.spyOn(imageEditorMock, 'startDrawingMode'); | |
| commonAction.modeChange('crop'); | |
| expect(startDrawingModeSpy).toHaveBeenCalledWith('CROPPER'); | |
| }); | |
| it('should be executed When the modeChange("shape") action occurs', () => { | |
| const setDrawingShapeSpy = jest.spyOn(imageEditorMock, 'setDrawingShape'); | |
| const changeActivateModeSpy = jest.spyOn(imageEditorMock, '_changeActivateMode'); | |
| commonAction.modeChange('shape'); | |
| expect(setDrawingShapeSpy).toHaveBeenCalled(); | |
| expect(changeActivateModeSpy).toHaveBeenCalledWith('SHAPE'); | |
| }); | |
| }); | |
| }); | |
| describe('reAction', () => { | |
| let changeHelpButtonEnabledSpy; | |
| beforeEach(() => { | |
| imageEditorMock.setReAction(); | |
| changeHelpButtonEnabledSpy = jest.spyOn(imageEditorMock.ui, 'changeHelpButtonEnabled'); | |
| }); | |
| describe('undoStackChanged', () => { | |
| it('should be true if the undo stack has a length greater than zero', () => { | |
| imageEditorMock.fire('undoStackChanged', 1); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(1, 'undo', true); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(2, 'reset', true); | |
| }); | |
| it('should be false if the undo stack has a length of 0', () => { | |
| imageEditorMock.fire('undoStackChanged', 0); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(1, 'undo', false); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(2, 'reset', false); | |
| }); | |
| }); | |
| describe('redoStackChanged', () => { | |
| it('should be true if the redo stack is greater than 0 length', () => { | |
| imageEditorMock.fire('redoStackChanged', 1); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(1, 'redo', true); | |
| }); | |
| it('should be false if the redo stack has a length of 0', () => { | |
| imageEditorMock.fire('redoStackChanged', 0); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(1, 'redo', false); | |
| }); | |
| }); | |
| describe('objectActivated', () => { | |
| it('should be enabled when objectActivated occurs', () => { | |
| imageEditorMock.fire('objectActivated', { id: 1 }); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(1, 'delete', true); | |
| expect(changeHelpButtonEnabledSpy).toHaveBeenNthCalledWith(2, 'deleteAll', true); | |
| }); | |
| it('should be enabled when objectActivated target is cropzone', () => { | |
| const changeApplyButtonStatusSpy = jest.spyOn( | |
| imageEditorMock.ui.crop, | |
| 'changeApplyButtonStatus' | |
| ); | |
| imageEditorMock.fire('objectActivated', { id: 1, type: 'cropzone' }); | |
| expect(changeApplyButtonStatusSpy).toHaveBeenCalledWith(true); | |
| }); | |
| it('should be changed to shape if the target of objectActivated is shape and the existing menu is not shape', () => { | |
| imageEditorMock.ui.submenu = 'crop'; | |
| imageEditorMock.ui.changeMenu = jest.fn(); | |
| imageEditorMock.ui.shape.setShapeStatus = jest.fn(); | |
| const setMaxStrokeValueSpy = jest.spyOn(imageEditorMock.ui.shape, 'setMaxStrokeValue'); | |
| imageEditorMock.fire('objectActivated', { id: 1, type: 'circle' }); | |
| expect(imageEditorMock.ui.changeMenu).toHaveBeenCalledWith('shape', false, false); | |
| expect(setMaxStrokeValueSpy).toHaveBeenCalled(); | |
| }); | |
| it('should be changed to text if the target of objectActivated is text and the existing menu is not text', () => { | |
| imageEditorMock.ui.submenu = 'crop'; | |
| imageEditorMock.ui.changeMenu = jest.fn(); | |
| imageEditorMock.fire('objectActivated', { id: 1, type: 'i-text' }); | |
| expect(imageEditorMock.ui.changeMenu).toHaveBeenCalledWith('text', false, false); | |
| }); | |
| it('should be changed to icon if the target of objectActivated is icon and the existing menu is not icon', () => { | |
| imageEditorMock.ui.submenu = 'crop'; | |
| imageEditorMock.ui.changeMenu = jest.fn(); | |
| const setIconPickerColorSpy = jest.spyOn(imageEditorMock.ui.icon, 'setIconPickerColor'); | |
| imageEditorMock.fire('objectActivated', { id: 1, type: 'icon' }); | |
| expect(imageEditorMock.ui.changeMenu).toHaveBeenCalledWith('icon', false, false); | |
| expect(setIconPickerColorSpy).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('addObjectAfter', () => { | |
| it('should be changed to match the size of the added object when addObjectAfter occurs', () => { | |
| const setMaxStrokeValueSpy = jest.spyOn(imageEditorMock.ui.shape, 'setMaxStrokeValue'); | |
| imageEditorMock.ui.shape.changeStandbyMode = jest.fn(); | |
| imageEditorMock.fire('addObjectAfter', { type: 'circle', width: 100, height: 200 }); | |
| expect(setMaxStrokeValueSpy).toHaveBeenCalledWith(100); | |
| expect(imageEditorMock.ui.shape.changeStandbyMode).toHaveBeenCalled(); | |
| }); | |
| }); | |
| describe('objectScaled', () => { | |
| it('should be changed if objectScaled occurs on an object of type text', () => { | |
| imageEditorMock.ui.text.fontSize = 0; | |
| imageEditorMock.fire('objectScaled', { type: 'i-text', fontSize: 20 }); | |
| expect(imageEditorMock.ui.text.fontSize).toBe(20); | |
| }); | |
| it('should be changed if objectScaled is for a shape type object and strokeValue is greater than the size of the object', () => { | |
| jest.spyOn(imageEditorMock.ui.shape, 'getStrokeValue').mockReturnValue(20); | |
| const setStrokeValueSpy = jest.spyOn(imageEditorMock.ui.shape, 'setStrokeValue'); | |
| imageEditorMock.fire('objectScaled', { type: 'rect', width: 10, height: 10 }); | |
| expect(setStrokeValueSpy).toHaveBeenCalledWith(10); | |
| }); | |
| }); | |
| describe('selectionCleared', () => { | |
| it('should be closed if selectionCleared occurs in the text menu state', () => { | |
| imageEditorMock.ui.submenu = 'text'; | |
| const changeCursorSpy = jest.spyOn(imageEditorMock, 'changeCursor'); | |
| imageEditorMock.fire('selectionCleared'); | |
| expect(changeCursorSpy).toHaveBeenCalledWith('text'); | |
| }); | |
| }); | |
| }); | |
| }); | |