import 'reflect-metadata'; import { CoordinateUtilitiesService, } from './coordinate-utilities.service'; import { CoordsInterface, } from '../../../models'; const initCoordinateUtilitiesService = () => { return new CoordinateUtilitiesService(); }; describe('getNearestDegrees', () => { test('Gets the nearest 90 degrees by default', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getNearestDegrees(45); expect(result).toBe(90); }); test('Gets the value to the nearest supplied degrees', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getNearestDegrees(45, 50); expect(result).toBe(50); }); }); describe('rotateCoords', () => { test('Rotates the x coordinates as expected for 90 degrees', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const newCoords = coordinateUtilitiesService.rotateCoords( { x: 0, y: 0, }, { x: 10, y: 10, }, 90, ); expect(newCoords.x).toBe(0); }); test('Rotates the y coordinates as expected for 90 degrees', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const newCoords = coordinateUtilitiesService.rotateCoords( { x: 0, y: 0, }, { x: 10, y: 10, }, 90, ); expect(newCoords.y).toBe(20); }); test('Rotates the x coordinates as expected for 180 degrees', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const newCoords = coordinateUtilitiesService.rotateCoords( { x: 0, y: 0, }, { x: 10, y: 10, }, 180, ); expect(newCoords.x).toBe(20); }); test('Rotates the y coordinates as expected for 180 degrees', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const newCoords = coordinateUtilitiesService.rotateCoords( { x: 0, y: 0, }, { x: 10, y: 10, }, 180, ); expect(newCoords.y).toBe(20); }); }); describe('rotateCoordsAroundCenterOfCoords', () => { const initRotateCoordsAroundCenterOfCoordsData = () => { const mockRotatedCoords = { x: 10, y: 10, }; const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.rotateCoords = jest.fn() .mockReturnValue(mockRotatedCoords); const points = [{ x: 0, y: 0, }, { x: 50, y: 50, }]; return { coordinateUtilitiesService, mockRotatedCoords, points, }; }; // tslint:disable-next-line test('Calls rotateCoords for each of the coords around the mid points', () => { const { coordinateUtilitiesService, points, } = initRotateCoordsAroundCenterOfCoordsData(); coordinateUtilitiesService.rotateCoordsAroundCenterOfCoords( points, 10, ); expect(coordinateUtilitiesService.rotateCoords).toHaveBeenCalledWith( points[0], { x: 25, y: 25, }, 10, ); expect(coordinateUtilitiesService.rotateCoords).toHaveBeenCalledWith( points[1], { x: 25, y: 25, }, 10, ); }); test('Returns the rotated coords', () => { const { coordinateUtilitiesService, mockRotatedCoords, points, } = initRotateCoordsAroundCenterOfCoordsData(); const result = coordinateUtilitiesService .rotateCoordsAroundCenterOfCoords( points, 10, ); expect(result[0]).toBe(mockRotatedCoords); expect(result[1]).toBe(mockRotatedCoords); }); }); describe('doCoordsFillArea', () => { // tslint:disable-next-line test('Returns false if the minimum x point is further right than a the minimum guide area x', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.doCoordsFillArea( [ { x: 15, y: 10 }, { x: 10, y: 15 }, ], { x: 11, y: 5, }, { x: 25, y: 20, }, ); expect(result).toBe(false); }); // tslint:disable-next-line test('Returns false if the maximum x point is further left than a the maximum guide area x', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.doCoordsFillArea( [ { x: 10, y: 10 }, { x: 15, y: 15 }, ], { x: 5, y: 5, }, { x: 14, y: 20, }, ); expect(result).toBe(false); }); // tslint:disable-next-line test('Returns false if the minimum y point is further down than the minimum guide area y', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.doCoordsFillArea( [ { x: 10, y: 10 }, { x: 15, y: 15 }, ], { x: 5, y: 11, }, { x: 20, y: 20, }, ); expect(result).toBe(false); }); // tslint:disable-next-line test('Returns false if the maximum y point is further up than the maximum guide area y', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.doCoordsFillArea( [ { x: 10, y: 10 }, { x: 15, y: 15 }, ], { x: 5, y: 5, }, { x: 20, y: 14, }, ); expect(result).toBe(false); }); // tslint:disable-next-line test('Returns true if the minimum and maximum coords cover the print area', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.doCoordsFillArea( [ { x: 10, y: 10 }, { x: 15, y: 15 }, ], { x: 9, y: 9, }, { x: 16, y: 16, }, ); expect(result).toBe(true); }); }); describe('doRotatedCoordsFillArea', () => { test('Calls rotateCoords with the minimum coords', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.doCoordsFillArea = jest.fn(); coordinateUtilitiesService.rotateCoords = jest.fn() .mockReturnValue({ x: 10, y: 10, }); const areaToFill = []; const elementToCheckMinCoords = { x: 0, y: 0, }; const elementToCheckMaxCoords = { x: 10, y: 10, }; const pointToRotateAround = { x: 5, y: 5, }; coordinateUtilitiesService.doRotatedCoordsFillArea( areaToFill, elementToCheckMinCoords, elementToCheckMaxCoords, 0, pointToRotateAround, ); expect(coordinateUtilitiesService.rotateCoords) .toHaveBeenCalledWith( elementToCheckMinCoords, pointToRotateAround, 0, ); }); test('Calls rotateCoords with the maximum coords', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.doCoordsFillArea = jest.fn(); coordinateUtilitiesService.rotateCoords = jest.fn() .mockReturnValue({ x: 10, y: 10, }); const areaToFill = []; const elementToCheckMinCoords = { x: 0, y: 0, }; const elementToCheckMaxCoords = { x: 10, y: 10, }; const pointToRotateAround = { x: 5, y: 5, }; coordinateUtilitiesService.doRotatedCoordsFillArea( areaToFill, elementToCheckMinCoords, elementToCheckMaxCoords, 0, pointToRotateAround, ); expect(coordinateUtilitiesService.rotateCoords) .toHaveBeenCalledWith( elementToCheckMaxCoords, pointToRotateAround, 0, ); }); test('Calls doCoordsFillArea with the rotated coords', () => { const areaToFill = []; const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.doCoordsFillArea = jest.fn(); const minRotatedCoords = { x: 5, y: 5, } as CoordsInterface; const maxRotatedCoords = { x: 10, y: 10, } as CoordsInterface; coordinateUtilitiesService.rotateCoords = jest.fn() .mockReturnValueOnce(minRotatedCoords) .mockReturnValue(maxRotatedCoords); coordinateUtilitiesService.doRotatedCoordsFillArea( areaToFill, undefined, undefined, undefined, undefined, ); expect(coordinateUtilitiesService.doCoordsFillArea) .toHaveBeenCalledWith( areaToFill, minRotatedCoords, maxRotatedCoords, ); }); // tslint:disable-next-line test('Calls doCoordsFillArea with the swapped coords if rotating them causes the min and max to change', () => { const areaToFill = []; const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.doCoordsFillArea = jest.fn(); const minRotatedCoords = { x: 5, y: 5, } as CoordsInterface; const maxRotatedCoords = { x: 10, y: 10, } as CoordsInterface; coordinateUtilitiesService.rotateCoords = jest.fn() .mockReturnValueOnce(maxRotatedCoords) .mockReturnValue(minRotatedCoords); coordinateUtilitiesService.doRotatedCoordsFillArea( areaToFill, undefined, undefined, undefined, undefined, ); expect(coordinateUtilitiesService.doCoordsFillArea) .toHaveBeenCalledWith( areaToFill, minRotatedCoords, maxRotatedCoords, ); }); // tslint:disable-next-line test('Returns the result of doCoordsFillArea', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.doCoordsFillArea = jest.fn(); coordinateUtilitiesService.rotateCoords = jest.fn() .mockReturnValue({}); coordinateUtilitiesService.doCoordsFillArea = jest.fn() .mockReturnValue(true); const result = coordinateUtilitiesService.doRotatedCoordsFillArea( undefined, undefined, undefined, undefined, undefined, ); expect(result).toBe(true); }); }); describe('getAngleBetweenCoordinates', () => { test('Gets the angle between 2 coordinates', () => { const coord1 = { x: 0, y: 0, } as CoordsInterface; const coord2 = { x: 50, y: 50, } as CoordsInterface; const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getAngleBetweenCoordinates( coord1, coord2, ); expect(result).toBe(45); }); }); describe('getLineGradient', () => { test('Gets the gradient between two coordinates', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getLineGradient({ x: 0, y: 0, }, { x: 10, y: 20, }); expect(result).toBe(2); }); test('Gets the gradient between two coordinates', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getLineGradient({ x: 0, y: 0, }, { x: 10, y: 20, }); expect(result).toBe(2); }); }); describe('getLineYIntercept', () => { test('Calculates the point the line intercepts the y axis', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getLineYIntercept( { x: 10, y: 10, }, 0.5, ); expect(result).toBe(5); }); }); describe('getDistanceBetweenCoords', () => { test('Calculates the distance between 2 coordinates', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getDistanceBetweenCoords( { x: 0, y: 0, }, { x: 3, y: 4, }, ); expect(result).toBe(5); }); }); describe('getXIntersect', () => { test('Calculates the x intersection from the supplied arguments', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getXIntersect( 10, 2, 1, ); expect(result).toBe(4.5); }); }); describe('getYIntersect', () => { test('Calculates the y intersection from the supplied arguments', () => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.getYIntersect( 4.5, 2, 1, ); expect(result).toBe(10); }); }); describe('getCoordinateAtConstraintIntersection', () => { const runGetCoordinateAtConstraintIntersectionTest = ({ currentCoord = { x: 50, y: 50, }, mockGradient = 10, }: { currentCoord?: CoordsInterface, mockGradient?: number, } = {}) => { const mockIntercept = 2; const mockXIntersect = 50; const mockYIntersect = 100; const coordinateUtilitiesService = initCoordinateUtilitiesService(); coordinateUtilitiesService.getLineGradient = jest.fn() .mockReturnValueOnce(mockGradient); coordinateUtilitiesService.getLineYIntercept = jest.fn() .mockReturnValueOnce(mockIntercept); coordinateUtilitiesService.getXIntersect = jest.fn() .mockReturnValueOnce(mockXIntersect); coordinateUtilitiesService.getYIntersect = jest.fn() .mockReturnValueOnce(mockYIntersect); const otherCoord = { x: 10, y: 10, }; const minConstraint = { x: 0, y: 0, }; const maxConstraint = { x: 100, y: 100, }; const result = coordinateUtilitiesService .getCoordinateAtConstraintIntersection( otherCoord, currentCoord, minConstraint, maxConstraint, ); return { coordinateUtilitiesService, currentCoord, maxConstraint, minConstraint, mockGradient, mockIntercept, mockXIntersect, mockYIntersect, otherCoord, result, }; }; test('Calls getLineGradient with the two coordinates', () => { const { coordinateUtilitiesService, currentCoord, otherCoord, } = runGetCoordinateAtConstraintIntersectionTest(); expect(coordinateUtilitiesService.getLineGradient) .toBeCalledWith(otherCoord, currentCoord); }); // tslint:disable-next-line test('Calls getLineYIntercept with the currentCoord and the gradient', () => { const { coordinateUtilitiesService, currentCoord, mockGradient, } = runGetCoordinateAtConstraintIntersectionTest(); expect(coordinateUtilitiesService.getLineYIntercept) .toBeCalledWith(currentCoord, mockGradient); }); // tslint:disable-next-line test('Gets the coordinate at the constraint intersection if the x coordinate is outside the constraint', () => { const { coordinateUtilitiesService, currentCoord, mockGradient, mockIntercept, } = runGetCoordinateAtConstraintIntersectionTest(); expect(coordinateUtilitiesService.getXIntersect) .toBeCalledWith(currentCoord.y, mockGradient, mockIntercept); }); // tslint:disable-next-line test('Gets the coordinate at the constraint intersection if the y coordinate is outside the constraint', () => { const { coordinateUtilitiesService, currentCoord, mockGradient, mockIntercept, } = runGetCoordinateAtConstraintIntersectionTest(); expect(coordinateUtilitiesService.getYIntersect) .toBeCalledWith(currentCoord.x, mockGradient, mockIntercept); }); // tslint:disable-next-line test('Sets the x and y coordinate from the intersects if they both are inside the constraint', () => { const { mockYIntersect, mockXIntersect, result, } = runGetCoordinateAtConstraintIntersectionTest(); expect(result.x).toBe(mockXIntersect); expect(result.y).toBe(mockYIntersect); }); // tslint:disable-next-line test('Sets the x coordinate to the constrained X if it is outside the constraint', () => { const { result, } = runGetCoordinateAtConstraintIntersectionTest({ currentCoord: { x: 101, y: 101, }, }); expect(result.x).toBe(100); }); // tslint:disable-next-line test('Sets the y coordinate to the constrained Y if it is outside the constraint', () => { const { result, } = runGetCoordinateAtConstraintIntersectionTest({ currentCoord: { x: 101, y: 101, }, }); expect(result.y).toBe(100); }); // tslint:disable-next-line test('Sets the x coordinate to the supplied x coordinate if the gradient is Infinity', () => { const { currentCoord, result, } = runGetCoordinateAtConstraintIntersectionTest({ mockGradient: Infinity, }); expect(result.x).toBe(currentCoord.x); }); // tslint:disable-next-line test('Sets the x coordinate to the supplied x coordinate if the gradient is -Infinity', () => { const { currentCoord, result, } = runGetCoordinateAtConstraintIntersectionTest({ mockGradient: -Infinity, }); expect(result.x).toBe(currentCoord.x); }); }); describe('isCoordinatesWithinConstraints', () => { const runIsCoordinatesWithinConstraintsTest = ({ coord = { x: 10, y: 10, }, }: { coord?: CoordsInterface, } = {}) => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const result = coordinateUtilitiesService.isCoordinatesWithinConstraints( coord, { x: 0, y: 0, }, { x: 100, y: 100, }, ); return { result, }; }; test('Returns true if x and y are within the constraints', () => { const { result, } = runIsCoordinatesWithinConstraintsTest(); expect(result).toBe(true); }); test('Returns false if x is less than the minConstraint', () => { const { result, } = runIsCoordinatesWithinConstraintsTest({ coord: { x: -1, y: 10, }, }); expect(result).toBe(false); }); test('Returns false if x is greater than the maxConstraint', () => { const { result, } = runIsCoordinatesWithinConstraintsTest({ coord: { x: 101, y: 10, }, }); expect(result).toBe(false); }); test('Returns false if y is less than the minConstraint', () => { const { result, } = runIsCoordinatesWithinConstraintsTest({ coord: { x: 10, y: -1, }, }); expect(result).toBe(false); }); test('Returns false if y is greater than the maxConstraint', () => { const { result, } = runIsCoordinatesWithinConstraintsTest({ coord: { x: 10, y: 101, }, }); expect(result).toBe(false); }); }); describe('constrainCoordinates', () => { const runConstrainCoordinatesTest = ({ coords = [{ x: 10, y: 10, }, { x: 20, y: 10, }, { x: 20, y: 20, }, { x: 10, y: 20, }], }: { coords?: CoordsInterface[], } = {}) => { const coordinateUtilitiesService = initCoordinateUtilitiesService(); const minConstraint = { x: 0, y: 0, }; const maxConstraint = { x: 100, y: 100, }; const result = coordinateUtilitiesService.constrainCoordinates( coords, minConstraint, maxConstraint, ); return { coordinateUtilitiesService, coords, maxConstraint, minConstraint, result, }; }; // tslint:disable-next-line test('If all coords are within the constrained bounds return those coords', () => { const { coords, result, } = runConstrainCoordinatesTest(); expect(result).toEqual(coords); }); // tslint:disable-next-line test('If all coords are within the constrained bounds return those coords', () => { const { coords, result, } = runConstrainCoordinatesTest(); expect(result).toEqual(coords); }); // tslint:disable-next-line test('If all coordinates are out of bounds return the constrained coordinates', () => { const { minConstraint, maxConstraint, result, } = runConstrainCoordinatesTest({ coords: [{ x: -50, y: -50, }, { x: 150, y: -50, }, { x: 150, y: 60, }, { x: -150, y: 60, }], }); expect(result).toEqual([{ x: minConstraint.x, y: minConstraint.y, }, { x: maxConstraint.x, y: minConstraint.y, }, { x: maxConstraint.x, y: 60, }, { x: minConstraint.x, y: 60, }]); }); // tslint:disable-next-line test('If a coordinate has both x and y out of bounds it should return the constrained values', () => { const { minConstraint, result, } = runConstrainCoordinatesTest({ coords: [{ x: -1, y: -1, }, { x: 99, y: 1, }, { x: 99, y: 99, }, { x: 1, y: 99, }], }); expect(result[0]).toEqual({ x: minConstraint.x, y: minConstraint.y, }); }); // tslint:disable-next-line test('If the two coords next to a certain coord are out of bounds return a coord which draws a line from the opposite coord to the maximum constraint', () => { const { result, } = runConstrainCoordinatesTest({ coords: [{ x: 25, y: 25, }, { x: 150, y: 150, }, { x: 125, y: 150, }, { x: 125, y: 175, }], }); expect(result[2]).toEqual({ x: 100, y: 100, }); }); // tslint:disable-next-line test('If a coord is out of bounds return a coord which exists on the nearest existing line from another coord', () => { const { result, } = runConstrainCoordinatesTest({ coords: [{ x: 25, y: 25, }, { x: 150, y: 150, }, { x: 75, y: 75, }, { x: 50, y: 100, }], }); expect(result[1]).toEqual({ x: 100, y: 100, }); }); });