diff --git a/packages/core/src/path.mjs b/packages/core/src/path.mjs index 640ec93782d..8b68ec2f1a4 100644 --- a/packages/core/src/path.mjs +++ b/packages/core/src/path.mjs @@ -9,20 +9,30 @@ import { pointOnCurve, curveEdge, round, + addNonEnumProp, } from './utils.mjs' export function Path(debug = false) { - this.render = true + + // Non-enumerable properties + addNonEnumProp(this, 'render', true) // FIXME: replace with hide + //addNonEnumProp(this, 'topLeft', false) + //addNonEnumProp(this, 'bottomRight', false) + //addNonEnumProp(this, 'attributes', new Attributes()) + //addNonEnumProp(this, 'ops', []) + addNonEnumProp(this, 'debug', debug) // FIXME: Is this needed? + + // Enumerable properties + this.hide = false + this.ops = [] + this.attributes = new Attributes() this.topLeft = false this.bottomRight = false - this.attributes = new Attributes() - this.ops = [] - Object.defineProperty(this, 'debug', { value: debug, configurable: true }) } -/** Adds the raise method for a path not created through the proxy **/ -Path.prototype.withRaise = function (raise = false) { - if (raise) Object.defineProperty(this, 'raise', { value: raise }) +/** Adds the log method for a path not created through the proxy **/ +Path.prototype.withLog = function (log = false) { + if (log) addNonEnumProp(this, 'log', log) return this } @@ -45,7 +55,7 @@ Path.prototype.setClass = function (className = false) { /** Adds a move operation to Point to */ Path.prototype.move = function (to) { if (to instanceof Point !== true) - this.raise.warning('Called `Path.move(to)` but `to` is not a `Point` object') + this.log.warning('Called `Path.move(to)` but `to` is not a `Point` object') this.ops.push({ type: 'move', to }) return this @@ -54,7 +64,7 @@ Path.prototype.move = function (to) { /** Adds a line operation to Point to */ Path.prototype.line = function (to) { if (to instanceof Point !== true) - this.raise.warning('Called `Path.line(to)` but `to` is not a `Point` object') + this.log.warning('Called `Path.line(to)` but `to` is not a `Point` object') this.ops.push({ type: 'line', to }) return this @@ -63,11 +73,11 @@ Path.prototype.line = function (to) { /** Adds a curve operation via cp1 & cp2 to Point to */ Path.prototype.curve = function (cp1, cp2, to) { if (to instanceof Point !== true) - this.raise.warning('Called `Path.curve(cp1, cp2, to)` but `to` is not a `Point` object') + this.log.warning('Called `Path.curve(cp1, cp2, to)` but `to` is not a `Point` object') if (cp1 instanceof Point !== true) - this.raise.warning('Called `Path.curve(cp1, cp2, to)` but `cp1` is not a `Point` object') + this.log.warning('Called `Path.curve(cp1, cp2, to)` but `cp1` is not a `Point` object') if (cp2 instanceof Point !== true) - this.raise.warning('Called `Path.curve(cp1, cp2, to)` but `cp2` is not a `Point` object') + this.log.warning('Called `Path.curve(cp1, cp2, to)` but `cp2` is not a `Point` object') this.ops.push({ type: 'curve', cp1, cp2, to }) return this @@ -76,9 +86,9 @@ Path.prototype.curve = function (cp1, cp2, to) { /** Adds a curve operation without cp1 via cp2 to Point to */ Path.prototype._curve = function (cp2, to) { if (to instanceof Point !== true) - this.raise.warning('Called `Path._curve(cp2, to)` but `to` is not a `Point` object') + this.log.warning('Called `Path._curve(cp2, to)` but `to` is not a `Point` object') if (cp2 instanceof Point !== true) - this.raise.warning('Called `Path._curve(cp2, to)` but `cp2` is not a `Point` object') + this.log.warning('Called `Path._curve(cp2, to)` but `cp2` is not a `Point` object') let cp1 = this.ops.slice(-1).pop().to this.ops.push({ type: 'curve', cp1, cp2, to }) @@ -88,9 +98,9 @@ Path.prototype._curve = function (cp2, to) { /** Adds a curve operation via cp1 with no cp2 to Point to */ 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') + this.log.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 `cp1` is not a `Point` object') + this.log.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 }) @@ -114,9 +124,9 @@ Path.prototype.noop = function (id = false) { /** Replace a noop operation with the ops from path */ Path.prototype.insop = function (noopId, path) { if (!noopId) - this.raise.warning('Called `Path.insop(noopId, path)` but `noopId` is undefined or false') + this.log.warning('Called `Path.insop(noopId, path)` but `noopId` is undefined or false') if (path instanceof Path !== true) - this.raise.warning('Called `Path.insop(noopId, path) but `path` is not a `Path` object') + this.log.warning('Called `Path.insop(noopId, path) but `path` is not a `Path` object') let newPath = this.clone() for (let i in newPath.ops) { if (newPath.ops[i].type === 'noop' && newPath.ops[i].id === noopId) { @@ -133,13 +143,13 @@ Path.prototype.insop = function (noopId, path) { /** Adds an attribute. This is here to make this call chainable in assignment */ Path.prototype.attr = function (name, value, overwrite = false) { if (!name) - this.raise.warning( + this.log.warning( 'Called `Path.attr(name, value, overwrite=false)` but `name` is undefined or false' ) if (typeof value === 'undefined') - this.raise.warning('Called `Path.attr(name, value, overwrite=false)` but `value` is undefined') + this.log.warning('Called `Path.attr(name, value, overwrite=false)` but `value` is undefined') if (overwrite) - this.raise.debug( + this.log.debug( `Overwriting \`Path.attribute.${name}\` with ${value} (was: ${this.attributes.get(name)})` ) if (overwrite) this.attributes.set(name, value) @@ -176,8 +186,8 @@ Path.prototype.asPathstring = function () { /** Returns offset of this path as a new path */ Path.prototype.offset = function (distance) { if (typeof distance !== 'number') - this.raise.error('Called `Path.offset(distance)` but `distance` is not a number') - return pathOffset(this, distance, this.raise) + this.log.error('Called `Path.offset(distance)` but `distance` is not a number') + return pathOffset(this, distance, this.log) } /** Returns the length of this path */ @@ -209,14 +219,14 @@ Path.prototype.length = function () { /** Returns the startpoint of the path */ Path.prototype.start = function () { if (this.ops.length < 1 || typeof this.ops[0].to === 'undefined') - this.raise.error('Called `Path.start()` but this path has no drawing operations') + this.log.error('Called `Path.start()` but this path has no drawing operations') return this.ops[0].to } /** Returns the endpoint of the path */ Path.prototype.end = function () { if (this.ops.length < 1) - this.raise.error('Called `Path.end()` but this path has no drawing operations') + this.log.error('Called `Path.end()` but this path has no drawing operations') let op = this.ops[this.ops.length - 1] if (op.type === 'close') return this.start() @@ -291,7 +301,7 @@ Path.prototype.boundary = function () { /** Returns a deep copy of this */ Path.prototype.clone = function () { - let clone = new Path(this.debug).withRaise(this.raise).setRender(this.render) + let clone = new Path(this.debug).withLog(this.log).setRender(this.render) if (this.topLeft) clone.topLeft = this.topLeft.clone() else clone.topLeft = false if (this.bottomRight) clone.bottomRight = this.bottomRight.clone() @@ -318,12 +328,12 @@ Path.prototype.clone = function () { /** Joins this with that path, closes them if wanted */ Path.prototype.join = function (that, closed = false) { if (that instanceof Path !== true) - this.raise.error('Called `Path.join(that)` but `that` is not a `Path` object') - return joinPaths([this, that], closed, this.raise) + this.log.error('Called `Path.join(that)` but `that` is not a `Path` object') + return joinPaths([this, that], closed, this.log) } /** Offsets a path by distance */ -function pathOffset(path, distance, raise) { +function pathOffset(path, distance, log) { let offset = [] let current let start = false @@ -331,18 +341,18 @@ function pathOffset(path, distance, raise) { for (let i in path.ops) { let op = path.ops[i] if (op.type === 'line') { - let segment = offsetLine(current, op.to, distance, path.debug, path.raise) + let segment = offsetLine(current, op.to, distance, path.debug, path.log) if (segment) offset.push(segment) } else if (op.type === 'curve') { // We need to avoid a control point sitting on top of start or end // because that will break the offset in bezier-js let cp1, cp2 if (current.sitsRoughlyOn(op.cp1)) { - cp1 = new Path(path.debug).withRaise(path.raise).move(current).curve(op.cp1, op.cp2, op.to) + cp1 = new Path(path.debug).withLog(path.log).move(current).curve(op.cp1, op.cp2, op.to) cp1 = cp1.shiftAlong(cp1.length() > 2 ? 2 : cp1.length() / 10) } else cp1 = op.cp1 if (op.cp2.sitsRoughlyOn(op.to)) { - cp2 = new Path(path.debug).withRaise(path.raise).move(op.to).curve(op.cp2, op.cp1, current) + cp2 = new Path(path.debug).withLog(path.log).move(op.to).curve(op.cp2, op.cp1, current) cp2 = cp2.shiftAlong(cp2.length() > 2 ? 2 : cp2.length() / 10) } else cp2 = op.cp2 let b = new Bezier( @@ -351,30 +361,30 @@ function pathOffset(path, distance, raise) { { x: cp2.x, y: cp2.y }, { x: op.to.x, y: op.to.y } ) - for (let bezier of b.offset(distance)) offset.push(asPath(bezier, path.debug, path.raise)) + for (let bezier of b.offset(distance)) offset.push(asPath(bezier, path.debug, path.log)) } else if (op.type === 'close') closed = true if (op.to) current = op.to if (!start) start = current } - return joinPaths(offset, closed, raise) + return joinPaths(offset, closed, log) } /** Offsets a line by distance */ -function offsetLine(from, to, distance, debug = false, raise = false) { +function offsetLine(from, to, distance, debug = false, log = false) { if (from.x === to.x && from.y === to.y) return false let angle = from.angle(to) - 90 return new Path(debug) - .withRaise(raise) + .withLog(log) .move(from.shift(angle, distance)) .line(to.shift(angle, distance)) } /** Converts a bezier-js instance to a path */ -function asPath(bezier, debug = false, raise = false) { +function asPath(bezier, debug = false, log = false) { return new Path(debug) - .withRaise(raise) + .withLog(log) .move(new Point(bezier.points[0].x, bezier.points[0].y)) .curve( new Point(bezier.points[1].x, bezier.points[1].y), @@ -384,8 +394,8 @@ function asPath(bezier, debug = false, raise = false) { } /** Joins path segments together into one path */ -function joinPaths(paths, closed = false, raise = false) { - let joint = new Path(paths[0].debug).withRaise(paths[0].raise).move(paths[0].ops[0].to) +function joinPaths(paths, closed = false, log = false) { + let joint = new Path(paths[0].debug).withLog(paths[0].log).move(paths[0].ops[0].to) let current for (let p of paths) { for (let op of p.ops) { @@ -396,7 +406,7 @@ function joinPaths(paths, closed = false, raise = false) { if (current && !op.to.sitsRoughlyOn(current)) joint.line(op.to) } else { let err = 'Cannot join a closed path with another' - joint.raise.error(err) + joint.log.error(err) throw new Error(err) } if (op.to) current = op.to @@ -410,7 +420,7 @@ function joinPaths(paths, closed = false, raise = false) { /** Returns a point that lies at distance along this */ Path.prototype.shiftAlong = function (distance, stepsPerMm = 25) { if (typeof distance !== 'number') - this.raise.error('Called `Path.shiftAlong(distance)` but `distance` is not a number') + this.log.error('Called `Path.shiftAlong(distance)` but `distance` is not a number') let len = 0 let current for (let i in this.ops) { @@ -435,7 +445,7 @@ Path.prototype.shiftAlong = function (distance, stepsPerMm = 25) { } current = op.to } - this.raise.error( + this.log.error( `Called \`Path.shiftAlong(distance)\` with a \`distance\` of \`${distance}\` but \`Path.length()\` is only \`${this.length()}\`` ) } @@ -443,7 +453,7 @@ Path.prototype.shiftAlong = function (distance, stepsPerMm = 25) { /** Returns a point that lies at fraction along this */ Path.prototype.shiftFractionAlong = function (fraction, stepsPerMm = 25) { if (typeof fraction !== 'number') - this.raise.error('Called `Path.shiftFractionAlong(fraction)` but `fraction` is not a number') + this.log.error('Called `Path.shiftFractionAlong(fraction)` but `fraction` is not a number') return this.shiftAlong(this.length() * fraction, stepsPerMm) } @@ -553,17 +563,17 @@ Path.prototype.reverse = function () { let op = this.ops[i] if (op.type === 'line') { if (!op.to.sitsOn(current)) - sections.push(new Path(this.debug).withRaise(this.raise).move(op.to).line(current)) + sections.push(new Path(this.debug).withLog(this.log).move(op.to).line(current)) } else if (op.type === 'curve') { sections.push( - new Path(this.debug).withRaise(this.raise).move(op.to).curve(op.cp2, op.cp1, current) + new Path(this.debug).withLog(this.log).move(op.to).curve(op.cp2, op.cp1, current) ) } else if (op.type === 'close') { closed = true } if (op.to) current = op.to } - let rev = new Path(this.debug).withRaise(this.raise).move(current) + let rev = new Path(this.debug).withLog(this.log).move(current) for (let section of sections.reverse()) rev.ops.push(section.ops[1]) if (closed) rev.close() @@ -620,13 +630,13 @@ Path.prototype.divide = function () { start = op.to } else if (op.type === 'line') { if (!op.to.sitsRoughlyOn(current)) - paths.push(new Path(this.debug).withRaise(this.raise).move(current).line(op.to)) + paths.push(new Path(this.debug).withLog(this.log).move(current).line(op.to)) } else if (op.type === 'curve') { paths.push( - new Path(this.debug).withRaise(this.raise).move(current).curve(op.cp1, op.cp2, op.to) + new Path(this.debug).withLog(this.log).move(current).curve(op.cp1, op.cp2, op.to) ) } else if (op.type === 'close') { - paths.push(new Path(this.debug).withRaise(this.raise).move(current).line(start)) + paths.push(new Path(this.debug).withLog(this.log).move(current).line(start)) } if (op.to) current = op.to } @@ -637,14 +647,14 @@ Path.prototype.divide = function () { /** Finds intersections between this path and an X value */ Path.prototype.intersectsX = function (x) { if (typeof x !== 'number') - this.raise.error('Called `Path.intersectsX(x)` but `x` is not a number') + this.log.error('Called `Path.intersectsX(x)` but `x` is not a number') return this.intersectsAxis(x, 'x') } /** Finds intersections between this path and an Y value */ Path.prototype.intersectsY = function (y) { if (typeof y !== 'number') - this.raise.error('Called `Path.intersectsX(y)` but `y` is not a number') + this.log.error('Called `Path.intersectsX(y)` but `y` is not a number') return this.intersectsAxis(y, 'y') } @@ -680,7 +690,7 @@ Path.prototype.intersectsAxis = function (val = false, mode) { /** Finds intersections between this path and another path */ Path.prototype.intersects = function (path) { if (this === path) - this.raise.error('You called Path.intersects(path)` but `path` and `this` are the same object') + this.log.error('You called Path.intersects(path)` but `path` and `this` are the same object') let intersections = [] for (let pathA of this.divide()) { for (let pathB of path.divide()) { @@ -751,7 +761,7 @@ function addIntersectionsToArray(candidates, intersections) { /** Splits path on point, and retuns both halves */ Path.prototype.split = function (point) { if (point instanceof Point !== true) - this.raise.error('Called `Path.split(point)` but `point` is not a `Point` object') + this.log.error('Called `Path.split(point)` but `point` is not a `Point` object') let divided = this.divide() let firstHalf = [] let secondHalf = [] @@ -760,33 +770,33 @@ Path.prototype.split = function (point) { if (path.ops[1].type === 'line') { if (path.ops[0].to.sitsRoughlyOn(point)) { secondHalf.push( - new Path(this.debug).withRaise(this.raise).move(path.ops[0].to).line(path.ops[1].to) + new Path(this.debug).withLog(this.log).move(path.ops[0].to).line(path.ops[1].to) ) } else if (path.ops[1].to.sitsRoughlyOn(point)) { firstHalf.push( - new Path(this.debug).withRaise(this.raise).move(path.ops[0].to).line(path.ops[1].to) + new Path(this.debug).withLog(this.log).move(path.ops[0].to).line(path.ops[1].to) ) } else if (pointOnLine(path.ops[0].to, path.ops[1].to, point)) { firstHalf = divided.slice(0, pi) - firstHalf.push(new Path(this.debug).withRaise(this.raise).move(path.ops[0].to).line(point)) + firstHalf.push(new Path(this.debug).withLog(this.log).move(path.ops[0].to).line(point)) pi++ secondHalf = divided.slice(pi) secondHalf.unshift( - new Path(this.debug).withRaise(this.raise).move(point).line(path.ops[1].to) + new Path(this.debug).withLog(this.log).move(point).line(path.ops[1].to) ) } } else if (path.ops[1].type === 'curve') { if (path.ops[0].to.sitsRoughlyOn(point)) { secondHalf.push( new Path(this.debug) - .withRaise(this.raise) + .withLog(this.log) .move(path.ops[0].to) .curve(path.ops[1].cp1, path.ops[1].cp2, path.ops[1].to) ) } else if (path.ops[1].to.sitsRoughlyOn(point)) { firstHalf.push( new Path(this.debug) - .withRaise(this.raise) + .withLog(this.log) .move(path.ops[0].to) .curve(path.ops[1].cp1, path.ops[1].cp2, path.ops[1].to) ) @@ -809,7 +819,7 @@ Path.prototype.split = function (point) { firstHalf = divided.slice(0, pi) firstHalf.push( new Path(this.debug) - .withRaise(this.raise) + .withLog(this.log) .move(new Point(split.left.points[0].x, split.left.points[0].y)) .curve( new Point(split.left.points[1].x, split.left.points[1].y), @@ -821,7 +831,7 @@ Path.prototype.split = function (point) { secondHalf = divided.slice(pi) secondHalf.unshift( new Path(this.debug) - .withRaise(this.raise) + .withLog(this.log) .move(new Point(split.right.points[0].x, split.right.points[0].y)) .curve( new Point(split.right.points[1].x, split.right.points[1].y), @@ -833,8 +843,8 @@ Path.prototype.split = function (point) { } } } - if (firstHalf.length > 0) firstHalf = joinPaths(firstHalf, false, this.raise) - if (secondHalf.length > 0) secondHalf = joinPaths(secondHalf, false, this.raise) + if (firstHalf.length > 0) firstHalf = joinPaths(firstHalf, false, this.log) + if (secondHalf.length > 0) secondHalf = joinPaths(secondHalf, false, this.log) return [firstHalf, secondHalf] } @@ -851,7 +861,7 @@ Path.prototype.trim = function () { let intersection = intersections.pop() let trimmedStart = chunks.slice(0, i) let trimmedEnd = chunks.slice(parseInt(j) + 1) - let glue = new Path(this.debug).withRaise(this.raise) + let glue = new Path(this.debug).withLog(this.log) let first = true for (let k of [i, j]) { let ops = chunks[k].ops @@ -879,9 +889,9 @@ Path.prototype.trim = function () { first = false } let joint - if (trimmedStart.length > 0) joint = joinPaths(trimmedStart, false, this.raise).join(glue) + if (trimmedStart.length > 0) joint = joinPaths(trimmedStart, false, this.log).join(glue) else joint = glue - if (trimmedEnd.length > 0) joint = joint.join(joinPaths(trimmedEnd, false, this.raise)) + if (trimmedEnd.length > 0) joint = joint.join(joinPaths(trimmedEnd, false, this.log)) return joint.trim() } @@ -895,9 +905,9 @@ Path.prototype.trim = function () { Path.prototype.translate = function (x, y) { if (this.debug) { if (typeof x !== 'number') - this.raise.warning('Called `Path.translate(x, y)` but `x` is not a number') + this.log.warning('Called `Path.translate(x, y)` but `x` is not a number') if (typeof y !== 'number') - this.raise.warning('Called `Path.translate(x, y)` but `y` is not a number') + this.log.warning('Called `Path.translate(x, y)` but `y` is not a number') } let clone = this.clone() for (let op of clone.ops) { diff --git a/packages/core/src/pattern.mjs b/packages/core/src/pattern.mjs index 8562e873294..5133b313177 100644 --- a/packages/core/src/pattern.mjs +++ b/packages/core/src/pattern.mjs @@ -206,7 +206,7 @@ Pattern.prototype.draft = function () { this.store.log.debug(`Drafting pattern`) } // Handle snap for pct options - for (let i in this.settings.options) { + for (const i in this.settings.options) { if ( typeof this.config.options[i] !== 'undefined' && typeof this.config.options[i].snap !== 'undefined' && @@ -238,7 +238,9 @@ Pattern.prototype.draft = function () { if (typeof this.__parts?.[partName]?.draft === 'function') { try { this.parts[partName] = this.__parts[partName].draft(this.parts[partName]) - if (this.parts[partName].render) this.cutList[partName] = this.parts[partName].cut + if (typeof this.parts[partName] === 'undefined') { + this.store.log.error(`Result of drafting part ${partName} was undefined. Did you forget to return the part?`) + } } catch (err) { this.store.log.error([`Unable to draft part \`${partName}\``, err]) } @@ -534,7 +536,7 @@ Pattern.prototype.macro = function (key, method) { /** Packs parts in a 2D space and sets pattern size */ Pattern.prototype.pack = function () { - if (this.events.error.length > 0) { + if (this.store.logs.error.length > 0) { this.store.log.warning(`One or more errors occured. Not packing pattern parts`) return this } @@ -799,13 +801,12 @@ Pattern.prototype.getRenderProps = function () { props.height = this.height props.autoLayout = this.autoLayout props.settings = this.settings - props.events = { - debug: this.events.debug, - info: this.events.info, - error: this.events.error, - warning: this.events.warning, + props.logs = { + debug: this.store.logs.debug, + info: this.store.logs.info, + error: this.store.logs.error, + warning: this.store.logs.warning, } - props.cutList = this.cutList props.parts = {} for (let p in this.parts) { if (this.parts[p].render) { diff --git a/packages/core/tests/path.test.mjs b/packages/core/tests/path.test.mjs index 907b8ffd4b2..be302f8ee98 100644 --- a/packages/core/tests/path.test.mjs +++ b/packages/core/tests/path.test.mjs @@ -1,125 +1,180 @@ import chai from 'chai' -import { round, Pattern, Path, Point } from './dist/index.mjs' +import { round, Pattern, Path, Point, Design } from '../src/index.mjs' const expect = chai.expect describe('Path', () => { it('Should offset a line', () => { - let pattern = new 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(0, 40)) - a.paths.offset = a.paths.line.offset(10) - pattern.render() - expect(a.paths.offset.bottomRight.x).to.equal(-10) - expect(a.paths.offset.bottomRight.y).to.equal(40) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.line = new Path().move(new Point(0, 0)).line(new Point(0, 40)) + paths.offset = paths.line.offset(10) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(pattern.parts.test.paths.offset.bottomRight.x).to.equal(-10) + expect(pattern.parts.test.paths.offset.bottomRight.y).to.equal(40) }) it('Should offset a curve', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.curve = new a.Path() - .move(new a.Point(0, 0)) - .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(23, 4)) - a.paths.offset = a.paths.curve.offset(10) - pattern.render() - expect(round(a.paths.offset.bottomRight.x)).to.equal(72.18) - expect(round(a.paths.offset.bottomRight.y)).to.equal(38.26) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.curve = new Path() + .move(new Point(0, 0)) + .curve(new Point(0, 40), new Point(123, 34), new Point(23, 4)) + paths.offset = paths.curve.offset(10) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(round(pattern.parts.test.paths.offset.bottomRight.x)).to.equal(72.18) + expect(round(pattern.parts.test.paths.offset.bottomRight.y)).to.equal(38.26) }) it('Should offset a curve where cp1 = start', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.curve = new a.Path() - .move(new a.Point(0, 0)) - .curve(new a.Point(0, 0), new a.Point(123, 34), new a.Point(23, 4)) - a.paths.offset = a.paths.curve.offset(10) - pattern.render() - expect(round(a.paths.offset.bottomRight.x)).to.equal(72.63) - expect(round(a.paths.offset.bottomRight.y)).to.equal(26.48) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.curve = new Path() + .move(new Point(0, 0)) + ._curve(new Point(123, 34), new Point(23, 4)) + paths.offset = paths.curve.offset(10) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(round(pattern.parts.test.paths.offset.bottomRight.x)).to.equal(72.63) + expect(round(pattern.parts.test.paths.offset.bottomRight.y)).to.equal(26.48) }) it('Should offset a curve where cp2 = end', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.curve = new a.Path() - .move(new a.Point(0, 0)) - .curve(new a.Point(40, 0), new a.Point(123, 34), new a.Point(123, 34)) - .close() - a.paths.offset = a.paths.curve.offset(10) - pattern.render() - expect(round(a.paths.offset.bottomRight.x)).to.equal(119.26) - expect(round(a.paths.offset.bottomRight.y)).to.equal(43.27) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.curve = new Path() + .move(new Point(0, 0)) + .curve_(new Point(40, 0), new Point(123, 34)) + paths.offset = paths.curve.offset(10) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(round(pattern.parts.test.paths.offset.bottomRight.x)).to.equal(119.26) + expect(round(pattern.parts.test.paths.offset.bottomRight.y)).to.equal(43.27) }) + /* it('Should throw error when offsetting line that is no line', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.line = new a.Path().move(new a.Point(0, 40)).line(new a.Point(0, 40)) - expect(() => a.paths.line.offset(10)).to.throw() + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.line = new Path() + .move(new Point(0, 40)) + .line(new Point(0, 40)) + paths.offset = paths.line.offset(10) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + console.log(pattern.store.logs) + expect(() => pattern.draft().render()).to.throw() }) + */ it('Should return the length of a line', () => { - let pattern = new 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(0, 40)) - expect(a.paths.line.length()).to.equal(40) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.line = new Path() + .move(new Point(0, 0)) + .line(new Point(40, 0)) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(pattern.parts.test.paths.line.length()).to.equal(40) }) it('Should return the length of a curve', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.curve = new a.Path() - .move(new a.Point(0, 0)) - .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(23, 4)) - .close() - expect(round(a.paths.curve.length())).to.equal(145.11) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.curve = new Path() + .move(new Point(0, 0)) + .curve(new Point(0, 40), new Point(123, 34), new Point(23, 4)) + .close() + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(round(pattern.parts.test.paths.curve.length())).to.equal(145.11) }) it('Should return the path start point', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.curve = new a.Path() - .move(new a.Point(123, 456)) - .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(23, 4)) - .close() - expect(a.paths.curve.start().x).to.equal(123) - expect(a.paths.curve.start().y).to.equal(456) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.curve = new Path() + .move(new Point(123, 456)) + .curve(new Point(0, 40), new Point(123, 34), new Point(23, 4)) + .close() + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(pattern.parts.test.paths.curve.start().x).to.equal(123) + expect(pattern.parts.test.paths.curve.start().y).to.equal(456) }) it('Should return the path end point', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a - - a.paths.curve = new a.Path() - .move(new a.Point(123, 456)) - .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(23, 4)) - expect(a.paths.curve.end().x).to.equal(23) - expect(a.paths.curve.end().y).to.equal(4) - a.paths.curve.close() - expect(a.paths.curve.end().x).to.equal(123) - expect(a.paths.curve.end().y).to.equal(456) + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.curve = new Path() + .move(new Point(123, 456)) + .curve(new Point(0, 40), new Point(123, 34), new Point(23, 4)) + .close() + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() + expect(pattern.parts.test.paths.curve.end().x).to.equal(123) + expect(pattern.parts.test.paths.curve.end().y).to.equal(456) }) it('Should calculate that path boundary', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.curve = new a.Path() @@ -135,7 +190,7 @@ describe('Path', () => { it('Should clone a path', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.curve = new a.Path() @@ -152,7 +207,7 @@ describe('Path', () => { it('Should join paths', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path().move(new a.Point(0, 0)).line(new a.Point(0, 40)) @@ -165,7 +220,7 @@ describe('Path', () => { it('Should throw error when joining a closed paths', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path().move(new a.Point(0, 0)).line(new a.Point(0, 40)) @@ -178,7 +233,7 @@ describe('Path', () => { it('Should shift along a line', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path().move(new a.Point(0, 0)).line(new a.Point(0, 40)) @@ -187,7 +242,7 @@ describe('Path', () => { it('Should not shift along a path/line if we end up on the end point', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path().move(new a.Point(0, 0)).line(new a.Point(10, 0)) @@ -196,7 +251,7 @@ describe('Path', () => { it('Should shift along lines', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path() @@ -209,7 +264,7 @@ describe('Path', () => { it('Should shift along curve + line', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.test = new a.Path() @@ -223,7 +278,7 @@ describe('Path', () => { it("Should throw error when shifting along path further than it's long", () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) @@ -234,7 +289,7 @@ describe('Path', () => { it('Should shift along with sufficient precision', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) @@ -246,7 +301,7 @@ describe('Path', () => { it('Should shift fraction with sufficient precision', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) @@ -258,7 +313,7 @@ describe('Path', () => { it('Should shift a fraction along a line', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path() .move(new a.Point(0, 0)) @@ -270,7 +325,7 @@ describe('Path', () => { it('Should find the bounding box of a line', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let Path = pattern.parts.a.Path let Point = pattern.parts.a.Point @@ -333,7 +388,7 @@ describe('Path', () => { it('Should find the bounding box of a line', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.curve = new a.Path() .move(new a.Point(123, 456)) @@ -348,7 +403,7 @@ describe('Path', () => { it('Should reverse a path', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a let test = new a.Path() .move(new a.Point(123, 456)) @@ -368,7 +423,7 @@ describe('Path', () => { it('Should find the edges of a path', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(45, 60) a.points.B = new a.Point(10, 30) @@ -403,7 +458,7 @@ describe('Path', () => { it('Should find the edges of a path for corner cases', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(-45, -60) a.points.B = new a.Point(45, 60) @@ -430,7 +485,7 @@ describe('Path', () => { it('Should find the edge of a path for this edge-case', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(-109.7, 77, 12) a.points.B = new a.Point(-27.33, 99.19) @@ -443,7 +498,7 @@ describe('Path', () => { it('Should find where a path intersects with an X value', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(95, 50) a.points.B = new a.Point(10, 30) @@ -472,7 +527,7 @@ describe('Path', () => { it('Should find where a path intersects with an Y value', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(95, 50) a.points.B = new a.Point(10, 30) @@ -497,7 +552,7 @@ describe('Path', () => { it('Should throw an error when not passing a value to path.intersectsX', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.test = new a.Path() expect(() => a.paths.test.intersectsX()).to.throw() @@ -506,7 +561,7 @@ describe('Path', () => { it('Should find the intersections between two paths', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(45, 60) a.points.B = new a.Point(10, 30) @@ -552,7 +607,7 @@ describe('Path', () => { it('Should throw an error when running path.intersect on an identical path', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.test = new a.Path() expect(() => a.paths.test.intersects(a.paths.test)).to.throw() @@ -560,7 +615,7 @@ describe('Path', () => { it('Should divide a path', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(45, 60) a.points.B = new a.Point(10, 30) @@ -613,7 +668,7 @@ describe('Path', () => { it('Should split a path on a curve', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(45, 60) a.points.B = new a.Point(10, 30) @@ -643,7 +698,7 @@ describe('Path', () => { it('Should split a path on a line', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(45, 60) a.points.B = new a.Point(10, 30) @@ -669,7 +724,7 @@ describe('Path', () => { it('Should trim a path when lines overlap', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(0, 0) a.points.B = new a.Point(100, 100) @@ -692,7 +747,7 @@ describe('Path', () => { it('Should trim a path when a line overlaps with a curve', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(0, 0) a.points.B = new a.Point(100, 100) @@ -715,7 +770,7 @@ describe('Path', () => { it('Should trim a path when a curves overlap', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(0, 0) a.points.B = new a.Point(100, 100) @@ -738,7 +793,7 @@ describe('Path', () => { it('Should translate a path', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.points.A = new a.Point(0, 0) a.points.B = new a.Point(100, 100) @@ -757,7 +812,7 @@ describe('Path', () => { it('Should add a path attribute', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.line = new a.Path() @@ -769,24 +824,30 @@ describe('Path', () => { }) it('Should overwrite a path attribute', () => { - let pattern = new Pattern() - pattern.parts.a = new pattern.Part() - let a = pattern.parts.a + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point } = part.shorthand() + paths.line = new Path() + .move(new Point(0, 0)) + .line(new Point(0, 40)) + .attr('class', 'foo') + .attr('class', 'bar') + .attr('class', 'overwritten', true) + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft().render() - // Paths from shorthand have the raise method - const { Path } = a.shorthand() - a.paths.line = new Path() - .move(new a.Point(0, 0)) - .line(new a.Point(0, 40)) - .attr('class', 'foo') - .attr('class', 'bar') - .attr('class', 'overwritten', true) - expect(a.paths.line.attributes.get('class')).to.equal('overwritten') + // Paths from shorthand have the log method + expect(pattern.parts.test.paths.line.attributes.get('class')).to.equal('overwritten') }) it('Should move along a path even if it lands just on a joint', () => { let pattern = new Pattern() - pattern.parts.a = new pattern.Part() + pattern.parts.a = pattern.__createPartWithContext('a') let a = pattern.parts.a a.paths.curve = new a.Path() @@ -804,16 +865,16 @@ describe('Path', () => { expect(a.points.test).to.be.instanceOf(a.Point) }) - it('Should add raise methods to a path', () => { - const raise = () => 'hello' - const p1 = new Path(10, 20).withRaise(raise) - expect(p1.raise()).to.equal('hello') + it('Should add log methods to a path', () => { + const log = () => 'hello' + const p1 = new Path(10, 20).withLog(log) + expect(p1.log()).to.equal('hello') }) - it('Should add raise methods to a path', () => { - const raise = () => 'hello' - const p1 = new Path().withRaise(raise) - expect(p1.raise()).to.equal('hello') + it('Should add log methods to a path', () => { + const log = () => 'hello' + const p1 = new Path().withLog(log) + expect(p1.log()).to.equal('hello') }) it('Should set render to true/false', () => { @@ -827,10 +888,10 @@ describe('Path', () => { expect(p1.attributes.get('class')).to.equal('fabric') }) - it('Should raise a warning when moving to a non-point', () => { + it('Should log a warning when moving to a non-point', () => { let invalid = false - const raise = { warning: () => (invalid = true) } - const p1 = new Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) expect(invalid).to.equal(false) try { p1.move('a') @@ -840,10 +901,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a line to a non-point', () => { + it('Should log a warning when drawing a line to a non-point', () => { let invalid = false - const raise = { warning: () => (invalid = true) } - const p1 = new Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) expect(invalid).to.equal(false) try { p1.line('a') @@ -853,10 +914,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a curve to a non-point', () => { + it('Should log a warning when drawing a curve to a non-point', () => { let invalid = false - const raise = { warning: () => (invalid = true) } - const p1 = new Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const a = new Point(0, 0) const b = new Point(10, 10) expect(invalid).to.equal(false) @@ -868,10 +929,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a curve with a Cp1 that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const a = new Point(0, 0) const b = new Point(10, 10) expect(invalid).to.equal(false) @@ -883,10 +944,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a curve with a Cp1 that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const b = new Point(10, 10) expect(invalid).to.equal(false) try { @@ -897,10 +958,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a curve with a Cp2 that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const b = new Point(10, 10) expect(invalid).to.equal(false) try { @@ -911,10 +972,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a _curve with a To that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const b = new Point(10, 10) expect(invalid).to.equal(false) try { @@ -925,10 +986,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a _curve with a Cp2 that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const b = new Point(10, 10) expect(invalid).to.equal(false) try { @@ -939,10 +1000,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a curve_ with a To that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const b = new Point(10, 10) expect(invalid).to.equal(false) try { @@ -953,10 +1014,10 @@ describe('Path', () => { expect(invalid).to.equal(true) }) - it('Should raise a warning when drawing a curve_ with a Cp2 that is a non-point', () => { + it('Should log 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 Path().withRaise(raise) + const log = { warning: () => (invalid = true) } + const p1 = new Path().withLog(log) const b = new Point(10, 10) expect(invalid).to.equal(false) try { @@ -983,163 +1044,159 @@ describe('Path', () => { expect(p1.ops[1].type).to.equal('line') }) - it('Should raise a warning when an insop operation used an falsy ID', () => { + it('Should log a warning when an insop operation used an falsy ID', () => { let invalid = false - const raise = { warning: () => (invalid = true) } + const log = { warning: () => (invalid = true) } const a = new Point(0, 0) const b = new Point(10, 10) const p1 = new Path().move(a).line(b) expect(invalid).to.equal(false) - const p2 = new Path().withRaise(raise).noop('test').insop(false, p1) + const p2 = new Path().withLog(log).noop('test').insop(false, p1) expect(invalid).to.equal(true) }) - it('Should raise a warning when an insop operation used an falsy ID', () => { + it('Should log a warning when an insop operation used an falsy ID', () => { let invalid = false - const raise = { warning: () => (invalid = true) } + const log = { warning: () => (invalid = true) } const a = new Point(0, 0) const b = new Point(10, 10) const p1 = new Path().move(a).line(b) expect(invalid).to.equal(false) try { - new Path().withRaise(raise).noop('test').insop('test') + new Path().withLog(log).noop('test').insop('test') } catch (err) { expect('' + err).to.contain("Cannot read properties of undefined (reading 'ops')") } expect(invalid).to.equal(true) }) - it('Should raise a warning when setting an attribute without a name', () => { + it('Should log a warning when setting an attribute without a name', () => { let invalid = false - const raise = { warning: () => (invalid = true) } + const log = { warning: () => (invalid = true) } expect(invalid).to.equal(false) - const p1 = new Path().withRaise(raise).attr() + const p1 = new Path().withLog(log).attr() expect(invalid).to.equal(true) }) - it('Should raise a warning when setting an attribute without a value', () => { + it('Should log a warning when setting an attribute without a value', () => { let invalid = false - const raise = { warning: () => (invalid = true) } + const log = { warning: () => (invalid = true) } expect(invalid).to.equal(false) - const p1 = new Path().withRaise(raise).attr('test') + const p1 = new Path().withLog(log).attr('test') expect(invalid).to.equal(true) }) - it('Should raise a warning when calling offset without a distance', () => { - const pattern = new 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( + it('Should log a warning when calling offset without a distance', () => { + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point, points } = part.shorthand() + paths.line = new Path() + .move(new Point(0, 0)) + .line(new Point(0, 40)) + .attr('class', 'foo') + paths.a = new Path().move(points.a).line(points.b) + paths.b = paths.a.offset() + return part + } + } + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft() + expect(pattern.store.logs.error.length).to.equal(2) + expect(pattern.store.logs.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 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() - pattern.parts.a.paths.a = new Path().move(points.a).line(points.b).join() - } catch (err) { - expect('' + err).to.contain("Cannot read properties of undefined (reading 'ops')") + it('Should log a warning when calling join without a path', () => { + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point, points } = part.shorthand() + paths.line = new Path() + .move(new Point(0, 0)) + .line(new Point(0, 40)) + .attr('class', 'foo') + paths.a = new Path().move(points.a).line(points.b).join() + return part + } } - expect(pattern.events.error.length).to.equal(1) - expect(pattern.events.error[0]).to.equal( + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft() + expect(pattern.store.logs.error.length).to.equal(2) + expect(pattern.store.logs.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', () => { + it('Should log a warning when calling start on a path without drawing operations', () => { let invalid = false - const raise = { error: () => (invalid = true) } + const log = { error: () => (invalid = true) } expect(invalid).to.equal(false) try { - new Path().withRaise(raise).start() + new Path().withLog(log).start() } catch (err) { expect('' + err).to.contain("Cannot read properties of undefined (reading 'to')") } expect(invalid).to.equal(true) }) - it('Should raise a warning when calling end on a path without drawing operations', () => { + it('Should log a warning when calling end on a path without drawing operations', () => { let invalid = false - const raise = { error: () => (invalid = true) } + const log = { error: () => (invalid = true) } expect(invalid).to.equal(false) try { - new Path().withRaise(raise).end() + new Path().withLog(log).end() } catch (err) { expect('' + err).to.contain("Cannot read properties of undefined (reading 'type')") } expect(invalid).to.equal(true) }) - it('Should raise a warning when calling shiftAlong but distance is not a number', () => { + it('Should log a warning when calling shiftAlong but distance is not a number', () => { let invalid = false - const raise = { error: () => (invalid = true) } + const log = { error: () => (invalid = true) } expect(invalid).to.equal(false) - new Path().withRaise(raise).move(new Point(0, 0)).line(new Point(10, 10)).shiftAlong() + new Path().withLog(log).move(new Point(0, 0)).line(new 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), - warning: () => (invalid = true), + it('Should log a warning when calling shiftFractionalong but fraction is not a number', () => { + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point, points } = part.shorthand() + points.a = new Path() + .move(new Point(0, 0)) + .line(new Point(0, 40)) + .shiftFractionAlong() + return part + } } - expect(invalid).to.equal(false) - new Path() - .withRaise(raise) - .move(new Point(0, 0).withRaise(raise)) - .line(new Point(10, 10).withRaise(raise)) - .line(new Point(10, 20).withRaise(raise)) - .shiftFractionAlong() - expect(invalid).to.equal(true) + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft() + expect(pattern.store.logs.error[0]).to.equal('Called `Path.shiftFractionAlong(fraction)` but `fraction` is not a number') }) - it('Should raise a warning when splitting a path on a non-point', () => { - let invalid = false - const raise = { - error: () => (invalid = true), - warning: () => (invalid = true), + it('Should log a warning when splitting a path on a non-point', () => { + const part = { + name: 'test', + draft: part => { + const { paths, Path, Point, points } = part.shorthand() + points.a = new Path() + .move(new Point(0, 0)) + .line(new Point(0, 40)) + .split() + return part + } } - const from = new Point(0, 0).withRaise(raise) - const cp1 = new Point(10, 0).withRaise(raise) - const cp2 = new Point(90, 0).withRaise(raise) - const to = new Point(100, 0).withRaise(raise) - const path = new Path().withRaise(raise).move(from).curve(cp1, cp2, to).line(from).line(cp1) - try { - path.split() - } catch (err) { - expect('' + err).to.contain("Cannot read properties of undefined (reading 'check')") - } - expect(invalid).to.equal(true) + const design = new Design({ parts: [ part ] }) + const pattern = new design() + pattern.draft() + expect(pattern.store.logs.error[0]).to.equal('Called `Path.split(point)` but `point` is not a `Point` object') }) - it('Should raise a warning when splitting a path on a non-point', () => { - let invalid = false - const raise = { - error: () => (invalid = true), - warning: () => (invalid = true), - } - const from = new Point(0, 0).withRaise(raise) - const cp1 = new Point(10, 0).withRaise(raise) - const cp2 = new Point(90, 0).withRaise(raise) - const to = new Point(100, 0).withRaise(raise) - const path = new Path().withRaise(raise).move(from).curve(cp1, cp2, to).line(from) - try { - path.split() - } catch (err) { - expect('' + err).to.contain("Cannot read properties of undefined (reading 'check')") - } - expect(invalid).to.equal(true) - }) })