From 470e4ccab61267beba7e6a6303f7c6efd58848e2 Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sat, 23 Jul 2022 17:00:48 +0200 Subject: [PATCH] chore(core): Working on test coverage --- packages/core/.nycrc.yaml | 1 + packages/core/src/point.js | 6 +- packages/core/src/utils.js | 2 +- packages/core/tests/attributes.test.js | 18 ++ packages/core/tests/design.test.js | 52 +++++ packages/core/tests/fixtures/render.js | 27 +++ packages/core/tests/point.test.js | 272 +++++++++++++++++++++++++ packages/core/tests/svg.test.js | 17 +- packages/core/tests/utils.test.js | 65 ++++++ 9 files changed, 456 insertions(+), 4 deletions(-) diff --git a/packages/core/.nycrc.yaml b/packages/core/.nycrc.yaml index 8e787be9169..f0a22b9c13f 100644 --- a/packages/core/.nycrc.yaml +++ b/packages/core/.nycrc.yaml @@ -1,4 +1,5 @@ exclude: - tests/fixtures + - tests - bin-pack diff --git a/packages/core/src/point.js b/packages/core/src/point.js index 9830e4349e0..7a138962bcf 100644 --- a/packages/core/src/point.js +++ b/packages/core/src/point.js @@ -85,12 +85,12 @@ Point.prototype.angle = function (that) { /** Rotate this point deg around that point */ Point.prototype.rotate = function (deg, that) { - this.check() - that.check() if (typeof deg !== 'number') this.raise.warning('Called `Point.rotate(deg,that)` but `deg` is not a number') if (that instanceof Point !== true) this.raise.warning('Called `Point.rotate(deg,that)` but `that` is not a `Point` object') + this.check() + that.check() let radius = this.dist(that) let angle = this.angle(that) let x = that.x + radius * Math.cos(this.deg2rad(angle + deg)) * -1 @@ -135,6 +135,8 @@ Point.prototype.flipY = function (that = false) { /** Shifts this point distance in the deg direction */ Point.prototype.shift = function (deg, distance) { this.check() + if (typeof deg !== 'number') + this.raise.warning('Called `Point.shift` but `deg` is not a number') if (typeof distance !== 'number') this.raise.warning('Called `Point.shift` but `distance` is not a number') let p = this.copy() diff --git a/packages/core/src/utils.js b/packages/core/src/utils.js index 41a2f2f2356..edc9ea06ffb 100644 --- a/packages/core/src/utils.js +++ b/packages/core/src/utils.js @@ -356,7 +356,7 @@ export { Bezier } export function pctBasedOn(measurement) { return { toAbs: (val, { measurements }) => measurements[measurement] * val, - fromAbs: (val, { measurements }) => Math.round((10 * val) / measurements[measurement]) / 10, + fromAbs: (val, { measurements }) => Math.round((10000 * val) / measurements[measurement]) / 10000, } } diff --git a/packages/core/tests/attributes.test.js b/packages/core/tests/attributes.test.js index ff8f74ffc0f..8d84e1aa591 100644 --- a/packages/core/tests/attributes.test.js +++ b/packages/core/tests/attributes.test.js @@ -61,3 +61,21 @@ it("Should render attributes as CSS", () => { .add("border", "1px solid red"); expect(a.renderAsCss()).to.equal(" line-height:1.2; border:1px solid red;"); }); + +it("Should return attributes as props and filter a prefix", () => { + const a = newAttr() + .set("line-height", 1.2) + .add("border", "1px solid red") + .set("data-text", "This is a test") + .set("data-text-class", "center"); + const props = a.asPropsIfPrefixIs('data-') + expect(props.text).to.equal("This is a test"); + expect(props['text-class']).to.equal("center"); +}); + +it("Should return attributes as props and handle special class case", () => { + const a = newAttr().set("class", "fabric"); + const props = a.asPropsIfPrefixIs('') + expect(props.className).to.equal("fabric"); +}); + diff --git a/packages/core/tests/design.test.js b/packages/core/tests/design.test.js index c4981369ab9..e367c5972ab 100644 --- a/packages/core/tests/design.test.js +++ b/packages/core/tests/design.test.js @@ -62,6 +62,58 @@ it("Design constructor should load array of plugins", () => { expect(pattern.hooks.preRender.length).to.equal(2); }); +it("Design constructor should load conditional plugin", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); + } + } + }; + const condition = () => true + const design = new freesewing.Design({}, [], { plugin, condition }); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(1); +}); + +it("Design constructor should not load conditional plugin", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); + } + } + }; + const condition = () => false + const design = new freesewing.Design({}, [], { plugin, condition }); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(0); +}); + +it("Design constructor should load multiple conditional plugins", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); + } + } + }; + const condition1 = () => true + const condition2 = () => false + const design = new freesewing.Design({}, [], [ + { plugin, condition: condition1 }, + { plugin, condition: condition2 }, + ]); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(1); +}); + it("Design constructor should construct basic part order", () => { let design = new freesewing.Design({ dependencies: { step4: "step3" }, diff --git a/packages/core/tests/fixtures/render.js b/packages/core/tests/fixtures/render.js index 4835f3b5470..c15a5db711b 100644 --- a/packages/core/tests/fixtures/render.js +++ b/packages/core/tests/fixtures/render.js @@ -333,6 +333,33 @@ var render = { +`, + rotatedSnippet: ` + + + + + + + + + + + + + + + + + ` } diff --git a/packages/core/tests/point.test.js b/packages/core/tests/point.test.js index 402e8f9daa0..f06e002873d 100644 --- a/packages/core/tests/point.test.js +++ b/packages/core/tests/point.test.js @@ -225,3 +225,275 @@ it("Should translate a point", () => { expect(p2.x).to.equal(25); expect(p2.y).to.equal(70); }); + +it("Should add raise methods to a point", () => { + const raise = () => 'hello' + const p1 = new Point(10, 20).withRaise(raise); + expect(p1.raise()).to.equal('hello'); +}); + +it("Should raise a warning on invalid point coordinates", () => { + const invalid = { x: false, y: false } + const raiseX = { warning: () => invalid.x = true } + const raiseY = { warning: () => invalid.y = true } + const p1 = new Point('a',10).withRaise(raiseX); + const p2 = new Point(20, 'b').withRaise(raiseY); + expect(invalid.x).to.equal(false); + expect(invalid.y).to.equal(false); + p1.check() + p2.check() + expect(invalid.x).to.equal(true); + expect(invalid.y).to.equal(true); +}); + +it("Should raise a warning if rotation is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20, 20).withRaise(raise); + expect(invalid).to.equal(false); + const p3 = p1.rotate('a', p2) + expect(invalid).to.equal(true); +}); + +it("Should raise a warning if rotating around what is not a point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20, 20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.rotate(45, 'a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when flipX'ing around what is not a point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20, 20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.flipX('a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when flipY'ing around what is not a point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20, 20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.flipY('a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting with a distance that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shift(0, 'a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting with an angle that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shift('a', 12) + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting towards with a distance that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20,20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shiftTowards(p2, 'a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting towards with a target that is not a point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20,20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shiftTowards('a', 10) + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting fraction towards with a distance that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20,20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shiftFractionTowards(p2, 'a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting a fraction towards with a target that is not a point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20,20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shiftFractionTowards('a', 0.1) + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting outowards with a distance that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20,20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shiftOutwards(p2, 'a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when shifting a outowards with a target that is not a point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + const p2 = new Point(20,20).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.shiftOutwards('a', 0.1) + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when translating with an X-delta that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.translate('a', 10) + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when translating with an Y-delta that is not a number", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.translate(10, 'a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when sitsOn receives a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.sitsOn('a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when sitsRoughlyOn receives a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new Point(10,10).withRaise(raise); + expect(invalid).to.equal(false); + try { + p1.sitsRoughlyOn('a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should set the data-text property in a chainable way", () => { + const p1 = new Point(10,10).setText('hello') + expect(p1.attributes.get('data-text')).to.equal('hello'); +}); + +it("Should set the data-text-class property in a chainable way", () => { + const p1 = new Point(10,10).setText('hello', 'fabric') + expect(p1.attributes.get('data-text')).to.equal('hello'); + expect(p1.attributes.get('data-text-class')).to.equal('fabric'); +}); + +it("Should set the data-circle property in a chainable way", () => { + const p1 = new Point(10,10).setCircle('20') + expect(p1.attributes.get('data-circle')).to.equal('20'); +}); + +it("Should set the data-circle-class property in a chainable way", () => { + const p1 = new Point(10,10).setCircle('20', 'fabric') + expect(p1.attributes.get('data-circle')).to.equal('20'); + expect(p1.attributes.get('data-circle-class')).to.equal('fabric'); +}); + diff --git a/packages/core/tests/svg.test.js b/packages/core/tests/svg.test.js index 7da10148ce2..8c8f77acc67 100644 --- a/packages/core/tests/svg.test.js +++ b/packages/core/tests/svg.test.js @@ -203,6 +203,19 @@ it("Should render an Svg snippet", () => { expect(pattern.render()).to.equalIgnoreSpaces(render.snippet); }); +it("Should render a rotated Svg snippet", () => { + let pattern = new freesewing.Pattern(); + pattern.render(); + pattern.parts.test = new pattern.Part(); + let p = pattern.parts.test; + p.snippets.test = new p.Snippet( + "test", + new p.Point(20, 20), + "This is a snippet" + ).attr('data-rotate', 90) + expect(pattern.render()).to.equalIgnoreSpaces(render.rotatedSnippet); +}); + it("Should replaced double quotes in Svg text", () => { const pattern = new freesewing.Pattern() pattern.render() @@ -247,9 +260,11 @@ it("Should run insertText hook", () => { }); it("Should run postRender hook", () => { - let pattern = new freesewing.Pattern(); + let pattern = new freesewing.Pattern() pattern.on("postRender", svg => { svg.svg = "test"; }); expect(pattern.render()).to.equal("test"); }); + + diff --git a/packages/core/tests/utils.test.js b/packages/core/tests/utils.test.js index db4f3436bca..ebbf8b13d10 100644 --- a/packages/core/tests/utils.test.js +++ b/packages/core/tests/utils.test.js @@ -499,3 +499,68 @@ it("Should find intersecting beams when a line is almost vertical", () => { expect(round(i.y)).to.equal(400); }); +it("Should check for valid coordinate", () => { + expect(utils.isCoord(23423.23)).to.equal(true); + expect(utils.isCoord(0)).to.equal(true); + expect(utils.isCoord()).to.equal(false); + expect(utils.isCoord(null)).to.equal(false); + expect(utils.isCoord('hi')).to.equal(false); + expect(utils.isCoord(NaN)).to.equal(false); +}); + +it("Should return the correct sample style", () => { + expect(utils.sampleStyle(0, 5)).to.equal("stroke: hsl(-66, 100%, 35%);") + expect(utils.sampleStyle(1, 5)).to.equal("stroke: hsl(0, 100%, 35%);") + expect(utils.sampleStyle(2, 5)).to.equal("stroke: hsl(66, 100%, 35%);") + expect(utils.sampleStyle(3, 5)).to.equal("stroke: hsl(132, 100%, 35%);") + expect(utils.sampleStyle(4, 5)).to.equal("stroke: hsl(198, 100%, 35%);") +}); + +it("Should return the correct sample styles", () => { + const styles = [ + "stroke: red;", + "stroke: blue;", + "stroke: green;", + "stroke: pink;", + "stroke: orange;", + ] + for (let i=0;i<5;i++) expect(utils.sampleStyle(i, 5, styles)).to.equal(styles[i]) +}); + +it("Should convert degrees to radians", () => { + expect(utils.deg2rad(0)).to.equal(0); + expect(round(utils.deg2rad(69))).to.equal(1.2); +}); + +it("Should convert radians to degrees", () => { + expect(utils.rad2deg(0)).to.equal(0); + expect(round(utils.rad2deg(69))).to.equal(3953.41); +}); + +it("Should shoulder return two methods for pctBasedOn", () => { + const result = utils.pctBasedOn('chest') + expect(typeof result.toAbs).to.equal("function"); + expect(typeof result.fromAbs).to.equal("function"); + const measurements = { chest: 1000 } + expect(result.toAbs(0.0123, { measurements })).to.equal(12.3) + expect(result.fromAbs(12.3, { measurements })).to.equal(0.0123) + +}); + +it("Should generate a part transform", () => { + let pattern = new freesewing.Pattern(); + pattern.settings.mode = "draft"; + let part = new pattern.Part(); + let short = part.shorthand(); + part.points.from = new short.Point(2, 2); + part.points.to = new short.Point(19, 76); + part.paths.test = new short.Path() + .move(part.points.from) + .line(part.points.to); + part.stack(); + const transform = utils.generatePartTransform(30,60,90,true,true,part) + expect(transform.transform).to.equal("translate(30,60) scale(-1, 1) scale(1, -1) rotate(90)"); + expect(transform['transform-origin']).to.equal("10.5 39") +}); + +