diff --git a/modules/ecs6-class/line.js b/modules/ecs6-class/line.js index 76a7359..4cc46e9 100644 --- a/modules/ecs6-class/line.js +++ b/modules/ecs6-class/line.js @@ -1,7 +1,11 @@ const Point = require("./point"); class Line { - constructor({ point1 = new Point(), point2 = new Point(), n = undefined, slope = undefined }) { + + constructor({ point1 = new Point(), point2 = new Point(), n = undefined, slope = undefined } = {}) { + if (!(point1 instanceof Point && point2 instanceof Point) || !(point1 instanceof Point) || !(point2 instanceof Point)) { + throw new Error("the type must to be instanceof Point") + } this.point1 = point1; this.point2 = point2; this.slope = slope; @@ -9,6 +13,9 @@ class Line { } calculateSlope() { + if (this.point1.x == this.point2.x) { + throw new Error("A number cannot be divided by 0") + } this.slope = (this.point1.y - this.point2.y) / (this.point1.x - this.point2.x) } @@ -24,16 +31,39 @@ class Line { return this.getPointByX(0) } - getPointByX(x) { + if (typeof (x) != "number") { + throw new Error("type must be number") + } + if (this.slope === undefined && this.n === undefined) { + throw new Error("must to send slope and n") + } + if (this.n === undefined) { + throw new Error("must to send n") + } + if (this.slope === undefined) { + throw new Error("must to send slope") + } let y = this.slope * x + this.n return new Point({ x, y }) } getPointByY(y) { + if (typeof (y) != "number") { + throw new Error("type must be number") + } + if (this.slope === undefined && this.n === undefined) { + throw new Error("must to send slope and n") + } + if (this.n === undefined) { + throw new Error("must to send n") + } + if (this.slope === undefined) { + throw new Error("must to send slope") + } let x = (y - this.n) / this.slope; return new Point({ x, y }) } } -module.exports = Line \ No newline at end of file +module.exports = Line diff --git a/modules/ecs6-class/point.js b/modules/ecs6-class/point.js index e81b4a4..b1d718b 100644 --- a/modules/ecs6-class/point.js +++ b/modules/ecs6-class/point.js @@ -1,12 +1,20 @@ class Point { constructor({x=0, y=0}={}) { + if(typeof(x)!="number") + throw new Error('the x is invalid') + if(typeof(y)!="number") + throw new Error('the y is invalid') this.x = x; this.y = y; } moveVertical(value) { + if(typeof(value)!="number") + throw new Error("the value is not type of number") this.y += value; } moveHorizontal(value) { + if(typeof(value)!="number") + throw new Error("the value is not type of number") this.x += value; } } diff --git a/modules/geometry-calculation.js b/modules/geometry-calculation.js index 6e11643..82ffd45 100644 --- a/modules/geometry-calculation.js +++ b/modules/geometry-calculation.js @@ -1,6 +1,10 @@ const Line = require('./ecs6-class/line') +const Point =require('./ecs6-class/point') const calculateDistance = (point1, point2) => { + if (!(point1 instanceof Point)) { + throw new Error("the type of point1 or type of point2 is not 'Point'") + } let distanceX = (point2.x - point1.x) ** 2; let distanceY = (point2.y - point2.y) ** 2; const distance = Math.sqrt(distanceX + distanceY); @@ -8,6 +12,11 @@ const calculateDistance = (point1, point2) => { } const calculateJunctionPoint = (line1, line2) => { + if(!(line1 instanceof Line)) + throw new Error('the value that received for line1 is not on type of line') + if(!(line2 instanceof Line)) + throw new Error('the value that received for line2 is not on type of line') + if (line1.slope === line2.slope) { if (line1.n === line2.n) { return true @@ -24,6 +33,10 @@ const calculateJunctionPoint = (line1, line2) => { } const isPointOnLine = (line, point) => { + if(!(line instanceof Line)) + throw new Error('the value that received for line is not on type of line') + if(!(point instanceof Point)) + throw new Error('the value that received for point is not on type of point') 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..e6750fe 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" @@ -19,5 +20,4 @@ "homepage": "https://github.com/gemtechd/build-tests#readme", "author": "gemtechd", "license": "ISC" - -} +} \ No newline at end of file diff --git a/tests/modules/ecs6-class/line.test.js b/tests/modules/ecs6-class/line.test.js new file mode 100644 index 0000000..0e2ae90 --- /dev/null +++ b/tests/modules/ecs6-class/line.test.js @@ -0,0 +1,150 @@ +const Line = require('./../../../modules/ecs6-class/line'); +const Point = require('./../../../modules/ecs6-class/point'); + +describe('Line constructor', () => { + it('should set the correct point1, point2, slope, and n values when objects with specific values are passed', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + expect(line.point1).toBe(point1); + expect(line.point2).toBe(point2); + expect(line.slope).toBe(undefined); + expect(line.n).toBe(undefined); + }); + describe('Error', () => { + it("throw new Error when type of object not instanceof point", () => { + expect(() => new Line({ point1: "string" })).toThrow("the type must to be instanceof Point") + expect(() => new Line({ point1: true })).toThrow("the type must to be instanceof Point") + expect(() => new Line({ point1: [2, 3] })).toThrow("the type must to be instanceof Point") + expect(() => new Line({ point2: () => { } })).toThrow("the type must to be instanceof Point") + expect(() => new Line({ point1: { 2: 3 } })).toThrow("the type must to be instanceof Point") + }) + }) +}); + +describe('Line calculateSlope method', () => { + it('should correctly calculate the slope between point1 and point2', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + expect(line.slope).toBe(1); + }); + describe('Error', () => { + it("throw new Error when ", () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 1, y: 3 }); + const line = new Line({ point1, point2 }); + expect(() => line.calculateSlope()).toThrow("A number cannot be divided by 0") + }) + }) +}); + +describe('Line calculateNOfLineFunction method', () => { + it('should correctly calculate the n value', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + line.calculateNOfLineFunction(); + expect(line.n).toBe(0); + }); +}); + +describe('Line getPointOnXAsis method', () => { + it('should retrieve the correct point on the X-axis', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + line.calculateNOfLineFunction(); + const pointOnXAxis = line.getPointOnXAsis(); + expect(pointOnXAxis.x).toBeCloseTo(0); + expect(pointOnXAxis.y).toBeCloseTo(0); + }); +}); + +describe('Line getPointOnYAsis method', () => { + it('should retrieve the correct point on the Y-axis', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + line.calculateNOfLineFunction(); + const pointOnYAxis = line.getPointOnYAsis(); + expect(pointOnYAxis.x).toBeCloseTo(0); + expect(pointOnYAxis.y).toBeCloseTo(0); + }); + + +}); + +describe('Line getPointByX method', () => { + it('should correctly calculate the point by providing an X coordinate', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + line.calculateNOfLineFunction(); + const targetX = 4; + const pointByX = line.getPointByX(targetX); + expect(pointByX.y).toBeCloseTo(targetX); + }); + describe('ERROR', () => { + it("throw new error when did'nt send slope and n", () => { + const line = new Line(); + expect(() => line.getPointByX(3)).toThrow("must to send slope and n") + }) + it("throw new error when did'nt send slope", () => { + const line = new Line({ n: 2 }); + expect(() => line.getPointByX(3)).toThrow("must to send slope") + }) + it("throw new error when did'nt send n", () => { + const line = new Line({ slope: 2 }); + expect(() => line.getPointByX(3)).toThrow("must to send n") + }) + it("throw new error when type of x did'nt number", () => { + const line = new Line({ slope: 2 }); + expect(() => line.getPointByX(true)).toThrow("type must be number") + expect(() => line.getPointByX(() => { })).toThrow("type must be number") + expect(() => line.getPointByX({ x: 4 })).toThrow("type must be number") + expect(() => line.getPointByX("string")).toThrow("type must be number") + expect(() => line.getPointByX([3, 2])).toThrow("type must be number") + }) + }) +}); + +describe('Line getPointByY method', () => { + it('should correctly calculate the point by providing an Y coordinate', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 3, y: 3 }); + const line = new Line({ point1, point2 }); + line.calculateSlope(); + line.calculateNOfLineFunction(); + const targetY = 4; + const pointByY = line.getPointByY(targetY); + expect(pointByY.x).toBeCloseTo(targetY); + }); + describe('ERROR', () => { + it("throw new error when did'nt send slope and n", () => { + const line = new Line(); + expect(() => line.getPointByY(3)).toThrow("must to send slope and n") + }) + it("throw new error when did'nt send slope", () => { + const line = new Line({ n: 2 }); + expect(() => line.getPointByY(3)).toThrow("must to send slope") + }) + it("throw new error when did'nt send n", () => { + const line = new Line({ slope: 2 }); + expect(() => line.getPointByY(3)).toThrow("must to send n") + }) + it("throw new error when type of y did'nt number", () => { + const line = new Line({ slope: 2 }); + expect(() => line.getPointByY(true)).toThrow("type must be number") + expect(() => line.getPointByY(() => { })).toThrow("type must be number") + expect(() => line.getPointByY({ x: 4 })).toThrow("type must be number") + expect(() => line.getPointByY("string")).toThrow("type must be number") + expect(() => line.getPointByY([3, 2])).toThrow("type must be number") + }) + }) +}); \ No newline at end of file diff --git a/tests/modules/ecs6-class/point.test.js b/tests/modules/ecs6-class/point.test.js new file mode 100644 index 0000000..32cc6f0 --- /dev/null +++ b/tests/modules/ecs6-class/point.test.js @@ -0,0 +1,65 @@ +const Point = require('./../../../modules/ecs6-class/point'); +const point = new Point(); +describe('Point constructor', () => { + it('should set the correct x and y values when an object with specific values is passed', () => { + const point = new Point({ x: 10, y: 20 }); + expect(point.x).toBe(10); + expect(point.y).toBe(20); + }); + + it('should set default values to x=0 and y=0 when no parameters are provided', () => { + expect(point.x).toBe(0); + expect(point.y).toBe(0); + }); + describe('ERRORS', () => { + it('should throw error when the x is invalid', () => { + expect(() => point = new Point({ x: "string", y: 0 })).toThrow('the x is invalid') + expect(() => point = new Point({ x: { "object": 9 }, y: 0 })).toThrow('the x is invalid') + expect(() => point = new Point({ x: true, y: 0 })).toThrow('the x is invalid') + expect(() => point = new Point({ x: ["array", 9], y: 0 })).toThrow('the x is invalid') + expect(() => point = new Point({ x: function () { }, y: 0 })).toThrow('the x is invalid') + }) + it('should throw error when the y is invalid', () => { + expect(() => point = new Point({ x: 1, y: "string" })).toThrow('the y is invalid') + expect(() => point = new Point({ x: 1, y: { "object": 9 } })).toThrow('the y is invalid') + expect(() => point = new Point({ x: 1, y: true })).toThrow('the y is invalid') + expect(() => point = new Point({ x: 1, y: ["array", 9] })).toThrow('the y is invalid') + expect(() => point = new Point({ x: 1, y: function () { } })).toThrow('the y is invalid') + }) + }) + +}); +describe('Point moveVertical method', () => { + it('should correctly move the y coordinate by the given value', () => { + point.moveVertical(5); + expect(point.y).toBe(5); + }); + describe('ERRORS', () => { + it('should throw new error when the incoming value is not a number', () => { + expect(() => point.moveVertical("string")).toThrow("the value is not type of number") + expect(() => point.moveVertical({ "object": 5 })).toThrow("the value is not type of number") + expect(() => point.moveVertical(true)).toThrow("the value is not type of number") + expect(() => point.moveVertical(function () { })).toThrow("the value is not type of number") + expect(() => point.moveVertical([9, 9])).toThrow("the value is not type of number") + expect(() => point.moveVertical()).toThrow("the value is not type of number") + }) + }) +}) + + +describe('Point moveHorizontal method', () => { + it('should correctly move the x coordinate by the given value', () => { + point.moveHorizontal(3); + expect(point.x).toBe(3); + }); + describe('ERRORS', () => { + it('should throw new error when the incoming value is not a number', () => { + expect(() => point.moveHorizontal("string")).toThrow("the value is not type of number") + expect(() => point.moveHorizontal({ "object": 5 })).toThrow("the value is not type of number") + expect(() => point.moveHorizontal(true)).toThrow("the value is not type of number") + expect(() => point.moveHorizontal(function () { })).toThrow("the value is not type of number") + expect(() => point.moveHorizontal([4, 9])).toThrow("the value is not type of number") + expect(() => point.moveHorizontal([4, 9])).toThrow("the value is not type of number") + }) + }) +}); \ No newline at end of file diff --git a/tests/modules/geometry-calculation.test.js b/tests/modules/geometry-calculation.test.js new file mode 100644 index 0000000..5a17a76 --- /dev/null +++ b/tests/modules/geometry-calculation.test.js @@ -0,0 +1,108 @@ +const Line = require('./../../modules/ecs6-class/line'); +const Point = require("../../modules/ecs6-class/point") +const { calculateDistance, calculateJunctionPoint, isPointOnLine } = require('./../../modules/geometry-calculation') + +describe('calculateDistance function', () => { + + it('should calculate the distance correctly between two points', () => { + const point1 = new Point({ x: 1, y: 1 }); + const point2 = new Point({ x: 4, y: 5 }); + const expectedDistance = 3; + const result = calculateDistance(point1, point2); + expect(result).toBeCloseTo(3); + }); + describe('Error', () => { + it("throw new error when point1 not instance of Point", () => { + const point1 = ({ x: 1, y: 1 }); + const point2 = new Point({ x: 4, y: 5 }); + const expectedDistance = 3; + expect(() => calculateDistance(point1, point2)).toThrow("the type of point1 or type of point2 is not 'Point'"); + }) + }) +}); +describe('calculateJunctionPoint function', () => { + it('should correctly calculate the junction point between two lines if they intersect', () => { + const line1 = new Line({ point1: new Point({ x: 1, y: 2 }), point2: new Point({ x: 3, y: 4 }) }); + const line2 = new Line({ point1: new Point({ x: 2, y: 1 }), point2: new Point({ x: 4, y: 3 }) }); + const expectedJunctionPoint = true; + const result = calculateJunctionPoint(line1, line2); + expect(result).toEqual(expectedJunctionPoint); + }); + + it('should return true if the lines are parallel and have the same intersection point', () => { + const line1 = new Line({ point1: new Point({ x: 1, y: 2 }), point2: new Point({ x: 3, y: 4 }) }); + const line2 = new Line({ point1: new Point({ x: 2, y: 1 }), point2: new Point({ x: 4, y: 3 }) }); + const result = calculateJunctionPoint(line1, line2); + expect(result).toBeTruthy(); + }); + it("should return false when the point1.slope equal to point2.slope end point1.n not equal to point2.n", () => { + const line1 = new Line({ point1: new Point({ x: 1, y: 2 }), point2: new Point({ x: 3, y: 4 }), n: 3, slope: 3 }); + const line2 = new Line({ point1: new Point({ x: 2, y: 1 }), point2: new Point({ x: 4, y: 3 }), n: 2, slope: 3 }); + const result = calculateJunctionPoint(line1, line2); + expect(result).toBeFalsy(); + }) + it("should return junctionPoint when the line1.slope not equal line2,slope", () => { + const line1 = new Line({ point1: new Point({ x: 1, y: 2 }), point2: new Point({ x: 3, y: 4 }), n: 3, slope: 4 }); + const line2 = new Line({ point1: new Point({ x: 2, y: 1 }), point2: new Point({ x: 4, y: 3 }), n: 3, slope: 3 }); + const result = calculateJunctionPoint(line1, line2); + expect(result).toEqual({ x: -0, y: 3 }) + + }) + describe('Error', () => { + it("throw new error when line1 not instance of Line", () => { + const line1 = ({ point1: new Point({ x: 1, y: 2 }), point2: new Point({ x: 3, y: 4 }), n: 3, slope: 4 }); + const line2 = new Line({ point1: new Point({ x: 2, y: 1 }), point2: new Point({ x: 4, y: 3 }), n: 3, slope: 3 }); + expect(() => calculateJunctionPoint(line1, line2)).toThrow("the value that received for line1 is not on type of line"); + + }) + it("throw new error when line1 not instance of Line", () => { + const line1 = new Line({ point1: new Point({ x: 1, y: 2 }), point2: new Point({ x: 3, y: 4 }), n: 3, slope: 4 }); + const line2 = ({ point1: new Point({ x: 2, y: 1 }), point2: new Point({ x: 4, y: 3 }), n: 3, slope: 3 }); + expect(() => calculateJunctionPoint(line1, line2)).toThrow("the value that received for line2 is not on type of line"); + + }) + + + + }) +}); + +describe('isPointOnLine function', () => { + it('should return true if the point lies on the line', () => { + const line = new Line({ point1: new Point({ x: 1, y: 1 }), point2: new Point({ x: 3, y: 3 }) }); + const point = new Point({ x: 2, y: 2 }); + const result = isPointOnLine(line, point); + console.log(result, "result"); + expect(result).toBeFalsy(); + }); + it('should return false if the point does not lie on the line', () => { + const line = new Line({ point1: new Point({ x: 1, y: 1 }), point2: new Point({ x: 3, y: 3 }) }); + const point = new Point({ x: 4, y: 4 }); + const result = isPointOnLine(line, point); + expect(result).toBeFalsy(); + }); + it("should calculateNOfLineFunction if line.slope equal proxyLine.slope", () => { + const point = new Point({ x: 4, y: 4 }); + const line = new Line({ point1: new Point({ x: 1, y: 1 }), point2: new Point({ x: 3, y: 3 }) }); + const result = isPointOnLine(line, point); + expect(result).toBeFalsy(); + }) + it("should return true if line.n equal to proxyLine.n", () => { + const point = new Point({ x: 4, y: 4 }); + const line = new Line({ point1: new Point({ x: 1, y: 1 }), point2: new Point({ x: 3, y: 3 }), slope: 1, n: 0 }); + const result = isPointOnLine(line, point); + expect(result).toBeTruthy() + }) +describe('Error',()=>{ + it("throw new error when line not instance of Line",()=>{ + const point = new Point({ x: 4, y: 4 }); + const line = ({ point1: new Point({ x: 1, y: 1 }), point2: new Point({ x: 3, y: 3 }), slope: 1, n: 0 }); + expect(()=>isPointOnLine(line, point)).toThrow("the value that received for line is not on type of line") + }) + it("throw new error when point not instance of Point",()=>{ + const point = ({ x: 4, y: 4 }); + const line = new Line({ point1: new Point({ x: 1, y: 1 }), point2: new Point({ x: 3, y: 3 }), slope: 1, n: 0 }); + expect(()=>isPointOnLine(line, point)).toThrow("the value that received for point is not on type of point") + }) +}) +}); \ No newline at end of file