import 'reflect-metadata'; import { requiredMocks, } from './../../../test-mocks'; requiredMocks(jest); import { empty, of, } from 'rxjs'; import { ChangeDetectorRef, } from '@angular/core'; import { ImageEditorDisplayComponent, } from './image-editor-display.component'; import { CanvasUtilitiesService, CoordinateUtilitiesService, ImagePreloaderService, WindowResizeEventsService, } from './../../helpers/services/index'; import { CanvasImageOnMaskComponent, } from './../../molecules/canvas-image-on-mask/canvas-image-on-mask.component'; import { CoordsInterface, DimensionsInterface, MaskImageMapInterface, } from '../../models'; const initImageEditorDisplayComponent = ( canvasUtilitiesService?: CanvasUtilitiesService, imagePreloaderService?: ImagePreloaderService, changeDetectorRef?: ChangeDetectorRef, coordinateUtilitiesService?: CoordinateUtilitiesService, windowResizeEventsService?: WindowResizeEventsService, ) => { return new ImageEditorDisplayComponent( canvasUtilitiesService, imagePreloaderService, changeDetectorRef, coordinateUtilitiesService, windowResizeEventsService, ); }; describe('constructor', () => { test('Sets showGridLines to the default value', () => { expect(initImageEditorDisplayComponent().showGridLines).toBe(false); }); test('Sets gridLinesColor to the default value', () => { expect(initImageEditorDisplayComponent().gridLinesColor) .toBe('#CC0000'); }); test('Sets gridLinesOpacity to the default value', () => { expect(initImageEditorDisplayComponent().gridLinesOpacity) .toBe(0.3); }); test('Sets gridLineStrokeWidth to the default value', () => { expect(initImageEditorDisplayComponent().gridLineStrokeWidth) .toBe(2); }); test('Sets distanceToShowSnapGrid to the default value', () => { expect(initImageEditorDisplayComponent().distanceToSnapToGrid) .toBe(0); }); test('Sets showRotationControl to the default value', () => { expect(initImageEditorDisplayComponent().showRotationControl) .toBe(false); }); test('Sets showRotationMeasurement to the default value', () => { expect(initImageEditorDisplayComponent().showRotationMeasurement) .toBe(false); }); test('Sets distanceToSnapToRotation to the default value', () => { expect(initImageEditorDisplayComponent().distanceToSnapToRotation) .toBe(0); }); test('Sets showScaleControl to the default value', () => { expect(initImageEditorDisplayComponent().showScaleControl) .toBe(false); }); test('Sets showDeleteButton to the default value', () => { expect(initImageEditorDisplayComponent().showDeleteButton) .toBe(false); }); }); describe('bleedAreas', () => { test('Returns all the bleed areas for the masksImagesMaps', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: { border: 0, }, mask: { bleed_area: {}, }, }, { imageEditorImage: { border: 0, }, mask: { bleed_area: {}, }, }] as MaskImageMapInterface[]; const result = imageEditorDisplayComponent.printGuideArea; expect(result[0]).toBe( imageEditorDisplayComponent.maskImagesMap[0].mask.bleed_area, ); expect(result[1]).toBe( imageEditorDisplayComponent.maskImagesMap[1].mask.bleed_area, ); }); }); describe('maskScale', () => { test('Returns the first maskImagesMap scale', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.maskImagesMap = [{ mask: { bleed_area: { maskScale: 10, }, }, }] as MaskImageMapInterface[]; const result = imageEditorDisplayComponent.maskScale; expect(result).toBe(10); }); test('Returns 1 if the first maskImagesMap has no scale', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.maskImagesMap = [{ mask: { bleed_area: {}, }, }] as MaskImageMapInterface[]; const result = imageEditorDisplayComponent.maskScale; expect(result).toBe(1); }); }); describe('ngOnChanges', () => { test('Calls loadAllImages', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.loadAllImages = jest.fn(); imageEditorDisplayComponent.ngOnChanges(); expect(imageEditorDisplayComponent.loadAllImages).toHaveBeenCalled(); }); }); describe('ngAfterViewInit', () => { const runNgAfterViewInitTest = () => { const mockAddEventFunction = jest.fn(); const windowResizeEventsService = {} as WindowResizeEventsService; windowResizeEventsService.addEvent = mockAddEventFunction; const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, undefined, undefined, undefined, windowResizeEventsService, ); imageEditorDisplayComponent.recalculateImageEditorDisplayMainDimensions = jest.fn(); imageEditorDisplayComponent.ngAfterViewInit(); return { imageEditorDisplayComponent, mockAddEventFunction, windowResizeEventsService, }; }; // tslint:disable-next-line test('Calls recalculateImageEditorDisplayMainDimensions once when the function is called', () => { const { imageEditorDisplayComponent, } = runNgAfterViewInitTest(); expect( imageEditorDisplayComponent .recalculateImageEditorDisplayMainDimensions, ).toHaveBeenCalledTimes(1); }); // tslint:disable-next-line test('Adds an event to the window resize service', () => { const { windowResizeEventsService, } = runNgAfterViewInitTest(); expect(windowResizeEventsService.addEvent).toHaveBeenCalled(); }); // tslint:disable-next-line test('Calls recalculateImageEditorDisplayMainDimensions a second time when the window resizes', () => { const { imageEditorDisplayComponent, mockAddEventFunction, } = runNgAfterViewInitTest(); mockAddEventFunction.mock.calls[0][0](); expect( imageEditorDisplayComponent .recalculateImageEditorDisplayMainDimensions, ).toHaveBeenCalledTimes(2); }); }); describe('recalculateImageEditorDisplayMainDimensions', () => { const runRecalculateImageEditorDisplayMainDimensions = () => { const boundingRect = { height: 10, left: 0, top: 5, width: 15, } as ClientRect; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageEditorDisplayMain = { nativeElement: { getBoundingClientRect: jest.fn() .mockReturnValueOnce(boundingRect), }, }; imageEditorDisplayComponent .recalculateImageEditorDisplayMainDimensions(); return { imageEditorDisplayComponent, }; }; // tslint:disable-next-line test('Calls getBoundingClientRect on the the imageEditorDisplayMain element', () => { const { imageEditorDisplayComponent, } = runRecalculateImageEditorDisplayMainDimensions(); expect( imageEditorDisplayComponent.imageEditorDisplayMain .nativeElement.getBoundingClientRect, ).toHaveBeenCalled(); }); // tslint:disable-next-line test('Sets the imageEditorDisplayMainDimensions to the width and height of the imageEditorDisplayMain element', () => { const { imageEditorDisplayComponent, } = runRecalculateImageEditorDisplayMainDimensions(); expect(imageEditorDisplayComponent.imageEditorDisplayMainDimensions) .toEqual({ height: 10, width: 15, }); }); // tslint:disable-next-line test('Sets the imageEditorDisplayMainTopLeftCoords to the top and left of the imageEditorDisplayMain element', () => { const { imageEditorDisplayComponent, } = runRecalculateImageEditorDisplayMainDimensions(); expect(imageEditorDisplayComponent.imageEditorDisplayMainTopLeftCoords) .toEqual({ x: 0, y: 5, }); }); }); describe('loadAllImages', () => { const initLoadAllImages = () => { const changeDetectorRef = {} as ChangeDetectorRef; changeDetectorRef.markForCheck = jest.fn(); const imagePreloaderService = {} as ImagePreloaderService; imagePreloaderService.load = jest.fn() .mockReturnValue(empty()); const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, imagePreloaderService, changeDetectorRef, ); imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: { urlToRender: 'urlToRender1', }, mask: { mask: 'mask1', }, }, { imageEditorImage: { urlToRender: 'urlToRender2', }, mask: { mask: 'mask2', }, }] as MaskImageMapInterface[]; imageEditorDisplayComponent.backgroundUrl = 'backgroundUrl'; imageEditorDisplayComponent.foregroundUrl = 'overlayImage'; return { changeDetectorRef, imageEditorDisplayComponent, imagePreloaderService, }; }; test('Sets isLoading to true', () => { const { imageEditorDisplayComponent, } = initLoadAllImages(); imageEditorDisplayComponent.isLoading = null; imageEditorDisplayComponent.loadAllImages(); expect(imageEditorDisplayComponent.isLoading).toBe(true); }); test('Calls imagePreloaderService.load with the expected images', () => { const { imagePreloaderService, imageEditorDisplayComponent, } = initLoadAllImages(); imageEditorDisplayComponent.loadAllImages(); expect(imagePreloaderService.load).toHaveBeenCalledWith([ 'urlToRender1', 'urlToRender2', 'mask1', 'mask2', 'backgroundUrl', 'overlayImage', ]); }); test('Sets the response of imagePreloaderService to loadedImages', () => { const { imagePreloaderService, imageEditorDisplayComponent, } = initLoadAllImages(); const mockLoadedImages = [{}] as HTMLImageElement[]; imagePreloaderService.load = jest.fn().mockReturnValue( of(mockLoadedImages), ); imageEditorDisplayComponent.loadAllImages(); expect(imageEditorDisplayComponent.loadedImages).toBe(mockLoadedImages); }); // tslint:disable-next-line test('After imagePreloaderService.load completes set isLoading to false', () => { const { imagePreloaderService, imageEditorDisplayComponent, } = initLoadAllImages(); imagePreloaderService.load = jest.fn().mockReturnValue( of([]), ); imageEditorDisplayComponent.isLoading = true; imageEditorDisplayComponent.loadAllImages(); expect(imageEditorDisplayComponent.isLoading).toBe(false); }); // tslint:disable-next-line test('After imagePreloaderService.load completes calls changeDetectorRef.markForCheck', () => { const { changeDetectorRef, imagePreloaderService, imageEditorDisplayComponent, } = initLoadAllImages(); imagePreloaderService.load = jest.fn().mockReturnValue( of([]), ); imageEditorDisplayComponent.loadAllImages(); expect(changeDetectorRef.markForCheck).toHaveBeenCalled(); }); // tslint:disable-next-line test('Does not call imagePreloaderService.load if the new loaded images are all contained in the previousImageUrls', () => { const { changeDetectorRef, imagePreloaderService, imageEditorDisplayComponent, } = initLoadAllImages(); imageEditorDisplayComponent.previousImageUrls = [ 'urlToRender1', 'urlToRender2', 'mask1', 'mask2', undefined, 'overlayImage', 'backgroundUrl', ]; imageEditorDisplayComponent.loadAllImages(); expect(imagePreloaderService.load).not.toHaveBeenCalled(); }); // tslint:disable-next-line test('Does not error if some of the maskImages have no imageEditorImage', () => { const { imageEditorDisplayComponent, } = initLoadAllImages(); imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: { urlToRender: 'url', }, mask: { mask: 'mask', }, }, { mask: { mask: 'otherMask', }, }] as MaskImageMapInterface[]; expect(() => imageEditorDisplayComponent.loadAllImages()) .not.toThrow(); }); }); describe('onMouseMove', () => { test('Does not throw if imageBeingDragged is null', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingDragged = null; expect( imageEditorDisplayComponent.onMouseMove .bind(imageEditorDisplayComponent), ).not.toThrow(); }); const initOnMouseMoveData = () => { const canvasUtilitiesService = {} as CanvasUtilitiesService; const getImageWithUrlResponse = {} as HTMLImageElement; canvasUtilitiesService.getImageWithUrl = jest.fn().mockReturnValueOnce( getImageWithUrlResponse, ); canvasUtilitiesService.toPrintImageCoordinateSystem = jest.fn() .mockReturnValueOnce(10) .mockReturnValueOnce(15); const imageEditorDisplayComponent = initImageEditorDisplayComponent( canvasUtilitiesService, ); imageEditorDisplayComponent.distanceToSnapToGrid = 10; imageEditorDisplayComponent.updateTranslations.emit = jest.fn(); imageEditorDisplayComponent.loadedImages = [{}] as HTMLImageElement[]; imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: { url_full: 'notMatching', }, }, { imageEditorImage: { tx: 5, ty: 10, url_full: 'doesMatchUrl', }, mask: { mask: 'matchingMask', }, }] as MaskImageMapInterface[]; imageEditorDisplayComponent.imageBeingDragged = { imageEditorImage: { url_full: 'doesMatchUrl', }, } as MaskImageMapInterface; imageEditorDisplayComponent.canvasImageOnMaskComponent = { canvas: {}, } as CanvasImageOnMaskComponent; imageEditorDisplayComponent.lastClientX = 10; imageEditorDisplayComponent.lastClientY = 10; imageEditorDisplayComponent.assetSize = {} as DimensionsInterface; const dpi = 300; imageEditorDisplayComponent.dpi = dpi; return { canvasUtilitiesService, getImageWithUrlResponse, imageEditorDisplayComponent, dpi, }; }; test('Calls canvasUtilitiesService.getImageWithUrl to get the mask image from the loaded images', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initOnMouseMoveData(); imageEditorDisplayComponent.onMouseMove({ clientX: 10, clientY: 5, } as MouseEvent); expect(canvasUtilitiesService.getImageWithUrl).toHaveBeenCalledWith( imageEditorDisplayComponent.loadedImages, 'matchingMask', ); }); test('Calls canvasUtilitiesService.toPrintImageCoordinateSystem to convert the newest x drag coordinate', () => { const { canvasUtilitiesService, getImageWithUrlResponse, imageEditorDisplayComponent, dpi, } = initOnMouseMoveData(); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(canvasUtilitiesService.toPrintImageCoordinateSystem) .toHaveBeenCalledWith( imageEditorDisplayComponent.canvasImageOnMaskComponent.canvas, 90, imageEditorDisplayComponent.maskImagesMap[1], getImageWithUrlResponse, imageEditorDisplayComponent.assetSize, dpi, ); }); test('Calls canvasUtilitiesService.toPrintImageCoordinateSystem to convert the newest y drag coordinate', () => { const { canvasUtilitiesService, getImageWithUrlResponse, imageEditorDisplayComponent, dpi, } = initOnMouseMoveData(); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(canvasUtilitiesService.toPrintImageCoordinateSystem) .toHaveBeenCalledWith( imageEditorDisplayComponent.canvasImageOnMaskComponent.canvas, 40, imageEditorDisplayComponent.maskImagesMap[1], getImageWithUrlResponse, imageEditorDisplayComponent.assetSize, dpi, ); }); test('Emits the new translations', () => { const { canvasUtilitiesService, getImageWithUrlResponse, imageEditorDisplayComponent, } = initOnMouseMoveData(); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(imageEditorDisplayComponent.updateTranslations.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.maskImagesMap[1], { x: 15, y: 25, }, ]); }); test('Sets the lastClientX to the value from the event', () => { const { canvasUtilitiesService, getImageWithUrlResponse, imageEditorDisplayComponent, } = initOnMouseMoveData(); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(imageEditorDisplayComponent.lastClientX).toBe(100); }); test('Sets the lastClientY to the value from the event', () => { const { canvasUtilitiesService, getImageWithUrlResponse, imageEditorDisplayComponent, } = initOnMouseMoveData(); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(imageEditorDisplayComponent.lastClientY).toBe(50); }); // tslint:disable-next-line test('Does not throw an error if one of the maskImages has no imageEditorImage', () => { const { imageEditorDisplayComponent, } = initOnMouseMoveData(); imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: {}, mask: {}, }, { mask: {}, }] as MaskImageMapInterface[]; expect(() => imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent)).not.toThrow(); }); // tslint:disable-next-line test('Snaps the X coords to the grid if the new X coordinate is within the distanceToShowSnapGrid', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initOnMouseMoveData(); canvasUtilitiesService.toPrintImageCoordinateSystem = jest.fn() .mockReturnValueOnce(5) .mockReturnValueOnce(15); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(imageEditorDisplayComponent.updateTranslations.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.maskImagesMap[1], { x: 0, y: 25, }, ]); }); // tslint:disable-next-line test('Snaps the Y coords to the grid if the new Y coordinate is within the distanceToShowSnapGrid', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initOnMouseMoveData(); canvasUtilitiesService.toPrintImageCoordinateSystem = jest.fn() .mockReturnValueOnce(10) .mockReturnValueOnce(0); imageEditorDisplayComponent.onMouseMove({ clientX: 100, clientY: 50, } as MouseEvent); expect(imageEditorDisplayComponent.updateTranslations.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.maskImagesMap[1], { x: 15, y: 0, }, ]); }); }); describe('onMouseDown', () => { const initOnMouseDownData = () => { const eventTarget = {} as HTMLElement; eventTarget.getBoundingClientRect = jest.fn().mockReturnValue({ left: 5, top: 10, }); const event = { clientX: 100, clientY: 50, target: eventTarget as any, } as MouseEvent; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const imageBeingDraggedResponse = {} as MaskImageMapInterface; imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage = jest.fn().mockReturnValue(imageBeingDraggedResponse); return { event, eventTarget, imageBeingDraggedResponse, imageEditorDisplayComponent, }; }; test('Gets the bounding client rect for the event target', () => { const { event, eventTarget, imageEditorDisplayComponent, } = initOnMouseDownData(); imageEditorDisplayComponent.onMouseDown(event); expect(eventTarget.getBoundingClientRect).toHaveBeenCalled(); }); // tslint:disable-next-line test('Calls getImageBeingDragged with the relative coords of the click', () => { const { event, imageEditorDisplayComponent, } = initOnMouseDownData(); imageEditorDisplayComponent.onMouseDown(event); expect(imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage) .toHaveBeenCalledWith( 95, 40, ); }); // tslint:disable-next-line test('Sets imageBeingDragged to the result of getImageBeingDraggedOrFirstImage', () => { const { event, imageBeingDraggedResponse, imageEditorDisplayComponent, } = initOnMouseDownData(); imageEditorDisplayComponent.onMouseDown(event); expect(imageEditorDisplayComponent.imageBeingDragged) .toBe(imageBeingDraggedResponse); }); test('Sets lastClientX to the clientX of the event', () => { const { event, imageEditorDisplayComponent, } = initOnMouseDownData(); imageEditorDisplayComponent.onMouseDown(event); expect(imageEditorDisplayComponent.lastClientX).toBe(100); }); test('Sets lastClientY to the clientY of the event', () => { const { event, imageEditorDisplayComponent, } = initOnMouseDownData(); imageEditorDisplayComponent.onMouseDown(event); expect(imageEditorDisplayComponent.lastClientY).toBe(50); }); }); describe('onMouseUp', () => { test('Sets imageBeingDragged to null', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingDragged = {} as MaskImageMapInterface; imageEditorDisplayComponent.onMouseUp(); expect(imageEditorDisplayComponent.imageBeingDragged).toBeNull(); }); }); describe('touchStart', () => { test('Calls onMouseDown with the first touch', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.onMouseDown = jest.fn(); const touch = {} as Touch; const touchEvent = { touches: {}, } as TouchEvent; touchEvent.touches.item = jest.fn().mockReturnValueOnce(touch); imageEditorDisplayComponent.touchStart(touchEvent); expect(imageEditorDisplayComponent.onMouseDown).toHaveBeenCalledWith( touch, ); }); }); describe('touchMove', () => { test('Calls onMouseMove with the first touch', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.onMouseMove = jest.fn(); const touch = {} as Touch; const touchEvent = { touches: {}, } as TouchEvent; touchEvent.touches.item = jest.fn().mockReturnValueOnce(touch); imageEditorDisplayComponent.touchMove(touchEvent); expect(imageEditorDisplayComponent.onMouseMove).toHaveBeenCalledWith( touch, ); }); }); describe('getImageBeingDraggedOrFirstImage', () => { // tslint:disable-next-line test('Returns the result of getImageBeingDragged if it returns a value', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const imageBeingDragged = {} as MaskImageMapInterface; imageEditorDisplayComponent.getImageBeingDragged = jest.fn() .mockReturnValue(imageBeingDragged); const result = imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage( 0, 10, ); expect(result).toBe(imageBeingDragged); }); // tslint:disable-next-line test('If getImageBeingDragged does not return a value return the first maskImageMap', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.getImageBeingDragged = jest.fn() .mockReturnValue(null); imageEditorDisplayComponent.maskImagesMap = [{}] as MaskImageMapInterface[]; const result = imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage( 0, 10, ); expect(result).toBe(imageEditorDisplayComponent.maskImagesMap[0]); }); // tslint:disable-next-line test('Calls getImageBeingDragged with the coordinates', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.getImageBeingDragged = jest.fn(); imageEditorDisplayComponent.maskImagesMap = [] as MaskImageMapInterface[]; imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage( 0, 10, ); expect(imageEditorDisplayComponent.getImageBeingDragged) .toHaveBeenCalledWith(0, 10); }); }); describe('getImageBeingDragged', () => { const initGetImageBeingDraggedData = () => { const canvasUtilitiesService = {} as CanvasUtilitiesService; canvasUtilitiesService.getScaledEnclosingQuad = jest.fn() .mockReturnValueOnce({ bottomRight: { x: 10, y: 10}, topLeft: { x: 0, y: 0}, }).mockReturnValueOnce({ bottomRight: { x: 6, y: 6}, topLeft: { x: 4, y: 4}, }); const mockImageWithUrl = {} as HTMLImageElement; canvasUtilitiesService.getImageWithUrl = jest.fn().mockReturnValue( mockImageWithUrl, ); const imageEditorDisplayComponent = initImageEditorDisplayComponent( canvasUtilitiesService, ); imageEditorDisplayComponent.maskImagesMap = [{ mask: { mask: 'mask1', }, }, { mask: { mask: 'mask2', }, }] as MaskImageMapInterface[]; imageEditorDisplayComponent.canvasImageOnMaskComponent = { canvas: {}, } as CanvasImageOnMaskComponent; imageEditorDisplayComponent.loadedImages = [{}, {}] as HTMLImageElement[]; const dpi = 300; imageEditorDisplayComponent.dpi = dpi; imageEditorDisplayComponent.assetSize = {} as DimensionsInterface; return { canvasUtilitiesService, imageEditorDisplayComponent, mockImageWithUrl, dpi, }; }; // tslint:disable-next-line test('Calls canvasUtilitiesService.getImageWithUrl for each mask', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initGetImageBeingDraggedData(); imageEditorDisplayComponent.getImageBeingDragged(5, 10); expect(canvasUtilitiesService.getImageWithUrl) .toHaveBeenCalledWith( imageEditorDisplayComponent.loadedImages, 'mask1', ); expect(canvasUtilitiesService.getImageWithUrl) .toHaveBeenCalledWith( imageEditorDisplayComponent.loadedImages, 'mask2', ); }); test('Calls canvasUtilitiesService.getScaledEnclosingQuad for each maskImageMap', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, mockImageWithUrl, dpi, } = initGetImageBeingDraggedData(); imageEditorDisplayComponent.getImageBeingDragged(5, 10); expect(canvasUtilitiesService.getScaledEnclosingQuad) .toHaveBeenCalledWith( imageEditorDisplayComponent.canvasImageOnMaskComponent.canvas, mockImageWithUrl, imageEditorDisplayComponent.maskImagesMap[0], {} as DimensionsInterface, dpi, ); expect(canvasUtilitiesService.getScaledEnclosingQuad) .toHaveBeenCalledWith( imageEditorDisplayComponent.canvasImageOnMaskComponent.canvas, mockImageWithUrl, imageEditorDisplayComponent.maskImagesMap[1], {} as DimensionsInterface, dpi, ); }); // tslint:disable-next-line test('Returns null if the coords is outside all the mask image quads', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initGetImageBeingDraggedData(); const result = imageEditorDisplayComponent.getImageBeingDragged(-1, -1); expect(result).toBeNull(); }); // tslint:disable-next-line test('Returns the last mask image mask if there are multiple mask images which have a quad containing the coords', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initGetImageBeingDraggedData(); const result = imageEditorDisplayComponent.getImageBeingDragged(5, 5); expect(result).toBe(imageEditorDisplayComponent.maskImagesMap[1]); }); // tslint:disable-next-line test('Returns the matching mask image mask if there is a single one which has a quad that the coords are within', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, } = initGetImageBeingDraggedData(); const result = imageEditorDisplayComponent.getImageBeingDragged(2, 2); expect(result).toBe(imageEditorDisplayComponent.maskImagesMap[0]); }); }); describe('pinchImageStart', () => { const initPinchImageStartData = () => { const targetBoundingClientRect = { left: 50, top: 100, }; const target = {} as HTMLElement; target.getBoundingClientRect = jest.fn().mockReturnValue( targetBoundingClientRect, ); const touchInput = { center: { x: 10, y: 15, }, scale: 2, target, } as TouchInput; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const mockFirstImage = {} as MaskImageMapInterface; imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage = jest.fn().mockReturnValue(mockFirstImage); return { imageEditorDisplayComponent, mockFirstImage, target, targetBoundingClientRect, touchInput, }; }; test('Calls getBoundingClientRect with the target', () => { const { imageEditorDisplayComponent, target, touchInput, } = initPinchImageStartData(); imageEditorDisplayComponent.pinchImageStart(touchInput); expect(target.getBoundingClientRect).toHaveBeenCalled(); }); // tslint:disable-next-line test('Calls getImageBeingDraggedOrFirstImage with the correct coordinates', () => { const { imageEditorDisplayComponent, targetBoundingClientRect, touchInput, } = initPinchImageStartData(); imageEditorDisplayComponent.pinchImageStart(touchInput); expect(imageEditorDisplayComponent.getImageBeingDraggedOrFirstImage) .toHaveBeenCalledWith( touchInput.center.x - targetBoundingClientRect.left, touchInput.center.y - targetBoundingClientRect.top, ); }); test('Sets.imageBeingPinched to the first ', () => { const { imageEditorDisplayComponent, mockFirstImage, touchInput, } = initPinchImageStartData(); imageEditorDisplayComponent.pinchImageStart(touchInput); expect(imageEditorDisplayComponent.imageBeingPinched) .toBe(mockFirstImage); }); // tslint:disable-next-line test('Sets lastRotation to the value from the rotation of the touch input', () => { const { imageEditorDisplayComponent, touchInput, } = initPinchImageStartData(); imageEditorDisplayComponent.pinchImageStart(touchInput); expect(imageEditorDisplayComponent.lastRotation) .toBe(touchInput.rotation); }); }); describe('pinchImageMove', () => { const initPinchImageMoveData = () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingPinched = { imageEditorImage: { rotate_degrees: 5, scale: 2, }, } as MaskImageMapInterface; imageEditorDisplayComponent.onPinchScaleImage.emit = jest.fn(); imageEditorDisplayComponent.onPinchRotateImage.emit = jest.fn(); imageEditorDisplayComponent.lastRotation = 2; const touchInput = { rotation: 9.5, scale: 5, } as TouchInput; return { imageEditorDisplayComponent, touchInput, }; }; // tslint:disable-next-line test('Emits the imageBeingPinched and the new scale to onPinchScaleImage', () => { const { imageEditorDisplayComponent, touchInput, } = initPinchImageMoveData(); imageEditorDisplayComponent.pinchImageMove(touchInput); expect(imageEditorDisplayComponent.onPinchScaleImage.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.imageBeingPinched, 6, ]); }); // tslint:disable-next-line test('Emits an event to onPinchRotateImage with the image being rotated and the new rotation', () => { const { imageEditorDisplayComponent, touchInput, } = initPinchImageMoveData(); imageEditorDisplayComponent.pinchImageMove(touchInput); expect(imageEditorDisplayComponent.onPinchRotateImage.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.imageBeingPinched, -3, ]); }); // tslint:disable-next-line test('Does not call onPinchScaleImage.emit if imageBeingPinched is null', () => { const { imageEditorDisplayComponent, touchInput, } = initPinchImageMoveData(); imageEditorDisplayComponent.imageBeingPinched = null; imageEditorDisplayComponent.pinchImageMove(touchInput); expect(imageEditorDisplayComponent.onPinchScaleImage.emit) .not.toHaveBeenCalled(); }); // tslint:disable-next-line test('Does not call onPinchRotateImage.emit if imageBeingPinched is null', () => { const { imageEditorDisplayComponent, touchInput, } = initPinchImageMoveData(); imageEditorDisplayComponent.imageBeingPinched = null; imageEditorDisplayComponent.pinchImageMove(touchInput); expect(imageEditorDisplayComponent.onPinchRotateImage.emit) .not.toHaveBeenCalled(); }); }); describe('areGridLinesVisible', () => { const initAreGridLinesVisibleData = ({ imageBeingDragged, showGridLines, }: { imageBeingDragged: MaskImageMapInterface, showGridLines: boolean, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.showGridLines = showGridLines; imageEditorDisplayComponent.imageBeingDragged = imageBeingDragged; return imageEditorDisplayComponent.areGridLinesVisible(); }; // tslint:disable-next-line test('Returns true if showGridLines is true and imageIsBeingDragged has a value', () => { const result = initAreGridLinesVisibleData({ imageBeingDragged: {} as MaskImageMapInterface, showGridLines: true, }); expect(result).toBe(true); }); // tslint:disable-next-line test('Returns false if showGridLines is true but imageIsBeingDragged has no value', () => { const result = initAreGridLinesVisibleData({ imageBeingDragged: null, showGridLines: true, }); expect(result).toBe(false); }); // tslint:disable-next-line test('Returns false if showGridLines is false', () => { const result = initAreGridLinesVisibleData({ imageBeingDragged: {} as MaskImageMapInterface, showGridLines: false, }); expect(result).toBe(false); }); }); describe('getGridLines', () => { const initGetGridLinesData = () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: { tx: 0, ty: 0, }, mask: { bleed_area: { points: [ [ { x: 0, y: 0, }, { x: 10, y: 10, }, ], [ { x: 15, y: 15, }, { x: 30, y: 30, }, ], ], }, }, }] as MaskImageMapInterface[]; imageEditorDisplayComponent.assetSize = { height: 100, width: 100, }; imageEditorDisplayComponent.distanceToSnapToGrid = 10; return { imageEditorDisplayComponent, }; }; test('Gets the expected grid lines from the points', () => { const { imageEditorDisplayComponent, } = initGetGridLinesData(); const result = imageEditorDisplayComponent.getGridLines(); expect(result).toEqual([{ points: [ [ { x: 0, y: 15, }, { x: 100, y: 15, }, ], [ { x: 15, y: 0, }, { x: 15, y: 100, }, ], ], }]); }); // tslint:disable-next-line test('Does not show the Y axis grid lines if the image center is further away than the distanceToSnapToGrid', () => { const { imageEditorDisplayComponent, } = initGetGridLinesData(); imageEditorDisplayComponent.maskImagesMap[0].imageEditorImage.tx = 11; const result = imageEditorDisplayComponent.getGridLines(); expect(result).toEqual([{ points: [ [ { x: 0, y: 15, }, { x: 100, y: 15, }, ], ], }]); }); // tslint:disable-next-line test('Does not show the X axis grid lines if the image center is further away than the distanceToShowSnapGrid', () => { const { imageEditorDisplayComponent, } = initGetGridLinesData(); imageEditorDisplayComponent.maskImagesMap[0].imageEditorImage.ty = 11; const result = imageEditorDisplayComponent.getGridLines(); expect(result).toEqual([{ points: [ [ { x: 15, y: 0, }, { x: 15, y: 100, }, ], ], }]); }); }); describe('getImageQuadCoords', () => { const initGetImageQuadCoordsData = () => { const mockMaskImage = { width: 10, } as HTMLImageElement; const mockUserImage = { width: 50, } as HTMLImageElement; const canvasUtilitiesService = {} as CanvasUtilitiesService; canvasUtilitiesService.getImageWithUrl = jest.fn() .mockReturnValueOnce(mockMaskImage) .mockReturnValueOnce(mockUserImage); const mockGetImageQuad = [{}, {}]; canvasUtilitiesService.getImageQuadCoords = jest.fn() .mockReturnValueOnce(mockGetImageQuad); const imageEditorDisplayComponent = initImageEditorDisplayComponent( canvasUtilitiesService, ); imageEditorDisplayComponent.imageEditorDisplayMainDimensions = { height: 100, width: 200, }; const maskImageMap = { imageEditorImage: { scale: 2, tx: 12, ty: 11, urlToRender: 'http://someuserurl', }, mask: { mask: 'http://mask.com', }, } as MaskImageMapInterface; imageEditorDisplayComponent.assetSize = { height: 500, width: 500, }; imageEditorDisplayComponent.loadedImages = []; const dpi = 300; imageEditorDisplayComponent.dpi = dpi; return { canvasUtilitiesService, imageEditorDisplayComponent, maskImageMap, mockGetImageQuad, mockMaskImage, mockUserImage, dpi, }; }; test('Gets the mask image from the loaded images', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, maskImageMap, } = initGetImageQuadCoordsData(); imageEditorDisplayComponent.getImageQuadCoords(maskImageMap); expect(canvasUtilitiesService.getImageWithUrl).toHaveBeenCalledWith( imageEditorDisplayComponent.loadedImages, maskImageMap.mask.mask, ); }); test('Gets the user image from the loaded images', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, maskImageMap, } = initGetImageQuadCoordsData(); imageEditorDisplayComponent.getImageQuadCoords(maskImageMap); expect(canvasUtilitiesService.getImageWithUrl).toHaveBeenCalledWith( imageEditorDisplayComponent.loadedImages, maskImageMap.imageEditorImage.urlToRender, ); }); test('Gets the image quad from the canvas utilities service', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, maskImageMap, mockMaskImage, mockUserImage, dpi, } = initGetImageQuadCoordsData(); imageEditorDisplayComponent.getImageQuadCoords(maskImageMap); expect(canvasUtilitiesService.getImageQuadCoords).toHaveBeenCalledWith( imageEditorDisplayComponent.imageEditorDisplayMainDimensions, mockMaskImage, mockUserImage, imageEditorDisplayComponent.assetSize, maskImageMap, dpi, ); }); test('Calls getImageQuadCoords with a height and width of 1 if there is no matching user image', () => { const { canvasUtilitiesService, imageEditorDisplayComponent, maskImageMap, dpi, } = initGetImageQuadCoordsData(); canvasUtilitiesService.getImageWithUrl = jest.fn().mockReturnValue(null); imageEditorDisplayComponent.getImageQuadCoords(maskImageMap); expect(canvasUtilitiesService.getImageQuadCoords).toHaveBeenCalledWith( imageEditorDisplayComponent.imageEditorDisplayMainDimensions, null, { height: 1, width: 1}, imageEditorDisplayComponent.assetSize, maskImageMap, dpi, ); }); test('Returns the resulting image quad', () => { const { imageEditorDisplayComponent, maskImageMap, mockGetImageQuad, } = initGetImageQuadCoordsData(); const result = imageEditorDisplayComponent.getImageQuadCoords(maskImageMap); expect(result).toBe(mockGetImageQuad); }); }); describe('getConstrainedImageQuadCoords', () => { const runGetConstrainedImageQuadCoordTest = () => { const mockConstrainedCoords = [{}] as CoordsInterface[]; const coordinateUtilitiesService = {} as CoordinateUtilitiesService; coordinateUtilitiesService.constrainCoordinates = jest.fn() .mockReturnValueOnce(mockConstrainedCoords); const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, undefined, undefined, coordinateUtilitiesService, ); const mockQuadCoords = [{}, {}] as CoordsInterface[]; imageEditorDisplayComponent.getImageQuadCoords = jest.fn() .mockReturnValueOnce(mockQuadCoords); imageEditorDisplayComponent.imageEditorDisplayMainDimensions = { height: 50, width: 10, }; const maskImageMap = {} as MaskImageMapInterface; const result = imageEditorDisplayComponent.getConstrainedImageQuadCoords( maskImageMap, ); return { coordinateUtilitiesService, imageEditorDisplayComponent, maskImageMap, mockConstrainedCoords, mockQuadCoords, result, }; }; test('Calls getImageQuadCoords with the maskImageMap', () => { const { imageEditorDisplayComponent, maskImageMap, } = runGetConstrainedImageQuadCoordTest(); expect(imageEditorDisplayComponent.getImageQuadCoords) .toHaveBeenCalledWith(maskImageMap); }); // tslint:disable-next-line test('Calls coordinateUtilitiesService.constrainCoordinates with the correct arguments', () => { const { coordinateUtilitiesService, imageEditorDisplayComponent, mockQuadCoords, } = runGetConstrainedImageQuadCoordTest(); expect(coordinateUtilitiesService.constrainCoordinates) .toHaveBeenCalledWith( mockQuadCoords, { x: 0, y: 0, }, { x: imageEditorDisplayComponent .imageEditorDisplayMainDimensions.width, y: imageEditorDisplayComponent .imageEditorDisplayMainDimensions.height, }, ); }); // tslint:disable-next-line test('Returns the result of coordinateUtilitiesService.constrainCoordinates', () => { const { mockConstrainedCoords, result, } = runGetConstrainedImageQuadCoordTest(); expect(result).toBe(mockConstrainedCoords); }); }); describe('getRotatedImageQuadCoords', () => { const initGetRotatedImageQuadCoords = () => { const mockRotatedQuad = [{}] as CoordsInterface[]; const coordinateUtilitiesService = {} as CoordinateUtilitiesService; coordinateUtilitiesService.rotateCoordsAroundCenterOfCoords = jest.fn() .mockReturnValueOnce(mockRotatedQuad); const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, undefined, undefined, coordinateUtilitiesService, ); const mockImageQuadCords = [{}, {}] as CoordsInterface[]; imageEditorDisplayComponent.getImageQuadCoords = jest.fn() .mockReturnValueOnce(mockImageQuadCords); const maskImageMap = { imageEditorImage: { rotate_degrees: 10, }, } as MaskImageMapInterface; return { coordinateUtilitiesService, imageEditorDisplayComponent, maskImageMap, mockImageQuadCords, mockRotatedQuad, }; }; test('Calls getImageQuadCoords with the maskImageMap', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetRotatedImageQuadCoords(); imageEditorDisplayComponent.getRotatedImageQuadCoords(maskImageMap); expect(imageEditorDisplayComponent.getImageQuadCoords) .toHaveBeenCalledWith(maskImageMap); }); // tslint:disable-next-line test('Calls coordinateUtilitiesService.rotateCoordsAroundCenterOfCoords with the image quad coords and the maskImageMap rotation', () => { const { coordinateUtilitiesService, imageEditorDisplayComponent, maskImageMap, mockImageQuadCords, } = initGetRotatedImageQuadCoords(); imageEditorDisplayComponent.getRotatedImageQuadCoords(maskImageMap); expect(coordinateUtilitiesService.rotateCoordsAroundCenterOfCoords) .toHaveBeenCalledWith( mockImageQuadCords, maskImageMap.imageEditorImage.rotate_degrees, ); }); // tslint:disable-next-line test('Returns the result of coordinateUtilitiesService.rotateCoordsAroundCenterOfCoords', () => { const { imageEditorDisplayComponent, maskImageMap, mockRotatedQuad, } = initGetRotatedImageQuadCoords(); const result = imageEditorDisplayComponent.getRotatedImageQuadCoords(maskImageMap); expect(result).toBe(mockRotatedQuad); }); }); describe('getConstrainedRotatedImageQuadCoords', () => { const runGetConstrainedRotatedImageQuadCoordsTest = () => { const mockConstrainedCoords = [{}] as CoordsInterface[]; const coordinateUtilitiesService = {} as CoordinateUtilitiesService; coordinateUtilitiesService.constrainCoordinates = jest.fn() .mockReturnValueOnce(mockConstrainedCoords); const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, undefined, undefined, coordinateUtilitiesService, ); const mockRotatedQuadCoords = [{}, {}] as CoordsInterface[]; imageEditorDisplayComponent.getRotatedImageQuadCoords = jest.fn() .mockReturnValueOnce(mockRotatedQuadCoords); imageEditorDisplayComponent.imageEditorDisplayMainDimensions = { height: 50, width: 10, }; const maskImageMap = {} as MaskImageMapInterface; const result = imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords( maskImageMap, ); return { coordinateUtilitiesService, imageEditorDisplayComponent, maskImageMap, mockConstrainedCoords, mockRotatedQuadCoords, result, }; }; test('Calls getRotatedImageQuadCoords with the maskImageMap', () => { const { imageEditorDisplayComponent, maskImageMap, } = runGetConstrainedRotatedImageQuadCoordsTest(); expect(imageEditorDisplayComponent.getRotatedImageQuadCoords) .toHaveBeenCalledWith(maskImageMap); }); // tslint:disable-next-line test('Calls coordinateUtilitiesService.constrainCoordinates with the correct arguments', () => { const { coordinateUtilitiesService, imageEditorDisplayComponent, mockRotatedQuadCoords, } = runGetConstrainedRotatedImageQuadCoordsTest(); expect(coordinateUtilitiesService.constrainCoordinates) .toHaveBeenCalledWith( mockRotatedQuadCoords, { x: 0, y: 0, }, { x: imageEditorDisplayComponent .imageEditorDisplayMainDimensions.width, y: imageEditorDisplayComponent .imageEditorDisplayMainDimensions.height, }, ); }); // tslint:disable-next-line test('Returns the result of coordinateUtilitiesService.constrainCoordinates', () => { const { mockConstrainedCoords, result, } = runGetConstrainedRotatedImageQuadCoordsTest(); expect(result).toBe(mockConstrainedCoords); }); }); describe('isImageBeingTransformed', () => { const testIsImageBeingTransformed = ({ expectedResult, imageBeingRotated, imageBeingScaled, imageBeingDragged, imageBeingPinched, }: { expectedResult: boolean, imageBeingRotated?: MaskImageMapInterface, imageBeingScaled?: MaskImageMapInterface, imageBeingDragged?: MaskImageMapInterface, imageBeingPinched?: MaskImageMapInterface, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingRotated = imageBeingRotated; imageEditorDisplayComponent.imageBeingScaled = imageBeingScaled; imageEditorDisplayComponent.imageBeingDragged = imageBeingDragged; imageEditorDisplayComponent.imageBeingPinched = imageBeingPinched; const result = imageEditorDisplayComponent.isImageBeingTransformed(); expect(result).toBe(expectedResult); }; test('Returns true if imageBeingRotated has a value', () => { testIsImageBeingTransformed({ expectedResult: true, imageBeingRotated: {} as MaskImageMapInterface, }); }); test('Returns true if imageBeingScaled has a value', () => { testIsImageBeingTransformed({ expectedResult: true, imageBeingScaled: {} as MaskImageMapInterface, }); }); test('Returns true if imageBeingDragged has a value', () => { testIsImageBeingTransformed({ expectedResult: true, imageBeingDragged: {} as MaskImageMapInterface, }); }); test('Returns true if imageBeingPinched has a value', () => { testIsImageBeingTransformed({ expectedResult: true, imageBeingPinched: {} as MaskImageMapInterface, }); }); // tslint:disable-next-line test('Returns false if none of the transforming image properties have values', () => { testIsImageBeingTransformed({ expectedResult: false, }); }); }); describe('isStartRotationControlVisible', () => { const runIsStartRotationControlVisibleTest = ({ expectedIsVisible, isImageBeingTransformed, showScaleControl, }: { expectedIsVisible: boolean, isImageBeingTransformed: boolean, showScaleControl: boolean, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.isImageBeingTransformed = jest.fn() .mockReturnValueOnce(isImageBeingTransformed); imageEditorDisplayComponent.showRotationControl = showScaleControl; expect(imageEditorDisplayComponent.isStartRotationControlVisible()) .toBe(expectedIsVisible); }; test('Returns false if there is an image being transformed', () => { runIsStartRotationControlVisibleTest({ expectedIsVisible: false, isImageBeingTransformed: true, showScaleControl: true, }); }); // tslint:disable-next-line test('Returns false if there is no image being transformed but showRotationControl is set to false', () => { runIsStartRotationControlVisibleTest({ expectedIsVisible: false, isImageBeingTransformed: false, showScaleControl: false, }); }); // tslint:disable-next-line test('Returns true if there is no image being transformed and showRotationControl is set to true', () => { runIsStartRotationControlVisibleTest({ expectedIsVisible: true, isImageBeingTransformed: false, showScaleControl: true, }); }); }); describe('mouseOverStartRotationControl', () => { const runMouseOverStartRotationControlData = () => { const mockBoundingClientRectResult = { left: 10, top: 10, } as ClientRect; const mockGetBoundingClientRecFunction = jest.fn() .mockReturnValueOnce(mockBoundingClientRectResult) as any; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageEditorDisplayMain = { nativeElement: { getBoundingClientRect: mockGetBoundingClientRecFunction, } as HTMLElement, }; const event = { clientX: 50, clientY: 100, } as MouseEvent; const maskImageMap = { imageEditorImage: { rotate_degrees: 10, }, } as MaskImageMapInterface; imageEditorDisplayComponent.mouseOverStartRotationControl( event, maskImageMap, ); return { event, imageEditorDisplayComponent, maskImageMap, mockBoundingClientRectResult, mockGetBoundingClientRecFunction, }; }; // tslint:disable-next-line test('Calls getBoundingClientRect on the imageEditorDisplayMain element', () => { const { mockGetBoundingClientRecFunction, } = runMouseOverStartRotationControlData(); expect(mockGetBoundingClientRecFunction).toHaveBeenCalled(); }); // tslint:disable-next-line test('Sets mouseCoordinatesForRotation to the coordinates of the cursor in the document', () => { const { imageEditorDisplayComponent, } = runMouseOverStartRotationControlData(); expect(imageEditorDisplayComponent.mouseCoordinatesForRotation.x) .toBe(40); expect(imageEditorDisplayComponent.mouseCoordinatesForRotation.y) .toBe(90); }); // tslint:disable-next-line test('Sets rotationOfRotationIcon to the negative version of the maskImageMap imageEditorImage rotation', () => { const { imageEditorDisplayComponent, maskImageMap, } = runMouseOverStartRotationControlData(); expect(imageEditorDisplayComponent.rotationOfRotationIcon) .toBe(-maskImageMap.imageEditorImage.rotate_degrees); }); }); describe('getMouseCoordsTranslations', () => { test('Returns the expected translations', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.mouseCoordinatesForRotation = { x: 10, y: 50, }; imageEditorDisplayComponent.rotationOfRotationIcon = 45; const result = imageEditorDisplayComponent.getMouseCoordsTranslations(); expect(result).toBe('translate(10px, 50px) rotate(45deg)'); }); }); describe('getStartRotationControlCoords', () => { const initGetStartRotationControlCoordsData = () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const mockImageQuadCoords = [{}, {}, { x: 50, y: 50, }, { x: 0, y: 50, }]; imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords = jest.fn().mockReturnValueOnce(mockImageQuadCoords); const maskImageMap = { imageEditorImage: { rotate_degrees: 50, }, } as MaskImageMapInterface; return { imageEditorDisplayComponent, maskImageMap, mockImageQuadCoords, }; }; test('Gets the constrained rotated coords for the maskImage', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetStartRotationControlCoordsData(); imageEditorDisplayComponent.getStartRotationControlCoords(maskImageMap); expect(imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords) .toHaveBeenCalledWith(maskImageMap); }); test('Returns the expected translations and rotations transforms', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetStartRotationControlCoordsData(); const result = imageEditorDisplayComponent .getStartRotationControlCoords(maskImageMap); expect(result).toBe('translate(25px, 35px) rotate(-50deg)'); }); }); describe('isRotatingControlVisible', () => { const runIsRotatingControlVisibleTest = ({ expectedIsVisible, imageBeingRotated, mouseCoordinatesForRotation, }: { expectedIsVisible: boolean, imageBeingRotated: MaskImageMapInterface, mouseCoordinatesForRotation: CoordsInterface, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingRotated = imageBeingRotated; imageEditorDisplayComponent.mouseCoordinatesForRotation = mouseCoordinatesForRotation; expect(imageEditorDisplayComponent.isRotatingControlVisible()) .toBe(expectedIsVisible); }; test('Returns false if mouseCoordinatesForRotation is null', () => { runIsRotatingControlVisibleTest({ expectedIsVisible: false, imageBeingRotated: {} as MaskImageMapInterface, mouseCoordinatesForRotation: null, }); }); // tslint:disable-next-line test('Returns false if mouseCoordinatesForRotation is defined but there is no image being rotated', () => { runIsRotatingControlVisibleTest({ expectedIsVisible: false, imageBeingRotated: null, mouseCoordinatesForRotation: {} as CoordsInterface, }); }); // tslint:disable-next-line test('Returns true if both mouseCoordinatesForRotation and imageBeingRotated are defined', () => { runIsRotatingControlVisibleTest({ expectedIsVisible: true, imageBeingRotated: {} as MaskImageMapInterface, mouseCoordinatesForRotation: {} as CoordsInterface, }); }); }); describe('getIsRotatingControlTransforms', () => { // tslint:disable-next-line test('Gets the x and y of the mouseCoordinatesForRotation and puts it in a transform string', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.mouseCoordinatesForRotation = { x: 50, y: 100, }; const result = imageEditorDisplayComponent.getIsRotatingControlTransforms(); expect(result).toBe('translate(50px, 100px)'); }); }); describe('getIsRotatingControlDegrees', () => { const getIsRotatingControlDegreesTest = ({ degrees, expectedValue, }: { degrees: number, expectedValue: string, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingRotated = { imageEditorImage: { urlToRender: 'url', }, } as MaskImageMapInterface; imageEditorDisplayComponent.maskImagesMap = [{ imageEditorImage: { rotate_degrees: degrees, urlToRender: 'url', }, }] as MaskImageMapInterface[]; const result = imageEditorDisplayComponent .getIsRotatingControlDegrees(); expect(result).toBe(expectedValue); }; [{ degrees: -90, expectedValue: '90', }, { degrees: -180, expectedValue: '180', }, { degrees: -270, expectedValue: '-90', }, { degrees: 90, expectedValue: '-90', }, { degrees: 0, expectedValue: '0', }, { degrees: -20.55, expectedValue: '21', }].forEach(({ degrees, expectedValue }) => { test(`Returns ${expectedValue} when the degrees are ${degrees}`, () => { getIsRotatingControlDegreesTest({ degrees, expectedValue, }); }); }); }); describe('beginRotation', () => { test('Sets imageBeingRotated to the provided maskImageMap', () => { const maskImageMap = {} as MaskImageMapInterface; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.beginRotation(maskImageMap); expect(imageEditorDisplayComponent.imageBeingRotated) .toBe(maskImageMap); }); }); describe('applyRotation', () => { const initApplyRotationData = () => { const event = { clientX: 20, clientY: 15, } as MouseEvent; const coordinateUtilitiesService = {} as CoordinateUtilitiesService; const mockAngleBetweenCoordinates = 45; coordinateUtilitiesService.getAngleBetweenCoordinates = jest.fn().mockReturnValueOnce(mockAngleBetweenCoordinates); const mockNearest90Degrees = 90; coordinateUtilitiesService.getNearestDegrees = jest.fn() .mockReturnValueOnce(mockNearest90Degrees); const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, undefined, undefined, coordinateUtilitiesService, ); imageEditorDisplayComponent.imageEditorDisplayMainTopLeftCoords = { x: 0, y: 10, }; const mockImageQuadCoords = [{ x: 0, y: 0, }, { x: 10, y: 50, }]; imageEditorDisplayComponent.getImageQuadCoords = jest.fn() .mockReturnValueOnce(mockImageQuadCoords); imageEditorDisplayComponent.onRotationControlRotate.emit = jest.fn(); imageEditorDisplayComponent.imageBeingRotated = {} as MaskImageMapInterface; return { coordinateUtilitiesService, event, imageEditorDisplayComponent, mockAngleBetweenCoordinates, mockNearest90Degrees, }; }; // tslint:disable-next-line test('Does not emit anything to onRotationControlRotate if there is no image being rotated', () => { const { event, imageEditorDisplayComponent, } = initApplyRotationData(); imageEditorDisplayComponent.imageBeingRotated = null; imageEditorDisplayComponent.applyRotation(event); expect(imageEditorDisplayComponent.onRotationControlRotate.emit) .not.toHaveBeenCalled(); }); test('Sets the mouseCoordinatesForRotation to the new coordinates', () => { const { event, imageEditorDisplayComponent, } = initApplyRotationData(); imageEditorDisplayComponent.applyRotation(event); expect(imageEditorDisplayComponent.mouseCoordinatesForRotation.x) .toBe(20); expect(imageEditorDisplayComponent.mouseCoordinatesForRotation.y) .toBe(5); }); test('Calls getImageQuadCoords with the imageBeingRotated', () => { const { event, imageEditorDisplayComponent, } = initApplyRotationData(); imageEditorDisplayComponent.applyRotation(event); expect(imageEditorDisplayComponent.getImageQuadCoords) .toHaveBeenCalledWith( imageEditorDisplayComponent.imageBeingRotated, ); }); // tslint:disable-next-line test('Calls coordinateUtilitiesService.getAngleBetweenCoordinates to get the angle between the mid and mouse target coordinates', () => { const { coordinateUtilitiesService, event, imageEditorDisplayComponent, } = initApplyRotationData(); imageEditorDisplayComponent.applyRotation(event); expect(coordinateUtilitiesService.getAngleBetweenCoordinates) .toHaveBeenCalledWith({ x: 20, y: 5, }, { x: 5, y: 25, }); }); // tslint:disable-next-line test('Calls coordinateUtilitiesService.getNearestDegrees with the result of getAngleBetweenCoordinates plus 90', () => { const { coordinateUtilitiesService, event, imageEditorDisplayComponent, mockAngleBetweenCoordinates, } = initApplyRotationData(); imageEditorDisplayComponent.applyRotation(event); expect(coordinateUtilitiesService.getNearestDegrees) .toHaveBeenCalledWith(mockAngleBetweenCoordinates + 90); }); test('Sets the rotationOfRotationIcon to the angle being emitted', () => { const { event, imageEditorDisplayComponent, mockAngleBetweenCoordinates, } = initApplyRotationData(); imageEditorDisplayComponent.applyRotation(event); expect(imageEditorDisplayComponent.rotationOfRotationIcon) .toBe(mockAngleBetweenCoordinates + 90); }); // tslint:disable-next-line test('If the result getAngleBetweenCoordinates minus the angleBetween is less than the distanceToSnapRotation emit the nearest 90', () => { const { event, imageEditorDisplayComponent, mockNearest90Degrees, } = initApplyRotationData(); imageEditorDisplayComponent.distanceToSnapToRotation = 50; imageEditorDisplayComponent.applyRotation(event); expect(imageEditorDisplayComponent.onRotationControlRotate.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.imageBeingRotated, -mockNearest90Degrees, ]); }); // tslint:disable-next-line test('If the result getAngleBetweenCoordinates minus the angleBetween is more than the distanceToSnapRotation emit the angleBetween', () => { const { event, imageEditorDisplayComponent, mockAngleBetweenCoordinates, } = initApplyRotationData(); imageEditorDisplayComponent.distanceToSnapToRotation = 0; imageEditorDisplayComponent.applyRotation(event); expect(imageEditorDisplayComponent.onRotationControlRotate.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.imageBeingRotated, -(mockAngleBetweenCoordinates + 90), ]); }); }); describe('endRotation', () => { test('Sets imageBeingRotated to null', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingRotated = {} as MaskImageMapInterface; imageEditorDisplayComponent.endRotation(); expect(imageEditorDisplayComponent.imageBeingRotated).toBeNull(); }); test('Sets mouseCoordinatesForRotation to null', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.mouseCoordinatesForRotation = {} as CoordsInterface; imageEditorDisplayComponent.endRotation(); expect(imageEditorDisplayComponent.mouseCoordinatesForRotation) .toBeNull(); }); }); describe('trackByUrl', () => { test('Returns undefined if there is no imageEditorImage on the maskImagesMap', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const result = imageEditorDisplayComponent.trackByUrl({ imageEditorImage: undefined, } as MaskImageMapInterface); expect(result).toBeUndefined(); }); test('Returns the urlToRender of the imageEditorImage on the maskImagesMap', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const result = imageEditorDisplayComponent.trackByUrl({ imageEditorImage: { urlToRender: 'http://url.com', }, } as MaskImageMapInterface); expect(result).toBe('http://url.com'); }); }); describe('isScaleControlVisible', () => { const runIsScaleControlVisibleTest = ({ expectedIsVisible, isImageBeingTransformed, showScaleControl, }: { expectedIsVisible: boolean, isImageBeingTransformed: boolean, showScaleControl: boolean, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.isImageBeingTransformed = jest.fn() .mockReturnValueOnce(isImageBeingTransformed); imageEditorDisplayComponent.showScaleControl = showScaleControl; expect(imageEditorDisplayComponent.isScaleControlVisible()) .toBe(expectedIsVisible); }; test('Returns false if there is an image being transformed', () => { runIsScaleControlVisibleTest({ expectedIsVisible: false, isImageBeingTransformed: true, showScaleControl: true, }); }); test('Returns false if there is no image being transformed but showScaleControl is set to false', () => { runIsScaleControlVisibleTest({ expectedIsVisible: false, isImageBeingTransformed: false, showScaleControl: false, }); }); test('Returns true if there is no image being transformed and showScaleControl is set to true', () => { runIsScaleControlVisibleTest({ expectedIsVisible: true, isImageBeingTransformed: false, showScaleControl: true, }); }); }); describe('getStartScaleControlCoords', () => { const initGetStartScaleControlCoords = () => { const mockRotatedImageQuad = [{ x: 0, y: 0, }, { x: 100, y: 100, }] as CoordsInterface[]; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords = jest.fn().mockReturnValueOnce(mockRotatedImageQuad); const maskImageMap = { imageEditorImage: { rotate_degrees: 10, }, } as MaskImageMapInterface; return { imageEditorDisplayComponent, maskImageMap, mockRotatedImageQuad, }; }; test('Calls getConstrainedRotatedImageQuadCoords with the maskImageMap', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetStartScaleControlCoords(); imageEditorDisplayComponent.getStartScaleControlCoords(maskImageMap, 1); expect(imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords) .toHaveBeenCalledWith(maskImageMap); }); test('Returns the expected translations for the supplied corner', () => { const { imageEditorDisplayComponent, maskImageMap, mockRotatedImageQuad, } = initGetStartScaleControlCoords(); const result = imageEditorDisplayComponent.getStartScaleControlCoords( maskImageMap, 1, ); expect(result).toBe( `translate(${mockRotatedImageQuad[1].x}px, ` + `${mockRotatedImageQuad[1].y}px) ` + `rotate(-${maskImageMap.imageEditorImage.rotate_degrees}deg)`, ); }); }); describe('mouseOverStartScaleControl', () => { const runMouseOverStartScaleControlData = () => { const mockBoundingClientRectResult = { left: 10, top: 10, } as ClientRect; const mockGetBoundingClientRecFunction = jest.fn() .mockReturnValueOnce(mockBoundingClientRectResult) as any; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageEditorDisplayMain = { nativeElement: { getBoundingClientRect: mockGetBoundingClientRecFunction, } as HTMLElement, }; const event = { clientX: 50, clientY: 100, } as MouseEvent; imageEditorDisplayComponent.mouseOverStartScaleControl( event, ); return { event, imageEditorDisplayComponent, mockBoundingClientRectResult, mockGetBoundingClientRecFunction, }; }; test('Calls getBoundingClientRect on the imageEditorDisplayMain element', () => { const { mockGetBoundingClientRecFunction, } = runMouseOverStartScaleControlData(); expect(mockGetBoundingClientRecFunction).toHaveBeenCalled(); }); test('Sets mouseCoordinatesForRotation to the coordinates of the cursor in the document', () => { const { imageEditorDisplayComponent, } = runMouseOverStartScaleControlData(); expect(imageEditorDisplayComponent.mouseCoordinatesForScale.x) .toBe(40); expect(imageEditorDisplayComponent.mouseCoordinatesForScale.y) .toBe(90); }); }); describe('getIsScalingControlTransforms', () => { const initGetIsScalingControlTransforms = () => { const mockMouseCoordinatesForScale = { x: 230, y: 143, } as CoordsInterface; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.mouseCoordinatesForScale = mockMouseCoordinatesForScale; return { imageEditorDisplayComponent, mockMouseCoordinatesForScale, }; }; test('returns the expected translations for the scale', () => { const { imageEditorDisplayComponent, mockMouseCoordinatesForScale, } = initGetIsScalingControlTransforms(); const { x, y, } = mockMouseCoordinatesForScale; const result = imageEditorDisplayComponent .getIsScalingControlTransforms(); expect(result).toBe( `translate(${x}px, ${y}px)`, ); }); }); describe('beginScaleFromCorner', () => { const runBeginScaleFromCornerData = () => { const maskImageMap = {} as MaskImageMapInterface; const imageCornerBeingScaled = 5; const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const event = { clientX: 10, clientY: 10, } as MouseEvent; imageEditorDisplayComponent.beginScaleFromCorner( maskImageMap, imageCornerBeingScaled, event, ); return { imageCornerBeingScaled, imageEditorDisplayComponent, maskImageMap, }; }; test('Sets the maskImageMap to the one from the arguments', () => { const { imageEditorDisplayComponent, maskImageMap, } = runBeginScaleFromCornerData(); expect(imageEditorDisplayComponent.imageBeingScaled) .toBe(maskImageMap); }); test('Sets the imageCornerBeingScaled to the one from the arguments', () => { const { imageEditorDisplayComponent, imageCornerBeingScaled, } = runBeginScaleFromCornerData(); expect(imageEditorDisplayComponent.imageCornerBeingScaled) .toBe(imageCornerBeingScaled); }); }); describe('applyScaleFromCorner', () => { const initApplyScaleFromCornerData = () => { const event = { clientX: 10, clientY: 10, } as MouseEvent; const mockDistanceBetweenOriginalCoords = 50; const mockDistanceBetweenNewCoords = 100; const mockProductDx = 10; const mockProductDy = 20; const mockHtmlImage = {} as HTMLImageElement; const coordinateUtilitiesService = {} as CoordinateUtilitiesService; coordinateUtilitiesService.getDistanceBetweenCoords = jest.fn() .mockReturnValueOnce(mockDistanceBetweenOriginalCoords) .mockReturnValueOnce(mockDistanceBetweenNewCoords); const canvasUtilitiesService = {} as CanvasUtilitiesService; canvasUtilitiesService.toPrintImageCoordinateSystem = jest.fn() .mockReturnValueOnce(mockProductDx) .mockReturnValueOnce(mockProductDy); canvasUtilitiesService.getImageWithUrl = jest.fn() .mockReturnValueOnce(mockHtmlImage); const imageEditorDisplayComponent = initImageEditorDisplayComponent( canvasUtilitiesService, undefined, undefined, coordinateUtilitiesService, ); imageEditorDisplayComponent.imageEditorDisplayMainTopLeftCoords = { x: 5, y: 5, }; imageEditorDisplayComponent.canvasImageOnMaskComponent = { canvas: {}, } as CanvasImageOnMaskComponent; imageEditorDisplayComponent.loadedImages = []; imageEditorDisplayComponent.imageBeingScaled = { imageEditorImage: { scale: 2, tx: 1, ty: 1, }, mask: {}, } as MaskImageMapInterface; const mockNewScale = ((imageEditorDisplayComponent.imageBeingScaled .imageEditorImage .scale * ( mockDistanceBetweenNewCoords / mockDistanceBetweenOriginalCoords )) * 100).toFixed(1); imageEditorDisplayComponent.imageCornerBeingScaled = 0; const mockRotatedImageQuadCoords = [{ x: 0, y: 0, }, { x: 5, y: 10, }, { x: 10, y: 20, }, { x: 15, y: 30, }] as CoordsInterface[]; const mockRotatedNewImageQuadCoords = [{ x: 5, y: 10, }, { x: 10, y: 20, }, { x: 15, y: 30, }, { x: 20, y: 40, }] as CoordsInterface[]; imageEditorDisplayComponent.getRotatedImageQuadCoords = jest.fn() .mockReturnValueOnce(mockRotatedImageQuadCoords) .mockReturnValueOnce(mockRotatedNewImageQuadCoords); imageEditorDisplayComponent.onScaleControlScaleAndTranslate.emit = jest.fn(); imageEditorDisplayComponent.assetSize = { height: 15, width: 10, } as DimensionsInterface; const mockTargetNewTopLeft = { x: event.clientX - imageEditorDisplayComponent .imageEditorDisplayMainTopLeftCoords.x, y: event.clientY - imageEditorDisplayComponent .imageEditorDisplayMainTopLeftCoords.y, }; const dpi = 300; imageEditorDisplayComponent.dpi = dpi; const boundingRect = { height: 10, left: 0, top: 5, width: 15, } as ClientRect; imageEditorDisplayComponent.imageEditorDisplayMain = { nativeElement: { getBoundingClientRect: jest.fn() .mockReturnValueOnce(boundingRect), }, }; return { canvasUtilitiesService, coordinateUtilitiesService, event, imageEditorDisplayComponent, mockDistanceBetweenNewCoords, mockDistanceBetweenOriginalCoords, mockHtmlImage, mockNewScale, mockProductDx, mockProductDy, mockRotatedImageQuadCoords, mockRotatedNewImageQuadCoords, mockTargetNewTopLeft, dpi, }; }; test('Does not emit anything if imageBeingScaled is null', () => { const { event, imageEditorDisplayComponent, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.imageBeingScaled = null; imageEditorDisplayComponent.applyScaleFromCorner(event); expect(imageEditorDisplayComponent.onScaleControlScaleAndTranslate.emit) .not.toHaveBeenCalled(); }); test('Sets mouseCoordinatesForScale to the adjusted coordinates of the cursor in the document', () => { const { event, imageEditorDisplayComponent, mockTargetNewTopLeft, } = initApplyScaleFromCornerData(); const boundingRect = { height: 5, left: 5, top: 5, width: 5, } as ClientRect; imageEditorDisplayComponent.imageEditorDisplayMain = { nativeElement: { getBoundingClientRect: jest.fn() .mockReturnValueOnce(boundingRect), }, }; imageEditorDisplayComponent.applyScaleFromCorner(event); expect(imageEditorDisplayComponent.mouseCoordinatesForScale) .toEqual(mockTargetNewTopLeft); }); test('Calls getRotatedImageQuadCoords with the imageBeingScaled', () => { const { event, imageEditorDisplayComponent, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(imageEditorDisplayComponent.getRotatedImageQuadCoords) .toHaveBeenCalledWith(imageEditorDisplayComponent.imageBeingScaled); }); test('Calls getDistanceBetweenCoords with the original coords and the opposite corners', () => { const { coordinateUtilitiesService, event, imageEditorDisplayComponent, mockRotatedImageQuadCoords, } = initApplyScaleFromCornerData(); const boundingRect = { height: 0, left: 0, top: 0, width: 0, } as ClientRect; imageEditorDisplayComponent.imageEditorDisplayMain = { nativeElement: { getBoundingClientRect: jest.fn() .mockReturnValueOnce(boundingRect), }, }; imageEditorDisplayComponent.applyScaleFromCorner(event); expect(coordinateUtilitiesService.getDistanceBetweenCoords) .toHaveBeenCalledWith( mockRotatedImageQuadCoords[0], mockRotatedImageQuadCoords[2], ); }); test('Calls getDistanceBetweenCoords with the new coords and the opposite corners', () => { const { coordinateUtilitiesService, event, imageEditorDisplayComponent, mockRotatedImageQuadCoords, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(coordinateUtilitiesService.getDistanceBetweenCoords) .toHaveBeenCalledWith( { x: event.clientX - imageEditorDisplayComponent .imageEditorDisplayMainTopLeftCoords.x, y: event.clientY - imageEditorDisplayComponent .imageEditorDisplayMainTopLeftCoords.y, }, mockRotatedImageQuadCoords[2], ); }); // tslint:disable-next-line test('Calls getRotatedImageQuadCoords with the result of scaling the image by the new amount', () => { const { event, imageEditorDisplayComponent, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(imageEditorDisplayComponent.getRotatedImageQuadCoords) .toHaveBeenCalledWith({ ...imageEditorDisplayComponent.imageBeingScaled, imageEditorImage: { ...imageEditorDisplayComponent.imageBeingScaled .imageEditorImage, scale: 2, }, }); }); test('Calls canvasUtilitiesService.getImageWithUrl to get the image mask htmlImage', () => { const { canvasUtilitiesService, event, imageEditorDisplayComponent, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(canvasUtilitiesService.getImageWithUrl) .toHaveBeenCalledWith( imageEditorDisplayComponent.loadedImages, imageEditorDisplayComponent.imageBeingScaled.mask.mask, ); }); test('Calls canvasUtilitiesService.toPrintImageCoordinateSystem to get the the x print coords', () => { const { canvasUtilitiesService, event, imageEditorDisplayComponent, mockHtmlImage, dpi, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(canvasUtilitiesService.toPrintImageCoordinateSystem) .toHaveBeenCalledWith( imageEditorDisplayComponent.canvasImageOnMaskComponent.canvas, -5, imageEditorDisplayComponent.imageBeingScaled, mockHtmlImage, imageEditorDisplayComponent.assetSize, dpi, ); }); test('Calls canvasUtilitiesService.toPrintImageCoordinateSystem to get the the y print coords', () => { const { canvasUtilitiesService, event, imageEditorDisplayComponent, mockHtmlImage, dpi, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(canvasUtilitiesService.toPrintImageCoordinateSystem) .toHaveBeenCalledWith( imageEditorDisplayComponent.canvasImageOnMaskComponent.canvas, -10, imageEditorDisplayComponent.imageBeingScaled, mockHtmlImage, imageEditorDisplayComponent.assetSize, dpi, ); }); // tslint:disable-next-line test('Emits an event to onScaleControlScaleAndTranslate with the maskImage being scaled, the new scale and the new translations', () => { const { event, imageEditorDisplayComponent, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(imageEditorDisplayComponent.onScaleControlScaleAndTranslate.emit) .toHaveBeenCalledWith([ imageEditorDisplayComponent.imageBeingScaled, 4, { x: 11, y: 21, }, ]); }); // tslint:disable-next-line test('Sets imageCurrentScale to a string of the percentage value of scale rounded to 1 decimal point', () => { const { event, imageEditorDisplayComponent, mockNewScale, } = initApplyScaleFromCornerData(); imageEditorDisplayComponent.applyScaleFromCorner(event); expect(imageEditorDisplayComponent.imageCurrentScale) .toBe(mockNewScale); }); }); describe('endScaleFromCorner', () => { test('Sets imageBeingScaled to null', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingScaled = {} as MaskImageMapInterface; imageEditorDisplayComponent.endScaleFromCorner(); expect(imageEditorDisplayComponent.imageBeingScaled) .toBeNull(); }); }); describe('getIsScalingNorthWestToSouthEastForCorner', () => { const initGetIsScalingNorthWestToSouthEastForCorner = ({ mockNearestDegrees = 180, }: { mockNearestDegrees?: number, } = {}) => { const maskImageMap = { imageEditorImage: { rotate_degrees: 10, }, } as MaskImageMapInterface; const coordinateUtilitiesService = {} as CoordinateUtilitiesService; coordinateUtilitiesService.getNearestDegrees = jest.fn() .mockReturnValueOnce(mockNearestDegrees); const imageEditorDisplayComponent = initImageEditorDisplayComponent( undefined, undefined, undefined, coordinateUtilitiesService, ); return { coordinateUtilitiesService, imageEditorDisplayComponent, maskImageMap, }; }; // tslint:disable-next-line test('Calls coordinateUtilitiesService.getNearestDegrees with the maskImagesMap degrees', () => { const { coordinateUtilitiesService, imageEditorDisplayComponent, maskImageMap, } = initGetIsScalingNorthWestToSouthEastForCorner(); imageEditorDisplayComponent.getIsScalingNorthWestToSouthEastForCorner( 0, maskImageMap, ); expect(coordinateUtilitiesService.getNearestDegrees) .toHaveBeenCalledWith(maskImageMap.imageEditorImage.rotate_degrees); }); // tslint:disable-next-line test('Returns true if using the top left corner index the nearest 90 degrees is 0', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetIsScalingNorthWestToSouthEastForCorner({ mockNearestDegrees: 0, }); const result = imageEditorDisplayComponent .getIsScalingNorthWestToSouthEastForCorner( 0, maskImageMap, ); expect(result).toBe(true); }); // tslint:disable-next-line test('Returns false if using the top left corner index the nearest 90 degrees is 90', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetIsScalingNorthWestToSouthEastForCorner({ mockNearestDegrees: 90, }); const result = imageEditorDisplayComponent .getIsScalingNorthWestToSouthEastForCorner( 0, maskImageMap, ); expect(result).toBe(false); }); // tslint:disable-next-line test('Returns true if using the top right corner index the nearest 90 degrees is 90', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetIsScalingNorthWestToSouthEastForCorner({ mockNearestDegrees: 90, }); const result = imageEditorDisplayComponent .getIsScalingNorthWestToSouthEastForCorner( 1, maskImageMap, ); expect(result).toBe(true); }); // tslint:disable-next-line test('Returns false if using the top right corner index the nearest 90 degrees is 180', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetIsScalingNorthWestToSouthEastForCorner({ mockNearestDegrees: 180, }); const result = imageEditorDisplayComponent .getIsScalingNorthWestToSouthEastForCorner( 1, maskImageMap, ); expect(result).toBe(false); }); }); describe('isScalingNorthWestToSouthEast', () => { const runIsScalingNorthWestToSouthEastData = () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.imageBeingScaled = {} as MaskImageMapInterface; imageEditorDisplayComponent.imageCornerBeingScaled = 5; const mockGetIsScalingNorthWestToSouthEastForCorner = true; imageEditorDisplayComponent.getIsScalingNorthWestToSouthEastForCorner = jest.fn().mockReturnValueOnce( mockGetIsScalingNorthWestToSouthEastForCorner, ); const result = imageEditorDisplayComponent.isScalingNorthWestToSouthEast(); return { imageEditorDisplayComponent, mockGetIsScalingNorthWestToSouthEastForCorner, result, }; }; // tslint:disable-next-line test('Calls getIsScalingNorthWestToSouthEastForCorner with the imageCornerBeingScaled and the imageBeingScaled', () => { const { imageEditorDisplayComponent, } = runIsScalingNorthWestToSouthEastData(); expect( imageEditorDisplayComponent .getIsScalingNorthWestToSouthEastForCorner, ).toHaveBeenCalledWith( imageEditorDisplayComponent.imageCornerBeingScaled, imageEditorDisplayComponent.imageBeingScaled, ); }); // tslint:disable-next-line test('Returns the result of getIsScalingNorthWestToSouthEastForCorner', () => { const { result, mockGetIsScalingNorthWestToSouthEastForCorner, } = runIsScalingNorthWestToSouthEastData(); expect(result).toBe(mockGetIsScalingNorthWestToSouthEastForCorner); }); }); describe('isDeleteControlVisible', () => { const runIsDeleteControlVisible = ({ expectedIsVisible, isImageBeingTransformed, showDeleteButton, }: { expectedIsVisible: boolean, isImageBeingTransformed: boolean, showDeleteButton: boolean, }) => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.isImageBeingTransformed = jest.fn() .mockReturnValueOnce(isImageBeingTransformed); imageEditorDisplayComponent.showRotationControl = showDeleteButton; expect(imageEditorDisplayComponent.isStartRotationControlVisible()) .toBe(expectedIsVisible); }; test('Returns false if there is an image being transformed', () => { runIsDeleteControlVisible({ expectedIsVisible: false, isImageBeingTransformed: true, showDeleteButton: true, }); }); // tslint:disable-next-line test('Returns false if there is no image being transformed but showDeleteButton is set to false', () => { runIsDeleteControlVisible({ expectedIsVisible: false, isImageBeingTransformed: false, showDeleteButton: false, }); }); // tslint:disable-next-line test('Returns true if there is no image being transformed and showDeleteButton is set to true', () => { runIsDeleteControlVisible({ expectedIsVisible: true, isImageBeingTransformed: false, showDeleteButton: true, }); }); }); describe('getDeleteButtonTransforms', () => { const initGetDeleteButtonTransformsData = () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); const mockImageQuadCoords = [{ x: 50, y: 50, }, { x: 0, y: 50, }, {}, {}]; imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords = jest.fn().mockReturnValueOnce(mockImageQuadCoords); const maskImageMap = { imageEditorImage: { rotate_degrees: 50, }, } as MaskImageMapInterface; return { imageEditorDisplayComponent, maskImageMap, mockImageQuadCoords, }; }; test('Gets the constrained rotatedCoords for the maskImage', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetDeleteButtonTransformsData(); imageEditorDisplayComponent.getDeleteButtonTransforms(maskImageMap); expect(imageEditorDisplayComponent.getConstrainedRotatedImageQuadCoords) .toHaveBeenCalledWith(maskImageMap); }); test('Returns the expected translations and rotations transforms', () => { const { imageEditorDisplayComponent, maskImageMap, } = initGetDeleteButtonTransformsData(); const result = imageEditorDisplayComponent .getDeleteButtonTransforms(maskImageMap); expect(result).toBe('translate(25px, 35px) rotate(-230deg)'); }); }); describe('deleteButtonClicked', () => { test('Emits an event to onDeleteButtonClicked', () => { const imageEditorDisplayComponent = initImageEditorDisplayComponent(); imageEditorDisplayComponent.onDeleteButtonClicked.emit = jest.fn(); const maskImageMap = {} as MaskImageMapInterface; imageEditorDisplayComponent.deleteButtonClicked(maskImageMap); expect(imageEditorDisplayComponent.onDeleteButtonClicked.emit) .toHaveBeenCalledWith(maskImageMap); }); });