From 785c03d01362f034f0f11410476f4e2644eb02ae Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sat, 23 Jul 2022 17:00:48 +0200 Subject: [PATCH 1/5] 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") +}); + + From a357c2e6420742290a1496d2b34571933550c621 Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sat, 23 Jul 2022 20:21:16 +0200 Subject: [PATCH 2/5] chore(core): Tests for path --- config/scripts.yaml | 2 +- packages/core/package.json | 2 +- packages/core/src/path.js | 3 +- packages/core/tests/path.test.js | 362 +++++++++++++++++++++++++++++++ 4 files changed, 365 insertions(+), 4 deletions(-) diff --git a/config/scripts.yaml b/config/scripts.yaml index e6492df9797..7ff69749c2d 100644 --- a/config/scripts.yaml +++ b/config/scripts.yaml @@ -25,7 +25,7 @@ components: test: *notests core: report: 'nyc report --reporter=html' - test: 'nyc -x node_modules -x tests/fixtures -x bin-pack npx mocha tests/*.test.js' + test: 'nyc -x node_modules -x tests -x bin-pack npx mocha tests/*.test.js' testci: "nyc --silent npx mocha tests/*.test.js --reporter ../../tests/reporters/terse.js && nyc report --reporter=json" testonly: 'npx mocha tests/*.test.js' i18n: diff --git a/packages/core/package.json b/packages/core/package.json index 89fd1a6d735..8fedebc13ec 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -32,7 +32,7 @@ "clean": "rimraf dist", "mbuild": "NO_MINIFY=1 node build.js", "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", - "test": "nyc -x node_modules -x tests/fixtures -x bin-pack npx mocha tests/*.test.js", + "test": "nyc -x node_modules -x tests -x bin-pack npx mocha tests/*.test.js", "vbuild": "VERBOSE=1 node build.js", "lab": "cd ../../sites/lab && yarn start", "tips": "node ../../scripts/help.mjs", diff --git a/packages/core/src/path.js b/packages/core/src/path.js index 710fa01f2fe..3ae6b21ac91 100644 --- a/packages/core/src/path.js +++ b/packages/core/src/path.js @@ -90,7 +90,7 @@ Path.prototype.curve_ = function (cp1, to) { if (to instanceof Point !== true) this.raise.warning('Called `Path.curve_(cp1, to)` but `to` is not a `Point` object') if (cp1 instanceof Point !== true) - this.raise.warning('Called `Path.curve_(cp1, to)` but `cp2` is not a `Point` object') + this.raise.warning('Called `Path.curve_(cp1, to)` but `cp1` is not a `Point` object') let cp2 = to.copy() this.ops.push({ type: 'curve', cp1, cp2, to }) @@ -599,7 +599,6 @@ Path.prototype.edge = function (side) { return curveEdge(curve, side) } } - this.raise.error(`Unable to find \`Path.edge(side)\` for side ${side}`) } function edgeCurveAsBezier(op) { diff --git a/packages/core/tests/path.test.js b/packages/core/tests/path.test.js index 8a9bae20b31..920acf409ef 100644 --- a/packages/core/tests/path.test.js +++ b/packages/core/tests/path.test.js @@ -183,6 +183,15 @@ it("Should shift along a line", () => { expect(a.paths.line.shiftAlong(20).y).to.equal(20); }); +it("Should not shift along a path/line if we end up on the end point", () => { + let pattern = new freesewing.Pattern(); + pattern.parts.a = new pattern.Part(); + let a = pattern.parts.a; + + a.paths.line = new a.Path().move(new a.Point(0, 0)).line(new a.Point(10, 0)); + expect(a.paths.line.shiftAlong(10).x).to.equal(10); +}); + it("Should shift along lines", () => { let pattern = new freesewing.Pattern(); pattern.parts.a = new pattern.Part(); @@ -796,3 +805,356 @@ it("Should move along a path even if it lands just on a joint", () => { a.points.test = a.paths.curve.shiftAlong(121.36690836797631) expect(a.points.test).to.be.instanceOf(a.Point) }) + +it("Should add raise methods to a path", () => { + const raise = () => 'hello' + const p1 = new freesewing.Path(10, 20).withRaise(raise); + expect(p1.raise()).to.equal('hello'); +}); + +it("Should add raise methods to a path", () => { + const raise = () => 'hello' + const p1 = new freesewing.Path().withRaise(raise); + expect(p1.raise()).to.equal('hello'); +}); + +it("Should set render to true/false", () => { + const p1 = new freesewing.Path().setRender(false) + expect(p1.render).to.equal(false); +}); + +it("Should set class with setClass", () => { + const p1 = new freesewing.Path().setClass('fabric') + p1.setClass() + expect(p1.attributes.get('class')).to.equal('fabric'); +}); + +it("Should raise a warning when moving to a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + expect(invalid).to.equal(false); + try { + p1.move('a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a line to a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + expect(invalid).to.equal(false); + try { + p1.line('a') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a curve to a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const a = new freesewing.Point(0,0) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b).curve(a, b, 'c') + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a curve with a Cp1 that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const a = new freesewing.Point(0,0) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b).curve(a, 'x', b) + } + catch (err) { + expect(''+err).to.contain("check is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a curve with a Cp1 that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b).curve('a', b, b) + } + catch (err) { + expect(''+err).to.contain("copy is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a curve with a Cp2 that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b).curve(b, 'a', b) + } + catch (err) { + expect(''+err).to.contain("copy is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a _curve with a To that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b)._curve(b, 'a') + } + catch (err) { + expect(''+err).to.contain("copy is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a _curve with a Cp2 that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b)._curve('a', b) + } + catch (err) { + expect(''+err).to.contain("copy is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a curve_ with a To that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b).curve_(b, 'a') + } + catch (err) { + expect(''+err).to.contain("copy is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when drawing a curve_ with a Cp2 that is a non-point", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const p1 = new freesewing.Path().withRaise(raise) + const b = new freesewing.Point(10,10) + expect(invalid).to.equal(false); + try { + p1.move(b).curve_('a', b) + } + catch (err) { + expect(''+err).to.contain("copy is not a function") + } + expect(invalid).to.equal(true); +}); + +it("Should add a noop operation", () => { + const p1 = new freesewing.Path().noop() + expect(p1.ops.length).to.equal(1); + expect(p1.ops[0].type).to.equal('noop'); +}); + +it("Should handle an insop operation", () => { + const a = new freesewing.Point(0,0) + const b = new freesewing.Point(10,10) + const p1 = new freesewing.Path().move(a).line(b) + const p2 = new freesewing.Path().noop('test').insop('test', p1) + expect(p2.ops.length).to.equal(2); + expect(p1.ops[0].type).to.equal('move'); + expect(p1.ops[1].type).to.equal('line'); +}); + +it("Should raise a warning when an insop operation used an falsy ID", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const a = new freesewing.Point(0,0) + const b = new freesewing.Point(10,10) + const p1 = new freesewing.Path().move(a).line(b) + expect(invalid).to.equal(false); + const p2 = new freesewing.Path().withRaise(raise).noop('test').insop(false, p1) + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when an insop operation used an falsy ID", () => { + let invalid = false + const raise = { warning: () => invalid = true } + const a = new freesewing.Point(0,0) + const b = new freesewing.Point(10,10) + const p1 = new freesewing.Path().move(a).line(b) + expect(invalid).to.equal(false); + try { + new freesewing.Path().withRaise(raise).noop('test').insop('test') + } + catch (err) { + expect(''+err).to.contain("Cannot read property 'ops") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when setting an attribute without a name", () => { + let invalid = false + const raise = { warning: () => invalid = true } + expect(invalid).to.equal(false); + const p1 = new freesewing.Path().withRaise(raise).attr() + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when setting an attribute without a value", () => { + let invalid = false + const raise = { warning: () => invalid = true } + expect(invalid).to.equal(false); + const p1 = new freesewing.Path().withRaise(raise).attr('test') + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when calling offset without a distance", () => { + const pattern = new freesewing.Pattern(); + pattern.parts.a = new pattern.Part(); + const { Path, Point, points, paths } = pattern.parts.a.shorthand() + points.a = new Point(0,0) + points.b = new Point(10,10) + paths.a = new Path().move(points.a).line(points.b) + paths.b = paths.a.offset() + expect(pattern.events.error.length).to.equal(1) + expect(pattern.events.error[0]).to.equal("Called `Path.offset(distance)` but `distance` is not a number") +}); + +it("Should raise a warning when calling join without a path", () => { + const pattern = new freesewing.Pattern(); + pattern.parts.a = new pattern.Part(); + const { Path, Point, points, paths } = pattern.parts.a.shorthand() + points.a = new Point(0,0) + points.b = new Point(10,10) + try { + paths.a = new Path().move(points.a).line(points.b).join() + } + catch (err) { + expect(''+err).to.contain("Cannot read property 'ops") + } + expect(pattern.events.error.length).to.equal(1) + expect(pattern.events.error[0]).to.equal("Called `Path.join(that)` but `that` is not a `Path` object") +}); + +it("Should raise a warning when calling start on a path without drawing operations", () => { + let invalid = false + const raise = { error: () => invalid = true } + expect(invalid).to.equal(false); + try { + new freesewing.Path().withRaise(raise).start() + } + catch (err) { + expect(''+err).to.contain("TypeError: Cannot read property") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when calling end on a path without drawing operations", () => { + let invalid = false + const raise = { error: () => invalid = true } + expect(invalid).to.equal(false); + try { + new freesewing.Path().withRaise(raise).end() + } + catch (err) { + expect(''+err).to.contain("TypeError: Cannot read property") + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when calling shiftAlong but distance is not a number", () => { + let invalid = false + const raise = { error: () => invalid = true } + expect(invalid).to.equal(false); + new freesewing.Path() + .withRaise(raise) + .move(new freesewing.Point(0,0)) + .line(new freesewing.Point(10,10)) + .shiftAlong() + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when calling shiftFractionalong but fraction is not a number", () => { + let invalid = false + const raise = { error: () => invalid = true } + expect(invalid).to.equal(false); + new freesewing.Path() + .withRaise(raise) + .move(new freesewing.Point(0,0)) + .line(new freesewing.Point(10,10)) + .shiftFractionAlong() + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when splitting a path on a non-point", () => { + let invalid = false + const raise = { error: () => invalid = true } + const from = new freesewing.Point(0,0).withRaise(raise) + const cp1 = new freesewing.Point(10,0).withRaise(raise) + const cp2 = new freesewing.Point(90,0).withRaise(raise) + const to = new freesewing.Point(100,0).withRaise(raise) + const path = new freesewing.Path() + .withRaise(raise) + .move(from) + .curve(cp1, cp2, to) + .line(from) + try { + path.split() + } + catch (err) { + console.log(err) + } + expect(invalid).to.equal(true); +}); + +it("Should raise a warning when splitting a path on a non-point", () => { + let invalid = false + const raise = { error: () => invalid = true } + const from = new freesewing.Point(0,0).withRaise(raise) + const cp1 = new freesewing.Point(10,0).withRaise(raise) + const cp2 = new freesewing.Point(90,0).withRaise(raise) + const to = new freesewing.Point(100,0).withRaise(raise) + const path = new freesewing.Path() + .withRaise(raise) + .move(from) + .curve(cp1, cp2, to) + .line(from) + try { + path.split() + } + catch (err) { + console.log(err) + } + expect(invalid).to.equal(true); +}); + From 293c6bec09ec864000dddade8f1a576d88809d37 Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sun, 24 Jul 2022 21:34:22 +0200 Subject: [PATCH 3/5] chore(core): Adding unit tests --- packages/core/src/part.js | 2 - packages/core/tests/part.test.js | 81 ++++++++++++++++++++++------- packages/core/tests/path.test.js | 26 ++++++--- packages/core/tests/pattern.test.js | 1 + 4 files changed, 82 insertions(+), 28 deletions(-) diff --git a/packages/core/src/part.js b/packages/core/src/part.js index 7a7829964d1..34698bf250a 100644 --- a/packages/core/src/part.js +++ b/packages/core/src/part.js @@ -147,8 +147,6 @@ Part.prototype.inject = function (orig) { for (let i in orig.points) { if (orig.points[i] === p) return i } - - return false } for (let i in orig.points) this.points[i] = orig.points[i].clone() diff --git a/packages/core/tests/part.test.js b/packages/core/tests/part.test.js index 68da7bd8f93..a0b67408024 100644 --- a/packages/core/tests/part.test.js +++ b/packages/core/tests/part.test.js @@ -82,11 +82,27 @@ it("Should set part attributes", () => { it("Should inject a part", () => { let pattern = new freesewing.Pattern(); let part = new pattern.Part(); - part.points.foo = new part.Point(12, 23); + part.points.a = new part.Point(12, 23); + part.points.b = new part.Point(10, 10); + part.points.c = new part.Point(20, 20); + part.paths.bar = new freesewing.Path() + .move(part.points.a) + .line(part.points.b) + .curve(part.points.c, part.points.b, part.points.a) + const { Snippet, snippets } = part.shorthand() + snippets.d = new Snippet('notch', part.points.a) let test = new pattern.Part(); test.inject(part); - expect(test.points.foo.x).to.equal(12); - expect(test.points.foo.y).to.equal(23); + expect(test.points.a.x).to.equal(12); + expect(test.points.a.y).to.equal(23); + expect(test.paths.bar.ops.length).to.equal(3) + for (let i=0;i<3;i++) { + expect(test.paths.bar.ops[i].type).to.equal(part.paths.bar.ops[i].type) + expect(test.paths.bar.ops[i].to.x).to.equal(part.paths.bar.ops[i].to.x) + expect(test.paths.bar.ops[i].to.y).to.equal(part.paths.bar.ops[i].to.y) + } + expect(test.snippets.d.anchor.x).to.equal(part.points.a.x) + expect(test.snippets.d.anchor.y).to.equal(part.points.a.y) }); it("Should return shorthand", () => { @@ -98,22 +114,31 @@ it("Should return shorthand", () => { expect(short.complete).to.equal(true); expect(short.paperless).to.equal(true); }); -/* -it("Should not allow a margin below 10 for paperless patterns", () => { - let pattern = new freesewing.Pattern(); - pattern.settings.paperless = true; - pattern.settings.margin = 2; - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.a = new pattern.Point(0,0); - a.points.b = new pattern.Point(0,100); - a.paths.a = new pattern.Path() - .move(a.points.a) - .line(a.points.b); - pattern.draft(); - expect(pattern.width).to.equal(120); + +it("Should raise a warning when setting a non-Point value in points", () => { + const pattern = new freesewing.Pattern(); + pattern.settings.mode = "draft"; + const part = new pattern.Part(); + const { points } = part.shorthand() + points.a = 'banana' + expect(pattern.events.warning.length).to.equal(3) + expect(pattern.events.warning[0]).to.equal('`points.a` was set with a value that is not a `Point` object') + expect(pattern.events.warning[1]).to.equal('`points.a` was set with a `x` parameter that is not a `number`') + expect(pattern.events.warning[2]).to.equal('`points.a` was set with a `y` parameter that is not a `number`') }); -*/ + +it("Should raise a warning when setting a non-Snippet value in snippets", () => { + const pattern = new freesewing.Pattern(); + pattern.settings.mode = "draft"; + const part = new pattern.Part(); + const { snippets } = part.shorthand() + snippets.a = 'banana' + expect(pattern.events.warning.length).to.equal(3) + expect(pattern.events.warning[0]).to.equal('`snippets.a` was set with a value that is not a `Snippet` object') + expect(pattern.events.warning[1]).to.equal('`snippets.a` was set with a `def` parameter that is not a `string`') + expect(pattern.events.warning[2]).to.equal('`snippets.a` was set with an `anchor` parameter that is not a `Point`') +}); + it("Should calculate the part boundary with default margin", () => { let pattern = new freesewing.Pattern(); pattern.settings.mode = "draft"; @@ -206,3 +231,23 @@ it("Should only stack a part if needed", () => { part.stack(); expect(part.attributes.get("transform")).to.equal(false); }); + +it("Should run hooks", () => { + let count = 0 + const pattern = new freesewing.Pattern() + const part = new pattern.Part(); + part.hooks.preDraft = [{ method: function(p) { count++ }} ] + part.runHooks('preDraft') + expect(count).to.equal(1); +}); + +it("Should get the units closure to raise a debug when passing a non-number", () => { + const pattern = new freesewing.Pattern(); + pattern.settings.mode = "draft"; + const part = new pattern.Part(); + const short = part.shorthand(); + short.units('a') + expect(pattern.events.debug.length).to.equal(1) + expect(pattern.events.debug[0]).to.equal('Calling `units(value)` but `value` is not a number (`string`)') +}); + diff --git a/packages/core/tests/path.test.js b/packages/core/tests/path.test.js index 920acf409ef..feeff9c2ce0 100644 --- a/packages/core/tests/path.test.js +++ b/packages/core/tests/path.test.js @@ -1106,19 +1106,26 @@ it("Should raise a warning when calling shiftAlong but distance is not a number" it("Should raise a warning when calling shiftFractionalong but fraction is not a number", () => { let invalid = false - const raise = { error: () => invalid = true } + const raise = { + error: () => invalid = true, + warning: () => invalid = true, + } expect(invalid).to.equal(false); new freesewing.Path() .withRaise(raise) - .move(new freesewing.Point(0,0)) - .line(new freesewing.Point(10,10)) + .move(new freesewing.Point(0,0).withRaise(raise)) + .line(new freesewing.Point(10,10).withRaise(raise)) + .line(new freesewing.Point(10,20).withRaise(raise)) .shiftFractionAlong() expect(invalid).to.equal(true); }); it("Should raise a warning when splitting a path on a non-point", () => { let invalid = false - const raise = { error: () => invalid = true } + const raise = { + error: () => invalid = true, + warning: () => invalid = true, + } const from = new freesewing.Point(0,0).withRaise(raise) const cp1 = new freesewing.Point(10,0).withRaise(raise) const cp2 = new freesewing.Point(90,0).withRaise(raise) @@ -1128,18 +1135,22 @@ it("Should raise a warning when splitting a path on a non-point", () => { .move(from) .curve(cp1, cp2, to) .line(from) + .line(cp1) try { path.split() } catch (err) { - console.log(err) + expect(''+err).to.contain("TypeError: Cannot read property") } expect(invalid).to.equal(true); }); it("Should raise a warning when splitting a path on a non-point", () => { let invalid = false - const raise = { error: () => invalid = true } + const raise = { + error: () => invalid = true, + warning: () => invalid = true, + } const from = new freesewing.Point(0,0).withRaise(raise) const cp1 = new freesewing.Point(10,0).withRaise(raise) const cp2 = new freesewing.Point(90,0).withRaise(raise) @@ -1153,8 +1164,7 @@ it("Should raise a warning when splitting a path on a non-point", () => { path.split() } catch (err) { - console.log(err) + expect(''+err).to.contain("TypeError: Cannot read property") } expect(invalid).to.equal(true); }); - diff --git a/packages/core/tests/pattern.test.js b/packages/core/tests/pattern.test.js index 2cba8f45a81..a9758104185 100644 --- a/packages/core/tests/pattern.test.js +++ b/packages/core/tests/pattern.test.js @@ -435,3 +435,4 @@ it("Should correctly merge settings for existing array", () => { expect(pattern.settings.only.length).to.equal(4); expect(pattern.settings.margin).to.equal(5); }); + From 1c87769e87c419f00a32fe779f138622d387385c Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sat, 30 Jul 2022 15:16:17 +0200 Subject: [PATCH 4/5] chore(core): Syntax change for better test coverage --- packages/core/src/pattern.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/pattern.js b/packages/core/src/pattern.js index 6ad0df971e2..7a353395e35 100644 --- a/packages/core/src/pattern.js +++ b/packages/core/src/pattern.js @@ -584,9 +584,9 @@ Pattern.prototype.resolveDependencies = function (graph = this.config.dependenci let dependency = this.config.inject[i] if (typeof this.config.dependencies[i] === 'undefined') this.config.dependencies[i] = dependency else if (this.config.dependencies[i] !== dependency) { - if (typeof this.config.dependencies[i] === 'string') + if (typeof this.config.dependencies[i] === 'string') { this.config.dependencies[i] = [this.config.dependencies[i], dependency] - else if (Array.isArray(this.config.dependencies[i])) { + } else if (Array.isArray(this.config.dependencies[i])) { if (this.config.dependencies[i].indexOf(dependency) === -1) this.config.dependencies[i].push(dependency) } else { From 62ebfa3b73aee08e12e099fca4d10340df5b91ad Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sat, 30 Jul 2022 16:53:07 +0200 Subject: [PATCH 5/5] chore(core): More unit tests --- packages/core/tests/part.test.js | 52 ++++++ packages/core/tests/pattern.test.js | 278 +++++++++++++++++++++++++++- packages/core/tests/point.test.js | 1 - packages/core/tests/utils.test.js | 1 - 4 files changed, 329 insertions(+), 3 deletions(-) diff --git a/packages/core/tests/part.test.js b/packages/core/tests/part.test.js index a0b67408024..b0bd0d5a049 100644 --- a/packages/core/tests/part.test.js +++ b/packages/core/tests/part.test.js @@ -251,3 +251,55 @@ it("Should get the units closure to raise a debug when passing a non-number", () expect(pattern.events.debug[0]).to.equal('Calling `units(value)` but `value` is not a number (`string`)') }); +it("Should generate the part transforms", () => { + 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(); + part.generateTransform({ + move: { + x: 10, + y: 20 + } + }) + expect(part.attributes.list.transform.length).to.equal(1) + expect(part.attributes.list.transform[0]).to.equal('translate(10,20)') + expect(part.attributes.list['transform-origin'][0]).to.equal('10.5 39') +}); + +it("Should set the part grain", () => { + let pattern = new freesewing.Pattern(); + pattern.settings.mode = "draft"; + let part = new pattern.Part(); + part.setGrain(666) + expect(part.attributes.list['data-grain'][0]).to.equal(666) + part.setGrain() + expect(part.attributes.list['data-grain'][0]).to.equal(90) +}); + +it("Should set the part cut", () => { + let pattern = new freesewing.Pattern(); + pattern.settings.mode = "draft"; + let part = new pattern.Part(); + const cut = { + count: 4, + mirror: false, + onFold: true + } + const dflt = { + count: 2, + mirror: true, + onFold: false + } + part.setCut(cut) + expect(JSON.stringify(part.attributes.list['data-cut'][0])).to.equal(JSON.stringify(cut)) + part.setCut() + expect(JSON.stringify(part.attributes.list['data-cut'][0])).to.equal(JSON.stringify(dflt)) +}); + diff --git a/packages/core/tests/pattern.test.js b/packages/core/tests/pattern.test.js index a9758104185..9dba8cc1b9f 100644 --- a/packages/core/tests/pattern.test.js +++ b/packages/core/tests/pattern.test.js @@ -139,7 +139,7 @@ it("Should throw an error if per-part draft method is missing", () => { it("Should sample an option", () => { let pattern = new freesewing.Pattern({ options: { - len: { pct: 30, min: 0, max: 100 }, + len: { pct: 30, min: 10 }, bonus: 10 } }); @@ -164,6 +164,122 @@ it("Should sample an option", () => { expect(pattern.parts.b.paths.test_10.ops[1].to.y).to.equal(10); }); +it("Should sample a list option", () => { + const Test = new freesewing.Design({ + name: "test", + parts: ['front'], + options: { + len: { + dflt: 1, + list: [1,2,3] + } + }, + }) + Test.prototype.draftFront = function(part) { + const { Point, points, Path, paths, options } = part.shorthand() + points.from = new Point(0, 0); + points.to = new Point( 100 * options.len, 0) + paths.line = new Path() + .move(points.from) + .line(points.to) + + return part + }; + const pattern = new Test({ + sample: { + type: 'option', + option: 'len' + } + }) + pattern.sample(); + expect(pattern.parts.front.paths.line_1.ops[1].to.x).to.equal(100); + expect(pattern.parts.front.paths.line_2.ops[1].to.x).to.equal(200); + expect(pattern.parts.front.paths.line_3.ops[1].to.x).to.equal(300); +}); + +it("Should sample a measurement", () => { + const Test = new freesewing.Design({ + name: "test", + parts: ['front'], + measurements: ['head'] + }) + Test.prototype.draftFront = function(part) { + const { Point, points, Path, paths, measurements } = part.shorthand() + points.from = new Point(0, 0); + points.to = new Point( measurements.head, 0) + paths.line = new Path() + .move(points.from) + .line(points.to) + + return part + }; + const pattern = new Test({ + measurements: { + head: 100 + }, + sample: { + type: 'measurement', + measurement: 'head' + } + }) + pattern.sample(); + expect(pattern.is).to.equal('sample') + expect(pattern.events.debug[0]).to.equal('Sampling measurement `head`') + for (let i=0;i<10;i++) { + const j = i + 1 + expect(pattern.parts.front.paths[`line_${j}`].ops[1].to.x).to.equal(90 + 2*i); + } + pattern.sampleMeasurement('nope') + expect(pattern.events.error.length).to.equal(1) + expect(pattern.events.error[0]).to.equal("Cannot sample measurement `nope` because it's `undefined`") +}); + +it("Should sample models", () => { + const Test = new freesewing.Design({ + name: "test", + parts: ['front'], + measurements: ['head'] + }) + Test.prototype.draftFront = function(part) { + const { Point, points, Path, paths, measurements } = part.shorthand() + points.from = new Point(0, 0); + points.to = new Point( measurements.head, 0) + paths.line = new Path() + .move(points.from) + .line(points.to) + + return part + }; + let pattern = new Test({ + sample: { + type: 'models', + models : { + a: { head: 100 }, + b: { head: 50 }, + } + } + }) + pattern.sample(); + expect(pattern.is).to.equal('sample') + expect(pattern.events.debug[0]).to.equal('Sampling models') + expect(pattern.parts.front.paths[`line_0`].ops[1].to.x).to.equal(100); + expect(pattern.parts.front.paths[`line_1`].ops[1].to.x).to.equal(50); + pattern = new Test({ + sample: { + type: 'models', + models : { + a: { head: 100 }, + b: { head: 50 }, + }, + focus: 'b' + } + }) + pattern.sample(); + expect(pattern.is).to.equal('sample') + expect(pattern.parts.front.paths[`line_-1`].ops[1].to.x).to.equal(50); + expect(pattern.parts.front.paths[`line_0`].ops[1].to.x).to.equal(100); +}); + it("Should register a hook via on", () => { let pattern = new freesewing.Pattern(); let count = 0; @@ -402,6 +518,39 @@ it("Should correctly resolve dependencies - issue #971 - broken version", () => expect(pattern.config.draftOrder[2]).to.equal('crotch'); }); +it("Should correctly resolve dependencies - Handle uncovered code path", () => { + let config = { + name: "test", + dependencies: { + front: 'side', + crotch:['front','back'], + back: 1, + }, + inject: { + front: 'back', + }, + parts: ['back','front','crotch'], + }; + const Test = function(settings = false) { + freesewing.Pattern.call(this, config); + return this; + }; + Test.prototype = Object.create(freesewing.Pattern.prototype); + Test.prototype.constructor = Test; + Test.prototype.draftBack = function(part) { + return part; + }; + Test.prototype.draftFront = function(part) { + return part; + }; + + let pattern = new Test(); + const deps = pattern.resolveDependencies() + expect(pattern.config.draftOrder[0]).to.equal('side'); + expect(pattern.config.draftOrder[1]).to.equal('back'); + expect(pattern.config.draftOrder[2]).to.equal('front'); +}); + it("Should check whether created parts get the pattern context", () => { let pattern = new freesewing.Pattern(); let part = new pattern.Part(); @@ -436,3 +585,130 @@ it("Should correctly merge settings for existing array", () => { expect(pattern.settings.margin).to.equal(5); }); +it("Should return all render props", () => { + const Test = new freesewing.Design({ + name: "test", + parts: ['front'], + }); + Test.prototype.draftFront = function(part) { + return part; + }; + const pattern = new Test() + pattern.draft(); + const rp = pattern.getRenderProps() + expect(rp.svg.body).to.equal(''); + expect(rp.width).to.equal(4); + expect(rp.height).to.equal(4); + expect(rp.parts.front.height).to.equal(4); +}); + +it("Should not pack a pattern with errors", () => { + const pattern = new freesewing.Pattern() + pattern.events.error.push('error') + pattern.pack() + expect(pattern.events.warning.length).to.equal(1) + expect(pattern.events.warning[0]).to.equal('One or more errors occured. Not packing pattern parts') +}); + +it("Should handle custom layouts", () => { + const Test = new freesewing.Design({ name: "test", parts: ['front'] }) + Test.prototype.draftFront = function(part) { return part } + const pattern = new Test({ + layout: { + width: 400, + height: 200, + parts: { front: { move: { x: 14, y: -202 } } } + } + }) + pattern.pack() + expect(pattern.width).to.equal(400) + expect(pattern.height).to.equal(200) +}); + +it("Should handle a simple snapped option", () => { + const Test = new freesewing.Design({ + name: "test", + parts: ['front'], + measurements: [ 'head' ], + options: { + len: { pct: 50, min: 22, max: 78, snap: 10, ...freesewing.pctBasedOn('head') } + } + }) + Test.prototype.draftFront = function(part) { + const { Point, points, Path, paths, absoluteOptions } = part.shorthand() + points.from = new Point(0, 0); + points.to = new Point( 2 * absoluteOptions.len, 0) + paths.line = new Path() + .move(points.from) + .line(points.to) + + return part + }; + let pattern = new Test({ + sample: { + type: 'option', + option: 'len' + }, + measurements: { + head: 43.23 + } + }) + pattern.sample(); + expect(pattern.is).to.equal('sample') + expect(pattern.events.debug[0]).to.equal('Sampling option `len`') + expect(pattern.parts.front.paths.line_1.ops[1].to.x).to.equal(20); + expect(pattern.parts.front.paths.line_2.ops[1].to.x).to.equal(40); + expect(pattern.parts.front.paths.line_3.ops[1].to.x).to.equal(40); + expect(pattern.parts.front.paths.line_4.ops[1].to.x).to.equal(40); + expect(pattern.parts.front.paths.line_5.ops[1].to.x).to.equal(60); + expect(pattern.parts.front.paths.line_6.ops[1].to.x).to.equal(60); + expect(pattern.parts.front.paths.line_7.ops[1].to.x).to.equal(60); + expect(pattern.parts.front.paths.line_8.ops[1].to.x).to.equal(60); + expect(pattern.parts.front.paths.line_9.ops[1].to.x).to.equal(80); + expect(pattern.parts.front.paths.line_10.ops[1].to.x).to.equal(80); +}); + +it("Should handle a list snapped option", () => { + const Test = new freesewing.Design({ + name: "test", + parts: ['front'], + measurements: [ 'head' ], + options: { + len: { pct: 50, min: 22, max: 78, snap: [10,14,19,28], ...freesewing.pctBasedOn('head') } + } + }) + Test.prototype.draftFront = function(part) { + const { Point, points, Path, paths, absoluteOptions } = part.shorthand() + points.from = new Point(0, 0); + points.to = new Point( absoluteOptions.len, 0) + paths.line = new Path() + .move(points.from) + .line(points.to) + + return part + }; + let pattern = new Test({ + sample: { + type: 'option', + option: 'len' + }, + measurements: { + head: 43.23 + } + }) + pattern.sample(); + expect(pattern.is).to.equal('sample') + expect(pattern.events.debug[0]).to.equal('Sampling option `len`') + expect(pattern.parts.front.paths.line_1.ops[1].to.x).to.equal(10); + expect(pattern.parts.front.paths.line_2.ops[1].to.x).to.equal(14); + expect(pattern.parts.front.paths.line_3.ops[1].to.x).to.equal(14); + expect(pattern.parts.front.paths.line_4.ops[1].to.x).to.equal(19); + expect(pattern.parts.front.paths.line_5.ops[1].to.x).to.equal(19); + expect(pattern.parts.front.paths.line_6.ops[1].to.x).to.equal(19); + expect(pattern.parts.front.paths.line_7.ops[1].to.x).to.equal(28); + expect(pattern.parts.front.paths.line_8.ops[1].to.x).to.equal(28); + expect(pattern.parts.front.paths.line_9.ops[1].to.x).to.equal(28); + expect(freesewing.utils.round(pattern.parts.front.paths.line_10.ops[1].to.x)).to.equal(33.72); +}); + + diff --git a/packages/core/tests/point.test.js b/packages/core/tests/point.test.js index f06e002873d..defaacac9d0 100644 --- a/packages/core/tests/point.test.js +++ b/packages/core/tests/point.test.js @@ -260,7 +260,6 @@ 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') diff --git a/packages/core/tests/utils.test.js b/packages/core/tests/utils.test.js index ebbf8b13d10..1f8c0effc78 100644 --- a/packages/core/tests/utils.test.js +++ b/packages/core/tests/utils.test.js @@ -544,7 +544,6 @@ it("Should shoulder return two methods for pctBasedOn", () => { 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", () => {