diff --git a/modules/ecs6-class/line.js b/modules/ecs6-class/line.js index 826c675..6c5850b 100644 --- a/modules/ecs6-class/line.js +++ b/modules/ecs6-class/line.js @@ -2,13 +2,24 @@ const Point = require("./point"); class Line { constructor({ point1 = new Point(), point2 = new Point(), n = undefined, slope = undefined }) { + if (!(point1 instanceof (Point)) && !(point2 instanceof (Point))) + throw new Error('point1 and point2 not valid') + if (!(point1 instanceof (Point))) + throw new Error('point1 not valid') + if (!(point2 instanceof (Point))) + throw new Error('point2 not valid') + if (typeof (slope) !== 'number' && typeof (slope) !== 'undefined') + throw new Error('slope should be a number'); + if (typeof (n) !== 'number' && typeof (n) !== 'undefined') + throw new Error('n should be a number'); this.point1 = point1; this.point2 = point2; this.slope = slope; this.n = n; } - calculateSlope = () => { + if ((this.point1.x - this.point2.x) === 0) + throw new Error('can`t divide by 0') this.slope = (this.point1.y - this.point2.y) / (this.point1.x - this.point2.x) } @@ -26,11 +37,29 @@ class Line { getPointByX(x) { + if (x === undefined) + throw new Error('value is undefined') + if (typeof (x) !== 'number') + throw new Error('argument is not a number') + if (this.slope === undefined) + this.calculateSlope() + if (this.n === undefined) + this.calculateNOfLineFunction() let y = this.slope * x + this.n return new Point({ x, y }) } getPointByY(y) { + if (y === undefined) + throw new Error('value is undefined') + if (typeof (y) !== 'number') + throw new Error('argument is not a number') + if (this.slope === undefined) + this.calculateSlope() + if (this.slope === 0) + throw new Error('slope can`t be 0') + if (this.n === undefined) + this.calculateNOfLineFunction() let x = (y - this.n) / this.slope; return new Point({ x, y }) } diff --git a/modules/ecs6-class/point.js b/modules/ecs6-class/point.js index e81b4a4..c7336db 100644 --- a/modules/ecs6-class/point.js +++ b/modules/ecs6-class/point.js @@ -1,12 +1,22 @@ class Point { constructor({x=0, y=0}={}) { + if (typeof (x) !== 'number' || typeof (y) !== 'number') + throw new Error('argument is not a number') this.x = x; this.y = y; } moveVertical(value) { + if (value === undefined) + throw new Error('value is undefined') + if (typeof (value) != 'number') + throw new Error('argument is not a number') this.y += value; } moveHorizontal(value) { + if (value === undefined) + throw new Error('value is undefined') + if (typeof (value) !== 'number') + throw new Error('argument is not a number') this.x += value; } } diff --git a/modules/geometry-calculation.js b/modules/geometry-calculation.js index 6e11643..a4a61eb 100644 --- a/modules/geometry-calculation.js +++ b/modules/geometry-calculation.js @@ -1,6 +1,11 @@ -const Line = require('./ecs6-class/line') +const Line = require('./ecs6-class/line'); +const Point = require('./ecs6-class/point'); const calculateDistance = (point1, point2) => { + if(point1 === undefined || point2 === undefined) + throw new Error('the function should get two arguments') + if(!(point1 instanceof(Point)) || !(point2 instanceof(Point))) + throw new Error('the argument should be point') let distanceX = (point2.x - point1.x) ** 2; let distanceY = (point2.y - point2.y) ** 2; const distance = Math.sqrt(distanceX + distanceY); @@ -8,6 +13,10 @@ const calculateDistance = (point1, point2) => { } const calculateJunctionPoint = (line1, line2) => { + if(line1 === undefined || line2 === undefined) + throw new Error('the function should get two arguments') + if(!(line1 instanceof(Line)) || !(line2 instanceof(Line))) + throw new Error('the argument should be line') if (line1.slope === line2.slope) { if (line1.n === line2.n) { return true @@ -24,6 +33,14 @@ const calculateJunctionPoint = (line1, line2) => { } const isPointOnLine = (line, point) => { + if(line === undefined || point === undefined) + throw new Error('the function should get two arguments') + if(!(line instanceof(Line))) + throw new Error('the argument should be line') + if(!(point instanceof(Point))) + throw new Error('the argument should be point') + if(line.slope === undefined) + line.calculateSlope() const proxyLine = new Line({ point1: line.point1, point2: point }) proxyLine.calculateSlope() if (line.slope === proxyLine.slope) { diff --git a/package.json b/package.json index 56bf17b..36c632d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "practice unit tests in javascript", "main": "index.js", "scripts": { - "test": "jest" + "test": "jest", + "coverage": "npm run test -- --coverage" }, "dependencies": { "jest": "^29.7.0" diff --git a/tests/ecs6-class/line.test.js b/tests/ecs6-class/line.test.js new file mode 100644 index 0000000..7df7acd --- /dev/null +++ b/tests/ecs6-class/line.test.js @@ -0,0 +1,150 @@ +const Line = require('../../modules/ecs6-class/line'); +const Point = require('../../modules/ecs6-class/point'); +const mockGetPointByY = jest.fn(() => ({ x: 0, y: 0 })); +const mockGetPointByX = jest.fn(() => ({ x: 0, y: 5 })); + +describe('CONSTRUCTOR', () => { + it('should build line when get point', () => { + const line = new Line({ point1: new Point({ x: 2, y: 2 }) }) + expect(line.point1).toEqual(new Point({ x: 2, y: 2 })); + }) + + describe('ERRORS', () => { + it('should throw string error when argument are no point', () => { + expect(() => new Line({ point1: new Line({}) })).toThrow('point1 not valid') + expect(() => new Line({ point2: 'hello' })).toThrow('point2 not valid') + expect(() => new Line({ point1: ['x', 'y'] })).toThrow('point1 not valid') + expect(() => new Line({ point2: false })).toThrow('point2 not valid') + expect(() => new Line({ point1: () => true, point2: () => 'y' })).toThrow('point1 and point2 not valid') + }) + + it('should throw string error when argumonts are no number string', () => { + expect(() => new Line({ slope: 'a' })).toThrow('slope should be a number') + expect(() => new Line({ slope: true })).toThrow('slope should be a number') + expect(() => new Line({ slope: ['a', 'b'] })).toThrow('slope should be a number') + expect(() => new Line({ slope: value => (value) })).toThrow('slope should be a number') + }) + + it('should throw string error when argumonts are no number string', () => { + expect(() => new Line({ n: 'a' })).toThrow('n should be a number') + expect(() => new Line({ n: true })).toThrow('n should be a number') + expect(() => new Line({ n: ['a', 'b'] })).toThrow('n should be a number') + expect(() => new Line({ n: value => (value) })).toThrow('n should be a number') + }) + }) +}) + +describe('CALCULATE_SLOPE', () => { + it('should calculate the slope', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + expect(line.slope).toBe(1) + }) + + it('should throw string error when point1.x - point2.x equal 0', () => { + const line1 = new Line({}); + expect(() => line1.calculateSlope()).toThrow('can`t divide by 0') + }) +}) + +describe('CALCULATE_N_OF_LINE_FUNCTION', () => { + it('should calculate n of line', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line = new Line({ point1, point2 }); + line.slope = 1; + line.calculateNOfLineFunction() + expect(line.n).toBe(-1) + }) +}) + +describe('GET_POINT_ON_X_ASIS', () => { + it('mock getPointOnXAsis', () => { + const LineInstance = new Line({}); + LineInstance.getPointByY = mockGetPointByY; + LineInstance.getPointOnXAsis(); + expect(mockGetPointByY).toHaveBeenCalledWith(0); + }); +}) + +describe('GET_POINT_ON_Y_ASIS', () => { + it('mock getPointOnYAsis', () => { + const LineInstance = new Line(2, 3); + LineInstance.getPointByX = mockGetPointByX; + const result = LineInstance.getPointOnYAsis(); + expect(mockGetPointByX).toHaveBeenCalledWith(0); + expect(result).toEqual({ x: 0, y: 5 }); + }); +}) + +describe('GET_POINT_BY_X', () => { + it('should return point x', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line = new Line({ point1, point2 }); + expect(line.getPointByX(5)).toEqual({ x: 5, y: 4 }) + }) + + it('should to send to function: calculateSlope if slope is undefined', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line2 = new Line({ point1, point2 }); + expect(line2.getPointByX(5)).toEqual({ x: 5, y: 4 }) + }) + + it('should to send to function: calculateNOfLineFunction if n is undefined', () => { + const line1 = new Line({}); + line1.slope = 0; + expect(line1.getPointByX(5)).toEqual({ x: 5, y: 0 }) + }) + + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line = new Line({ point1, point2 }); + expect(() => line.getPointByX('a')).toThrow('argument is not a number') + expect(() => line.getPointByX(true)).toThrow('argument is not a number') + expect(() => line.getPointByX(['x', 'y'])).toThrow('argument is not a number') + expect(() => line.getPointByX()).toThrow('value is undefined') + expect(() => line.getPointByX(value => (value))).toThrow('argument is not a number') + }) +}) + +describe('GET_POINT_BY_Y', () => { + it('should return point y', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line = new Line({ point1, point2 }); + expect(line.getPointByY(2)).toEqual({ x: 3, y: 2 }) + }) + + it('should to send to function: calculateSlope if slope is undefined', () => { + const line3 = new Line({}); + line3.slope = 2; + expect(line3.getPointByY(2)).toEqual({ x: 1, y: 2 }) + }) + + it('should to send to function: calculateNOfLineFunction if n is undefined', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line4 = new Line({ point1, point2 }); + line4.n = 0; + expect(line4.getPointByY(2)).toEqual({ x: 2, y: 2 }) + }) + + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line = new Line({ point1, point2 }); + const line1 = new Line({}); + line1.slope = 0; + expect(() => line.getPointByY('a')).toThrow('argument is not a number') + expect(() => line.getPointByY(true)).toThrow('argument is not a number') + expect(() => line.getPointByY(['x', 'y'])).toThrow('argument is not a number') + expect(() => line.getPointByY()).toThrow('value is undefined') + expect(() => line.getPointByY(value => (value))).toThrow('argument is not a number') + expect(() => line1.getPointByY(2)).toThrow('slope can`t be 0') + }) +}) \ No newline at end of file diff --git a/tests/ecs6-class/point.test.js b/tests/ecs6-class/point.test.js new file mode 100644 index 0000000..e94e7ea --- /dev/null +++ b/tests/ecs6-class/point.test.js @@ -0,0 +1,57 @@ +const Point = require('../../modules/ecs6-class/point'); +const point1 = new Point(); + +describe('CONSTRUCTOR', () => { + it('should build point when get two arguments', () => { + expect(new Point({ x: 2, y: 2 })).toEqual({ x: 2, y: 2 }) + }) + + it('should build point when get no arguments', () => { + expect(new Point()).toEqual({ x: 0, y: 0 }) + }) + + describe('ERRORS', () => { + it('should throw string error when argumonts no type of point', () => { + expect(() => new Point({ x: 'x' })).toThrow('argument is not a number') + expect(() => new Point({ y: false })).toThrow('argument is not a number') + expect(() => new Point({ x: ['x', 'y'] })).toThrow('argument is not a number') + expect(() => new Point({ x: () => true })).toThrow('argument is not a number') + expect(() => new Point({ y: () => 'y' })).toThrow('argument is not a number') + }) + }) +}) + +describe('MOVE_VERTICAL', () => { + it('should to add the value to y', () => { + const point = new Point({ x: 2, y: 2 }); + point.moveVertical(2); + expect(point).toEqual({ x: 2, y: 4 }); + }) + + describe('ERRORS', () => { + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + expect(() => point1.moveVertical('a')).toThrow('argument is not a number') + expect(() => point1.moveVertical(true)).toThrow('argument is not a number') + expect(() => point1.moveVertical(['x', 'y'])).toThrow('argument is not a number') + expect(() => point1.moveVertical()).toThrow('value is undefined') + expect(() => point1.moveVertical(value => (value))).toThrow('argument is not a number') + }) + }) +}) + +describe('MOVE_HORIZONTAL', () => { + it('should to add the value to x', () => { + const point = new Point(); + point.moveHorizontal(2); + expect(point).toEqual({ x: 2, y: 0 }); + }) + describe('ERRORS', () => { + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + expect(() => point1.moveHorizontal('a')).toThrow('argument is not a number') + expect(() => point1.moveHorizontal(true)).toThrow('argument is not a number') + expect(() => point1.moveHorizontal(['x', 'y'])).toThrow('argument is not a number') + expect(() => point1.moveHorizontal()).toThrow('value is undefined') + expect(() => point1.moveHorizontal(value => (value))).toThrow('argument is not a number') + }) + }) +}) \ No newline at end of file diff --git a/tests/geometry-calculation.test.js b/tests/geometry-calculation.test.js new file mode 100644 index 0000000..2d3db28 --- /dev/null +++ b/tests/geometry-calculation.test.js @@ -0,0 +1,107 @@ +const Line = require('../modules/ecs6-class/line'); +const Point = require('../modules/ecs6-class/point'); +const { calculateDistance, calculateJunctionPoint, isPointOnLine } = require('../modules/geometry-calculation'); + +describe('CALCULATE_DISTANCE', () => { + it('should calculate distance', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + expect(calculateDistance(point1, point2)).toEqual(1) + }) + + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + expect(() => calculateDistance(new Line({}), new Line({}))).toThrow('the argument should be point') + expect(() => calculateDistance(1, 2)).toThrow('the argument should be point') + expect(() => calculateDistance(true)).toThrow('the function should get two arguments') + expect(() => calculateDistance(['x', 'y'])).toThrow('the function should get two arguments') + expect(() => calculateDistance(() => true)).toThrow('the function should get two arguments') + expect(() => calculateDistance()).toThrow('the function should get two arguments') + }) +}) + +describe('CALCULATE_JUNCTION_POINT', () => { + it('should return true', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line1 = new Line({ point1, point2, slope: 2, n: 3 }); + expect(calculateJunctionPoint(line1, line1)).toEqual(true) + }) + + it('should return false', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line1 = new Line({ point1, point2, slope: 2, n: 3 }); + const point3 = new Point({ x: 2, y: 2 }); + const point4 = new Point({ x: 2, y: 1 }); + const line2 = new Line({ point1: point3, point2: point4, slope: 2, n: 5 }); + expect(calculateJunctionPoint(line1, line2)).toEqual(false) + }) + + it('should return new point', () => { + const point3 = new Point({ x: 2, y: 2 }); + const point4 = new Point({ x: 2, y: 1 }); + const line2 = new Line({ point1: point3, point2: point4, slope: 2, n: 5 }); + const line3 = new Line({ point1: point3, point2: point4, slope: 4, n: 3 }); + expect(calculateJunctionPoint(line2, line3)).toEqual({ x: 1, y: 7 }) + }) + + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + expect(() => calculateJunctionPoint(new Point(), new Point())).toThrow('the argument should be line') + expect(() => calculateJunctionPoint(1, 2)).toThrow('the argument should be line') + expect(() => calculateJunctionPoint(true)).toThrow('the function should get two arguments') + expect(() => calculateJunctionPoint(['x', 'y'])).toThrow('the function should get two arguments') + expect(() => calculateJunctionPoint(() => true)).toThrow('the function should get two arguments') + expect(() => calculateJunctionPoint()).toThrow('the function should get two arguments') + }) +}) + +describe('IS_POINT_ON_LINE', () => { + it('should return true if the slope and n equals', () => { + const point5 = new Point({ x: 2, y: 2 }); + const point6 = new Point({ x: 1, y: 1 }); + const line4 = new Line({ point1: point5, point2: point6, slope: 1, n: 0 }); + expect(isPointOnLine(line4, point6)).toEqual(true) + }) + + it('should return false if the slope equal and n not equal', () => { + const point4 = new Point({ x: 2, y: 1 }); + const point5 = new Point({ x: 2, y: 2 }); + const point6 = new Point({ x: 1, y: 1 }); + const line5 = new Line({ point1: point5, point2: point4, slope: 1, n: 3 }); + expect(isPointOnLine(line5, point6)).toEqual(false) + }) + + it('should return true if the slope and n not equals', () => { + const point4 = new Point({ x: 2, y: 1 }); + const point1 = new Point({ x: 4, y: 3 }); + const point2 = new Point({ x: 3, y: 2 }); + const line1 = new Line({ point1, point2, slope: 2, n: 3 }); + expect(isPointOnLine(line1, point4)).toEqual(false) + }) + + it('should to send to function: calculateSlope if slope is undefined', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point5 = new Point({ x: 2, y: 2 }); + const point6 = new Point({ x: 1, y: 1 }); + const line6 = new Line({ point1: point5, point2: point6, n: 0 }); + expect(isPointOnLine(line6, point1)).toEqual(false) + }) + + it('should to send to function: calculateNOfLineFunction if n is undefined', () => { + const point1 = new Point({ x: 4, y: 3 }); + const point4 = new Point({ x: 2, y: 1 }); + const point5 = new Point({ x: 2, y: 2 }); + const line7 = new Line({ point1: point5, point2: point4, slope: 1 }); + expect(isPointOnLine(line7, point1)).toEqual(false) + }) + + it('should throw string error when argumonts are no number string or undefined when argument is undefined', () => { + expect(() => isPointOnLine(new Point(), new Point())).toThrow('the argument should be line') + expect(() => isPointOnLine(new Line({}), new Line({}))).toThrow('the argument should be point') + expect(() => isPointOnLine(1, 2)).toThrow('the argument should be line') + expect(() => isPointOnLine(true)).toThrow('the function should get two arguments') + expect(() => isPointOnLine(['x', 'y'])).toThrow('the function should get two arguments') + expect(() => isPointOnLine(() => true)).toThrow('the function should get two arguments') + expect(() => isPointOnLine()).toThrow('the function should get two arguments') + }) +}) \ No newline at end of file