From 0cbffd6dc63c356ae1a37bba61acc12ea20395de Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Fri, 9 Sep 2022 20:20:38 +0200 Subject: [PATCH] wip(core): Work on late-stage config resolver This moves resolving of the config from the pattern constructor to the init() method. The idea is that adding a part to a pattern is exactly the same as adding a part to a design. In other words, late-stage adding of parts would be no different as the config gets resolved after that. This is currently broken in many different ways, but the unit tests particular to this new way of resolving the config do pass. --- config/exceptions.yaml | 8 + config/scripts.yaml | 8 +- packages/core/.c8rc.json | 7 + packages/core/.travis.yml | 9 - packages/core/package.json | 8 +- packages/core/src/attributes.mjs | 1 - packages/core/src/design.mjs | 37 +- packages/core/src/index.mjs | 5 +- packages/core/src/option.mjs | 1 - packages/core/src/part.mjs | 17 +- packages/core/src/path.mjs | 1 - packages/core/src/pattern.mjs | 490 +++---- packages/core/src/point.mjs | 8 +- packages/core/src/snippet.mjs | 1 - packages/core/src/store.mjs | 6 +- packages/core/src/svg.mjs | 1 - packages/core/src/utils.mjs | 280 ++-- packages/core/tests/attributes.test.mjs | 114 +- packages/core/tests/design.test.mjs | 152 +-- packages/core/tests/hooks.test.mjs | 18 +- packages/core/tests/new.test.mjs | 146 ++ packages/core/tests/part.test.mjs | 513 +++---- packages/core/tests/path.test.mjs | 1633 +++++++++++------------ packages/core/tests/pattern-draft.mjs | 1081 +++++++++++++++ packages/core/tests/pattern-init.mjs | 240 ++++ packages/core/tests/pattern.test.mjs | 795 +++++------ packages/core/tests/point.test.mjs | 754 +++++------ packages/core/tests/snap.mjs | 84 +- packages/core/tests/snippet.test.mjs | 50 +- packages/core/tests/store.test.mjs | 122 +- packages/core/tests/svg.test.mjs | 428 +++--- packages/core/tests/utils.test.mjs | 902 ++++++------- 32 files changed, 4536 insertions(+), 3384 deletions(-) create mode 100644 packages/core/.c8rc.json delete mode 100644 packages/core/.travis.yml create mode 100644 packages/core/tests/new.test.mjs create mode 100644 packages/core/tests/pattern-draft.mjs create mode 100644 packages/core/tests/pattern-init.mjs diff --git a/config/exceptions.yaml b/config/exceptions.yaml index 69fbc62950b..7b0fb7b7f21 100644 --- a/config/exceptions.yaml +++ b/config/exceptions.yaml @@ -13,6 +13,14 @@ packageJson: author: bobgeorgethe3rd (https://github.com/bobgeorgethe3rd) benjamin: author: woutervdub (https://github.com/woutervdub) + code: + c8: + reporter: html + all: yes + extension: mjs + exclude: + - "node_modules/*" + - "tests" hi: author: woutervdub (https://github.com/woutervdub) holmes: diff --git a/config/scripts.yaml b/config/scripts.yaml index bc48c2f0a4d..e2eabfc02ed 100644 --- a/config/scripts.yaml +++ b/config/scripts.yaml @@ -17,10 +17,10 @@ _types: test: *test testci: *testci core: - report: 'nyc report --reporter=html' - test: 'nyc -x node_modules -x tests -x bin-pack npx mocha tests/*.test.mjs' - testci: "nyc --silent npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js && nyc report --reporter=json" - testonly: 'npx mocha tests/*.test.mjs' + report: 'c8 report' + test: 'c8 mocha tests/*.test.mjs' + testci: "mocha tests/*.test.mjs" + prettier: "npx prettier --write 'src/*.mjs' 'tests/*.mjs'" i18n: prebuild: 'node scripts/prebuilder.mjs' test: *test diff --git a/packages/core/.c8rc.json b/packages/core/.c8rc.json new file mode 100644 index 00000000000..2d34c12a557 --- /dev/null +++ b/packages/core/.c8rc.json @@ -0,0 +1,7 @@ +{ + "reporter": "html", + "all": true, + "extension": "mjs", + "exclude": ["node_modules/*", "tests"] +} + diff --git a/packages/core/.travis.yml b/packages/core/.travis.yml deleted file mode 100644 index 121b29f66a4..00000000000 --- a/packages/core/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: node_js -node_js: - - "node" -install: - - npm install - - npm run build -script: - - npm run test - - npm run coverage diff --git a/packages/core/package.json b/packages/core/package.json index 14bec188410..9b50d950314 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -35,13 +35,13 @@ "clean": "rimraf dist", "mbuild": "NO_MINIFY=1 node build.mjs", "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", - "test": "nyc -x node_modules -x tests -x bin-pack npx mocha tests/*.test.mjs", + "test": "c8 mocha tests/*.test.mjs", "vbuild": "VERBOSE=1 node build.mjs", "lab": "cd ../../sites/lab && yarn start", "tips": "node ../../scripts/help.mjs", - "report": "nyc report --reporter=html", - "testci": "nyc --silent npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js && nyc report --reporter=json", - "testonly": "npx mocha tests/*.test.mjs", + "report": "c8 report", + "testci": "mocha tests/*.test.mjs", + "prettier": "npx prettier --write 'src/*.mjs' 'tests/*.mjs'", "cibuild_step0": "node build.mjs" }, "peerDependencies": {}, diff --git a/packages/core/src/attributes.mjs b/packages/core/src/attributes.mjs index baa587e0c81..4108a487da3 100644 --- a/packages/core/src/attributes.mjs +++ b/packages/core/src/attributes.mjs @@ -102,4 +102,3 @@ Attributes.prototype.clone = function () { return clone } - diff --git a/packages/core/src/design.mjs b/packages/core/src/design.mjs index 91bc4a791b2..5587361d286 100644 --- a/packages/core/src/design.mjs +++ b/packages/core/src/design.mjs @@ -1,7 +1,6 @@ import { Pattern } from './pattern.mjs' import { addPartConfig } from './utils.mjs' - /* * The Design constructor. Returns a Pattern constructor * So it's sort of a super-constructor @@ -14,43 +13,18 @@ export function Design(config) { optionalMeasurements: [], options: {}, parts: [], + data: {}, plugins: [], - // A place to store deprecation and other warnings before we even have a pattern instantiated - events: { - debug: [], - error: [], - info: [], - suggestion: [], - warning: [], - }, ...config } - const raiseEvent = function (data, type) { - config.events[type].push(data) - } - // Polyfill for pattern raise methods - const raise = { - debug: data => raiseEvent(`[early] `+data, 'debug'), - error: data => raiseEvent(`[early] `+data, 'error'), - info: data => raiseEvent(`[early] `+data, 'info'), - suggestion: data => raiseEvent(`[early] `+data, 'suggestion'), - warning: data => raiseEvent(`[early] `+data, 'warning'), - } - const parts = {} - for (const part of config.parts) { - if (typeof part === 'object') { - parts[part.name] = part - config = addPartConfig(parts[part.name], config, raise ) - } - else throw("Invalid part configuration. Part is not an object") - } - // Replace config.parts with the resolved config - config.parts = parts + // Create the pattern constructor const pattern = function (settings) { + // Pass the design config Pattern.call(this, config) - return this.init().apply(settings) + // Pass the pattern settings + return this.__applySettings(settings) } // Set up inheritance @@ -62,4 +36,3 @@ export function Design(config) { return pattern } - diff --git a/packages/core/src/index.mjs b/packages/core/src/index.mjs index ef797354ac9..9a3aa19091d 100644 --- a/packages/core/src/index.mjs +++ b/packages/core/src/index.mjs @@ -34,7 +34,7 @@ import { Bezier, generatePartTransform, macroName, -} from "./utils.mjs" +} from './utils.mjs' import { version } from '../data.mjs' // Named exports @@ -46,7 +46,6 @@ export { Path, Snippet, Store, - Bezier, capitalize, beamsIntersect, @@ -75,7 +74,5 @@ export { generatePartTransform, macroName, isCoord, - version, } - diff --git a/packages/core/src/option.mjs b/packages/core/src/option.mjs index d60aead5c7e..e579e7b5991 100644 --- a/packages/core/src/option.mjs +++ b/packages/core/src/option.mjs @@ -5,4 +5,3 @@ export function Option(config) { return this } - diff --git a/packages/core/src/part.mjs b/packages/core/src/part.mjs index c3693cc1be3..cb4b69462fe 100644 --- a/packages/core/src/part.mjs +++ b/packages/core/src/part.mjs @@ -200,9 +200,10 @@ Part.prototype.shorthand = function () { // Add top-level store methods and add a part name parameter const partName = this.name for (const [key, method] of Object.entries(this.context.store)) { - if (typeof method === 'function') shorthand[key] = function(...args) { - return method(partName, ...args) - } + if (typeof method === 'function') + shorthand[key] = function (...args) { + return method(partName, ...args) + } } // We'll need this @@ -345,16 +346,16 @@ Part.prototype.shorthand = function () { return shorthand } -Part.prototype.generateTransform = function(transforms) { - const {move, rotate, flipX, flipY} = transforms; - const generated = utils.generatePartTransform(move.x, move.y, rotate, flipX, flipY, this); +Part.prototype.generateTransform = function (transforms) { + const { move, rotate, flipX, flipY } = transforms + const generated = utils.generatePartTransform(move.x, move.y, rotate, flipX, flipY, this) for (var t in generated) { - this.attr(t, generated[t], true); + this.attr(t, generated[t], true) } } -Part.prototype.isEmpty = function() { +Part.prototype.isEmpty = function () { if (Object.keys(this.snippets).length > 0) return false if (Object.keys(this.paths).length > 0) { diff --git a/packages/core/src/path.mjs b/packages/core/src/path.mjs index 980f24f0157..640ec93782d 100644 --- a/packages/core/src/path.mjs +++ b/packages/core/src/path.mjs @@ -912,4 +912,3 @@ Path.prototype.translate = function (x, y) { return clone } - diff --git a/packages/core/src/pattern.mjs b/packages/core/src/pattern.mjs index a594d5bd6dc..982f8520110 100644 --- a/packages/core/src/pattern.mjs +++ b/packages/core/src/pattern.mjs @@ -1,6 +1,7 @@ import { Attributes } from './attributes.mjs' import pack from 'bin-pack' import { + addNonEnumProp, macroName, sampleStyle, capitalize, @@ -16,146 +17,108 @@ import { Store } from './store.mjs' import { Hooks } from './hooks.mjs' import { version } from '../data.mjs' -/* - * Makes sure an object passed to be attached as a part it not merely a method - */ -const decoratePartDependency = (obj, name) => (typeof obj === 'function') ? { draft: obj, name } : obj +export function Pattern(config) { + // Non-enumerable properties + addNonEnumProp(this, 'plugins', {}) + addNonEnumProp(this, 'width', 0) + addNonEnumProp(this, 'height', 0) + addNonEnumProp(this, 'autoLayout', { parts: {} }) + addNonEnumProp(this, 'is', '') + addNonEnumProp(this, 'hooks', new Hooks()) + addNonEnumProp(this, 'Point', Point) + addNonEnumProp(this, 'Path', Path) + addNonEnumProp(this, 'Snippet', Snippet) + addNonEnumProp(this, 'Attributes', Attributes) + addNonEnumProp(this, 'macros', {}) + addNonEnumProp(this, '__parts', {}) + addNonEnumProp(this, '__inject', {}) + addNonEnumProp(this, '__dependencies', {}) + addNonEnumProp(this, '__resolvedDependencies', {}) + addNonEnumProp(this, '__draftOrder', []) + addNonEnumProp(this, '__hide', {}) - -export function Pattern(config = { options: {} }) { - - // Apply default settings - this.settings = { - complete: true, - idPrefix: 'fs-', - locale: 'en', - units: 'metric', - margin: 2, - scale: 1, - layout: true, - debug: false, - options: {}, - absoluteOptions: {}, - } - - // Object to hold events - this.events = { - debug: [], - error: [], - info: [], - suggestion: [], - warning: [], - } - - // Keep track of loaded plugins - this.plugins = {} - - // Raise methods - Make events and settings avialable in them - const events = this.events - const settings = this.settings - this.raise = { - debug: function (data) { - // Debug only if debug is active - if (settings.debug) events.debug.push(data) - }, - error: function (data) { - events.error.push(data) - }, - info: function (data) { - events.info.push(data) - }, - suggestion: function (data) { - events.info.push(data) - }, - warning: function (data) { - events.warning.push(data) - }, - } - - // Say hi - const name = config?.data?.name || 'No Name' - const patversion = config?.data?.version || 'No Version' - this.raise.info( - `New \`${name}:${patversion}\` pattern using \`@freesewing/core:${version}\`` - ) - - // More things that go in a pattern - this.config = config // Pattern configuration - this.width = 0 // Will be set after render - this.height = 0 // Will be set after render - this.is = '' // Will be set when drafting/sampling - this.autoLayout = { parts: {} } // Will hold auto-generated layout - this.cutList = {} // Will hold the cutlist - this.store = new Store([[ 'log', this.raise]]) // Store for sharing data across parts + // Enumerable properties + this.config = config // Design config this.parts = {} // Parts container - this.hooks = new Hooks() // Hooks container - this.Point = Point // Point constructor - this.Path = Path // Path constructor - this.Snippet = Snippet // Snippet constructor - this.Attributes = Attributes // Attributes constructor - this.initialized = 0 // Keep track of init calls - this.macros = {} // Macros + this.store = new Store() // Store for sharing data across parts - if (typeof this.config.dependencies === 'undefined') this.config.dependencies = {} - if (typeof this.config.inject === 'undefined') this.config.inject = {} - if (typeof this.config.hide === 'undefined') this.config.hide = [] + return this +} - // Convert options - this.addOptions(config.options) - if (this.config.parts) { - for (const partName in this.config.parts) { - if (this.config.parts[partName].options) this.addOptions(this.config.parts[partName].options) - } - } +/* + * We allow late-stage updating of the design config (adding parts for example) + * so we need to do the things we used to do in the contructor at a later stage. + * This methods does that, and resolves the design config + user settings + * Defer some things that used to happen in the constructor to + * and in doing so creating a pattern we can draft + */ +Pattern.prototype.init = function () { + // Resolve configuration + this.__resolveParts() // Resolves parts + .__resolveDependencies() // Resolves dependencies + .__resolveDraftOrder() // Resolves draft order + .__loadPlugins() // Loads plugins + .__filterOptionalMeasurements() // Removes required m's from optional list + .__loadConfigData() // Makes config data available in store + .__loadOptionDefaults() // Merges default options with user provided ones + // Say hello + this.store.log.info( + `New \`${this.store.get('data.name', 'No Name')}:` + + `${this.store.get('data.version', 'No version')}\` pattern using \`@freesewing/core:${version}\`` + ) + this.store.log.info(`Pattern initialized. Draft order is: ${this.__draftOrder.join(', ')}`) + + return this +} + +Pattern.prototype.__loadConfigData = function () { + if (this.config.data) this.store.set('data', this.config.data) + + return this +} + +Pattern.prototype.__createPartWithContext = function (name) { // Context object to add to Part closure - const context = { + const part = new Part() + part.name = name + part.context = { parts: this.parts, config: this.config, settings: this.settings, store: this.store, macros: this.macros, - events: this.events, - raise: this.raise, } - // Part closure - this.Part = function (name = false) { - let part = new Part() - part.context = context - for (let macro in context.macros) { - part[macroName(macro)] = context.macros[macro] - } - if (name) part.name = name - - return part + for (const macro in this.macros) { + part[macroName(macro)] = this.macros[macro] } + + return part } -// Converts/adds options -Pattern.prototype.addOptions = function(options={}) { - for (const i in options) { - // Add to config - const option = options[i] - this.config.options[i] = option - if (typeof option === 'object') { - if (typeof option.pct !== 'undefined') this.settings.options[i] = option.pct / 100 - else if (typeof option.mm !== 'undefined') this.settings.options[i] = option.mm - else if (typeof option.deg !== 'undefined') this.settings.options[i] = option.deg - else if (typeof option.count !== 'undefined') this.settings.options[i] = option.count - else if (typeof option.bool !== 'undefined') this.settings.options[i] = option.bool - else if (typeof option.dflt !== 'undefined') this.settings.options[i] = option.dflt - else { - let err = 'Unknown option type: ' + JSON.stringify(option) - this.raise.error(err) - throw new Error(err) - } - } else { - this.settings.options[i] = option +// Merges default for options with user-provided options +Pattern.prototype.__loadOptionDefaults = function () { + if (Object.keys(this.config.options).length < 1) return this + for (const [name, option] of Object.entries(this.config.options)) { + // Don't overwrite user-provided settings.options + if (typeof this.settings.options[name] === 'undefined') { + if (typeof option === 'object') { + if (typeof option.pct !== 'undefined') this.settings.options[name] = option.pct / 100 + else if (typeof option.mm !== 'undefined') this.settings.options[name] = option.mm + else if (typeof option.deg !== 'undefined') this.settings.options[name] = option.deg + else if (typeof option.count !== 'undefined') this.settings.options[name] = option.count + else if (typeof option.bool !== 'undefined') this.settings.options[name] = option.bool + else if (typeof option.dflt !== 'undefined') this.settings.options[name] = option.dflt + else { + let err = 'Unknown option type: ' + JSON.stringify(option) + this.store.log.error(err) + throw new Error(err) + } + } else this.settings.options[name] = option } } - // Make it chainable return this } @@ -171,37 +134,6 @@ Pattern.prototype.getPartList = function () { return Object.keys(this.config.parts) || [] } - -/* - * Defer some things that used to happen in the constructor to - * facilitate late-stage adding of parts - */ -Pattern.prototype.init = function () { - this.initialized++ - // Resolve all dependencies - this.dependencies = this.config.dependencies - this.inject = this.config.inject - this.__parts = this.config.parts - this.preresolveDependencies() - this.resolvedDependencies = this.resolveDependencies(this.dependencies) - this.config.resolvedDependencies = this.resolvedDependencies - this.config.draftOrder = this.draftOrder(this.resolvedDependencies) - // Load plugins - if (this.config.plugins) { - for (const plugin of Object.values(this.config.plugins)) this.use(plugin) - } - - // Make all parts uniform - if (this.__parts) { - for (const [key, value] of Object.entries(this.__parts)) { - this.__parts[key] = decoratePartDependency(value) - } - } - - return this -} - - function snappedOption(option, pattern) { const conf = pattern.config.options[option] const abs = conf.toAbs(pattern.settings.options[option], pattern.settings) @@ -232,34 +164,11 @@ function snappedOption(option, pattern) { return abs } -// Merges settings object with this.settings -Pattern.prototype.apply = function (settings) { - if (typeof settings !== 'object') { - this.raise.warning('Pattern instantiated without any settings') - return this - } - for (let key of Object.keys(settings)) { - if (Array.isArray(settings[key])) { - if (Array.isArray(this.settings[key])) { - for (let entry of settings[key]) this.settings[key].push(entry) - } else this.settings[key] = settings[key] - } else if (typeof settings[key] === 'object') { - this.settings[key] = { - ...this.settings[key], - ...settings[key], - } - } else this.settings[key] = settings[key] - } - if (!this.settings.debug) this.debug = false - - return this -} - Pattern.prototype.runHooks = function (hookName, data = false) { if (data === false) data = this let hooks = this.hooks[hookName] if (hooks.length > 0) { - this.raise.debug(`Running \`${hookName}\` hooks`) + this.store.log.debug(`Running \`${hookName}\` hooks`) for (let hook of hooks) { hook.method(data, hook.data) } @@ -274,11 +183,9 @@ Pattern.prototype.addPart = function (part) { if (part.name) { this.config.parts[part.name] = part // Add part-level config to config - this.config = addPartConfig(part, this.config, this.raise) - } - else this.raise.error(`Part must have a name`) - } - else this.raise.error(`Part must have a draft() method`) + this.config = addPartConfig(part, this.config, this.store) + } else this.store.log.error(`Part must have a name`) + } else this.store.log.error(`Part must have a draft() method`) return this } @@ -293,7 +200,7 @@ Pattern.prototype.draft = function () { if (this.is !== 'sample') { this.is = 'draft' this.cutList = {} - this.raise.debug(`Drafting pattern`) + this.store.log.debug(`Drafting pattern`) } // Handle snap for pct options for (let i in this.settings.options) { @@ -308,23 +215,18 @@ Pattern.prototype.draft = function () { this.runHooks('preDraft') // Don't forget about parts without any dependencies - const allParts = [...new Set([ - ...this.config.draftOrder, - ...Object.keys(this.__parts) - ])] + const allParts = [...new Set([...this.config.draftOrder, ...Object.keys(this.__parts)])] for (const partName of allParts) { // Create parts - this.raise.debug(`Creating part \`${partName}\``) - this.parts[partName] = new this.Part(partName) + this.store.log.debug(`Creating part \`${partName}\``) + this.parts[partName] = this.__createPartWithContext(partName) // Handle inject/inheritance if (typeof this.inject[partName] === 'string') { - this.raise.debug( - `Injecting part \`${this.inject[partName]}\` into part \`${partName}\`` - ) + this.store.log.debug(`Injecting part \`${this.inject[partName]}\` into part \`${partName}\``) try { this.parts[partName].inject(this.parts[this.inject[partName]]) } catch (err) { - this.raise.error([ + this.store.log.error([ `Could not inject part \`${this.inject[partName]}\` into part \`${partName}\``, err, ]) @@ -337,18 +239,17 @@ Pattern.prototype.draft = function () { this.parts[partName] = this.__parts[partName].draft(this.parts[partName]) if (this.parts[partName].render) this.cutList[partName] = this.parts[partName].cut } catch (err) { - this.raise.error([`Unable to draft part \`${partName}\``, err]) + this.store.log.error([`Unable to draft part \`${partName}\``, err]) } - } - else this.raise.error(`Unable to draft pattern. Part.draft() is not callable`) + } else this.store.log.error(`Unable to draft pattern. Part.draft() is not callable`) try { this.parts[partName].render = this.parts[partName].render === false ? false : this.wants(partName) } catch (err) { - this.raise.error([`Unable to set \`render\` property on part \`${partName}\``, err]) + this.store.log.error([`Unable to set \`render\` property on part \`${partName}\``, err]) } } else { - this.raise.debug( + this.store.log.debug( `Part \`${partName}\` is not needed. Skipping draft and setting render to \`false\`` ) this.parts[partName].render = false @@ -430,7 +331,7 @@ Pattern.prototype.sampleRun = function (parts, anchors, run, runs, extraClass = */ Pattern.prototype.sampleOption = function (optionName) { this.is = 'sample' - this.raise.debug(`Sampling option \`${optionName}\``) + this.store.log.debug(`Sampling option \`${optionName}\``) this.runHooks('preSample') let step, val let factor = 1 @@ -480,13 +381,13 @@ Pattern.prototype.sampleListOption = function (optionName) { */ Pattern.prototype.sampleMeasurement = function (measurementName) { this.is = 'sample' - this.raise.debug(`Sampling measurement \`${measurementName}\``) + this.store.log.debug(`Sampling measurement \`${measurementName}\``) this.runHooks('preSample') let anchors = {} let parts = this.sampleParts() let val = this.settings.measurements[measurementName] if (val === undefined) - this.raise.error(`Cannot sample measurement \`${measurementName}\` because it's \`undefined\``) + this.store.log.error(`Cannot sample measurement \`${measurementName}\` because it's \`undefined\``) let step = val / 50 val = val * 0.9 for (let run = 1; run < 11; run++) { @@ -505,7 +406,7 @@ Pattern.prototype.sampleMeasurement = function (measurementName) { */ Pattern.prototype.sampleModels = function (models, focus = false) { this.is = 'sample' - this.raise.debug(`Sampling models`) + this.store.log.debug(`Sampling models`) this.runHooks('preSample') let anchors = {} let parts = this.sampleParts() @@ -545,46 +446,53 @@ Pattern.prototype.on = function (hook, method, data) { return this } -Pattern.prototype.loadPlugin = function (plugin, data, explicit=false) { - this.plugins[plugin.name] = plugin - if (plugin.hooks) this.loadPluginHooks(plugin, data) - if (plugin.macros) this.loadPluginMacros(plugin) - if (plugin.store) this.loadPluginStoreMethods(plugin) - this.raise.info(`Loaded plugin \`${plugin.name}:${plugin.version}\``) +Pattern.prototype.__loadPlugins = function () { + for (const plugin of this.config.plugins) this.use(plugin) return this } +Pattern.prototype.__loadPlugin = function (plugin, data, explicit = false) { + this.plugins[plugin.name] = plugin + if (plugin.hooks) this.__loadPluginHooks(plugin, data) + if (plugin.macros) this.__loadPluginMacros(plugin) + if (plugin.store) this.__loadPluginStoreMethods(plugin) + this.store.log.info(`Loaded plugin \`${plugin.name}:${plugin.version}\``) + + return this +} Pattern.prototype.use = function (plugin, data) { - // Existing plugin - But we may still need to load it - // if it was previously loaded conditionally, and is now loaded explicitly if (this.plugins?.[plugin.name]?.condition && !plugin.condition) { - this.raise.info( + // Plugin was first loaded conditionally, and is now loaded explicitly + this.store.log.info( `Plugin \`${plugin.plugin.name} was loaded conditionally earlier, but is now loaded explicitly.` ) - return this.loadPlugin(plugin, data) + return this.__loadPlugin(plugin, data) } - // New plugin? - else if (!this.plugins?.[plugin.name]) return (plugin.plugin && plugin.condition) - ? this.useIf(plugin, data) // Conditional plugin - : this.loadPlugin(plugin, data) // Regular plugin + // New plugin + else if (!this.plugins?.[plugin.name]) + return plugin.plugin && plugin.condition + ? this.__useIf(plugin, data) // Conditional plugin + : this.__loadPlugin(plugin, data) // Regular plugin - this.raise.info( - `Plugin \`${plugin.plugin ? plugin.plugin.name : plugin.name}\` was requested, but it's already loaded. Skipping.` + this.store.log.info( + `Plugin \`${ + plugin.plugin ? plugin.plugin.name : plugin.name + }\` was requested, but it's already loaded. Skipping.` ) return this } -Pattern.prototype.useIf = function (plugin, settings) { +Pattern.prototype.__useIf = function (plugin, settings) { if (plugin.condition(settings)) { - this.raise.info( + this.store.log.info( `Condition met: Loaded plugin \`${plugin.plugin.name}:${plugin.plugin.version}\`` ) - this.loadPlugin(plugin.plugin, plugin.data) + this.__loadPlugin(plugin.plugin, plugin.data) } else { - this.raise.info( + this.store.log.info( `Condition not met: Skipped loading plugin \`${plugin.plugin.name}:${plugin.plugin.version}\`` ) } @@ -592,7 +500,7 @@ Pattern.prototype.useIf = function (plugin, settings) { return this } -Pattern.prototype.loadPluginHooks = function (plugin, data) { +Pattern.prototype.__loadPluginHooks = function (plugin, data) { for (let hook of Object.keys(this.hooks)) { if (typeof plugin.hooks[hook] === 'function') { this.on(hook, plugin.hooks[hook], data) @@ -604,7 +512,7 @@ Pattern.prototype.loadPluginHooks = function (plugin, data) { } } -Pattern.prototype.loadPluginMacros = function (plugin) { +Pattern.prototype.__loadPluginMacros = function (plugin) { for (let macro in plugin.macros) { if (typeof plugin.macros[macro] === 'function') { this.macro(macro, plugin.macros[macro]) @@ -612,9 +520,9 @@ Pattern.prototype.loadPluginMacros = function (plugin) { } } -Pattern.prototype.loadPluginStoreMethods = function (plugin) { +Pattern.prototype.__loadPluginStoreMethods = function (plugin) { if (Array.isArray(plugin.store)) this.store = this.store.extend(...plugin.store) - else this.raise.warning(`Plugin store methods should be an Array`) + else this.store.log.warning(`Plugin store methods should be an Array`) } Pattern.prototype.macro = function (key, method) { @@ -624,7 +532,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) { - this.raise.warning(`One or more errors occured. Not packing pattern parts`) + this.store.log.warning(`One or more errors occured. Not packing pattern parts`) return this } let bins = [] @@ -666,7 +574,7 @@ Pattern.prototype.pack = function () { // Some parts are added by late-stage plugins if (this.parts[partId]) { let transforms = this.settings.layout.parts[partId] - this.parts[partId].generateTransform(transforms); + this.parts[partId].generateTransform(transforms) } } } @@ -675,7 +583,7 @@ Pattern.prototype.pack = function () { } /** Determines the order to draft parts in, based on dependencies */ -Pattern.prototype.draftOrder = function (graph = this.resolveDependencies()) { +Pattern.prototype.__resolveDraftOrder = function (graph = this.__resolvedDependencies) { let sorted = [] let visited = {} Object.keys(graph).forEach(function visit(name, ancestors) { @@ -691,16 +599,19 @@ Pattern.prototype.draftOrder = function (graph = this.resolveDependencies()) { if (sorted.indexOf(name) < 0) sorted.push(name) }) - return sorted + // Don't forget about parts without dependencies + for (const part in this.__parts) { + if (sorted.indexOf(part) === -1) sorted.push(part) + } + + this.__draftOrder = sorted + this.config.draftOrder = sorted + + return this } /** Recursively solves part dependencies for a part */ -Pattern.prototype.resolveDependency = function ( - seen, - part, - graph = this.dependencies, - deps = [] -) { +Pattern.prototype.resolveDependency = function (seen, part, graph = this.dependencies, deps = []) { if (typeof seen[part] === 'undefined') seen[part] = true if (typeof graph[part] === 'string') graph[part] = [graph[part]] if (Array.isArray(graph[part])) { @@ -715,103 +626,97 @@ Pattern.prototype.resolveDependency = function ( } /** Adds a part as a simple dependency **/ -Pattern.prototype.addDependency = function (name, part, dep) { - // FIXME: This causes issues - //if (part.hideDependencies || part.hideAll) { - // dep.hide = true - // dep.hideAll = true - //} - this.dependencies[name] = mergeDependencies(dep.name, this.dependencies[name]) +Pattern.prototype.__addDependency = function (name, part, dep) { + this.__dependencies[name] = mergeDependencies(dep.name, this.__dependencies[name]) if (typeof this.__parts[dep.name] === 'undefined') { - this.__parts[dep.name] = decoratePartDependency(dep) - addPartConfig(this.__parts[dep.name], this.config, this.raise) + this.config = addPartConfig(this.__parts[dep.name], this.config, this.store) } return this } /** Filter optional measurements out if they are also required measurements */ -Pattern.prototype.filterOptionalMeasurements = function () { +Pattern.prototype.__filterOptionalMeasurements = function () { this.config.optionalMeasurements = this.config.optionalMeasurements.filter( - m => this.config.measurements.indexOf(m) === -1 + (m) => this.config.measurements.indexOf(m) === -1 ) return this } /** Pre-Resolves part dependencies that are passed in 2022 style */ -Pattern.prototype.preresolveDependencies = function (count=0) { - if (!this.__parts) return +Pattern.prototype.__resolveParts = function (count = 0) { + if (count === 0) { + for (const part of this.config.parts) { + this.__parts[part.name] = part + } + } for (const [name, part] of Object.entries(this.__parts)) { // Inject (from) if (part.from) { - this.inject[name] = part.from.name + this.__parts[part.from.name] = part.from + this.__inject[name] = part.from.name if (typeof this.__parts[part.from.name] === 'undefined') { - this.__parts[part.from.name] = decoratePartDependency(part.from) if (part.hideDependencies || part.hideAll) { this.__parts[part.from.name].hide = true this.__parts[part.from.name].hideAll = true } - addPartConfig(this.__parts[part.from.name], this.config, this.raise) + //this.config = addPartConfig(this.__parts[part.from.name], this.config, this.store) } } // Simple dependency (after) if (part.after) { if (Array.isArray(part.after)) { - for (const dep of part.after) this.addDependency(name, part, dep) + for (const dep of part.after) { + this.__parts[dep.name] = dep + this.__addDependency(name, part, dep) + } + } else { + this.__parts[part.after.name] = part.after + this.__addDependency(name, part, part.after) } - else this.addDependency(name, part, part.after) } } // Did we discover any new dependencies? const len = Object.keys(this.__parts).length - - if (len > count) return this.preresolveDependencies(len) + // If so, resolve recursively + if (len > count) return this.__resolveParts(len) for (const [name, part] of Object.entries(this.__parts)) { - addPartConfig(part, this.config, this.raise) + this.config = addPartConfig(part, this.config, this.store) } - // Weed out doubles - return this.filterOptionalMeasurements() + return this } /** Resolves part dependencies into a flat array */ -Pattern.prototype.resolveDependencies = function (graph = this.dependencies) { - for (let i in this.inject) { - let dependency = this.inject[i] - if (typeof this.dependencies[i] === 'undefined') this.dependencies[i] = dependency - else if (this.dependencies[i] !== dependency) { - if (typeof this.dependencies[i] === 'string') { - this.dependencies[i] = [this.dependencies[i], dependency] - } else if (Array.isArray(this.dependencies[i])) { - if (this.dependencies[i].indexOf(dependency) === -1) - this.dependencies[i].push(dependency) +Pattern.prototype.__resolveDependencies = function (graph = false) { + if (!graph) graph = this.__dependencies + for (const i in this.__inject) { + const dependency = this.__inject[i] + if (typeof this.__dependencies[i] === 'undefined') this.__dependencies[i] = dependency + else if (this.__dependencies[i] !== dependency) { + if (typeof this.__dependencies[i] === 'string') { + this.__dependencies[i] = [this.__dependencies[i], dependency] + } else if (Array.isArray(this.__dependencies[i])) { + if (this.__dependencies[i].indexOf(dependency) === -1) + this.__dependencies[i].push(dependency) } else { - this.raise.error('Part dependencies should be a string or an array of strings') + this.store.log.error('Part dependencies should be a string or an array of strings') throw new Error('Part dependencies should be a string or an array of strings') } } - // Parts both in the parts and dependencies array trip up the dependency resolver - if (Array.isArray(this.__parts)) { - let pos = this.__parts.indexOf(this.inject[i]) - if (pos !== -1) this.__parts.splice(pos, 1) - } } - // Include parts outside the dependency graph - //if (typeof this.config.parts === 'object') { - // for (const part of Object.values(this.config.parts)) { - // if (typeof part === 'string' && typeof this.dependencies[part] === 'undefined') this.dependencies[part] = [] - // } - //} - let resolved = {} let seen = {} for (let part in graph) resolved[part] = this.resolveDependency(seen, part, graph) for (let part in seen) if (typeof resolved[part] === 'undefined') resolved[part] = [] - return resolved + this.__resolvedDependencies = resolved + this.config.resolvedDependencies = resolved + + return this } /** Determines whether a part is needed @@ -856,7 +761,7 @@ Pattern.prototype.isHidden = function (partName) { */ Pattern.prototype.wants = function (partName) { if (this.isHidden(partName)) return false - else if (typeof this.settings.only === 'string') return (this.settings.only === partName) + else if (typeof this.settings.only === 'string') return this.settings.only === partName else if (Array.isArray(this.settings.only)) { for (const part of this.settings.only) { if (part === partName) return true @@ -916,3 +821,22 @@ Pattern.prototype.getRenderProps = function () { return props } + +// Merges settings object with default settings +Pattern.prototype.__applySettings = function (settings) { + this.settings = { + complete: true, + idPrefix: 'fs-', + locale: 'en', + units: 'metric', + margin: 2, + scale: 1, + layout: true, + debug: false, + options: {}, + absoluteOptions: {}, + ...settings + } + + return this +} diff --git a/packages/core/src/point.mjs b/packages/core/src/point.mjs index f9ff37bf212..a958d9a58de 100644 --- a/packages/core/src/point.mjs +++ b/packages/core/src/point.mjs @@ -135,8 +135,7 @@ 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 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() @@ -234,7 +233,7 @@ Point.prototype.translate = function (x, y) { } /** Chainable way to set the data-text property (and optional class) */ -Point.prototype.setText = function (text = '', className=false) { +Point.prototype.setText = function (text = '', className = false) { this.attributes.set('data-text', text) if (className) this.attributes.set('data-text-class', className) @@ -242,10 +241,9 @@ Point.prototype.setText = function (text = '', className=false) { } /** Chainable way to set the data-circle property (and optional class) */ -Point.prototype.setCircle = function (radius = false, className=false) { +Point.prototype.setCircle = function (radius = false, className = false) { if (radius) this.attributes.set('data-circle', radius) if (className) this.attributes.set('data-circle-class', className) return this } - diff --git a/packages/core/src/snippet.mjs b/packages/core/src/snippet.mjs index 829a6ad29f1..724d547b680 100644 --- a/packages/core/src/snippet.mjs +++ b/packages/core/src/snippet.mjs @@ -30,4 +30,3 @@ Snippet.prototype.clone = function () { return clone } - diff --git a/packages/core/src/store.mjs b/packages/core/src/store.mjs index cb708a8ae79..b1ff749afe3 100644 --- a/packages/core/src/store.mjs +++ b/packages/core/src/store.mjs @@ -4,7 +4,7 @@ import get from 'lodash.get' const avoid = ['set', 'setIfUnset', 'push', 'unset', 'get', 'extend'] -export function Store(methods=[]) { +export function Store(methods = []) { for (const method of methods) { if (avoid.indexOf(method[0]) !== -1) { console.log(`WARNING: You can't squat ${method[0]}in the store`) @@ -96,8 +96,8 @@ Store.prototype.unset = function (path) { } /** Retrieve a key */ -Store.prototype.get = function (path) { - const val = get(this, path) +Store.prototype.get = function (path, dflt) { + const val = get(this, path, dflt) if (typeof val === 'undefined') { this.log.warning(`Store.get(key) on key \`${path}\`, which is undefined`) } diff --git a/packages/core/src/svg.mjs b/packages/core/src/svg.mjs index ae275cd2dee..30b71e2de06 100644 --- a/packages/core/src/svg.mjs +++ b/packages/core/src/svg.mjs @@ -311,4 +311,3 @@ Svg.prototype.getId = function () { return '' + this.freeId } - diff --git a/packages/core/src/utils.mjs b/packages/core/src/utils.mjs index d245f5a424f..92eb46c8cbb 100644 --- a/packages/core/src/utils.mjs +++ b/packages/core/src/utils.mjs @@ -356,16 +356,16 @@ export { Bezier } export function pctBasedOn(measurement) { return { toAbs: (val, { measurements }) => measurements[measurement] * val, - fromAbs: (val, { measurements }) => Math.round((10000 * val) / measurements[measurement]) / 10000, + fromAbs: (val, { measurements }) => + Math.round((10000 * val) / measurements[measurement]) / 10000, } } /** Generates the transform attributes needed for a given part */ export const generatePartTransform = (x, y, rotate, flipX, flipY, part) => { - const transforms = [] - let xTotal = x || 0; - let yTotal = y || 0; + let xTotal = x || 0 + let yTotal = y || 0 let scaleX = 1 let scaleY = 1 @@ -391,8 +391,8 @@ export const generatePartTransform = (x, y, rotate, flipX, flipY, part) => { if (rotate) { // we can put the center as the rotation origin, so get the center const center = { - x: part.topLeft.x + part.width/2, - y: part.topLeft.y + part.height/2, + x: part.topLeft.x + part.width / 2, + y: part.topLeft.y + part.height / 2, } // add the rotation around the center to the transforms @@ -400,9 +400,7 @@ export const generatePartTransform = (x, y, rotate, flipX, flipY, part) => { } // put the translation before any other transforms to avoid having to make complex calculations once the matrix has been rotated or scaled - if (xTotal !== 0 || yTotal !== 0) transforms.unshift( - `translate(${xTotal} ${yTotal})` - ) + if (xTotal !== 0 || yTotal !== 0) transforms.unshift(`translate(${xTotal} ${yTotal})`) return { transform: transforms.join(' '), @@ -410,135 +408,7 @@ export const generatePartTransform = (x, y, rotate, flipX, flipY, part) => { } } -// Add part-level options -const addPartOptions = (part, config) => { - if (part.options) { - for (const optionName in part.options) { - config.options[optionName] = part.options[optionName] - } - } - if (part.from) addPartOptions(part.from, config) - if (part.after) { - if (Array.isArray(part.after)) { - for (const dep of part.after) addPartOptions(dep, config) - } else addPartOptions(part.after, config) - } - - return config -} - -/* -// Helper method for detecting a array with only strings -const isStringArray = val => (Array.isArray(val) && val.length > 0) - ? val.reduce((prev=true, cur) => (prev && typeof cur === 'string')) - : false -// Helper method for detecting an object -const isObject = obj => obj && typeof obj === 'object' - -// Hat-tip to jhildenbiddle => https://stackoverflow.com/a/48218209 -const mergeOptionSubgroup = (...objects) => objects.reduce((prev, obj) => { - Object.keys(obj).forEach(key => { - const pVal = prev[key]; - const oVal = obj[key]; - - if (Array.isArray(pVal) && Array.isArray(oVal)) { - prev[key] = pVal.concat(...oVal); - } - else if (isObject(pVal) && isObject(oVal)) { - prev[key] = mergeOptionSubgroup(pVal, oVal); - } - else { - prev[key] = oVal; - } - }) - - return prev -}, {}) - -const mergeOptionGroups = (cur, add) => { - if (isStringArray(cur) && isStringArray(add)) return [...new Set([...cur, ...add])] - else if (!Array.isArray(cur) && !Array.isArray(add)) return mergeOptionSubgroup(cur, add) - else { - const all = [...cur] - for (const entry of add) { - if (typeof add === 'string' && all.indexOf(entry) === -1) all.push(entry) - else all.push(entry) - } - return all - } - - return cur -} -*/ -// Add part-level optionGroups -const addPartOptionGroups = (part, config) => { - if (typeof config.optionGroups === 'undefined') { - if (part.optionGroups) config.optionGroups = part.optionGroups - return config - } - if (part.optionGroups) { - for (const group in part.optionGroups) { - if (typeof config.optionGroups[group] === 'undefined') config.optionGroups[group] = part.optionGroups[group] - else config.optionGroups[group] = mergeOptionGroups(config.optionGroups[group], part.optionGroups[group]) - } - } - if (part.from) addPartOptionGroups(part.from, config) - if (part.after) { - if (Array.isArray(part.after)) { - for (const dep of part.after) addPartOptionGroups(dep, config) - } else addPartOptionGroups(part.after, config) - } - - return config -} - -// Add part-level measurements -const addPartMeasurements = (part, config, raise, list=false) => { - if (!list) list = config.measurements - ? [...config.measurements] - : [] - if (part.measurements) { - for (const m of part.measurements) list.push(m) - } - if (part.from) addPartMeasurements(part.from, config, raise, list) - if (part.after) { - if (Array.isArray(part.after)) { - for (const dep of part.after) addPartMeasurements(dep, config, raise, list) - } else addPartMeasurements(part.after, config, raise, list) - } - - // Weed out duplicates - config.measurements = [...new Set(list)] - - return config -} - -// Add part-level optional measurements -const addPartOptionalMeasurements = (part, config, raise, list=false) => { - if (!list) list = config.optionalMeasurements - ? [...config.optionalMeasurements] - : [] - if (part.optionalMeasurements) { - for (const m of part.optionalMeasurements) { - // Don't add it's a required measurement for another part - if (config.measurements.indexOf(m) === -1) list.push(m) - } - } - if (part.from) addPartOptionalMeasurements(part.from, config, list) - if (part.after) { - if (Array.isArray(part.after)) { - for (const dep of part.after) addPartOptionalMeasurements(dep, config, list) - } else addPartOptionalMeasurements(part.after, config, list) - } - - // Weed out duplicates - config.optionalMeasurements = [...new Set(list)] - - return config -} - - -export const mergeDependencies = (dep=[], current=[]) => { +export const mergeDependencies = (dep = [], current = []) => { // Current dependencies const list = [] if (Array.isArray(current)) list.push(...current) @@ -557,43 +427,129 @@ export const mergeDependencies = (dep=[], current=[]) => { return deps } -// Add part-level dependencies -export const addPartDependencies = (part, config) => { +// Decorate an object with a non-enumerable property +export function addNonEnumProp(obj, name, value) { + Object.defineProperty(obj, name, { + enumerable: false, + configurable: false, + writable: true, + value, + }) +} + +// Add part-level options +const addPartOptions = (part, config, store) => { + if (part.options) { + for (const optionName in part.options) { + store.log.debug(`Config resolver: Option __${optionName}__ in ${part.name}`) + config.options[optionName] = part.options[optionName] + } + } + if (part.from) addPartOptions(part.from, config, store) if (part.after) { - if (typeof config.dependencies === 'undefined') config.dependencies = {} - config.dependencies[part.name] = mergeDependencies(config.dependencies[part.name], part.after) + if (Array.isArray(part.after)) { + for (const dep of part.after) addPartOptions(dep, config, store) + } else addPartOptions(part.after, config, store) } return config } +// Add part-level measurements +const addPartMeasurements = (part, config, store, list = false) => { + if (!list) list = config.measurements ? [...config.measurements] : [] + if (part.measurements) { + for (const m of part.measurements) { + list.push(m) + store.log.debug(`Config resolver: Measurement __${m}__ is required in ${part.name}`) + } + } + if (part.from) addPartMeasurements(part.from, config, store, list) + if (part.after) { + if (Array.isArray(part.after)) { + for (const dep of part.after) addPartMeasurements(dep, config, store, list) + } else addPartMeasurements(part.after, config, store, list) + } + + // Weed out duplicates + config.measurements = [...new Set(list)] + + return config +} + +// Add part-level optional measurements +const addPartOptionalMeasurements = (part, config, store, list = false) => { + if (!list) list = config.optionalMeasurements ? [...config.optionalMeasurements] : [] + if (part.optionalMeasurements) { + for (const m of part.optionalMeasurements) { + // Don't add it's a required measurement for another part + if (config.measurements.indexOf(m) === -1) { + store.log.debug(`Config resolver: Measurement __${m}__ is optional in ${part.name}`) + list.push(m) + } + } + } + if (part.from) addPartOptionalMeasurements(part.from, config, store, list) + if (part.after) { + if (Array.isArray(part.after)) { + for (const dep of part.after) addPartOptionalMeasurements(dep, config, store, list) + } else addPartOptionalMeasurements(part.after, config, store, list) + } + + // Weed out duplicates + config.optionalMeasurements = [...new Set(list)] + + return config +} + +// Add part-level dependencies +//export const addPartDependencies = (part, config, store) => { +// if (part.after) { +// if (typeof config.dependencies === 'undefined') config.dependencies = {} +// config.dependencies[part.name] = mergeDependencies(config.dependencies[part.name], part.after) +// } +// +// return config +//} + // Add part-level plugins -export const addPartPlugins = (part, config, raise) => { +export const addPartPlugins = (part, config, store) => { + const plugins = {} if (!part.plugins) return config - if (!Array.isArray(part.plugins)) part.plugins = [ part.plugins ] + for (const plugin of config.plugins) plugins[plugin.name] = plugin + if (!Array.isArray(part.plugins)) part.plugins = [part.plugins] for (const plugin of part.plugins) { + store.log.debug(`Config resolver: Plugin __${plugin.name}__ in ${part.name}`) // Do not overwrite an existing plugin with a conditional plugin unless it is also conditional if (plugin.plugin && plugin.condition) { - if (config.plugins[plugin.plugin.name]?.condition) { - raise.info(`Plugin \`${plugin.plugin.name}\` was re-requested conditionally. Overwriting earlier condition.`) - config.plugins[plugin.plugin.name] = plugin - } - else raise.info(`Plugin \`${plugin.plugin.name}\` was requested conditionally, but is already loaded explicitly. Not loading.`) + if (plugins[plugin.plugin.name]?.condition) { + store.log.info( + `Plugin \`${plugin.plugin.name}\` was re-requested conditionally. Overwriting earlier condition.` + ) + plugins[plugin.plugin.name] = plugin + } else + store.log.info( + `Plugin \`${plugin.plugin.name}\` was requested conditionally, but is already loaded explicitly. Not loading.` + ) + } else { + plugins[plugin.name] = plugin + } } - else config.plugins[plugin.name] = plugin + + return { + ...config, + plugins: [...new Set(Object.values(plugins))] } +} + +export const addPartConfig = (part, config, store) => { + // Add parts, using set to keep them unique in the array + config.parts = [...new Set(config.parts).add(part)] + config = addPartOptions(part, config, store) + config = addPartMeasurements(part, config, store) + config = addPartOptionalMeasurements(part, config, store) + //config = addPartDependencies(part, config, store) + config = addPartPlugins(part, config, store) return config } - -export const addPartConfig = (part, config, raise) => { - config = addPartOptions(part, config, raise) - config = addPartMeasurements(part, config, raise) - config = addPartOptionalMeasurements(part, config, raise) - config = addPartDependencies(part, config, raise) - config = addPartOptionGroups(part, config, raise) - config = addPartPlugins(part, config, raise) - - return config -} - diff --git a/packages/core/tests/attributes.test.mjs b/packages/core/tests/attributes.test.mjs index 318d56e52e0..49cdd724ce6 100644 --- a/packages/core/tests/attributes.test.mjs +++ b/packages/core/tests/attributes.test.mjs @@ -1,86 +1,76 @@ -import chai from "chai" -import { Point } from "./dist/index.mjs" +import chai from 'chai' +import { Point } from '../src/index.mjs' const expect = chai.expect -const newAttr = () => new Point(0, 0).attributes; +const newAttr = () => new Point(0, 0).attributes -const a = newAttr(); +const a = newAttr() describe('Attributes', () => { - it("Should set an attribute", () => { + it('Should set an attribute', () => { a.set('hold', 'me') - expect(a.get("hold")).to.equal('me'); - }); + expect(a.get('hold')).to.equal('me') + }) - it("Should remove an attribute", () => { + it('Should remove an attribute', () => { a.remove('hold') - expect(a.get("hold")).to.equal(false); - }); + expect(a.get('hold')).to.equal(false) + }) - it("Should only set an unset attribute", () => { + it('Should only set an unset attribute', () => { a.setIfUnset('hold', 'me') - expect(a.get("hold")).to.equal('me'); + expect(a.get('hold')).to.equal('me') a.setIfUnset('hold', 'thatDudeOverThere') - expect(a.get("hold")).to.equal('me'); - }); + expect(a.get('hold')).to.equal('me') + }) - it("Should return false when getting an unset attribute", () => { - let a = newAttr(); - expect(a.get("test")).to.equal(false); - }); - - it("Should render attributes correctly", () => { + it('Should return false when getting an unset attribute', () => { let a = newAttr() - .set("class", "test") - .add("class", "render") - .set("transform", "scale(1)"); - expect(a.render()).to.equal(' class="test render" transform="scale(1)"'); - }); + expect(a.get('test')).to.equal(false) + }) - it("Should render attributes with given prefix only", () => { + it('Should render attributes correctly', () => { + let a = newAttr().set('class', 'test').add('class', 'render').set('transform', 'scale(1)') + expect(a.render()).to.equal(' class="test render" transform="scale(1)"') + }) + + it('Should render attributes with given prefix only', () => { let a = newAttr() - .set("class", "test") - .add("class", "render") - .add("data-text", "foo") - .add("data-text", "bar") - .add("data-mode", "test") - .set("transform", "scale(1)"); - expect(a.renderIfPrefixIs("data-")).to.equal(' text="foo bar" mode="test"'); - }); + .set('class', 'test') + .add('class', 'render') + .add('data-text', 'foo') + .add('data-text', 'bar') + .add('data-mode', 'test') + .set('transform', 'scale(1)') + expect(a.renderIfPrefixIs('data-')).to.equal(' text="foo bar" mode="test"') + }) - it("Should return attributes as array", () => { - let a = newAttr() - .set("class", "test") - .add("class", "render"); - expect(JSON.stringify(a.getAsArray("class"))).to.equal( - JSON.stringify(["test", "render"]) - ); - expect(a.getAsArray("nope")).to.equal(false); - }); + it('Should return attributes as array', () => { + let a = newAttr().set('class', 'test').add('class', 'render') + expect(JSON.stringify(a.getAsArray('class'))).to.equal(JSON.stringify(['test', 'render'])) + expect(a.getAsArray('nope')).to.equal(false) + }) - it("Should render attributes as CSS", () => { - let a = newAttr() - .set("line-height", 1.2) - .add("border", "1px solid red"); - expect(a.renderAsCss()).to.equal(" line-height:1.2; border:1px solid red;"); - }); + it('Should render attributes as CSS', () => { + let a = newAttr().set('line-height', 1.2).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", () => { + 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"); + .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"); - }); + 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"); + 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"); - }); + expect(props.className).to.equal('fabric') + }) }) - diff --git a/packages/core/tests/design.test.mjs b/packages/core/tests/design.test.mjs index afa54a29efe..98225bd8ff3 100644 --- a/packages/core/tests/design.test.mjs +++ b/packages/core/tests/design.test.mjs @@ -1,113 +1,53 @@ -import chai from "chai" -import { Design } from "./dist/index.mjs" +import chai from 'chai' +import { Design } from '../src/index.mjs' const expect = chai.expect +const arrays = ['measurements', 'optionalMeasurements', 'parts', 'plugins'] + describe('Design', () => { - it("Design constructor should return pattern constructor", () => { - const design = new Design({ - foo: "bar", + it('Design constructor should return pattern constructor', () => { + const Pattern = new Design() + expect(typeof Pattern).to.equal('function') + }) + + it('Design constructor should load the default config', () => { + const Pattern = new Design() + const config = Pattern.config + for (const key of arrays) { + expect(Array.isArray(config[key])).to.equal(true) + expect(config[key].length).to.equal(0) + } + expect(typeof config.options).to.equal('object') + expect(Object.keys(config.options).length).to.equal(0) + }) + + for (const key of arrays) { + it(`Design constructor should add ${key} to config`, () => { + const settings = {} + settings[key] = ['one', 'two'] + const Pattern = new Design(settings) + const m = Pattern.config.parts + expect(Pattern.config[key].length).to.equal(2) + expect(Pattern.config[key][0]).to.equal('one') + expect(Pattern.config[key][1]).to.equal('two') + }) + } + it(`Design constructor should add options to config`, () => { + const settings = { options: { - constant: 2, - percentage: { pct: 30, min: 0, max: 100 } - } - }); - - const pattern = new design(); - expect(pattern.width).to.equal(0); - expect(pattern.height).to.equal(0); - expect(pattern.settings.complete).to.equal(true); - expect(pattern.parts).to.eql({}); - expect(pattern.settings.units).to.equal("metric"); - expect(pattern.config.foo).to.equal("bar"); - expect(pattern.settings.options.constant).to.equal(2); - expect(pattern.settings.options.percentage).to.equal(0.3); - }); - - /* - it("Design constructor should not require depencies for injected parts", () => { - let design = new freesewing.Design({ - inject: { step4: "step3" }, - parts: ["step1", "step2"] - }); - let pattern = new design().init(); - expect(pattern.config.draftOrder[0]).to.equal("step3"); - expect(pattern.config.draftOrder[1]).to.equal("step4"); - expect(pattern.config.draftOrder[2]).to.equal("step1"); - expect(pattern.config.draftOrder[3]).to.equal("step2"); - }); - - it("Design constructor should handle parts and dependencies overlap", () => { - let design = new freesewing.Design({ - inject: { step4: "step3" }, - parts: ["step1", "step2", "step3"] - }); - let pattern = new design().init(); - expect(pattern.config.draftOrder[0]).to.equal("step3"); - expect(pattern.config.draftOrder[1]).to.equal("step4"); - expect(pattern.config.draftOrder[2]).to.equal("step1"); - expect(pattern.config.draftOrder[3]).to.equal("step2"); - }); - - it("Design constructor discover all parts", () => { - let design = new freesewing.Design({ - inject: { - step4: "step3", - step5: "step4", - step6: "step5", - step7: "step6", - step8: "step7", - step9: "step8", - step10: "step9", - step11: "step10" + one: { pct: 50, min: 0, max: 100 }, + two: { deg: 10, min: 5, max: 15 }, }, - hide: [], - parts: ["step1", "step2"] - }); - let pattern = new design().init(); - expect(pattern.config.draftOrder[0]).to.equal("step3"); - expect(pattern.config.draftOrder[1]).to.equal("step4"); - expect(pattern.config.draftOrder[2]).to.equal("step5"); - expect(pattern.config.draftOrder[3]).to.equal("step6"); - expect(pattern.config.draftOrder[4]).to.equal("step7"); - expect(pattern.config.draftOrder[5]).to.equal("step8"); - expect(pattern.config.draftOrder[6]).to.equal("step9"); - expect(pattern.config.draftOrder[7]).to.equal("step10"); - expect(pattern.config.draftOrder[8]).to.equal("step11"); - expect(pattern.config.draftOrder[9]).to.equal("step1"); - expect(pattern.config.draftOrder[10]).to.equal("step2"); - }); - - it("Design constructor should handle Simon", () => { - let design = new freesewing.Design({ - dependencies: { - sleeve: ["front", "back"] - }, - inject: { - frontBase: "base", - backBase: "base", - back: "backBase", - front: "frontBase", - frontRight: "front", - frontLeft: "front", - buttonPlacket: "front", - buttonholePlacket: "front", - yoke: "backBase", - sleeve: "sleeveBase" - }, - parts: [ - "collarStand", - "collar", - "sleevePlacketUnderlap", - "sleevePlacketOverlap", - "cuff" - ], - hide: ["base", "frontBase", "front", "backBase", "sleeveBase"] - }); - let pattern = new design().init(); - }); - - */ - + } + const Pattern = new Design(settings) + const o = Pattern.config.options + expect(Object.keys(o).length).to.equal(2) + expect(o.one.pct).to.equal(50) + expect(o.one.min).to.equal(0) + expect(o.one.max).to.equal(100) + expect(o.two.deg).to.equal(10) + expect(o.two.min).to.equal(5) + expect(o.two.max).to.equal(15) + }) }) - diff --git a/packages/core/tests/hooks.test.mjs b/packages/core/tests/hooks.test.mjs index 5f256cd37df..e2f229d24fc 100644 --- a/packages/core/tests/hooks.test.mjs +++ b/packages/core/tests/hooks.test.mjs @@ -1,12 +1,12 @@ -import chai from "chai" -import { Pattern } from "./dist/index.mjs" +import chai from 'chai' +import { Pattern } from '../src/index.mjs' const expect = chai.expect describe('Hooks', () => { - it("Should contain all hooks", () => { - const pattern = new Pattern(); - const h = pattern.hooks; + it('Should contain all hooks', () => { + const pattern = new Pattern() + const h = pattern.hooks const test = { preDraft: [], postDraft: [], @@ -16,7 +16,7 @@ describe('Hooks', () => { preRender: [], postRender: [], insertText: [], - }; - expect(h).to.eql(test); - }); -}); + } + expect(h).to.eql(test) + }) +}) diff --git a/packages/core/tests/new.test.mjs b/packages/core/tests/new.test.mjs new file mode 100644 index 00000000000..095f8e84cbc --- /dev/null +++ b/packages/core/tests/new.test.mjs @@ -0,0 +1,146 @@ +import chai from 'chai' +import { Design } from '../src/index.mjs' +import { pluginBundle } from '@freesewing/plugin-bundle' + +const expect = chai.expect + +const fabricLines = { + name: 'legend.fabricLines', + plugins: pluginBundle, + draft: legendFabricLines, +} +const lineStrokes = { + name: 'legend.lineStrokes', + plugins: pluginBundle, + //after: fabricLines, + draft: legendLineStrokes, +} +const lineWidths = { + name: 'legend.lineWidths', + plugins: pluginBundle, + //from: lineStrokes, + draft: legendLineWidths, + options: { + waistEase: { pct: 12, min: 0, max: 100 }, + }, +} +const saLines = { + name: 'legend.saLines', + plugins: pluginBundle, + draft: legendSaLines, +} +const otherLines = { + name: 'legend.otherLines', + plugins: pluginBundle, + draft: legendOtherLines, +} + +const parts = [otherLines, saLines, fabricLines, lineStrokes, lineWidths] + +describe('Design', () => { + it('FIXME', () => { + const Pattern = new Design({ + data: { foo: 'bar' }, + parts, + }) + + const pattern = new Pattern({ + paperless: true, + }) + pattern.init() + console.log(pattern.store.logs) + //console.log('plugins:', pattern.config.plugins) + }) +}) + +const allFabricTypes = ['fabric', 'lining', 'canvas', 'interfacing', 'various'] +const allLineTypes = ['note', 'mark', 'contrast', 'help'] +const allLineStrokes = ['dotted', 'dashed', 'lashed'] +const allLineWidths = ['stroke-xs', 'stroke-sm', 'default', 'stroke-lg', 'stroke-xl', 'stroke-xxl'] + +function legendFabricLines(part) { + let y = 10 + for (const t of allFabricTypes) { + drawLine(part, y, t) + y += 15 + } + + return box(part, 120, 65) +} + +function legendLineStrokes(part) { + let y = 10 + for (const t of allLineStrokes) { + drawLine(part, y, t) + y += 15 + } + + return box(part, 120, 50) +} + +function legendLineWidths(part) { + let y = 10 + for (const t of allLineWidths) { + drawLine(part, y, t) + y += 15 + } + + return box(part, 120, 95) +} + +function legendSaLines(part) { + let y = 10 + for (const t of allFabricTypes) { + drawLine(part, y, t + ' sa') + y += 15 + } + + return box(part, 120, 65) +} + +function legendOtherLines(part) { + const { points, Point, paths, Path } = part.shorthand() + + const drawLine = (y, t) => { + points[`${t}From`] = new Point(10, y) + points[`${t}To`] = new Point(w, y) + paths[t] = new Path() + .move(points[`${t}From`]) + .line(points[`${t}To`]) + .attr('class', t) + .attr('data-text', t) + .attr('data-text-class', 'center') + } + + let y = 10 + let w = 110 + for (const t of allLineTypes) { + drawLine(y, t) + y += 15 + } + + return box(part, 120, 65) +} + +function box(part, w = 100, h = 50) { + part.paths.box = new part.Path() + .move(new part.Point(0, 0)) + .line(new part.Point(w, h)) + .attr('class', 'hidden') + + return part +} + +function drawLine(part, y, t) { + let { points, Point, paths, Path } = part.shorthand() + points[`${t}From`] = new Point(10, y) + points[`${t}To`] = new Point(110, y) + paths[t] = new Path() + .move(points[`${t}From`]) + .line(points[`${t}To`]) + .attr('class', t) + .attr('data-text', t) + .attr('data-text-class', 'center') + + return part +} diff --git a/packages/core/tests/part.test.mjs b/packages/core/tests/part.test.mjs index f39d9bdc6f8..e5276ca9044 100644 --- a/packages/core/tests/part.test.mjs +++ b/packages/core/tests/part.test.mjs @@ -1,339 +1,346 @@ -import chai from "chai" -import { Pattern, Path } from "./dist/index.mjs" +import chai from 'chai' +import { Pattern, Path } from '../src/index.mjs' const expect = chai.expect describe('Part', () => { - it("Svg constructor should initialize object", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - expect(part.paths).to.eql({}); - expect(part.snippets).to.eql({}); - expect(part.freeId).to.equal(0); - expect(part.topLeft).to.equal(false); - expect(part.bottomRight).to.equal(false); - expect(part.width).to.equal(false); - expect(part.height).to.equal(false); - expect(part.render).to.equal(true); - }); + it('Svg constructor should initialize object', () => { + let pattern = new Pattern() + let part = new pattern.Part() + expect(part.paths).to.eql({}) + expect(part.snippets).to.eql({}) + expect(part.freeId).to.equal(0) + expect(part.topLeft).to.equal(false) + expect(part.bottomRight).to.equal(false) + expect(part.width).to.equal(false) + expect(part.height).to.equal(false) + expect(part.render).to.equal(true) + }) - it("Should return a function from macroClosure", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - expect(typeof part.macroClosure()).to.equal("function"); - }); + it('Should return a function from macroClosure', () => { + let pattern = new Pattern() + let part = new pattern.Part() + expect(typeof part.macroClosure()).to.equal('function') + }) - it("Should not run an unknown macro", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - let macro = part.macroClosure(); - expect(macro("unknown")).to.equal(undefined); - }); + it('Should not run an unknown macro', () => { + let pattern = new Pattern() + let part = new pattern.Part() + let macro = part.macroClosure() + expect(macro('unknown')).to.equal(undefined) + }) - it("Should register and run a macro", () => { - let pattern = new Pattern(); + it('Should register and run a macro', () => { + let pattern = new Pattern() let plugin = { - name: "test", - version: "0.1-test", + name: 'test', + version: '0.1-test', macros: { - test: function(so) { - let points = this.points; - points.macro = new this.Point(so.x, so.y); - } - } - }; - pattern.use(plugin); - let part = new pattern.Part(); - let macro = part.macroClosure(); - macro("test", { x: 123, y: 456 }); - expect(part.points.macro.x).to.equal(123); - expect(part.points.macro.y).to.equal(456); - }); + test: function (so) { + let points = this.points + points.macro = new this.Point(so.x, so.y) + }, + }, + } + pattern.use(plugin) + let part = new pattern.Part() + let macro = part.macroClosure() + macro('test', { x: 123, y: 456 }) + expect(part.points.macro.x).to.equal(123) + expect(part.points.macro.y).to.equal(456) + }) - it("Should return a free ID", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - let free = part.getId(); - expect(part.getId()).to.equal("" + (parseInt(free) + 1)); - }); + it('Should return a free ID', () => { + let pattern = new Pattern() + let part = new pattern.Part() + let free = part.getId() + expect(part.getId()).to.equal('' + (parseInt(free) + 1)) + }) - it("Should return a function from unitsClosure", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - expect(typeof part.unitsClosure()).to.equal("function"); - }); + it('Should return a function from unitsClosure', () => { + let pattern = new Pattern() + let part = new pattern.Part() + expect(typeof part.unitsClosure()).to.equal('function') + }) - it("Should convert units", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - let units = part.unitsClosure(); - expect(units(123.456)).to.equal("12.35cm"); - expect(part.units(123.456)).to.equal("12.35cm"); - }); + it('Should convert units', () => { + let pattern = new Pattern() + let part = new pattern.Part() + let units = part.unitsClosure() + expect(units(123.456)).to.equal('12.35cm') + expect(part.units(123.456)).to.equal('12.35cm') + }) - it("Should set part attributes", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.attr("foo", "bar"); - expect(part.attributes.get("foo")).to.equal("bar"); - part.attr("foo", "baz"); - expect(part.attributes.get("foo")).to.equal("bar baz"); - part.attr("foo", "schmoo", true); - expect(part.attributes.get("foo")).to.equal("schmoo"); - }); + it('Should set part attributes', () => { + let pattern = new Pattern() + let part = new pattern.Part() + part.attr('foo', 'bar') + expect(part.attributes.get('foo')).to.equal('bar') + part.attr('foo', 'baz') + expect(part.attributes.get('foo')).to.equal('bar baz') + part.attr('foo', 'schmoo', true) + expect(part.attributes.get('foo')).to.equal('schmoo') + }) - it("Should inject a part", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.points.a = new part.Point(12, 23); - part.points.b = new part.Point(10, 10); - part.points.c = new part.Point(20, 20); + it('Should inject a part', () => { + let pattern = new Pattern() + let part = new pattern.Part() + 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 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.a.x).to.equal(12); - expect(test.points.a.y).to.equal(23); + let test = new pattern.Part() + test.inject(part) + 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++) { + 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", () => { - let pattern = new Pattern(); - pattern.settings.mode = "draft"; - pattern.settings.paperless = true; - let part = new pattern.Part(); - let short = part.shorthand(); - expect(short.complete).to.equal(true); - expect(short.paperless).to.equal(true); - }); + it('Should return shorthand', () => { + let pattern = new Pattern() + pattern.settings.mode = 'draft' + pattern.settings.paperless = true + let part = new pattern.Part() + let short = part.shorthand() + expect(short.complete).to.equal(true) + expect(short.paperless).to.equal(true) + }) - it("Should raise a warning when setting a non-Point value in points", () => { - const pattern = new Pattern(); - pattern.settings.mode = "draft"; - const part = new pattern.Part(); + it('Should raise a warning when setting a non-Point value in points', () => { + const pattern = new Pattern() + pattern.settings.mode = 'draft' + const part = new pattern.Part() const { points } = part.shorthand() points.a = 'banana' expect(pattern.events.warning.length).to.equal(4) - 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`') - }); + 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 Pattern(); - pattern.settings.mode = "draft"; - const part = new pattern.Part(); + it('Should raise a warning when setting a non-Snippet value in snippets', () => { + const pattern = new Pattern() + pattern.settings.mode = 'draft' + const part = new pattern.Part() const { snippets } = part.shorthand() snippets.a = 'banana' expect(pattern.events.warning.length).to.equal(4) - 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`') - }); + 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 Pattern(); - pattern.settings.mode = "draft"; - let part = new pattern.Part(); - let short = part.shorthand(); - part.points.from = new short.Point(123, 456); - part.points.to = new short.Point(19, 76); - part.paths.test = new short.Path() - .move(part.points.from) - .line(part.points.to); - let boundary = part.boundary(); - expect(boundary.topLeft.x).to.equal(17); - expect(boundary.topLeft.y).to.equal(74); - expect(boundary.bottomRight.x).to.equal(125); - expect(boundary.bottomRight.y).to.equal(458); - boundary = part.boundary(); - expect(boundary.width).to.equal(108); - expect(boundary.height).to.equal(384); - }); + it('Should calculate the part boundary with default margin', () => { + let pattern = new Pattern() + pattern.settings.mode = 'draft' + let part = new pattern.Part() + let short = part.shorthand() + part.points.from = new short.Point(123, 456) + part.points.to = new short.Point(19, 76) + part.paths.test = new short.Path().move(part.points.from).line(part.points.to) + let boundary = part.boundary() + expect(boundary.topLeft.x).to.equal(17) + expect(boundary.topLeft.y).to.equal(74) + expect(boundary.bottomRight.x).to.equal(125) + expect(boundary.bottomRight.y).to.equal(458) + boundary = part.boundary() + expect(boundary.width).to.equal(108) + expect(boundary.height).to.equal(384) + }) - it("Should calculate the part boundary with custom margin", () => { - let pattern = new Pattern(); - pattern.settings.mode = "draft"; - pattern.settings.margin = 5; - let part = new pattern.Part(); - let short = part.shorthand(); - part.points.from = new short.Point(123, 456); - part.points.to = new short.Point(19, 76); - part.paths.test = new short.Path() - .move(part.points.from) - .line(part.points.to); - let boundary = part.boundary(); - expect(boundary.topLeft.x).to.equal(14); - expect(boundary.topLeft.y).to.equal(71); - expect(boundary.bottomRight.x).to.equal(128); - expect(boundary.bottomRight.y).to.equal(461); - boundary = part.boundary(); - expect(boundary.width).to.equal(114); - expect(boundary.height).to.equal(390); - }); + it('Should calculate the part boundary with custom margin', () => { + let pattern = new Pattern() + pattern.settings.mode = 'draft' + pattern.settings.margin = 5 + let part = new pattern.Part() + let short = part.shorthand() + part.points.from = new short.Point(123, 456) + part.points.to = new short.Point(19, 76) + part.paths.test = new short.Path().move(part.points.from).line(part.points.to) + let boundary = part.boundary() + expect(boundary.topLeft.x).to.equal(14) + expect(boundary.topLeft.y).to.equal(71) + expect(boundary.bottomRight.x).to.equal(128) + expect(boundary.bottomRight.y).to.equal(461) + boundary = part.boundary() + expect(boundary.width).to.equal(114) + expect(boundary.height).to.equal(390) + }) - it("Should calculate the part boundary for paperless", () => { - let pattern = new Pattern(); - pattern.settings.mode = "draft"; - pattern.settings.margin = 5; - pattern.settings.paperless = true; - let part = new pattern.Part(); - let short = part.shorthand(); - part.points.from = new short.Point(123, 456); - part.points.to = new short.Point(19, 76); - part.paths.test = new short.Path() - .move(part.points.from) - .line(part.points.to); - let boundary = part.boundary(); - expect(boundary.topLeft.x).to.equal(9); - expect(boundary.topLeft.y).to.equal(66); - expect(boundary.bottomRight.x).to.equal(133); - expect(boundary.bottomRight.y).to.equal(466); - boundary = part.boundary(); - expect(boundary.width).to.equal(124); - expect(boundary.height).to.equal(400); - }); + it('Should calculate the part boundary for paperless', () => { + let pattern = new Pattern() + pattern.settings.mode = 'draft' + pattern.settings.margin = 5 + pattern.settings.paperless = true + let part = new pattern.Part() + let short = part.shorthand() + part.points.from = new short.Point(123, 456) + part.points.to = new short.Point(19, 76) + part.paths.test = new short.Path().move(part.points.from).line(part.points.to) + let boundary = part.boundary() + expect(boundary.topLeft.x).to.equal(9) + expect(boundary.topLeft.y).to.equal(66) + expect(boundary.bottomRight.x).to.equal(133) + expect(boundary.bottomRight.y).to.equal(466) + boundary = part.boundary() + expect(boundary.width).to.equal(124) + expect(boundary.height).to.equal(400) + }) - it("Should stack a part", () => { - let pattern = new Pattern(); - pattern.settings.mode = "draft"; - let part = new pattern.Part(); - let short = part.shorthand(); - part.points.from = new short.Point(123, 456); - part.points.to = new short.Point(19, 76); - part.paths.test = new short.Path() - .move(part.points.from) - .line(part.points.to); - part.stack(); - expect(part.attributes.get("transform")).to.equal("translate(-17, -74)"); - }); + it('Should stack a part', () => { + let pattern = new Pattern() + pattern.settings.mode = 'draft' + let part = new pattern.Part() + let short = part.shorthand() + part.points.from = new short.Point(123, 456) + part.points.to = new short.Point(19, 76) + part.paths.test = new short.Path().move(part.points.from).line(part.points.to) + part.stack() + expect(part.attributes.get('transform')).to.equal('translate(-17, -74)') + }) - it("Should only stack a part if needed", () => { - let pattern = new 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(); - expect(part.attributes.get("transform")).to.equal(false); - part.stack(); - expect(part.attributes.get("transform")).to.equal(false); - }); + it('Should only stack a part if needed', () => { + let pattern = new 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() + expect(part.attributes.get('transform')).to.equal(false) + part.stack() + expect(part.attributes.get('transform')).to.equal(false) + }) - it("Should run hooks", () => { + it('Should run hooks', () => { let count = 0 const pattern = new Pattern() - const part = new pattern.Part(); - part.hooks.preDraft = [{ method: function(p) { count++ }} ] + const part = new pattern.Part() + part.hooks.preDraft = [ + { + method: function (p) { + count++ + }, + }, + ] part.runHooks('preDraft') - expect(count).to.equal(1); - }); + expect(count).to.equal(1) + }) - it("Should get the units closure to raise a debug when passing a non-number", () => { - const pattern = new Pattern(); - pattern.settings.mode = "draft"; + it('Should get the units closure to raise a debug when passing a non-number', () => { + const pattern = new Pattern() + pattern.settings.mode = 'draft' pattern.settings.debug = true - const part = new pattern.Part(); - const short = part.shorthand(); + 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`)') - }); + 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 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(); + it('Should generate the part transforms', () => { + let pattern = new 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 - } + y: 20, + }, }) expect(part.attributes.list.transform.length).to.equal(1) expect(part.attributes.list.transform[0]).to.equal('translate(10 20)') - }); + }) describe('isEmpty', () => { - it("Should return true if the part has no paths or snippets", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); + it('Should return true if the part has no paths or snippets', () => { + let pattern = new Pattern() + let part = new pattern.Part() expect(part.isEmpty()).to.be.true }) - it("Should return true if the part has paths but they have no length", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const { Path, paths, Point } = part.shorthand() + it('Should return true if the part has paths but they have no length', () => { + let pattern = new Pattern() + let part = new pattern.Part() + const { Path, paths, Point } = part.shorthand() paths.seam = new Path() expect(part.isEmpty()).to.be.true }) it("Should return true if the part has paths but they don't render", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const { Path, paths, Point } = part.shorthand() - paths.seam = new Path().move(new Point(0,0)).line(new Point(2,3)).setRender(false) + let pattern = new Pattern() + let part = new pattern.Part() + const { Path, paths, Point } = part.shorthand() + paths.seam = new Path().move(new Point(0, 0)).line(new Point(2, 3)).setRender(false) expect(part.isEmpty()).to.be.true }) - it("Should return false if the part has a path with length", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const { Path, paths, Point } = part.shorthand() - paths.seam = new Path().move(new Point(0,0)).line(new Point(2,3)) + it('Should return false if the part has a path with length', () => { + let pattern = new Pattern() + let part = new pattern.Part() + const { Path, paths, Point } = part.shorthand() + paths.seam = new Path().move(new Point(0, 0)).line(new Point(2, 3)) expect(part.isEmpty()).to.be.false }) - it("Should return false if the part has a snippet", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const { Point, snippets, Snippet } = part.shorthand() - snippets.test = new Snippet('test', new Point(0,0)) + it('Should return false if the part has a snippet', () => { + let pattern = new Pattern() + let part = new pattern.Part() + const { Point, snippets, Snippet } = part.shorthand() + snippets.test = new Snippet('test', new Point(0, 0)) expect(part.isEmpty()).to.be.false }) - it("Should return false if the part has a point that has text", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const {Point, points} = part.shorthand() - points.test = new Point(0,0) + it('Should return false if the part has a point that has text', () => { + let pattern = new Pattern() + let part = new pattern.Part() + const { Point, points } = part.shorthand() + points.test = new Point(0, 0) points.test.attributes.set('data-text', 'text') expect(part.isEmpty()).to.be.false }) - it("Should return false if the part has a point that has a circle", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const {Point, points} = part.shorthand() - points.test = new Point(0,0) + it('Should return false if the part has a point that has a circle', () => { + let pattern = new Pattern() + let part = new pattern.Part() + const { Point, points } = part.shorthand() + points.test = new Point(0, 0) points.test.attributes.set('data-circle', 10) expect(part.isEmpty()).to.be.false }) }) - }) diff --git a/packages/core/tests/path.test.mjs b/packages/core/tests/path.test.mjs index 701b70051b7..907b8ffd4b2 100644 --- a/packages/core/tests/path.test.mjs +++ b/packages/core/tests/path.test.mjs @@ -1,682 +1,680 @@ -import chai from "chai" -import { round, Pattern, Path, Point } from "./dist/index.mjs" +import chai from 'chai' +import { round, Pattern, Path, Point } from './dist/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; + 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); - }); + 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) + }) - it("Should offset a curve", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + 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); - }); + .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) + }) - it("Should offset a curve where cp1 = start", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + 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); - }); + .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) + }) - it("Should offset a curve where cp2 = end", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + 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); - }); + .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) + }) - 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; + 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(); - }); + 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() + }) - it("Should return the length of a line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + 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); - }); + 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) + }) - it("Should return the length of a curve", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + 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); - }); + .close() + expect(round(a.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; + 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); - }); + .close() + expect(a.paths.curve.start().x).to.equal(123) + expect(a.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; + 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); - }); + .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) + }) - it("Should calculate that path boundary", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should calculate that path boundary', () => { + 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(230, 4)); - a.paths.curve.boundary(); - expect(a.paths.curve.topLeft.x).to.equal(71.6413460920667); - expect(a.paths.curve.topLeft.y).to.equal(4); - a.paths.curve.boundary(); - expect(a.paths.curve.bottomRight.x).to.equal(230); - expect(a.paths.curve.bottomRight.y).to.equal(456); - }); - - it("Should clone a path", () => { - 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(230, 4)); - let b = a.paths.curve.clone(); - b.boundary(); - expect(b.topLeft.x).to.equal(71.6413460920667); - expect(b.topLeft.y).to.equal(4); - b = b.clone(); - expect(b.bottomRight.x).to.equal(230); - expect(b.bottomRight.y).to.equal(456); - }); - - it("Should join paths", () => { - 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.curve = new a.Path() - .move(new a.Point(123, 456)) - .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(230, 4)); - a.paths.joint = a.paths.curve.join(a.paths.line); - expect(a.paths.joint.ops.length).to.equal(4); - }); - - it("Should throw error when joining a closed paths", () => { - 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.curve = new a.Path() .move(new a.Point(123, 456)) .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(230, 4)) - .close(); - expect(() => a.paths.curve.join(a.paths.line)).to.throw(); - }); + a.paths.curve.boundary() + expect(a.paths.curve.topLeft.x).to.equal(71.6413460920667) + expect(a.paths.curve.topLeft.y).to.equal(4) + a.paths.curve.boundary() + expect(a.paths.curve.bottomRight.x).to.equal(230) + expect(a.paths.curve.bottomRight.y).to.equal(456) + }) - it("Should shift along a line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should clone a path', () => { + 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.shiftAlong(20).y).to.equal(20); - }); + 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(230, 4)) + let b = a.paths.curve.clone() + b.boundary() + expect(b.topLeft.x).to.equal(71.6413460920667) + expect(b.topLeft.y).to.equal(4) + b = b.clone() + expect(b.bottomRight.x).to.equal(230) + expect(b.bottomRight.y).to.equal(456) + }) - 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(); - let a = pattern.parts.a; + it('Should join paths', () => { + 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(10, 0)); - expect(a.paths.line.shiftAlong(10).x).to.equal(10); - }); + a.paths.line = new a.Path().move(new a.Point(0, 0)).line(new a.Point(0, 40)) + 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(230, 4)) + a.paths.joint = a.paths.curve.join(a.paths.line) + expect(a.paths.joint.ops.length).to.equal(4) + }) - it("Should shift along lines", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should throw error when joining a closed paths', () => { + 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.curve = new a.Path() + .move(new a.Point(123, 456)) + .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(230, 4)) + .close() + expect(() => a.paths.curve.join(a.paths.line)).to.throw() + }) + + it('Should shift along 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.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 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 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)) - .line(new a.Point(100, 40)); - expect(a.paths.line.shiftAlong(50).x).to.equal(10); - expect(a.paths.line.shiftAlong(50).y).to.equal(40); - }); + .line(new a.Point(100, 40)) + expect(a.paths.line.shiftAlong(50).x).to.equal(10) + expect(a.paths.line.shiftAlong(50).y).to.equal(40) + }) - it("Should shift along curve + line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should shift along curve + line', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) .line(new a.Point(0, 40)) .curve(new a.Point(40, 40), new a.Point(40, 0), new a.Point(200, 0)) - .line(new a.Point(200, 400)); - expect(round(a.paths.test.shiftAlong(500).x)).to.equal(200); - expect(round(a.paths.test.shiftAlong(500).y)).to.equal(253.74); - }); + .line(new a.Point(200, 400)) + expect(round(a.paths.test.shiftAlong(500).x)).to.equal(200) + expect(round(a.paths.test.shiftAlong(500).y)).to.equal(253.74) + }) it("Should throw error when shifting along path further than it's long", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) .line(new a.Point(0, 40)) - .line(new a.Point(200, 400)); - expect(() => a.paths.test.shiftAlong(500)).to.throw(); - }); + .line(new a.Point(200, 400)) + expect(() => a.paths.test.shiftAlong(500)).to.throw() + }) - it("Should shift along with sufficient precision", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should shift along with sufficient precision', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) .curve(new a.Point(123, 123), new a.Point(-123, 456), new a.Point(456, -123)) a.points.a = a.paths.test.shiftAlong(100) - a.points.b = a.paths.test.reverse().shiftAlong(a.paths.test.length()-100) - expect(a.points.a.dist(a.points.b)).to.below(0.05); - }); + a.points.b = a.paths.test.reverse().shiftAlong(a.paths.test.length() - 100) + expect(a.points.a.dist(a.points.b)).to.below(0.05) + }) - it("Should shift fraction with sufficient precision", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should shift fraction with sufficient precision', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a a.paths.test = new a.Path() .move(new a.Point(0, 0)) .curve(new a.Point(123, 123), new a.Point(-123, 456), new a.Point(456, -123)) a.points.a = a.paths.test.shiftFractionAlong(0.5) a.points.b = a.paths.test.reverse().shiftFractionAlong(0.5) - expect(a.points.a.dist(a.points.b)).to.below(0.05); - }); + expect(a.points.a.dist(a.points.b)).to.below(0.05) + }) - it("Should shift a fraction along a line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should shift a fraction along 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)) - .line(new a.Point(100, 40)); - expect(round(a.paths.line.shiftFractionAlong(0.5).x)).to.equal(30); - expect(round(a.paths.line.shiftFractionAlong(0.5).y)).to.equal(40); - }); + .line(new a.Point(100, 40)) + expect(round(a.paths.line.shiftFractionAlong(0.5).x)).to.equal(30) + expect(round(a.paths.line.shiftFractionAlong(0.5).y)).to.equal(40) + }) - it("Should find the bounding box of a line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let Path = pattern.parts.a.Path; - let Point = pattern.parts.a.Point; + it('Should find the bounding box of a line', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let Path = pattern.parts.a.Path + let Point = pattern.parts.a.Point - let line = new Path().move(new Point(3, 2)).line(new Point(10, 40)); - let box = line.bbox(); - expect(box.topLeft.x).to.equal(3); - expect(box.topLeft.y).to.equal(2); - expect(box.bottomRight.x).to.equal(10); - expect(box.bottomRight.y).to.equal(40); + let line = new Path().move(new Point(3, 2)).line(new Point(10, 40)) + let box = line.bbox() + expect(box.topLeft.x).to.equal(3) + expect(box.topLeft.y).to.equal(2) + expect(box.bottomRight.x).to.equal(10) + expect(box.bottomRight.y).to.equal(40) - line = new Path().move(new Point(10, 40)).line(new Point(3, 2)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(3); - expect(box.topLeft.y).to.equal(2); - expect(box.bottomRight.x).to.equal(10); - expect(box.bottomRight.y).to.equal(40); + line = new Path().move(new Point(10, 40)).line(new Point(3, 2)) + box = line.bbox() + expect(box.topLeft.x).to.equal(3) + expect(box.topLeft.y).to.equal(2) + expect(box.bottomRight.x).to.equal(10) + expect(box.bottomRight.y).to.equal(40) - line = new Path().move(new Point(1, 40)).line(new Point(31, 2)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(1); - expect(box.topLeft.y).to.equal(2); - expect(box.bottomRight.x).to.equal(31); - expect(box.bottomRight.y).to.equal(40); + line = new Path().move(new Point(1, 40)).line(new Point(31, 2)) + box = line.bbox() + expect(box.topLeft.x).to.equal(1) + expect(box.topLeft.y).to.equal(2) + expect(box.bottomRight.x).to.equal(31) + expect(box.bottomRight.y).to.equal(40) - line = new Path().move(new Point(31, 2)).line(new Point(1, 40)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(1); - expect(box.topLeft.y).to.equal(2); - expect(box.bottomRight.x).to.equal(31); - expect(box.bottomRight.y).to.equal(40); + line = new Path().move(new Point(31, 2)).line(new Point(1, 40)) + box = line.bbox() + expect(box.topLeft.x).to.equal(1) + expect(box.topLeft.y).to.equal(2) + expect(box.bottomRight.x).to.equal(31) + expect(box.bottomRight.y).to.equal(40) - line = new Path().move(new Point(11, 2)).line(new Point(11, 40)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(11); - expect(box.topLeft.y).to.equal(2); - expect(box.bottomRight.x).to.equal(11); - expect(box.bottomRight.y).to.equal(40); + line = new Path().move(new Point(11, 2)).line(new Point(11, 40)) + box = line.bbox() + expect(box.topLeft.x).to.equal(11) + expect(box.topLeft.y).to.equal(2) + expect(box.bottomRight.x).to.equal(11) + expect(box.bottomRight.y).to.equal(40) - line = new Path().move(new Point(11, 40)).line(new Point(11, 2)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(11); - expect(box.topLeft.y).to.equal(2); - expect(box.bottomRight.x).to.equal(11); - expect(box.bottomRight.y).to.equal(40); + line = new Path().move(new Point(11, 40)).line(new Point(11, 2)) + box = line.bbox() + expect(box.topLeft.x).to.equal(11) + expect(box.topLeft.y).to.equal(2) + expect(box.bottomRight.x).to.equal(11) + expect(box.bottomRight.y).to.equal(40) - line = new Path().move(new Point(11, 12)).line(new Point(41, 12)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(11); - expect(box.topLeft.y).to.equal(12); - expect(box.bottomRight.x).to.equal(41); - expect(box.bottomRight.y).to.equal(12); + line = new Path().move(new Point(11, 12)).line(new Point(41, 12)) + box = line.bbox() + expect(box.topLeft.x).to.equal(11) + expect(box.topLeft.y).to.equal(12) + expect(box.bottomRight.x).to.equal(41) + expect(box.bottomRight.y).to.equal(12) - line = new Path().move(new Point(41, 12)).line(new Point(11, 12)); - box = line.bbox(); - expect(box.topLeft.x).to.equal(11); - expect(box.topLeft.y).to.equal(12); - expect(box.bottomRight.x).to.equal(41); - expect(box.bottomRight.y).to.equal(12); - }); + line = new Path().move(new Point(41, 12)).line(new Point(11, 12)) + box = line.bbox() + expect(box.topLeft.x).to.equal(11) + expect(box.topLeft.y).to.equal(12) + expect(box.bottomRight.x).to.equal(41) + expect(box.bottomRight.y).to.equal(12) + }) - it("Should find the bounding box of a line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should find the bounding box of a line', () => { + 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(230, 4)) - .close(); - let box = a.paths.curve.bbox(); - expect(round(box.topLeft.x)).to.equal(71.64); - expect(box.topLeft.y).to.equal(4); - expect(box.bottomRight.x).to.equal(230); - expect(box.bottomRight.y).to.equal(456); - }); + .close() + let box = a.paths.curve.bbox() + expect(round(box.topLeft.x)).to.equal(71.64) + expect(box.topLeft.y).to.equal(4) + expect(box.bottomRight.x).to.equal(230) + expect(box.bottomRight.y).to.equal(456) + }) - it("Should reverse a path", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should reverse a path', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a let test = new a.Path() .move(new a.Point(123, 456)) .line(new a.Point(12, 23)) .curve(new a.Point(0, 40), new a.Point(123, 34), new a.Point(230, 4)) - .close(); - let rev = test.reverse(); - let tb = test.bbox(); - let rb = rev.bbox(); - expect(tb.topLeft.x).to.equal(rb.topLeft.x); - expect(tb.topLeft.y).to.equal(rb.topLeft.y); - expect(tb.bottomRight.x).to.equal(rb.bottomRight.x); - expect(tb.bottomRight.y).to.equal(rb.bottomRight.y); - expect(rev.ops[1].type).to.equal("curve"); - expect(rev.ops[2].type).to.equal("line"); - }); + .close() + let rev = test.reverse() + let tb = test.bbox() + let rb = rev.bbox() + expect(tb.topLeft.x).to.equal(rb.topLeft.x) + expect(tb.topLeft.y).to.equal(rb.topLeft.y) + expect(tb.bottomRight.x).to.equal(rb.bottomRight.x) + expect(tb.bottomRight.y).to.equal(rb.bottomRight.y) + expect(rev.ops[1].type).to.equal('curve') + expect(rev.ops[2].type).to.equal('line') + }) - it("Should find the edges of a path", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(45, 60); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(-60, 90); - a.points.E = new a.Point(90, 190); + it('Should find the edges of a path', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(45, 60) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(-60, 90) + a.points.E = new a.Point(90, 190) a.paths.test = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) .curve(a.points.E, a.points.D, a.points.A) - .close(); - expect(round(a.paths.test.edge("topLeft").x)).to.equal(7.7); - expect(round(a.paths.test.edge("topLeft").y)).to.equal(0.97); - expect(round(a.paths.test.edge("bottomLeft").x)).to.equal(7.7); - expect(round(a.paths.test.edge("bottomLeft").y)).to.equal(118.46); - expect(round(a.paths.test.edge("bottomRight").x)).to.equal(90); - expect(round(a.paths.test.edge("bottomRight").y)).to.equal(118.46); - expect(round(a.paths.test.edge("topRight").x)).to.equal(90); - expect(round(a.paths.test.edge("topRight").y)).to.equal(0.97); - expect(round(a.paths.test.edge("left").x)).to.equal(7.7); - expect(round(a.paths.test.edge("left").y)).to.equal(91.8); - expect(round(a.paths.test.edge("bottom").x)).to.equal(40.63); - expect(round(a.paths.test.edge("bottom").y)).to.equal(118.46); - expect(round(a.paths.test.edge("right").x)).to.equal(89.76); - expect(round(a.paths.test.edge("right").y)).to.equal(29.64); - expect(round(a.paths.test.edge("top").x)).to.equal(55.98); - expect(round(a.paths.test.edge("top").y)).to.equal(0.97); - }); + .close() + expect(round(a.paths.test.edge('topLeft').x)).to.equal(7.7) + expect(round(a.paths.test.edge('topLeft').y)).to.equal(0.97) + expect(round(a.paths.test.edge('bottomLeft').x)).to.equal(7.7) + expect(round(a.paths.test.edge('bottomLeft').y)).to.equal(118.46) + expect(round(a.paths.test.edge('bottomRight').x)).to.equal(90) + expect(round(a.paths.test.edge('bottomRight').y)).to.equal(118.46) + expect(round(a.paths.test.edge('topRight').x)).to.equal(90) + expect(round(a.paths.test.edge('topRight').y)).to.equal(0.97) + expect(round(a.paths.test.edge('left').x)).to.equal(7.7) + expect(round(a.paths.test.edge('left').y)).to.equal(91.8) + expect(round(a.paths.test.edge('bottom').x)).to.equal(40.63) + expect(round(a.paths.test.edge('bottom').y)).to.equal(118.46) + expect(round(a.paths.test.edge('right').x)).to.equal(89.76) + expect(round(a.paths.test.edge('right').y)).to.equal(29.64) + expect(round(a.paths.test.edge('top').x)).to.equal(55.98) + expect(round(a.paths.test.edge('top').y)).to.equal(0.97) + }) - it("Should find the edges of a path for corner cases", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(-45, -60); - a.points.B = new a.Point(45, 60); - a.points.C = new a.Point(-90, -160); - a.paths.test = new a.Path().move(a.points.A).line(a.points.B); - expect(round(a.paths.test.edge("top").x)).to.equal(-45); - expect(round(a.paths.test.edge("top").y)).to.equal(-60); - expect(round(a.paths.test.edge("left").x)).to.equal(-45); - expect(round(a.paths.test.edge("left").y)).to.equal(-60); - expect(round(a.paths.test.edge("bottom").x)).to.equal(45); - expect(round(a.paths.test.edge("bottom").y)).to.equal(60); - expect(round(a.paths.test.edge("right").x)).to.equal(45); - expect(round(a.paths.test.edge("right").y)).to.equal(60); - a.paths.test = new a.Path().move(a.points.B).line(a.points.A); - expect(round(a.paths.test.edge("top").x)).to.equal(-45); - expect(round(a.paths.test.edge("top").y)).to.equal(-60); - expect(round(a.paths.test.edge("left").x)).to.equal(-45); - expect(round(a.paths.test.edge("left").y)).to.equal(-60); - expect(round(a.paths.test.edge("bottom").x)).to.equal(45); - expect(round(a.paths.test.edge("bottom").y)).to.equal(60); - expect(round(a.paths.test.edge("right").x)).to.equal(45); - expect(round(a.paths.test.edge("right").y)).to.equal(60); - }); + it('Should find the edges of a path for corner cases', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(-45, -60) + a.points.B = new a.Point(45, 60) + a.points.C = new a.Point(-90, -160) + a.paths.test = new a.Path().move(a.points.A).line(a.points.B) + expect(round(a.paths.test.edge('top').x)).to.equal(-45) + expect(round(a.paths.test.edge('top').y)).to.equal(-60) + expect(round(a.paths.test.edge('left').x)).to.equal(-45) + expect(round(a.paths.test.edge('left').y)).to.equal(-60) + expect(round(a.paths.test.edge('bottom').x)).to.equal(45) + expect(round(a.paths.test.edge('bottom').y)).to.equal(60) + expect(round(a.paths.test.edge('right').x)).to.equal(45) + expect(round(a.paths.test.edge('right').y)).to.equal(60) + a.paths.test = new a.Path().move(a.points.B).line(a.points.A) + expect(round(a.paths.test.edge('top').x)).to.equal(-45) + expect(round(a.paths.test.edge('top').y)).to.equal(-60) + expect(round(a.paths.test.edge('left').x)).to.equal(-45) + expect(round(a.paths.test.edge('left').y)).to.equal(-60) + expect(round(a.paths.test.edge('bottom').x)).to.equal(45) + expect(round(a.paths.test.edge('bottom').y)).to.equal(60) + expect(round(a.paths.test.edge('right').x)).to.equal(45) + expect(round(a.paths.test.edge('right').y)).to.equal(60) + }) - it("Should find the edge of a path for this edge-case", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - 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); - a.points.C = new a.Point(-39.45, 137.4); - a.points.D = new a.Point(-61.52, 219.77); - a.paths.test = new a.Path() - .move(a.points.A) - .curve(a.points.B, a.points.C, a.points.D); - expect(round(a.paths.test.edge("right").x)).to.equal(-45.22); - expect(round(a.paths.test.edge("right").y)).to.equal(139.4); - }); + it('Should find the edge of a path for this edge-case', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + 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) + a.points.C = new a.Point(-39.45, 137.4) + a.points.D = new a.Point(-61.52, 219.77) + a.paths.test = new a.Path().move(a.points.A).curve(a.points.B, a.points.C, a.points.D) + expect(round(a.paths.test.edge('right').x)).to.equal(-45.22) + expect(round(a.paths.test.edge('right').y)).to.equal(139.4) + }) - it("Should find where a path intersects with an X value", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(95, 50); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(50, 130); - a.points.DCp1 = new a.Point(150, 30); + it('Should find where a path intersects with an X value', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(95, 50) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(50, 130) + a.points.DCp1 = new a.Point(150, 30) a.paths.test = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) .curve(a.points.DCp1, a.points.DCp1, a.points.D) - .close(); - let intersections = a.paths.test.intersectsX(60); - expect(intersections.length).to.equal(4); - expect(round(intersections[0].x)).to.equal(60); - expect(round(intersections[0].y)).to.equal(41.76); - expect(round(intersections[1].x)).to.equal(60); - expect(round(intersections[1].y)).to.equal(1.45); - expect(round(intersections[2].x)).to.equal(60); - expect(round(intersections[2].y)).to.equal(120); - expect(round(intersections[3].x)).to.equal(60); - expect(round(intersections[3].y)).to.equal(112.22); - }); + .close() + let intersections = a.paths.test.intersectsX(60) + expect(intersections.length).to.equal(4) + expect(round(intersections[0].x)).to.equal(60) + expect(round(intersections[0].y)).to.equal(41.76) + expect(round(intersections[1].x)).to.equal(60) + expect(round(intersections[1].y)).to.equal(1.45) + expect(round(intersections[2].x)).to.equal(60) + expect(round(intersections[2].y)).to.equal(120) + expect(round(intersections[3].x)).to.equal(60) + expect(round(intersections[3].y)).to.equal(112.22) + }) - it("Should find where a path intersects with an Y value", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(95, 50); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(50, 130); - a.points.DCp1 = new a.Point(150, 30); + it('Should find where a path intersects with an Y value', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(95, 50) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(50, 130) + a.points.DCp1 = new a.Point(150, 30) a.paths.test = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) .curve(a.points.DCp1, a.points.DCp1, a.points.D) - .close(); - let intersections = a.paths.test.intersectsY(60); - expect(intersections.length).to.equal(2); - expect(round(intersections[0].x)).to.equal(117.83); - expect(round(intersections[0].y)).to.equal(60); - expect(round(intersections[1].x)).to.equal(89.38); - expect(round(intersections[1].y)).to.equal(60); - }); + .close() + let intersections = a.paths.test.intersectsY(60) + expect(intersections.length).to.equal(2) + expect(round(intersections[0].x)).to.equal(117.83) + expect(round(intersections[0].y)).to.equal(60) + expect(round(intersections[1].x)).to.equal(89.38) + expect(round(intersections[1].y)).to.equal(60) + }) - it("Should throw an error when not passing a value to path.intersectsX", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.paths.test = new a.Path(); - expect(() => a.paths.test.intersectsX()).to.throw(); - expect(() => a.paths.test.intersectsY()).to.throw(); - }); + it('Should throw an error when not passing a value to path.intersectsX', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.paths.test = new a.Path() + expect(() => a.paths.test.intersectsX()).to.throw() + expect(() => a.paths.test.intersectsY()).to.throw() + }) - it("Should find the intersections between two paths", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(45, 60); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(50, 130); - a.points.DCp1 = new a.Point(150, 30); + it('Should find the intersections between two paths', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(45, 60) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(50, 130) + a.points.DCp1 = new a.Point(150, 30) - a.points._A = new a.Point(55, 40); - a.points._B = new a.Point(0, 55); - a.points._BCp2 = new a.Point(40, -20); - a.points._C = new a.Point(90, 40); - a.points._CCp1 = new a.Point(50, -30); - a.points._D = new a.Point(40, 120); - a.points._DCp1 = new a.Point(180, 40); + a.points._A = new a.Point(55, 40) + a.points._B = new a.Point(0, 55) + a.points._BCp2 = new a.Point(40, -20) + a.points._C = new a.Point(90, 40) + a.points._CCp1 = new a.Point(50, -30) + a.points._D = new a.Point(40, 120) + a.points._DCp1 = new a.Point(180, 40) a.paths.example1 = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) - .curve(a.points.DCp1, a.points.DCp1, a.points.D); + .curve(a.points.DCp1, a.points.DCp1, a.points.D) a.paths.example2 = new a.Path() .move(a.points._A) .line(a.points._B) .curve(a.points._BCp2, a.points._CCp1, a.points._C) - .curve(a.points._DCp1, a.points._DCp1, a.points._D); - let intersections = a.paths.example1.intersects(a.paths.example2); - expect(intersections.length).to.equal(6); - expect(round(intersections[0].x)).to.equal(29.71); - expect(round(intersections[0].y)).to.equal(46.9); - expect(round(intersections[1].x)).to.equal(12.48); - expect(round(intersections[1].y)).to.equal(32.12); - expect(round(intersections[2].x)).to.equal(14.84); - expect(round(intersections[2].y)).to.equal(27.98); - expect(round(intersections[3].x)).to.equal(66.33); - expect(round(intersections[3].y)).to.equal(4.1); - expect(round(intersections[4].x)).to.equal(130.65); - expect(round(intersections[4].y)).to.equal(40.52); - expect(round(intersections[5].x)).to.equal(86.52); - expect(round(intersections[5].y)).to.equal(93.31); - }); + .curve(a.points._DCp1, a.points._DCp1, a.points._D) + let intersections = a.paths.example1.intersects(a.paths.example2) + expect(intersections.length).to.equal(6) + expect(round(intersections[0].x)).to.equal(29.71) + expect(round(intersections[0].y)).to.equal(46.9) + expect(round(intersections[1].x)).to.equal(12.48) + expect(round(intersections[1].y)).to.equal(32.12) + expect(round(intersections[2].x)).to.equal(14.84) + expect(round(intersections[2].y)).to.equal(27.98) + expect(round(intersections[3].x)).to.equal(66.33) + expect(round(intersections[3].y)).to.equal(4.1) + expect(round(intersections[4].x)).to.equal(130.65) + expect(round(intersections[4].y)).to.equal(40.52) + expect(round(intersections[5].x)).to.equal(86.52) + expect(round(intersections[5].y)).to.equal(93.31) + }) - it("Should throw an error when running path.intersect on an identical path", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.paths.test = new a.Path(); - expect(() => a.paths.test.intersects(a.paths.test)).to.throw(); - }); + it('Should throw an error when running path.intersect on an identical path', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.paths.test = new a.Path() + expect(() => a.paths.test.intersects(a.paths.test)).to.throw() + }) - it("Should divide a path", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(45, 60); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(-60, 90); - a.points.E = new a.Point(90, 190); + it('Should divide a path', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(45, 60) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(-60, 90) + a.points.E = new a.Point(90, 190) a.paths.test = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) .curve(a.points.E, a.points.D, a.points.A) - .close(); - let divided = a.paths.test.divide(); - expect(divided.length).to.equal(4); - expect(divided[0].ops[0].type).to.equal("move"); - expect(divided[0].ops[0].to.x).to.equal(45); - expect(divided[0].ops[0].to.y).to.equal(60); - expect(divided[0].ops[1].type).to.equal("line"); - expect(divided[0].ops[1].to.x).to.equal(10); - expect(divided[0].ops[1].to.y).to.equal(30); - expect(divided[1].ops[0].type).to.equal("move"); - expect(divided[1].ops[0].to.x).to.equal(10); - expect(divided[1].ops[0].to.y).to.equal(30); - expect(divided[1].ops[1].type).to.equal("curve"); - expect(divided[1].ops[1].cp1.x).to.equal(40); - expect(divided[1].ops[1].cp1.y).to.equal(20); - expect(divided[1].ops[1].cp2.x).to.equal(50); - expect(divided[1].ops[1].cp2.y).to.equal(-30); - expect(divided[1].ops[1].to.x).to.equal(90); - expect(divided[1].ops[1].to.y).to.equal(30); - expect(divided[2].ops[0].type).to.equal("move"); - expect(divided[2].ops[0].to.x).to.equal(90); - expect(divided[2].ops[0].to.y).to.equal(30); - expect(divided[2].ops[1].type).to.equal("curve"); - expect(divided[2].ops[1].cp1.x).to.equal(90); - expect(divided[2].ops[1].cp1.y).to.equal(190); - expect(divided[2].ops[1].cp2.x).to.equal(-60); - expect(divided[2].ops[1].cp2.y).to.equal(90); - expect(divided[2].ops[1].to.x).to.equal(45); - expect(divided[2].ops[1].to.y).to.equal(60); - expect(divided[3].ops[0].type).to.equal("move"); - expect(divided[3].ops[0].to.x).to.equal(45); - expect(divided[3].ops[0].to.y).to.equal(60); - expect(divided[3].ops[1].type).to.equal("line"); - expect(divided[3].ops[1].to.x).to.equal(45); - expect(divided[3].ops[1].to.y).to.equal(60); - }); + .close() + let divided = a.paths.test.divide() + expect(divided.length).to.equal(4) + expect(divided[0].ops[0].type).to.equal('move') + expect(divided[0].ops[0].to.x).to.equal(45) + expect(divided[0].ops[0].to.y).to.equal(60) + expect(divided[0].ops[1].type).to.equal('line') + expect(divided[0].ops[1].to.x).to.equal(10) + expect(divided[0].ops[1].to.y).to.equal(30) + expect(divided[1].ops[0].type).to.equal('move') + expect(divided[1].ops[0].to.x).to.equal(10) + expect(divided[1].ops[0].to.y).to.equal(30) + expect(divided[1].ops[1].type).to.equal('curve') + expect(divided[1].ops[1].cp1.x).to.equal(40) + expect(divided[1].ops[1].cp1.y).to.equal(20) + expect(divided[1].ops[1].cp2.x).to.equal(50) + expect(divided[1].ops[1].cp2.y).to.equal(-30) + expect(divided[1].ops[1].to.x).to.equal(90) + expect(divided[1].ops[1].to.y).to.equal(30) + expect(divided[2].ops[0].type).to.equal('move') + expect(divided[2].ops[0].to.x).to.equal(90) + expect(divided[2].ops[0].to.y).to.equal(30) + expect(divided[2].ops[1].type).to.equal('curve') + expect(divided[2].ops[1].cp1.x).to.equal(90) + expect(divided[2].ops[1].cp1.y).to.equal(190) + expect(divided[2].ops[1].cp2.x).to.equal(-60) + expect(divided[2].ops[1].cp2.y).to.equal(90) + expect(divided[2].ops[1].to.x).to.equal(45) + expect(divided[2].ops[1].to.y).to.equal(60) + expect(divided[3].ops[0].type).to.equal('move') + expect(divided[3].ops[0].to.x).to.equal(45) + expect(divided[3].ops[0].to.y).to.equal(60) + expect(divided[3].ops[1].type).to.equal('line') + expect(divided[3].ops[1].to.x).to.equal(45) + expect(divided[3].ops[1].to.y).to.equal(60) + }) - it("Should split a path on a curve", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(45, 60); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(50, 130); - a.points.DCp1 = new a.Point(150, 30); + it('Should split a path on a curve', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(45, 60) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(50, 130) + a.points.DCp1 = new a.Point(150, 30) a.paths.test = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) - .curve(a.points.DCp1, a.points.DCp1, a.points.D); + .curve(a.points.DCp1, a.points.DCp1, a.points.D) - a.points.split = a.paths.test.shiftAlong(120); - let halves = a.paths.test.split(a.points.split); - let curve = halves[0].ops.pop(); - expect(curve.type).to.equal("curve"); - expect(round(curve.cp1.x)).to.equal(35.08); - expect(round(curve.cp1.y)).to.equal(21.64); - expect(round(curve.cp2.x)).to.equal(46.19); - expect(round(curve.cp2.y)).to.equal(-14.69); - expect(round(curve.to.x)).to.equal(72.53); - expect(round(curve.to.y)).to.equal(8.71); - }); + a.points.split = a.paths.test.shiftAlong(120) + let halves = a.paths.test.split(a.points.split) + let curve = halves[0].ops.pop() + expect(curve.type).to.equal('curve') + expect(round(curve.cp1.x)).to.equal(35.08) + expect(round(curve.cp1.y)).to.equal(21.64) + expect(round(curve.cp2.x)).to.equal(46.19) + expect(round(curve.cp2.y)).to.equal(-14.69) + expect(round(curve.to.x)).to.equal(72.53) + expect(round(curve.to.y)).to.equal(8.71) + }) - it("Should split a path on a line", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(45, 60); - a.points.B = new a.Point(10, 30); - a.points.BCp2 = new a.Point(40, 20); - a.points.C = new a.Point(90, 30); - a.points.CCp1 = new a.Point(50, -30); - a.points.D = new a.Point(50, 130); - a.points.DCp1 = new a.Point(150, 30); + it('Should split a path on a line', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(45, 60) + a.points.B = new a.Point(10, 30) + a.points.BCp2 = new a.Point(40, 20) + a.points.C = new a.Point(90, 30) + a.points.CCp1 = new a.Point(50, -30) + a.points.D = new a.Point(50, 130) + a.points.DCp1 = new a.Point(150, 30) a.paths.test = new a.Path() .move(a.points.A) .line(a.points.B) .curve(a.points.BCp2, a.points.CCp1, a.points.C) - .curve(a.points.DCp1, a.points.DCp1, a.points.D); + .curve(a.points.DCp1, a.points.DCp1, a.points.D) - a.points.split = a.paths.test.shiftAlong(20); - let halves = a.paths.test.split(a.points.split); - let line = halves[0].ops.pop(); - expect(line.type).to.equal("line"); - expect(round(line.to.x)).to.equal(29.81); - expect(round(line.to.y)).to.equal(46.98); - }); + a.points.split = a.paths.test.shiftAlong(20) + let halves = a.paths.test.split(a.points.split) + let line = halves[0].ops.pop() + expect(line.type).to.equal('line') + expect(round(line.to.x)).to.equal(29.81) + expect(round(line.to.y)).to.equal(46.98) + }) - it("Should trim a path when lines overlap", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(0, 0); - a.points.B = new a.Point(100, 100); - a.points.C = new a.Point(0, 100); - a.points.D = new a.Point(100, 0); + it('Should trim a path when lines overlap', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(0, 0) + a.points.B = new a.Point(100, 100) + a.points.C = new a.Point(0, 100) + a.points.D = new a.Point(100, 0) let test = new a.Path() .move(new a.Point(0, 20)) @@ -685,21 +683,21 @@ describe('Path', () => { .line(a.points.C) .line(a.points.D) .line(a.points.A) - .trim(); + .trim() - expect(test.ops.length).to.equal(5); - expect(test.ops[2].to.x).to.equal(50); - expect(test.ops[2].to.y).to.equal(50); - }); + expect(test.ops.length).to.equal(5) + expect(test.ops[2].to.x).to.equal(50) + expect(test.ops[2].to.y).to.equal(50) + }) - it("Should trim a path when a line overlaps with a curve", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(0, 0); - a.points.B = new a.Point(100, 100); - a.points.C = new a.Point(0, 100); - a.points.D = new a.Point(100, 0); + it('Should trim a path when a line overlaps with a curve', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(0, 0) + a.points.B = new a.Point(100, 100) + a.points.C = new a.Point(0, 100) + a.points.D = new a.Point(100, 0) let test = new a.Path() .move(new a.Point(0, 20)) @@ -708,21 +706,21 @@ describe('Path', () => { .line(a.points.C) .line(a.points.D) .line(a.points.A) - .trim(); + .trim() - expect(test.ops.length).to.equal(5); - expect(round(test.ops[2].to.x)).to.equal(72.19); - expect(round(test.ops[2].to.y)).to.equal(27.81); - }); + expect(test.ops.length).to.equal(5) + expect(round(test.ops[2].to.x)).to.equal(72.19) + expect(round(test.ops[2].to.y)).to.equal(27.81) + }) - it("Should trim a path when a curves overlap", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(0, 0); - a.points.B = new a.Point(100, 100); - a.points.C = new a.Point(0, 100); - a.points.D = new a.Point(100, 0); + it('Should trim a path when a curves overlap', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(0, 0) + a.points.B = new a.Point(100, 100) + a.points.C = new a.Point(0, 100) + a.points.D = new a.Point(100, 0) let test = new a.Path() .move(new a.Point(0, 20)) @@ -731,67 +729,65 @@ describe('Path', () => { .line(a.points.C) .curve(a.points.C, a.points.A, a.points.D) .line(a.points.A) - .trim(); + .trim() - expect(test.ops.length).to.equal(5); - expect(round(test.ops[2].to.x)).to.equal(50); - expect(round(test.ops[2].to.y)).to.equal(11.01); - }); + expect(test.ops.length).to.equal(5) + expect(round(test.ops[2].to.x)).to.equal(50) + expect(round(test.ops[2].to.y)).to.equal(11.01) + }) - it("Should translate a path", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; - a.points.A = new a.Point(0, 0); - a.points.B = new a.Point(100, 100); - a.points.C = new a.Point(0, 100); - a.points.D = new a.Point(100, 0); + it('Should translate a path', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a + a.points.A = new a.Point(0, 0) + a.points.B = new a.Point(100, 100) + a.points.C = new a.Point(0, 100) + a.points.D = new a.Point(100, 0) - let base = new a.Path() - .move(a.points.A) - .curve(a.points.B, a.points.C, a.points.D); - let test = base.translate(10, 20); + let base = new a.Path().move(a.points.A).curve(a.points.B, a.points.C, a.points.D) + let test = base.translate(10, 20) - expect(test.ops.length).to.equal(2); - expect(test.ops[0].to.x).to.equal(10); - expect(test.ops[0].to.y).to.equal(20); - expect(test.ops[1].to.x).to.equal(110); - expect(test.ops[1].to.y).to.equal(20); - }); + expect(test.ops.length).to.equal(2) + expect(test.ops[0].to.x).to.equal(10) + expect(test.ops[0].to.y).to.equal(20) + expect(test.ops[1].to.x).to.equal(110) + expect(test.ops[1].to.y).to.equal(20) + }) - it("Should add a path attribute", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should add a path attribute', () => { + 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)) - .attr("class", "foo") - .attr("class", "bar"); - expect(a.paths.line.attributes.get("class")).to.equal("foo bar"); - }); + .attr('class', 'foo') + .attr('class', 'bar') + expect(a.paths.line.attributes.get('class')).to.equal('foo bar') + }) - it("Should overwrite a path attribute", () => { - let pattern = new Pattern(); - pattern.parts.a = new pattern.Part(); - let a = pattern.parts.a; + it('Should overwrite a path attribute', () => { + let pattern = new Pattern() + pattern.parts.a = new pattern.Part() + let a = pattern.parts.a // 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"); - }); + .attr('class', 'foo') + .attr('class', 'bar') + .attr('class', 'overwritten', true) + expect(a.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(); - let a = pattern.parts.a; + it('Should move along a path even if it lands just on a joint', () => { + 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(20.979322245694167, -219.8547313525503)) @@ -808,367 +804,342 @@ describe('Path', () => { expect(a.points.test).to.be.instanceOf(a.Point) }) - it("Should add raise methods to a path", () => { + 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'); - }); + const p1 = new Path(10, 20).withRaise(raise) + expect(p1.raise()).to.equal('hello') + }) - it("Should add raise methods to a path", () => { + it('Should add raise methods to a path', () => { const raise = () => 'hello' - const p1 = new Path().withRaise(raise); - expect(p1.raise()).to.equal('hello'); - }); + const p1 = new Path().withRaise(raise) + expect(p1.raise()).to.equal('hello') + }) - it("Should set render to true/false", () => { + it('Should set render to true/false', () => { const p1 = new Path().setRender(false) - expect(p1.render).to.equal(false); - }); + expect(p1.render).to.equal(false) + }) - it("Should set class with setClass", () => { + it('Should set class with setClass', () => { const p1 = new Path().setClass('fabric') p1.setClass() - expect(p1.attributes.get('class')).to.equal('fabric'); - }); + expect(p1.attributes.get('class')).to.equal('fabric') + }) - it("Should raise a warning when moving to a non-point", () => { + it('Should raise a warning when moving to a non-point', () => { let invalid = false - const raise = { warning: () => invalid = true } + const raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - expect(invalid).to.equal(false); + expect(invalid).to.equal(false) try { p1.move('a') + } catch (err) { + expect('' + err).to.contain('check is not a function') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a line to a non-point", () => { + it('Should raise a warning when drawing a line to a non-point', () => { let invalid = false - const raise = { warning: () => invalid = true } + const raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - expect(invalid).to.equal(false); + expect(invalid).to.equal(false) try { p1.line('a') + } catch (err) { + expect('' + err).to.contain('check is not a function') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a curve to a non-point", () => { + it('Should raise a warning when drawing a curve to a non-point', () => { let invalid = false - const raise = { warning: () => invalid = true } + const raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const a = new Point(0,0) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const a = new Point(0, 0) + const b = new 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a curve with a Cp1 that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const a = new Point(0,0) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const a = new Point(0, 0) + const b = new 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a curve with a Cp1 that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const b = new 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') } - catch (err) { - expect(''+err).to.contain("copy is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a curve with a Cp2 that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const b = new 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') } - catch (err) { - expect(''+err).to.contain("copy is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a _curve with a To that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const b = new 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') } - catch (err) { - expect(''+err).to.contain("copy is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a _curve with a Cp2 that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const b = new 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') } - catch (err) { - expect(''+err).to.contain("copy is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a curve_ with a To that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const b = new 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') } - catch (err) { - expect(''+err).to.contain("copy is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when drawing a curve_ with a Cp2 that is a non-point", () => { + 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 raise = { warning: () => (invalid = true) } const p1 = new Path().withRaise(raise) - const b = new Point(10,10) - expect(invalid).to.equal(false); + const b = new 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') } - catch (err) { - expect(''+err).to.contain("copy is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should add a noop operation", () => { + it('Should add a noop operation', () => { const p1 = new Path().noop() - expect(p1.ops.length).to.equal(1); - expect(p1.ops[0].type).to.equal('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 Point(0,0) - const b = new Point(10,10) + it('Should handle an insop operation', () => { + const a = new Point(0, 0) + const b = new Point(10, 10) const p1 = new Path().move(a).line(b) const p2 = new 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'); - }); + 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", () => { + it('Should raise a warning when an insop operation used an falsy ID', () => { let invalid = false - const raise = { warning: () => invalid = true } - const a = new Point(0,0) - const b = new Point(10,10) + const raise = { 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); + expect(invalid).to.equal(false) const p2 = new Path().withRaise(raise).noop('test').insop(false, p1) - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when an insop operation used an falsy ID", () => { + it('Should raise a warning when an insop operation used an falsy ID', () => { let invalid = false - const raise = { warning: () => invalid = true } - const a = new Point(0,0) - const b = new Point(10,10) + const raise = { 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); + expect(invalid).to.equal(false) try { new Path().withRaise(raise).noop('test').insop('test') + } catch (err) { + expect('' + err).to.contain("Cannot read properties of undefined (reading 'ops')") } - catch (err) { - expect(''+err).to.contain("Cannot read properties of undefined (reading 'ops')") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when setting an attribute without a name", () => { + 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 raise = { warning: () => (invalid = true) } + expect(invalid).to.equal(false) const p1 = new Path().withRaise(raise).attr() - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when setting an attribute without a value", () => { + 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 raise = { warning: () => (invalid = true) } + expect(invalid).to.equal(false) const p1 = new Path().withRaise(raise).attr('test') - expect(invalid).to.equal(true); - }); + 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(); + 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) + 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") - }); + 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 Pattern(); - pattern.parts.a = new pattern.Part(); + 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) + 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')") + } catch (err) { + expect('' + err).to.contain("Cannot read properties of undefined (reading '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") - }); + 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", () => { + 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); + const raise = { error: () => (invalid = true) } + expect(invalid).to.equal(false) try { new Path().withRaise(raise).start() + } catch (err) { + expect('' + err).to.contain("Cannot read properties of undefined (reading 'to')") } - catch (err) { - expect(''+err).to.contain("Cannot read properties of undefined (reading 'to')") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when calling end on a path without drawing operations", () => { + 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); + const raise = { error: () => (invalid = true) } + expect(invalid).to.equal(false) try { new Path().withRaise(raise).end() + } catch (err) { + expect('' + err).to.contain("Cannot read properties of undefined (reading 'type')") } - catch (err) { - expect(''+err).to.contain("Cannot read properties of undefined (reading 'type')") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when calling shiftAlong but distance is not a number", () => { + 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 Path() - .withRaise(raise) - .move(new Point(0,0)) - .line(new Point(10,10)) - .shiftAlong() - expect(invalid).to.equal(true); - }); + const raise = { error: () => (invalid = true) } + expect(invalid).to.equal(false) + new Path().withRaise(raise).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", () => { + 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, + error: () => (invalid = true), + warning: () => (invalid = true), } - expect(invalid).to.equal(false); + 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)) + .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); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when splitting a path on a non-point", () => { + it('Should raise a warning when splitting a path on a non-point', () => { let invalid = false const raise = { - error: () => invalid = true, - warning: () => invalid = true, + 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) - .line(cp1) + 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')") } - catch (err) { - expect(''+err).to.contain("Cannot read properties of undefined (reading 'check')") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when splitting a path on a non-point", () => { + it('Should raise a warning when splitting a path on a non-point', () => { let invalid = false const raise = { - error: () => invalid = true, - warning: () => invalid = true, + 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) + 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')") } - catch (err) { - expect(''+err).to.contain("Cannot read properties of undefined (reading 'check')") - } - expect(invalid).to.equal(true); - }); -}); + expect(invalid).to.equal(true) + }) +}) diff --git a/packages/core/tests/pattern-draft.mjs b/packages/core/tests/pattern-draft.mjs new file mode 100644 index 00000000000..c5d06a074af --- /dev/null +++ b/packages/core/tests/pattern-draft.mjs @@ -0,0 +1,1081 @@ +import chai from 'chai' +import { round, Pattern, Design, pctBasedOn } from '../src/index.mjs' + +const expect = chai.expect + +describe('Pattern', () => { + + + it('Should merge settings with default settings', () => { + let pattern = new Pattern() + let settings = { + foo: 'bar', + deep: { + free: 'ze', + }, + } + pattern.apply(settings) + expect(pattern.settings.foo).to.equal('bar') + expect(pattern.settings.locale).to.equal('en') + expect(pattern.settings.margin).to.equal(2) + expect(pattern.settings.idPrefix).to.equal('fs-') + expect(pattern.settings.deep.free).to.equal('ze') + }) + + it('Should draft according to settings', () => { + let count = 0 + const back = { + name: 'back', + hide: true, + draft: function (part) { + count++ + return part + }, + } + const front = { + name: 'front', + from: back, + draft: function (part) { + count++ + return part + }, + } + const Test = new Design({ + name: 'test', + parts: [back, front], + }) + + const pattern = new Test() + pattern.draft() + expect(count).to.equal(2) + }) + + it('Should sample an option', () => { + let pattern = new Pattern({ + options: { + len: { pct: 30, min: 10 }, + bonus: 10, + }, + }) + pattern.draft = function () { + pattern.parts.a = new pattern.Part() + pattern.parts.b = new pattern.Part() + let a = pattern.parts.a + a.points.from = new a.Point(0, 0) + a.points.to = new a.Point( + 100 * a.context.settings.options.len, + a.context.settings.options.bonus + ) + a.paths.test = new a.Path().move(a.points.from).line(a.points.to) + pattern.parts.b.inject(a) + } + pattern.settings.sample = { + type: 'option', + option: 'len', + } + pattern.sample() + expect(pattern.parts.a.paths.test_1.render).to.equal(true) + expect(pattern.parts.b.paths.test_10.ops[1].to.y).to.equal(10) + }) + /* + it("Should sample a list option", () => { + const front = { + name: 'front', + options: { + len: { + dflt: 1, + list: [1,2,3] + } + }, + draft: 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 Test = new freesewing.Design({ + name: "test", + parts: [front], + }) + const pattern = new Test({ + sample: { + type: 'option', + option: 'len' + } + }) + pattern.sample(); + console.log(pattern.parts) + 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 Pattern(); + let count = 0; + pattern._draft = () => {}; + pattern.on("preDraft", function(pattern) { + count++; + }); + pattern.draft(); + expect(count).to.equal(1); + }); + + it("Should register a hook from a plugin", () => { + let pattern = new Pattern(); + let count = 0; + pattern._draft = () => {}; + let plugin = { + name: "test", + version: "0.1-test", + hooks: { + preDraft: function(pattern) { + count++; + } + } + }; + pattern.use(plugin); + pattern.draft(); + expect(count).to.equal(1); + }); + + it("Should register multiple methods on a single hook", () => { + let pattern = new Pattern(); + let count = 0; + pattern._draft = () => {}; + let plugin = { + name: "test", + version: "0.1-test", + hooks: { + preDraft: [ + function(pattern) { + count++; + }, + function(pattern) { + count++; + } + ] + } + }; + pattern.use(plugin); + pattern.draft(); + expect(count).to.equal(2); + }); + */ + + it('Should check whether a part is needed', () => { + let config = { + name: 'test', + dependencies: { back: 'front', side: 'back' }, + inject: { back: 'front' }, + hide: ['back'], + } + const Test = new Design(config) + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test().init() + pattern.settings.only = 'back' + //expect(pattern.needs("back")).to.equal(true); + expect(pattern.needs('front')).to.equal(true) + //expect(pattern.needs("side")).to.equal(false); + //pattern.settings.only = ["back", "side"]; + //expect(pattern.needs("back")).to.equal(true); + //expect(pattern.needs("front")).to.equal(true); + //expect(pattern.needs("side")).to.equal(true); + }) + + it('Should check whether a part is wanted', () => { + let config = { + name: 'test', + dependencies: { back: 'front', side: 'back' }, + inject: { back: 'front' }, + hide: ['back'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test() + pattern.settings.only = 'back' + expect(pattern.wants('back')).to.equal(true) + expect(pattern.wants('front')).to.equal(false) + expect(pattern.wants('side')).to.equal(false) + pattern.settings.only = ['back', 'side'] + expect(pattern.wants('back')).to.equal(true) + expect(pattern.wants('front')).to.equal(false) + expect(pattern.wants('side')).to.equal(true) + }) + + it('Should correctly resolve dependencies - string version', () => { + let config = { + name: 'test', + dependencies: { front: 'back', side: 'back', hood: 'front', stripe: 'hood' }, + } + const Test = new Design(config) + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test().init() + expect(pattern.config.resolvedDependencies.front.length).to.equal(1) + expect(pattern.config.resolvedDependencies.front[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.side.length).to.equal(1) + expect(pattern.config.resolvedDependencies.side[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.hood.length).to.equal(2) + expect(pattern.config.resolvedDependencies.hood[0]).to.equal('front') + expect(pattern.config.resolvedDependencies.hood[1]).to.equal('back') + expect(pattern.config.resolvedDependencies.stripe.length).to.equal(3) + expect(pattern.config.resolvedDependencies.stripe[0]).to.equal('hood') + expect(pattern.config.resolvedDependencies.stripe[1]).to.equal('front') + expect(pattern.config.resolvedDependencies.stripe[2]).to.equal('back') + expect(pattern.config.resolvedDependencies.back.length).to.equal(0) + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('side') + expect(pattern.config.draftOrder[3]).to.equal('hood') + }) + + it('Should correctly resolve dependencies - array version', () => { + let config = { + name: 'test', + dependencies: { front: ['back'], side: ['back'], hood: ['front'], stripe: ['hood'] }, + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test().init() + expect(pattern.config.resolvedDependencies.front.length).to.equal(1) + expect(pattern.config.resolvedDependencies.front[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.side.length).to.equal(1) + expect(pattern.config.resolvedDependencies.side[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.hood.length).to.equal(2) + expect(pattern.config.resolvedDependencies.hood[0]).to.equal('front') + expect(pattern.config.resolvedDependencies.hood[1]).to.equal('back') + expect(pattern.config.resolvedDependencies.stripe.length).to.equal(3) + expect(pattern.config.resolvedDependencies.stripe[0]).to.equal('hood') + expect(pattern.config.resolvedDependencies.stripe[1]).to.equal('front') + expect(pattern.config.resolvedDependencies.stripe[2]).to.equal('back') + expect(pattern.config.resolvedDependencies.back.length).to.equal(0) + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('side') + expect(pattern.config.draftOrder[3]).to.equal('hood') + }) + + it('Should correctly resolve dependencies - issue #971 - working version', () => { + let config = { + name: 'test', + dependencies: { front: ['back'], crotch: ['front', 'back'] }, + parts: ['back', 'front', 'crotch'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test().init() + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('crotch') + }) + + it('Should correctly resolve dependencies - issue #971 - broken version', () => { + let config = { + name: 'test', + dependencies: { front: 'back', crotch: ['front', 'back'] }, + parts: ['back', 'front', 'crotch'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test().init() + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + 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) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } + + let pattern = new Test().init() + 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 Pattern() + let part = new pattern.Part() + expect(part.context.settings).to.equal(pattern.settings) + }) + + it('Should correctly merge settings', () => { + let pattern = new Pattern() + let settings = { + complete: false, + only: [1, 2, 3], + margin: 5, + } + pattern.apply(settings) + expect(pattern.settings.complete).to.equal(false) + expect(pattern.settings.only[1]).to.equal(2) + expect(pattern.settings.margin).to.equal(5) + expect(pattern.settings.only.length).to.equal(3) + }) + + it('Should correctly merge settings for existing array', () => { + let pattern = new Pattern() + pattern.settings.only = [1] + let settings = { + complete: false, + only: [2, 3, 4], + margin: 5, + } + pattern.apply(settings) + expect(pattern.settings.complete).to.equal(false) + expect(pattern.settings.only.length).to.equal(4) + expect(pattern.settings.margin).to.equal(5) + }) + + it('Should return all render props', () => { + const front = { + name: 'front', + draft: function (part) { + return part + }, + } + const Test = new Design({ + name: 'test', + parts: [front], + }) + 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 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 generate an auto layout if there is no set layout", () => { + const Test = new freesewing.Design({ + name: "test", + parts: [ + { + name: 'front', + draft: function(part) { + const {Path, paths, Point} = part.shorthand() + paths.seam = new Path().move(new Point(0,0)) + .line(new Point(5,5)) + return part + } + } + ] + }) + const pattern = new Test() + pattern.parts.front = new pattern.Part('front') + pattern.draftFront(pattern.parts.front); + pattern.pack() + expect(pattern.autoLayout.parts.front).to.exist + expect(pattern.autoLayout.parts.front.move.y).to.equal(2) + expect(pattern.autoLayout.parts.front.move.x).to.equal(2) + }) + + it("Should handle custom layouts", () => { + const Test = new 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 Design({ + name: "test", + parts: ['front'], + measurements: [ 'head' ], + options: { + len: { pct: 50, min: 22, max: 78, snap: 10, ...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 Design({ + name: "test", + parts: [ + { + name: 'front', + draft: 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 + } + } + ], + measurements: [ 'head' ], + options: { + len: { pct: 50, min: 22, max: 78, snap: [10,14,19,28], ...pctBasedOn('head') } + } + }) + 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(round(pattern.parts.front.paths.line_10.ops[1].to.x)).to.equal(33.72); + }); + + + it("Should retrieve the cutList", () => { + const Test = new Design({ + name: "test", + parts: [{ + name: 'front', + draft: function(part) { + const { addCut } = part.shorthand() + addCut(4, 'lining', true) + return part + } + }], + }) + const pattern = new Test() + expect(JSON.stringify(pattern.getCutList())).to.equal(JSON.stringify({})) + pattern.draft() + const list = `{"front":{"grain":90,"materials":{"lining":{"cut":4,"identical":true}}}}` + expect(JSON.stringify(pattern.getCutList())).to.equal(list) + }); + */ + + // 2022 style part inheritance + // I am aware this does too much for one unit test, but this is to simplify TDD + // we can split it up later + it('Design constructor should resolve nested injections', () => { + const partA = { + name: 'partA', + options: { optionA: { bool: true } }, + measurements: ['measieA'], + optionalMeasurements: ['optmeasieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.a1 = new Point(1, 1) + points.a2 = new Point(11, 11) + paths.a = new Path().move(points.a1).line(points.a2) + return part + }, + } + const partB = { + name: 'partB', + from: partA, + options: { optionB: { pct: 12, min: 2, max: 20 } }, + measurements: ['measieB'], + optionalMeasurements: ['optmeasieB', 'measieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.b1 = new Point(2, 2) + points.b2 = new Point(22, 22) + paths.b = new Path().move(points.b1).line(points.b2) + return part + }, + } + const partC = { + name: 'partC', + from: partB, + options: { optionC: { deg: 5, min: 0, max: 15 } }, + measurements: ['measieC'], + optionalMeasurements: ['optmeasieC', 'measieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.c1 = new Point(3, 3) + points.c2 = new Point(33, 33) + paths.c = new Path().move(points.c1).line(points.c2) + return part + }, + } + const partR = { + // R for runtime, which is when this wil be attached + name: 'partR', + from: partA, + after: partC, + options: { optionR: { dflt: 'red', list: ['red', 'green', 'blue'] } }, + measurements: ['measieR'], + optionalMeasurements: ['optmeasieR', 'measieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.r1 = new Point(4, 4) + points.r2 = new Point(44, 44) + paths.r = new Path().move(points.r1).line(points.r2) + return part + }, + } + + const design = new Design({ parts: [partC] }) + const pattern = new design().addPart(partR).draft() + // Measurements + expect(pattern.config.measurements.length).to.equal(4) + expect(pattern.config.measurements.indexOf('measieA') === -1).to.equal(false) + expect(pattern.config.measurements.indexOf('measieB') === -1).to.equal(false) + expect(pattern.config.measurements.indexOf('measieC') === -1).to.equal(false) + expect(pattern.config.measurements.indexOf('measieR') === -1).to.equal(false) + // Optional measurements + expect(pattern.config.optionalMeasurements.length).to.equal(4) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieA') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieB') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieC') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieR') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('measieA') === -1).to.equal(true) + // Options + expect(pattern.config.options.optionA.bool).to.equal(true) + expect(pattern.config.options.optionB.pct).to.equal(12) + expect(pattern.config.options.optionB.min).to.equal(2) + expect(pattern.config.options.optionB.max).to.equal(20) + expect(pattern.config.options.optionC.deg).to.equal(5) + expect(pattern.config.options.optionC.min).to.equal(0) + expect(pattern.config.options.optionC.max).to.equal(15) + expect(pattern.config.options.optionR.dflt).to.equal('red') + expect(pattern.config.options.optionR.list[0]).to.equal('red') + expect(pattern.config.options.optionR.list[1]).to.equal('green') + expect(pattern.config.options.optionR.list[2]).to.equal('blue') + // Dependencies + expect(pattern.config.dependencies.partB[0]).to.equal('partA') + expect(pattern.config.dependencies.partC[0]).to.equal('partB') + expect(pattern.config.dependencies.partR[0]).to.equal('partC') + expect(pattern.config.dependencies.partR[1]).to.equal('partA') + // Inject + expect(pattern.config.inject.partB).to.equal('partA') + expect(pattern.config.inject.partC).to.equal('partB') + expect(pattern.config.inject.partR).to.equal('partA') + // Draft order + expect(pattern.config.draftOrder[0]).to.equal('partA') + expect(pattern.config.draftOrder[1]).to.equal('partB') + expect(pattern.config.draftOrder[2]).to.equal('partC') + expect(pattern.config.draftOrder[3]).to.equal('partR') + // Points + expect(pattern.parts.partA.points.a1.x).to.equal(1) + expect(pattern.parts.partA.points.a1.y).to.equal(1) + expect(pattern.parts.partA.points.a2.x).to.equal(11) + expect(pattern.parts.partA.points.a2.y).to.equal(11) + expect(pattern.parts.partB.points.b1.x).to.equal(2) + expect(pattern.parts.partB.points.b1.y).to.equal(2) + expect(pattern.parts.partB.points.b2.x).to.equal(22) + expect(pattern.parts.partB.points.b2.y).to.equal(22) + expect(pattern.parts.partC.points.c1.x).to.equal(3) + expect(pattern.parts.partC.points.c1.y).to.equal(3) + expect(pattern.parts.partC.points.c2.x).to.equal(33) + expect(pattern.parts.partC.points.c2.y).to.equal(33) + expect(pattern.parts.partR.points.r1.x).to.equal(4) + expect(pattern.parts.partR.points.r1.y).to.equal(4) + expect(pattern.parts.partR.points.r2.x).to.equal(44) + expect(pattern.parts.partR.points.r2.y).to.equal(44) + // Paths in partA + expect(pattern.parts.partA.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partA.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partA.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partA.paths.a.ops[1].to.y).to.equal(11) + // Paths in partB + expect(pattern.parts.partB.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partB.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partB.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partB.paths.a.ops[1].to.y).to.equal(11) + expect(pattern.parts.partB.paths.b.ops[0].to.x).to.equal(2) + expect(pattern.parts.partB.paths.b.ops[0].to.y).to.equal(2) + expect(pattern.parts.partB.paths.b.ops[1].to.x).to.equal(22) + expect(pattern.parts.partB.paths.b.ops[1].to.y).to.equal(22) + // Paths in partC + expect(pattern.parts.partC.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partC.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partC.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partC.paths.a.ops[1].to.y).to.equal(11) + expect(pattern.parts.partC.paths.b.ops[0].to.x).to.equal(2) + expect(pattern.parts.partC.paths.b.ops[0].to.y).to.equal(2) + expect(pattern.parts.partC.paths.b.ops[1].to.x).to.equal(22) + expect(pattern.parts.partC.paths.b.ops[1].to.y).to.equal(22) + expect(pattern.parts.partC.paths.c.ops[0].to.x).to.equal(3) + expect(pattern.parts.partC.paths.c.ops[0].to.y).to.equal(3) + expect(pattern.parts.partC.paths.c.ops[1].to.x).to.equal(33) + expect(pattern.parts.partC.paths.c.ops[1].to.y).to.equal(33) + // Paths in partR + expect(pattern.parts.partC.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partC.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partC.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partC.paths.a.ops[1].to.y).to.equal(11) + expect(pattern.parts.partR.paths.r.ops[0].to.x).to.equal(4) + expect(pattern.parts.partR.paths.r.ops[0].to.y).to.equal(4) + expect(pattern.parts.partR.paths.r.ops[1].to.x).to.equal(44) + expect(pattern.parts.partR.paths.r.ops[1].to.y).to.equal(44) + }) + + it('Design constructor should resolve nested dependencies (2022)', () => { + const partA = { + name: 'partA', + options: { optionA: { bool: true } }, + measurements: ['measieA'], + optionalMeasurements: ['optmeasieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.a1 = new Point(1, 1) + points.a2 = new Point(11, 11) + paths.a = new Path().move(points.a1).line(points.a2) + return part + }, + } + const partB = { + name: 'partB', + from: partA, + options: { optionB: { pct: 12, min: 2, max: 20 } }, + measurements: ['measieB'], + optionalMeasurements: ['optmeasieB', 'measieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.b1 = new Point(2, 2) + points.b2 = new Point(22, 22) + paths.b = new Path().move(points.b1).line(points.b2) + return part + }, + } + const partC = { + name: 'partC', + from: partB, + options: { optionC: { deg: 5, min: 0, max: 15 } }, + measurements: ['measieC'], + optionalMeasurements: ['optmeasieC', 'measieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.c1 = new Point(3, 3) + points.c2 = new Point(33, 33) + paths.c = new Path().move(points.c1).line(points.c2) + return part + }, + } + const partD = { + name: 'partD', + after: partC, + options: { optionD: { dflt: 'red', list: ['red', 'green', 'blue'] } }, + measurements: ['measieD'], + optionalMeasurements: ['optmeasieD', 'measieA'], + draft: (part) => { + const { points, Point, paths, Path } = part.shorthand() + points.d1 = new Point(4, 4) + points.d2 = new Point(44, 44) + paths.d = new Path().move(points.d1).line(points.d2) + return part + }, + } + const design = new Design({ parts: [partD] }) + const pattern = new design().draft() + // Measurements + expect(pattern.config.measurements.length).to.equal(4) + expect(pattern.config.measurements.indexOf('measieA') === -1).to.equal(false) + expect(pattern.config.measurements.indexOf('measieB') === -1).to.equal(false) + expect(pattern.config.measurements.indexOf('measieC') === -1).to.equal(false) + expect(pattern.config.measurements.indexOf('measieD') === -1).to.equal(false) + // Optional measurements + expect(pattern.config.optionalMeasurements.length).to.equal(4) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieA') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieB') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieC') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('optmeasieD') === -1).to.equal(false) + expect(pattern.config.optionalMeasurements.indexOf('measieA') === -1).to.equal(true) + // Options + expect(pattern.config.options.optionA.bool).to.equal(true) + expect(pattern.config.options.optionB.pct).to.equal(12) + expect(pattern.config.options.optionB.min).to.equal(2) + expect(pattern.config.options.optionB.max).to.equal(20) + expect(pattern.config.options.optionC.deg).to.equal(5) + expect(pattern.config.options.optionC.min).to.equal(0) + expect(pattern.config.options.optionC.max).to.equal(15) + expect(pattern.config.options.optionD.dflt).to.equal('red') + expect(pattern.config.options.optionD.list[0]).to.equal('red') + expect(pattern.config.options.optionD.list[1]).to.equal('green') + expect(pattern.config.options.optionD.list[2]).to.equal('blue') + // Dependencies + expect(pattern.config.dependencies.partB[0]).to.equal('partA') + expect(pattern.config.dependencies.partC[0]).to.equal('partB') + expect(pattern.config.dependencies.partD[0]).to.equal('partC') + // Inject + expect(pattern.config.inject.partB).to.equal('partA') + expect(pattern.config.inject.partC).to.equal('partB') + // Draft order + expect(pattern.config.draftOrder[0]).to.equal('partA') + expect(pattern.config.draftOrder[1]).to.equal('partB') + expect(pattern.config.draftOrder[2]).to.equal('partC') + expect(pattern.config.draftOrder[3]).to.equal('partD') + // Points + expect(pattern.parts.partA.points.a1.x).to.equal(1) + expect(pattern.parts.partA.points.a1.y).to.equal(1) + expect(pattern.parts.partA.points.a2.x).to.equal(11) + expect(pattern.parts.partA.points.a2.y).to.equal(11) + expect(pattern.parts.partB.points.b1.x).to.equal(2) + expect(pattern.parts.partB.points.b1.y).to.equal(2) + expect(pattern.parts.partB.points.b2.x).to.equal(22) + expect(pattern.parts.partB.points.b2.y).to.equal(22) + expect(pattern.parts.partC.points.c1.x).to.equal(3) + expect(pattern.parts.partC.points.c1.y).to.equal(3) + expect(pattern.parts.partC.points.c2.x).to.equal(33) + expect(pattern.parts.partC.points.c2.y).to.equal(33) + expect(pattern.parts.partD.points.d1.x).to.equal(4) + expect(pattern.parts.partD.points.d1.y).to.equal(4) + expect(pattern.parts.partD.points.d2.x).to.equal(44) + expect(pattern.parts.partD.points.d2.y).to.equal(44) + // Paths in partA + expect(pattern.parts.partA.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partA.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partA.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partA.paths.a.ops[1].to.y).to.equal(11) + // Paths in partB + expect(pattern.parts.partB.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partB.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partB.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partB.paths.a.ops[1].to.y).to.equal(11) + expect(pattern.parts.partB.paths.b.ops[0].to.x).to.equal(2) + expect(pattern.parts.partB.paths.b.ops[0].to.y).to.equal(2) + expect(pattern.parts.partB.paths.b.ops[1].to.x).to.equal(22) + expect(pattern.parts.partB.paths.b.ops[1].to.y).to.equal(22) + // Paths in partC + expect(pattern.parts.partC.paths.a.ops[0].to.x).to.equal(1) + expect(pattern.parts.partC.paths.a.ops[0].to.y).to.equal(1) + expect(pattern.parts.partC.paths.a.ops[1].to.x).to.equal(11) + expect(pattern.parts.partC.paths.a.ops[1].to.y).to.equal(11) + expect(pattern.parts.partC.paths.b.ops[0].to.x).to.equal(2) + expect(pattern.parts.partC.paths.b.ops[0].to.y).to.equal(2) + expect(pattern.parts.partC.paths.b.ops[1].to.x).to.equal(22) + expect(pattern.parts.partC.paths.b.ops[1].to.y).to.equal(22) + expect(pattern.parts.partC.paths.c.ops[0].to.x).to.equal(3) + expect(pattern.parts.partC.paths.c.ops[0].to.y).to.equal(3) + expect(pattern.parts.partC.paths.c.ops[1].to.x).to.equal(33) + expect(pattern.parts.partC.paths.c.ops[1].to.y).to.equal(33) + // Paths in partR + expect(pattern.parts.partD.paths.d.ops[0].to.x).to.equal(4) + expect(pattern.parts.partD.paths.d.ops[0].to.y).to.equal(4) + expect(pattern.parts.partD.paths.d.ops[1].to.x).to.equal(44) + expect(pattern.parts.partD.paths.d.ops[1].to.y).to.equal(44) + }) + + it('Pattern should load single plugin', () => { + const plugin = { + name: 'example', + version: 1, + hooks: { + preRender: function (svg, attributes) { + svg.attributes.add('freesewing:plugin-example', version) + }, + }, + } + + const part = { + name: 'test.part', + plugins: plugin, + draft: (part) => part, + } + const design = new Design({ parts: [part] }) + const pattern = new design() + pattern.init() + expect(pattern.hooks.preRender.length).to.equal(1) + }) + /* + it("Design constructor should load array of plugins", () => { + let plugin1 = { + name: "example1", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example1", version); + } + } + }; + let plugin2 = { + name: "example2", + version: 2, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example2", version); + } + } + }; + + let design = new Design( { plugins: [plugin1, plugin2] }); + let pattern = new design(); + 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 Design({ plugins: { 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 Design({ plugins: { 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 Design({ plugins: [ + { plugin, condition: condition1 }, + { plugin, condition: condition2 }, + ]}); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(1); +*/ +}) diff --git a/packages/core/tests/pattern-init.mjs b/packages/core/tests/pattern-init.mjs new file mode 100644 index 00000000000..702252b3b53 --- /dev/null +++ b/packages/core/tests/pattern-init.mjs @@ -0,0 +1,240 @@ +import chai from 'chai' +import { round, Design, Point, pctBasedOn } from '../src/index.mjs' + +const expect = chai.expect + +describe('Pattern', () => { + + describe('Pattern.constructor()', () => { + + it('Pattern constructor should return pattern object', () => { + const Pattern = new Design() + const pattern = new Pattern() + expect(typeof pattern).to.equal('object') + }) + + it('Pattern constructor should add enumerable properties', () => { + const Pattern = new Design() + const pattern = new Pattern() + expect(typeof pattern.settings).to.equal('object') + expect(typeof pattern.config).to.equal('object') + expect(typeof pattern.parts).to.equal('object') + expect(typeof pattern.store).to.equal('object') + expect(Object.keys(pattern).length).to.equal(4) + }) + + it('Pattern constructor should add non-enumerable properties', () => { + const Pattern = new Design() + const pattern = new Pattern() + expect(typeof pattern.plugins).to.equal('object') + expect(typeof pattern.autoLayout).to.equal('object') + expect(typeof pattern.hooks).to.equal('object') + expect(typeof pattern.Point).to.equal('function') + expect(typeof pattern.Path).to.equal('function') + expect(typeof pattern.Snippet).to.equal('function') + expect(typeof pattern.Attributes).to.equal('function') + expect(typeof pattern.macros).to.equal('object') + expect(typeof pattern.__parts).to.equal('object') + expect(typeof pattern.__inject).to.equal('object') + expect(typeof pattern.__dependencies).to.equal('object') + expect(typeof pattern.__resolvedDependencies).to.equal('object') + expect(typeof pattern.__hide).to.equal('object') + expect(Array.isArray(pattern.__draftOrder)).to.equal(true) + expect(pattern.width).to.equal(0) + expect(pattern.height).to.equal(0) + expect(pattern.is).to.equal('') + }) + + it('Pattern constructor should add default settings', () => { + const Pattern = new Design() + const pattern = new Pattern() + const dflts = { + complete: true, + idPrefix: 'fs-', + locale: 'en', + units: 'metric', + margin: 2, + scale: 1, + layout: true, + debug: false, + options: {}, + absoluteOptions: {}, + } + for (const [key, value] of Object.entries(dflts)) { + if (typeof value === 'object') expect(Object.keys(value).length).to.equal(0) + else expect(pattern.settings[key]).to.equal(value) + } + }) + + }) + + describe('Pattern.init()', () => { + + const partA = { + name: 'test.partA', + measurements: ['head', 'knee'], + optionalMeasurements: [ 'chest', 'waist'], + options: { + optA: { pct: 40, min: 20, max: 80 } + }, + draft: () => { } + } + const partB = { + name: 'test.partB', + measurements: ['head', 'knee'], + optionalMeasurements: [ 'knee'], + after: partA, + plugins: [{ + name: 'testPlugin', + hooks: { + preRender: () => {} + } + }], + options: { + optB: { deg: 40, min: 20, max: 80 } + }, + draft: () => { } + } + const partC = { + name: 'test.partC', + measurements: ['head', 'knee'], + optionalMeasurements: [ 'knee'], + from: partB, + options: { + optC: { pct: 20, min: 10, max: 30 } + }, + draft: () => { } + } + + const Pattern = new Design({ + data: { + name: 'test', + version: '1.2.3', + }, + parts: [ partC ] + }) + const pattern = new Pattern() + pattern.init() + + it('Pattern.init() should resolve all measurements', () => { + expect([ + ...pattern.config.measurements, + ...pattern.config.optionalMeasurements + ].length).to.equal(4) + }) + + it('Pattern.init() should resolve required measurements', () => { + expect(pattern.config.measurements.length).to.equal(2) + expect(pattern.config.measurements[0]).to.equal('head') + expect(pattern.config.measurements[1]).to.equal('knee') + }) + + it('Pattern.init() should resolve optional measurements', () => { + expect(pattern.config.optionalMeasurements.length).to.equal(2) + expect(pattern.config.optionalMeasurements[0]).to.equal('chest') + expect(pattern.config.optionalMeasurements[1]).to.equal('waist') + }) + + it('Pattern.init() should resolve options', () => { + expect(Object.keys(pattern.config.options).length).to.equal(3) + for (const [key, value] of Object.entries(partA.options.optA)) { + expect(pattern.config.options.optA[key]).to.equal(value) + } + for (const [key, value] of Object.entries(partB.options.optB)) { + expect(pattern.config.options.optB[key]).to.equal(value) + } + for (const [key, value] of Object.entries(partC.options.optC)) { + expect(pattern.config.options.optC[key]).to.equal(value) + } + }) + + it('Pattern.init() should resolve parts', () => { + expect(pattern.config.parts.length).to.equal(3) + }) + + it('Pattern.init() should resolve plugins', () => { + expect(pattern.config.plugins.length).to.equal(1) + }) + + it('Pattern.init() should set config data in the store', () => { + expect(pattern.store.get('data.name')).to.equal('test') + expect(pattern.store.get('data.version')).to.equal('1.2.3') + }) + + it('Pattern.init() should resolve dependencies', () => { + expect(typeof pattern.config.resolvedDependencies).to.equal('object') + expect(Array.isArray(pattern.config.resolvedDependencies['test.partA'])).to.equal(true) + expect(pattern.config.resolvedDependencies['test.partA'].length).to.equal(0) + expect(Array.isArray(pattern.config.resolvedDependencies['test.partB'])).to.equal(true) + expect(pattern.config.resolvedDependencies['test.partB'].length).to.equal(1) + expect(pattern.config.resolvedDependencies['test.partB'][0]).to.equal('test.partA') + expect(Array.isArray(pattern.config.resolvedDependencies['test.partC'])).to.equal(true) + expect(pattern.config.resolvedDependencies['test.partC'].length).to.equal(2) + expect(pattern.config.resolvedDependencies['test.partC'].indexOf('test.partA') !== -1).to.equal(true) + expect(pattern.config.resolvedDependencies['test.partC'].indexOf('test.partB') !== -1).to.equal(true) + }) + + it('Pattern.init() should resolve the draft order', () => { + expect(Array.isArray(pattern.config.draftOrder)).to.equal(true) + expect(pattern.config.draftOrder[0]).to.equal('test.partA') + expect(pattern.config.draftOrder[1]).to.equal('test.partB') + expect(pattern.config.draftOrder[2]).to.equal('test.partC') + }) + + }) + + + describe('Pattern.settings', () => { + + const part = { + name: 'test.part', + options: { + pct: { pct: 30, min: 10, max: 50 }, + altpct: { pct: 30, min: 10, max: 50 }, + mm: { mm: 12, min: 4, max: 23 }, + deg: { deg: 2, min: 1, max: 3 }, + list: { + dflt: 'd', + choices: ['a', 'b' ,'c', 'd'] + }, + count: { count: 4, min: 1, max: 13 }, + bool: { bool: false }, + }, + draft: () => { } + } + const Pattern = new Design({ + data: { + name: 'test', + version: '1.2.3', + }, + parts: [ part ] + }) + const pattern = new Pattern() + pattern.init() + + it('Pattern settings should contain percentage options', () => { + expect(pattern.settings.options.pct).to.equal(0.3) + }) + + it('Pattern settings should contain millimeter options', () => { + expect(pattern.settings.options.mm).to.equal(12) + }) + + it('Pattern settings should contain degree options', () => { + expect(pattern.settings.options.deg).to.equal(2) + }) + + it('Pattern settings should contain list options', () => { + expect(pattern.settings.options.list).to.equal('d') + }) + + it('Pattern settings should contain count options', () => { + expect(pattern.settings.options.count).to.equal(4) + }) + + it('Pattern settings should contain bool options', () => { + expect(pattern.settings.options.bool).to.equal(false) + }) + }) +}) + diff --git a/packages/core/tests/pattern.test.mjs b/packages/core/tests/pattern.test.mjs index 429e8f9fdf9..1697e94b9d7 100644 --- a/packages/core/tests/pattern.test.mjs +++ b/packages/core/tests/pattern.test.mjs @@ -1,167 +1,166 @@ -import chai from "chai" -import { round, Pattern, Design, pctBasedOn } from "./dist/index.mjs" +import chai from 'chai' +import { round, Pattern, Design, pctBasedOn } from '../src/index.mjs' const expect = chai.expect describe('Pattern', () => { - it("Pattern constructor should initialize object", () => { + it('Pattern constructor should initialize object', () => { let pattern = new Pattern({ - foo: "bar", + foo: 'bar', options: { constant: 2, - percentage: { pct: 30, min: 0, max: 100 } - } - }); - expect(pattern.width).to.equal(0); - expect(pattern.height).to.equal(0); - expect(pattern.settings.complete).to.equal(true); - expect(pattern.parts).to.eql({}); - expect(pattern.settings.units).to.equal("metric"); - expect(pattern.config.foo).to.equal("bar"); - expect(pattern.settings.options.constant).to.equal(2); - expect(pattern.settings.options.percentage).to.equal(0.3); - }); + percentage: { pct: 30, min: 0, max: 100 }, + }, + }) + expect(pattern.width).to.equal(0) + expect(pattern.height).to.equal(0) + expect(pattern.settings.complete).to.equal(true) + expect(pattern.parts).to.eql({}) + expect(pattern.settings.units).to.equal('metric') + expect(pattern.config.foo).to.equal('bar') + expect(pattern.settings.options.constant).to.equal(2) + expect(pattern.settings.options.percentage).to.equal(0.3) + }) - - it("Should load percentage options", () => { + it('Should load percentage options', () => { let pattern = new Pattern({ options: { - test: { pct: 30 } - } - }); - expect(pattern.settings.options.test).to.equal(0.3); - }); + test: { pct: 30 }, + }, + }) + expect(pattern.settings.options.test).to.equal(0.3) + }) - it("Should load millimeter options", () => { + it('Should load millimeter options', () => { let pattern = new Pattern({ options: { - test: { mm: 30 } - } - }); - expect(pattern.settings.options.test).to.equal(30); - }); + test: { mm: 30 }, + }, + }) + expect(pattern.settings.options.test).to.equal(30) + }) - it("Should load degree options", () => { + it('Should load degree options', () => { let pattern = new Pattern({ options: { - test: { deg: 15 } - } - }); - expect(pattern.settings.options.test).to.equal(15); - }); + test: { deg: 15 }, + }, + }) + expect(pattern.settings.options.test).to.equal(15) + }) - it("Should load an array option", () => { + it('Should load an array option', () => { let pattern = new Pattern({ options: { - test: { dflt: "foo" } - } - }); - expect(pattern.settings.options.test).to.equal("foo"); - }); + test: { dflt: 'foo' }, + }, + }) + expect(pattern.settings.options.test).to.equal('foo') + }) - it("Should load a count option", () => { + it('Should load a count option', () => { let pattern = new Pattern({ options: { - test: { count: 3 } - } - }); - expect(pattern.settings.options.test).to.equal(3); - }); + test: { count: 3 }, + }, + }) + expect(pattern.settings.options.test).to.equal(3) + }) - it("Should load a boolean option", () => { + it('Should load a boolean option', () => { let pattern = new Pattern({ options: { test1: { bool: false }, - test2: { bool: true } - } - }); - expect(pattern.settings.options.test1).to.be.false; - expect(pattern.settings.options.test2).to.be.true; - }); + test2: { bool: true }, + }, + }) + expect(pattern.settings.options.test1).to.be.false + expect(pattern.settings.options.test2).to.be.true + }) - it("Should throw an error for an unknown option", () => { + it('Should throw an error for an unknown option', () => { expect( () => new Pattern({ options: { - test: { foo: "bar" } - } + test: { foo: 'bar' }, + }, }) - ).to.throw(); - }); + ).to.throw() + }) - it("Should merge settings with default settings", () => { - let pattern = new Pattern(); + it('Should merge settings with default settings', () => { + let pattern = new Pattern() let settings = { - foo: "bar", + foo: 'bar', deep: { - free: "ze" - } - }; - pattern.apply(settings); - expect(pattern.settings.foo).to.equal("bar"); - expect(pattern.settings.locale).to.equal("en"); - expect(pattern.settings.margin).to.equal(2); - expect(pattern.settings.idPrefix).to.equal("fs-"); - expect(pattern.settings.deep.free).to.equal("ze"); - }); + free: 'ze', + }, + } + pattern.apply(settings) + expect(pattern.settings.foo).to.equal('bar') + expect(pattern.settings.locale).to.equal('en') + expect(pattern.settings.margin).to.equal(2) + expect(pattern.settings.idPrefix).to.equal('fs-') + expect(pattern.settings.deep.free).to.equal('ze') + }) - it("Should draft according to settings", () => { + it('Should draft according to settings', () => { let count = 0 const back = { name: 'back', hide: true, - draft: function(part) { - count ++ - return part; - } + draft: function (part) { + count++ + return part + }, } const front = { name: 'front', from: back, - draft: function(part) { - count ++ - return part; - } + draft: function (part) { + count++ + return part + }, } const Test = new Design({ - name: "test", - parts: [ back, front ], - }); + name: 'test', + parts: [back, front], + }) - const pattern = new Test(); - pattern.draft(); - expect(count).to.equal(2); - }); + const pattern = new Test() + pattern.draft() + expect(count).to.equal(2) + }) - it("Should sample an option", () => { + it('Should sample an option', () => { let pattern = new Pattern({ options: { len: { pct: 30, min: 10 }, - bonus: 10 - } - }); - pattern.draft = function() { - pattern.parts.a = new pattern.Part(); - pattern.parts.b = new pattern.Part(); - let a = pattern.parts.a; - a.points.from = new a.Point(0, 0); + bonus: 10, + }, + }) + pattern.draft = function () { + pattern.parts.a = new pattern.Part() + pattern.parts.b = new pattern.Part() + let a = pattern.parts.a + a.points.from = new a.Point(0, 0) a.points.to = new a.Point( 100 * a.context.settings.options.len, a.context.settings.options.bonus - ); - a.paths.test = new a.Path().move(a.points.from).line(a.points.to); - pattern.parts.b.inject(a); - }; + ) + a.paths.test = new a.Path().move(a.points.from).line(a.points.to) + pattern.parts.b.inject(a) + } pattern.settings.sample = { - type: "option", - option: "len" - }; - pattern.sample(); - expect(pattern.parts.a.paths.test_1.render).to.equal(true); - expect(pattern.parts.b.paths.test_10.ops[1].to.y).to.equal(10); - }); -/* + type: 'option', + option: 'len', + } + pattern.sample() + expect(pattern.parts.a.paths.test_1.render).to.equal(true) + expect(pattern.parts.b.paths.test_10.ops[1].to.y).to.equal(10) + }) + /* it("Should sample a list option", () => { const front = { name: 'front', @@ -335,276 +334,280 @@ describe('Pattern', () => { }); */ - it("Should check whether a part is needed", () => { + it('Should check whether a part is needed', () => { let config = { - name: "test", - dependencies: { back: "front", side: "back" }, - inject: { back: "front" }, - hide: ["back"] - }; + name: 'test', + dependencies: { back: 'front', side: 'back' }, + inject: { back: 'front' }, + hide: ['back'], + } const Test = new Design(config) - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test().init(); - pattern.settings.only = "back"; + let pattern = new Test().init() + pattern.settings.only = 'back' //expect(pattern.needs("back")).to.equal(true); - expect(pattern.needs("front")).to.equal(true); + expect(pattern.needs('front')).to.equal(true) //expect(pattern.needs("side")).to.equal(false); //pattern.settings.only = ["back", "side"]; //expect(pattern.needs("back")).to.equal(true); //expect(pattern.needs("front")).to.equal(true); //expect(pattern.needs("side")).to.equal(true); - }); + }) - it("Should check whether a part is wanted", () => { + it('Should check whether a part is wanted', () => { let config = { - name: "test", - dependencies: { back: "front", side: "back" }, - inject: { back: "front" }, - hide: ["back"] - }; - const Test = function(settings = false) { - Pattern.call(this, config); - return this; - }; - Test.prototype = Object.create(Pattern.prototype); - Test.prototype.constructor = Test; - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + name: 'test', + dependencies: { back: 'front', side: 'back' }, + inject: { back: 'front' }, + hide: ['back'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test(); - pattern.settings.only = "back"; - expect(pattern.wants("back")).to.equal(true); - expect(pattern.wants("front")).to.equal(false); - expect(pattern.wants("side")).to.equal(false); - pattern.settings.only = ["back", "side"]; - expect(pattern.wants("back")).to.equal(true); - expect(pattern.wants("front")).to.equal(false); - expect(pattern.wants("side")).to.equal(true); - }); + let pattern = new Test() + pattern.settings.only = 'back' + expect(pattern.wants('back')).to.equal(true) + expect(pattern.wants('front')).to.equal(false) + expect(pattern.wants('side')).to.equal(false) + pattern.settings.only = ['back', 'side'] + expect(pattern.wants('back')).to.equal(true) + expect(pattern.wants('front')).to.equal(false) + expect(pattern.wants('side')).to.equal(true) + }) - it("Should correctly resolve dependencies - string version", () => { + it('Should correctly resolve dependencies - string version', () => { let config = { - name: "test", - dependencies: { front: "back", side: "back", hood: "front", stripe: "hood" }, - }; + name: 'test', + dependencies: { front: 'back', side: 'back', hood: 'front', stripe: 'hood' }, + } const Test = new Design(config) - Test.prototype = Object.create(Pattern.prototype); - Test.prototype.constructor = Test; - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test().init(); - expect(pattern.config.resolvedDependencies.front.length).to.equal(1); - expect(pattern.config.resolvedDependencies.front[0]).to.equal('back'); - expect(pattern.config.resolvedDependencies.side.length).to.equal(1); - expect(pattern.config.resolvedDependencies.side[0]).to.equal('back'); - expect(pattern.config.resolvedDependencies.hood.length).to.equal(2); - expect(pattern.config.resolvedDependencies.hood[0]).to.equal('front'); - expect(pattern.config.resolvedDependencies.hood[1]).to.equal('back'); - expect(pattern.config.resolvedDependencies.stripe.length).to.equal(3); - expect(pattern.config.resolvedDependencies.stripe[0]).to.equal('hood'); - expect(pattern.config.resolvedDependencies.stripe[1]).to.equal('front'); - expect(pattern.config.resolvedDependencies.stripe[2]).to.equal('back'); - expect(pattern.config.resolvedDependencies.back.length).to.equal(0); - expect(pattern.config.draftOrder[0]).to.equal('back'); - expect(pattern.config.draftOrder[1]).to.equal('front'); - expect(pattern.config.draftOrder[2]).to.equal('side'); - expect(pattern.config.draftOrder[3]).to.equal('hood'); - }); + let pattern = new Test().init() + expect(pattern.config.resolvedDependencies.front.length).to.equal(1) + expect(pattern.config.resolvedDependencies.front[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.side.length).to.equal(1) + expect(pattern.config.resolvedDependencies.side[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.hood.length).to.equal(2) + expect(pattern.config.resolvedDependencies.hood[0]).to.equal('front') + expect(pattern.config.resolvedDependencies.hood[1]).to.equal('back') + expect(pattern.config.resolvedDependencies.stripe.length).to.equal(3) + expect(pattern.config.resolvedDependencies.stripe[0]).to.equal('hood') + expect(pattern.config.resolvedDependencies.stripe[1]).to.equal('front') + expect(pattern.config.resolvedDependencies.stripe[2]).to.equal('back') + expect(pattern.config.resolvedDependencies.back.length).to.equal(0) + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('side') + expect(pattern.config.draftOrder[3]).to.equal('hood') + }) - it("Should correctly resolve dependencies - array version", () => { + it('Should correctly resolve dependencies - array version', () => { let config = { - name: "test", - dependencies: { front: ["back"], side: ["back"], hood: ["front"], stripe: ["hood"]}, - }; - const Test = function(settings = false) { - Pattern.call(this, config); - return this; - }; - Test.prototype = Object.create(Pattern.prototype); - Test.prototype.constructor = Test; - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + name: 'test', + dependencies: { front: ['back'], side: ['back'], hood: ['front'], stripe: ['hood'] }, + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test().init(); - expect(pattern.config.resolvedDependencies.front.length).to.equal(1); - expect(pattern.config.resolvedDependencies.front[0]).to.equal('back'); - expect(pattern.config.resolvedDependencies.side.length).to.equal(1); - expect(pattern.config.resolvedDependencies.side[0]).to.equal('back'); - expect(pattern.config.resolvedDependencies.hood.length).to.equal(2); - expect(pattern.config.resolvedDependencies.hood[0]).to.equal('front'); - expect(pattern.config.resolvedDependencies.hood[1]).to.equal('back'); - expect(pattern.config.resolvedDependencies.stripe.length).to.equal(3); - expect(pattern.config.resolvedDependencies.stripe[0]).to.equal('hood'); - expect(pattern.config.resolvedDependencies.stripe[1]).to.equal('front'); - expect(pattern.config.resolvedDependencies.stripe[2]).to.equal('back'); - expect(pattern.config.resolvedDependencies.back.length).to.equal(0); - expect(pattern.config.draftOrder[0]).to.equal('back'); - expect(pattern.config.draftOrder[1]).to.equal('front'); - expect(pattern.config.draftOrder[2]).to.equal('side'); - expect(pattern.config.draftOrder[3]).to.equal('hood'); - }); + let pattern = new Test().init() + expect(pattern.config.resolvedDependencies.front.length).to.equal(1) + expect(pattern.config.resolvedDependencies.front[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.side.length).to.equal(1) + expect(pattern.config.resolvedDependencies.side[0]).to.equal('back') + expect(pattern.config.resolvedDependencies.hood.length).to.equal(2) + expect(pattern.config.resolvedDependencies.hood[0]).to.equal('front') + expect(pattern.config.resolvedDependencies.hood[1]).to.equal('back') + expect(pattern.config.resolvedDependencies.stripe.length).to.equal(3) + expect(pattern.config.resolvedDependencies.stripe[0]).to.equal('hood') + expect(pattern.config.resolvedDependencies.stripe[1]).to.equal('front') + expect(pattern.config.resolvedDependencies.stripe[2]).to.equal('back') + expect(pattern.config.resolvedDependencies.back.length).to.equal(0) + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('side') + expect(pattern.config.draftOrder[3]).to.equal('hood') + }) - it("Should correctly resolve dependencies - issue #971 - working version", () => { + it('Should correctly resolve dependencies - issue #971 - working version', () => { let config = { - name: "test", - dependencies: {front:['back'],crotch:['front','back']}, - parts: ['back','front','crotch'], - }; - const Test = function(settings = false) { - Pattern.call(this, config); - return this; - }; - Test.prototype = Object.create(Pattern.prototype); - Test.prototype.constructor = Test; - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + name: 'test', + dependencies: { front: ['back'], crotch: ['front', 'back'] }, + parts: ['back', 'front', 'crotch'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test().init(); - expect(pattern.config.draftOrder[0]).to.equal('back'); - expect(pattern.config.draftOrder[1]).to.equal('front'); - expect(pattern.config.draftOrder[2]).to.equal('crotch'); - }); + let pattern = new Test().init() + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('crotch') + }) - it("Should correctly resolve dependencies - issue #971 - broken version", () => { + it('Should correctly resolve dependencies - issue #971 - broken version', () => { let config = { - name: "test", - dependencies: {front:'back',crotch:['front','back']}, - parts: ['back','front','crotch'], - }; - const Test = function(settings = false) { - Pattern.call(this, config); - return this; - }; - Test.prototype = Object.create(Pattern.prototype); - Test.prototype.constructor = Test; - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + name: 'test', + dependencies: { front: 'back', crotch: ['front', 'back'] }, + parts: ['back', 'front', 'crotch'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test().init(); - expect(pattern.config.draftOrder[0]).to.equal('back'); - expect(pattern.config.draftOrder[1]).to.equal('front'); - expect(pattern.config.draftOrder[2]).to.equal('crotch'); - }); + let pattern = new Test().init() + expect(pattern.config.draftOrder[0]).to.equal('back') + expect(pattern.config.draftOrder[1]).to.equal('front') + expect(pattern.config.draftOrder[2]).to.equal('crotch') + }) - it("Should correctly resolve dependencies - Handle uncovered code path", () => { + it('Should correctly resolve dependencies - Handle uncovered code path', () => { let config = { - name: "test", + name: 'test', dependencies: { front: 'side', - crotch:['front','back'], + crotch: ['front', 'back'], back: 1, }, inject: { front: 'back', }, - parts: ['back','front','crotch'], - }; - const Test = function(settings = false) { - Pattern.call(this, config); - return this; - }; - Test.prototype = Object.create(Pattern.prototype); - Test.prototype.constructor = Test; - Test.prototype.draftBack = function(part) { - return part; - }; - Test.prototype.draftFront = function(part) { - return part; - }; + parts: ['back', 'front', 'crotch'], + } + const Test = function (settings = false) { + Pattern.call(this, config) + return this + } + Test.prototype = Object.create(Pattern.prototype) + Test.prototype.constructor = Test + Test.prototype.draftBack = function (part) { + return part + } + Test.prototype.draftFront = function (part) { + return part + } - let pattern = new Test().init(); + let pattern = new Test().init() 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'); - }); + 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 Pattern(); - let part = new pattern.Part(); - expect(part.context.settings).to.equal(pattern.settings); - }); + it('Should check whether created parts get the pattern context', () => { + let pattern = new Pattern() + let part = new pattern.Part() + expect(part.context.settings).to.equal(pattern.settings) + }) - it("Should correctly merge settings", () => { - let pattern = new Pattern(); + it('Should correctly merge settings', () => { + let pattern = new Pattern() let settings = { complete: false, only: [1, 2, 3], - margin: 5 - }; - pattern.apply(settings); - expect(pattern.settings.complete).to.equal(false); - expect(pattern.settings.only[1]).to.equal(2); - expect(pattern.settings.margin).to.equal(5); - expect(pattern.settings.only.length).to.equal(3); - }); + margin: 5, + } + pattern.apply(settings) + expect(pattern.settings.complete).to.equal(false) + expect(pattern.settings.only[1]).to.equal(2) + expect(pattern.settings.margin).to.equal(5) + expect(pattern.settings.only.length).to.equal(3) + }) - it("Should correctly merge settings for existing array", () => { - let pattern = new Pattern(); - pattern.settings.only = [1]; + it('Should correctly merge settings for existing array', () => { + let pattern = new Pattern() + pattern.settings.only = [1] let settings = { complete: false, only: [2, 3, 4], - margin: 5 - }; - pattern.apply(settings); - expect(pattern.settings.complete).to.equal(false); - expect(pattern.settings.only.length).to.equal(4); - expect(pattern.settings.margin).to.equal(5); - }); + margin: 5, + } + pattern.apply(settings) + expect(pattern.settings.complete).to.equal(false) + expect(pattern.settings.only.length).to.equal(4) + expect(pattern.settings.margin).to.equal(5) + }) - it("Should return all render props", () => { + it('Should return all render props', () => { const front = { name: 'front', - draft: function(part) { return part } + draft: function (part) { + return part + }, } const Test = new Design({ - name: "test", + name: 'test', parts: [front], - }); + }) const pattern = new Test() - pattern.draft(); + 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); - }); + 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", () => { + it('Should not pack a pattern with errors', () => { const pattern = new 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') - }); + expect(pattern.events.warning[0]).to.equal( + 'One or more errors occured. Not packing pattern parts' + ) + }) /* it("Should generate an auto layout if there is no set layout", () => { @@ -760,65 +763,66 @@ describe('Pattern', () => { // 2022 style part inheritance // I am aware this does too much for one unit test, but this is to simplify TDD // we can split it up later - it("Design constructor should resolve nested injections", () => { + it('Design constructor should resolve nested injections', () => { const partA = { - name: "partA", + name: 'partA', options: { optionA: { bool: true } }, - measurements: [ 'measieA' ], - optionalMeasurements: [ 'optmeasieA' ], - draft: part => { + measurements: ['measieA'], + optionalMeasurements: ['optmeasieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.a1 = new Point(1,1) - points.a2 = new Point(11,11) + points.a1 = new Point(1, 1) + points.a2 = new Point(11, 11) paths.a = new Path().move(points.a1).line(points.a2) return part - } + }, } const partB = { - name: "partB", + name: 'partB', from: partA, options: { optionB: { pct: 12, min: 2, max: 20 } }, - measurements: [ 'measieB' ], - optionalMeasurements: [ 'optmeasieB', 'measieA' ], - draft: part => { + measurements: ['measieB'], + optionalMeasurements: ['optmeasieB', 'measieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.b1 = new Point(2,2) - points.b2 = new Point(22,22) + points.b1 = new Point(2, 2) + points.b2 = new Point(22, 22) paths.b = new Path().move(points.b1).line(points.b2) return part - } + }, } const partC = { - name: "partC", + name: 'partC', from: partB, options: { optionC: { deg: 5, min: 0, max: 15 } }, - measurements: [ 'measieC' ], - optionalMeasurements: [ 'optmeasieC', 'measieA' ], - draft: part => { + measurements: ['measieC'], + optionalMeasurements: ['optmeasieC', 'measieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.c1 = new Point(3,3) - points.c2 = new Point(33,33) + points.c1 = new Point(3, 3) + points.c2 = new Point(33, 33) paths.c = new Path().move(points.c1).line(points.c2) return part - } + }, } - const partR = { // R for runtime, which is when this wil be attached - name: "partR", + const partR = { + // R for runtime, which is when this wil be attached + name: 'partR', from: partA, after: partC, options: { optionR: { dflt: 'red', list: ['red', 'green', 'blue'] } }, - measurements: [ 'measieR' ], - optionalMeasurements: [ 'optmeasieR', 'measieA' ], - draft: part => { + measurements: ['measieR'], + optionalMeasurements: ['optmeasieR', 'measieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.r1 = new Point(4,4) - points.r2 = new Point(44,44) + points.r1 = new Point(4, 4) + points.r2 = new Point(44, 44) paths.r = new Path().move(points.r1).line(points.r2) return part - } + }, } - const design = new Design({ parts: [ partC ] }); + const design = new Design({ parts: [partC] }) const pattern = new design().addPart(partR).draft() // Measurements expect(pattern.config.measurements.length).to.equal(4) @@ -914,63 +918,63 @@ describe('Pattern', () => { expect(pattern.parts.partR.paths.r.ops[1].to.y).to.equal(44) }) - it("Design constructor should resolve nested dependencies (2022)", () => { + it('Design constructor should resolve nested dependencies (2022)', () => { const partA = { - name: "partA", + name: 'partA', options: { optionA: { bool: true } }, - measurements: [ 'measieA' ], - optionalMeasurements: [ 'optmeasieA' ], - draft: part => { + measurements: ['measieA'], + optionalMeasurements: ['optmeasieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.a1 = new Point(1,1) - points.a2 = new Point(11,11) + points.a1 = new Point(1, 1) + points.a2 = new Point(11, 11) paths.a = new Path().move(points.a1).line(points.a2) return part - } + }, } const partB = { - name: "partB", + name: 'partB', from: partA, options: { optionB: { pct: 12, min: 2, max: 20 } }, - measurements: [ 'measieB' ], - optionalMeasurements: [ 'optmeasieB', 'measieA' ], - draft: part => { + measurements: ['measieB'], + optionalMeasurements: ['optmeasieB', 'measieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.b1 = new Point(2,2) - points.b2 = new Point(22,22) + points.b1 = new Point(2, 2) + points.b2 = new Point(22, 22) paths.b = new Path().move(points.b1).line(points.b2) return part - } + }, } const partC = { - name: "partC", + name: 'partC', from: partB, options: { optionC: { deg: 5, min: 0, max: 15 } }, - measurements: [ 'measieC' ], - optionalMeasurements: [ 'optmeasieC', 'measieA' ], - draft: part => { + measurements: ['measieC'], + optionalMeasurements: ['optmeasieC', 'measieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.c1 = new Point(3,3) - points.c2 = new Point(33,33) + points.c1 = new Point(3, 3) + points.c2 = new Point(33, 33) paths.c = new Path().move(points.c1).line(points.c2) return part - } + }, } const partD = { - name: "partD", + name: 'partD', after: partC, options: { optionD: { dflt: 'red', list: ['red', 'green', 'blue'] } }, - measurements: [ 'measieD' ], - optionalMeasurements: [ 'optmeasieD', 'measieA' ], - draft: part => { + measurements: ['measieD'], + optionalMeasurements: ['optmeasieD', 'measieA'], + draft: (part) => { const { points, Point, paths, Path } = part.shorthand() - points.d1 = new Point(4,4) - points.d2 = new Point(44,44) + points.d1 = new Point(4, 4) + points.d2 = new Point(44, 44) paths.d = new Path().move(points.d1).line(points.d2) return part - } + }, } - const design = new Design({ parts: [ partD ] }); + const design = new Design({ parts: [partD] }) const pattern = new design().draft() // Measurements expect(pattern.config.measurements.length).to.equal(4) @@ -1060,28 +1064,28 @@ describe('Pattern', () => { expect(pattern.parts.partD.paths.d.ops[1].to.y).to.equal(44) }) - it("Pattern should load single plugin", () => { + it('Pattern should load single plugin', () => { const plugin = { - name: "example", + name: 'example', version: 1, hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example", version); - } - } - }; + preRender: function (svg, attributes) { + svg.attributes.add('freesewing:plugin-example', version) + }, + }, + } const part = { name: 'test.part', plugins: plugin, - draft: (part) => part + draft: (part) => part, } - const design = new Design({ parts: [ part ] }) - const pattern = new design(); + const design = new Design({ parts: [part] }) + const pattern = new design() pattern.init() - expect(pattern.hooks.preRender.length).to.equal(1); - }); -/* + expect(pattern.hooks.preRender.length).to.equal(1) + }) + /* it("Design constructor should load array of plugins", () => { let plugin1 = { name: "example1", @@ -1158,4 +1162,3 @@ describe('Pattern', () => { expect(pattern.hooks.preRender.length).to.equal(1); */ }) - diff --git a/packages/core/tests/point.test.mjs b/packages/core/tests/point.test.mjs index 50eae0a1f20..d50589a3e3b 100644 --- a/packages/core/tests/point.test.mjs +++ b/packages/core/tests/point.test.mjs @@ -1,500 +1,484 @@ -import chai from "chai" -import { round, Point } from "./dist/index.mjs" +import chai from 'chai' +import { round, Point } from '../src/index.mjs' const expect = chai.expect describe('Point', () => { - it("Should return point object", () => { - let result = new Point(2, 4); - expect(result).to.be.a("object"); - expect(result.x).to.equal(2); - expect(result.y).to.equal(4); - }); + it('Should return point object', () => { + let result = new Point(2, 4) + expect(result).to.be.a('object') + expect(result.x).to.equal(2) + expect(result.y).to.equal(4) + }) - it("Should not limit point precision", () => { - let result = new Point(2.12345, 4.98765); - expect(result.x).to.equal(2.12345); - expect(result.y).to.equal(4.98765); - }); + it('Should not limit point precision', () => { + let result = new Point(2.12345, 4.98765) + expect(result.x).to.equal(2.12345) + expect(result.y).to.equal(4.98765) + }) - it("Should return distance", () => { - expect(round(new Point(2, 4).dist(new Point(-123, -32423)))).to.equal(32427.24); - }); + it('Should return distance', () => { + expect(round(new Point(2, 4).dist(new Point(-123, -32423)))).to.equal(32427.24) + }) - it("Should return slope", () => { - let from = new Point(0, 0); - expect(from.slope(new Point(0, -10))).to.equal(-Infinity); - expect(from.slope(new Point(10, 0))).to.equal(0); - expect(from.slope(new Point(0, 10))).to.equal(Infinity); - expect(from.slope(new Point(-10, 0))).to.equal(-0); - expect(from.slope(new Point(10, 10))).to.equal(1); - expect(from.slope(new Point(-10, 5))).to.equal(-0.5); - }); + it('Should return slope', () => { + let from = new Point(0, 0) + expect(from.slope(new Point(0, -10))).to.equal(-Infinity) + expect(from.slope(new Point(10, 0))).to.equal(0) + expect(from.slope(new Point(0, 10))).to.equal(Infinity) + expect(from.slope(new Point(-10, 0))).to.equal(-0) + expect(from.slope(new Point(10, 10))).to.equal(1) + expect(from.slope(new Point(-10, 5))).to.equal(-0.5) + }) - it("Should return angle", () => { - let from = new Point(0, 0); - expect(from.angle(new Point(10, 0))).to.equal(0); - expect(from.angle(new Point(-20, 0))).to.equal(180); - expect(from.angle(new Point(0, -10))).to.equal(90); - expect(from.angle(new Point(0, 10))).to.equal(270); - expect(from.angle(new Point(10, -10))).to.equal(45); - expect(from.angle(new Point(10, 10))).to.equal(315); - }); + it('Should return angle', () => { + let from = new Point(0, 0) + expect(from.angle(new Point(10, 0))).to.equal(0) + expect(from.angle(new Point(-20, 0))).to.equal(180) + expect(from.angle(new Point(0, -10))).to.equal(90) + expect(from.angle(new Point(0, 10))).to.equal(270) + expect(from.angle(new Point(10, -10))).to.equal(45) + expect(from.angle(new Point(10, 10))).to.equal(315) + }) - it("Should copy a point", () => { - let result = new Point(2, 4).copy(); - expect(result.x).to.equal(2); - expect(result.y).to.equal(4); - }); + it('Should copy a point', () => { + let result = new Point(2, 4).copy() + expect(result.x).to.equal(2) + expect(result.y).to.equal(4) + }) - it("Should check points for equality", () => { - let a = new Point(-123, 456); - let b = new Point(-123, 456); - expect(a).to.deep.equal(b); - }); + it('Should check points for equality', () => { + let a = new Point(-123, 456) + let b = new Point(-123, 456) + expect(a).to.deep.equal(b) + }) - it("Should flip point around unset X value", () => { - let result = new Point(2, 4).flipX(); - expect(result.x).to.equal(-2); - expect(result.y).to.equal(4); - }); + it('Should flip point around unset X value', () => { + let result = new Point(2, 4).flipX() + expect(result.x).to.equal(-2) + expect(result.y).to.equal(4) + }) - it("Should flip point around X value that is zero", () => { - let flip = new Point(0, 0); - let result = new Point(2, 4).flipX(flip); - expect(result.x).to.equal(-2); - expect(result.y).to.equal(4); - }); + it('Should flip point around X value that is zero', () => { + let flip = new Point(0, 0) + let result = new Point(2, 4).flipX(flip) + expect(result.x).to.equal(-2) + expect(result.y).to.equal(4) + }) - it("Should flip point around X value", () => { - let result = new Point(2, 4).flipX(new Point(-20, 19)); - expect(result.x).to.equal(-42); - expect(result.y).to.equal(4); - }); + it('Should flip point around X value', () => { + let result = new Point(2, 4).flipX(new Point(-20, 19)) + expect(result.x).to.equal(-42) + expect(result.y).to.equal(4) + }) - it("Should flip point around unset Y value", () => { - let result = new Point(2, 4).flipY(); - expect(result.x).to.equal(2); - expect(result.y).to.equal(-4); - }); + it('Should flip point around unset Y value', () => { + let result = new Point(2, 4).flipY() + expect(result.x).to.equal(2) + expect(result.y).to.equal(-4) + }) - it("Should flip point around Y value that is zero", () => { - let flip = new Point(0, 0); - let result = new Point(2, 4).flipY(flip); - expect(result.x).to.equal(2); - expect(result.y).to.equal(-4); - }); + it('Should flip point around Y value that is zero', () => { + let flip = new Point(0, 0) + let result = new Point(2, 4).flipY(flip) + expect(result.x).to.equal(2) + expect(result.y).to.equal(-4) + }) - it("Should flip point around Y value", () => { - let result = new Point(2, 4).flipY(new Point(12, -14)); - expect(result.x).to.equal(2); - expect(result.y).to.equal(-32); - }); + it('Should flip point around Y value', () => { + let result = new Point(2, 4).flipY(new Point(12, -14)) + expect(result.x).to.equal(2) + expect(result.y).to.equal(-32) + }) - it("Should shift a point", () => { - let origin = new Point(0, 0); - let n = origin.shift(90, 10); - let e = origin.shift(0, 10); - let s = origin.shift(270, 10); - let w = origin.shift(180, 10); - expect(round(n.x)).to.equal(0); - expect(round(n.y)).to.equal(-10); - expect(round(e.x)).to.equal(10); - expect(round(e.y)).to.equal(0); - expect(round(s.x)).to.equal(0); - expect(round(s.y)).to.equal(10); - expect(round(w.x)).to.equal(-10); - expect(round(w.y)).to.equal(0); - let rand = origin.shift(-123, 456); - expect(round(rand.x)).to.equal(-248.36); - expect(round(rand.y)).to.equal(382.43); - }); + it('Should shift a point', () => { + let origin = new Point(0, 0) + let n = origin.shift(90, 10) + let e = origin.shift(0, 10) + let s = origin.shift(270, 10) + let w = origin.shift(180, 10) + expect(round(n.x)).to.equal(0) + expect(round(n.y)).to.equal(-10) + expect(round(e.x)).to.equal(10) + expect(round(e.y)).to.equal(0) + expect(round(s.x)).to.equal(0) + expect(round(s.y)).to.equal(10) + expect(round(w.x)).to.equal(-10) + expect(round(w.y)).to.equal(0) + let rand = origin.shift(-123, 456) + expect(round(rand.x)).to.equal(-248.36) + expect(round(rand.y)).to.equal(382.43) + }) - it("Should shift a point towards another", () => { - let origin = new Point(0, 0); - let n = new Point(0, -10); - let e = new Point(10, 0); - let s = new Point(0, 10); - let w = new Point(-10, 0); - let sn = origin.shiftTowards(n, 123); - let se = origin.shiftTowards(e, 123); - let ss = origin.shiftTowards(s, 123); - let sw = origin.shiftTowards(w, 123); - expect(round(sn.x)).to.equal(0); - expect(round(sn.y)).to.equal(-123); - expect(round(se.x)).to.equal(123); - expect(round(se.y)).to.equal(0); - expect(round(ss.x)).to.equal(0); - expect(round(ss.y)).to.equal(123); - expect(round(sw.x)).to.equal(-123); - expect(round(sw.y)).to.equal(0); - expect(round(sw.shiftTowards(sn, 100).x)).to.equal(-52.29); - expect(round(ss.shiftTowards(se, 200).y)).to.equal(-18.42); - }); + it('Should shift a point towards another', () => { + let origin = new Point(0, 0) + let n = new Point(0, -10) + let e = new Point(10, 0) + let s = new Point(0, 10) + let w = new Point(-10, 0) + let sn = origin.shiftTowards(n, 123) + let se = origin.shiftTowards(e, 123) + let ss = origin.shiftTowards(s, 123) + let sw = origin.shiftTowards(w, 123) + expect(round(sn.x)).to.equal(0) + expect(round(sn.y)).to.equal(-123) + expect(round(se.x)).to.equal(123) + expect(round(se.y)).to.equal(0) + expect(round(ss.x)).to.equal(0) + expect(round(ss.y)).to.equal(123) + expect(round(sw.x)).to.equal(-123) + expect(round(sw.y)).to.equal(0) + expect(round(sw.shiftTowards(sn, 100).x)).to.equal(-52.29) + expect(round(ss.shiftTowards(se, 200).y)).to.equal(-18.42) + }) - it("Should shift a point a fraction towards another", () => { - let origin = new Point(0, 0); - let n = new Point(0, -10); - let e = new Point(10, 0); - let s = new Point(0, 10); - let w = new Point(-10, 0); - let sn = origin.shiftFractionTowards(n, 1.5); - let se = origin.shiftFractionTowards(e, 1.5); - let ss = origin.shiftFractionTowards(s, 0.5); - let sw = origin.shiftFractionTowards(w, 2.5); - expect(round(sn.x)).to.equal(0); - expect(round(sn.y)).to.equal(-15); - expect(round(se.x)).to.equal(15); - expect(round(se.y)).to.equal(0); - expect(round(ss.x)).to.equal(0); - expect(round(ss.y)).to.equal(5); - expect(round(sw.x)).to.equal(-25); - expect(round(sw.y)).to.equal(0); - expect(round(sw.shiftFractionTowards(sn, 100).x)).to.equal(2475); - expect(round(ss.shiftFractionTowards(se, 200).y)).to.equal(-995); - }); + it('Should shift a point a fraction towards another', () => { + let origin = new Point(0, 0) + let n = new Point(0, -10) + let e = new Point(10, 0) + let s = new Point(0, 10) + let w = new Point(-10, 0) + let sn = origin.shiftFractionTowards(n, 1.5) + let se = origin.shiftFractionTowards(e, 1.5) + let ss = origin.shiftFractionTowards(s, 0.5) + let sw = origin.shiftFractionTowards(w, 2.5) + expect(round(sn.x)).to.equal(0) + expect(round(sn.y)).to.equal(-15) + expect(round(se.x)).to.equal(15) + expect(round(se.y)).to.equal(0) + expect(round(ss.x)).to.equal(0) + expect(round(ss.y)).to.equal(5) + expect(round(sw.x)).to.equal(-25) + expect(round(sw.y)).to.equal(0) + expect(round(sw.shiftFractionTowards(sn, 100).x)).to.equal(2475) + expect(round(ss.shiftFractionTowards(se, 200).y)).to.equal(-995) + }) - it("Should shift a point beyond another", () => { - let origin = new Point(0, 0); - let n = new Point(0, -10); - let e = new Point(10, 0); - let s = new Point(0, 10); - let w = new Point(-10, 0); - let sn = origin.shiftOutwards(n, 100); - let se = origin.shiftOutwards(e, 100); - let ss = origin.shiftOutwards(s, 100); - let sw = origin.shiftOutwards(w, 100); - expect(round(sn.x)).to.equal(0); - expect(round(sn.y)).to.equal(-110); - expect(round(se.x)).to.equal(110); - expect(round(se.y)).to.equal(0); - expect(round(ss.x)).to.equal(0); - expect(round(ss.y)).to.equal(110); - expect(round(sw.x)).to.equal(-110); - expect(round(sw.y)).to.equal(0); - expect(round(sw.shiftOutwards(sn, 100).x)).to.equal(70.71); - expect(round(ss.shiftOutwards(se, 200).y)).to.equal(-141.42); - }); + it('Should shift a point beyond another', () => { + let origin = new Point(0, 0) + let n = new Point(0, -10) + let e = new Point(10, 0) + let s = new Point(0, 10) + let w = new Point(-10, 0) + let sn = origin.shiftOutwards(n, 100) + let se = origin.shiftOutwards(e, 100) + let ss = origin.shiftOutwards(s, 100) + let sw = origin.shiftOutwards(w, 100) + expect(round(sn.x)).to.equal(0) + expect(round(sn.y)).to.equal(-110) + expect(round(se.x)).to.equal(110) + expect(round(se.y)).to.equal(0) + expect(round(ss.x)).to.equal(0) + expect(round(ss.y)).to.equal(110) + expect(round(sw.x)).to.equal(-110) + expect(round(sw.y)).to.equal(0) + expect(round(sw.shiftOutwards(sn, 100).x)).to.equal(70.71) + expect(round(ss.shiftOutwards(se, 200).y)).to.equal(-141.42) + }) - it("Should rotate a point around another", () => { - let sun = new Point(0, 0); - let moon = new Point(10, 0); - let a = moon.rotate(90, sun); - expect(round(a.x)).to.equal(0); - expect(round(a.y)).to.equal(-10); - let b = moon.rotate(-90, sun); - expect(round(b.x)).to.equal(0); - expect(round(b.y)).to.equal(10); - let c = moon.rotate(180, sun); - expect(round(c.x)).to.equal(-10); - expect(round(c.y)).to.equal(0); - let sun2 = new Point(222, 44); - let moon2 = new Point(212, 41); - let d = moon2.rotate(90, sun2); - expect(round(d.x)).to.equal(219); - expect(round(d.y)).to.equal(54); - }); + it('Should rotate a point around another', () => { + let sun = new Point(0, 0) + let moon = new Point(10, 0) + let a = moon.rotate(90, sun) + expect(round(a.x)).to.equal(0) + expect(round(a.y)).to.equal(-10) + let b = moon.rotate(-90, sun) + expect(round(b.x)).to.equal(0) + expect(round(b.y)).to.equal(10) + let c = moon.rotate(180, sun) + expect(round(c.x)).to.equal(-10) + expect(round(c.y)).to.equal(0) + let sun2 = new Point(222, 44) + let moon2 = new Point(212, 41) + let d = moon2.rotate(90, sun2) + expect(round(d.x)).to.equal(219) + expect(round(d.y)).to.equal(54) + }) - it("Should set an attribute", () => { - let p = new Point(0, 0).attr("class", "test"); - expect(p.attributes.get("class")).to.equal("test"); - p.attr("class", "more"); - expect(p.attributes.get("class")).to.equal("test more"); - p.attr("class", "less", true); - expect(p.attributes.get("class")).to.equal("less"); - }); + it('Should set an attribute', () => { + let p = new Point(0, 0).attr('class', 'test') + expect(p.attributes.get('class')).to.equal('test') + p.attr('class', 'more') + expect(p.attributes.get('class')).to.equal('test more') + p.attr('class', 'less', true) + expect(p.attributes.get('class')).to.equal('less') + }) - it("Should detect points in the same location", () => { - let p1 = new Point(123, 456); - let p2 = new Point(123, 456); - expect(p1.sitsOn(p2)).to.equal(true); - p2.x = 122.99; - expect(p1.sitsOn(p2)).to.equal(false); - }); + it('Should detect points in the same location', () => { + let p1 = new Point(123, 456) + let p2 = new Point(123, 456) + expect(p1.sitsOn(p2)).to.equal(true) + p2.x = 122.99 + expect(p1.sitsOn(p2)).to.equal(false) + }) - it("Should clone a point", () => { - let p1 = new Point(123, 456).attr("class", "something"); - p1.attr("class", "else"); - let p2 = p1.clone(); - expect(p2.sitsOn(p1)).to.equal(true); - expect(p2.attributes.get("class")).to.equal("something else"); - }); + it('Should clone a point', () => { + let p1 = new Point(123, 456).attr('class', 'something') + p1.attr('class', 'else') + let p2 = p1.clone() + expect(p2.sitsOn(p1)).to.equal(true) + expect(p2.attributes.get('class')).to.equal('something else') + }) - it("Should translate a point", () => { - let p1 = new Point(10, 20); - let p2 = p1.translate(15, 50); - expect(p2.x).to.equal(25); - expect(p2.y).to.equal(70); - }); + it('Should translate a point', () => { + let p1 = new Point(10, 20) + let p2 = p1.translate(15, 50) + expect(p2.x).to.equal(25) + expect(p2.y).to.equal(70) + }) - it("Should add raise methods to a point", () => { + 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'); - }); + const p1 = new Point(10, 20).withRaise(raise) + expect(p1.raise()).to.equal('hello') + }) - it("Should raise a warning on invalid point coordinates", () => { + 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); + 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); - }); + expect(invalid.x).to.equal(true) + expect(invalid.y).to.equal(true) + }) - it("Should raise a warning if rotation is not a number", () => { + 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 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); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning if rotating around what is not a point", () => { + 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); - expect(invalid).to.equal(false); + const raise = { warning: () => (invalid = true) } + const p1 = new Point(10, 10).withRaise(raise) + expect(invalid).to.equal(false) try { p1.rotate(45, 'a') + } catch (err) { + expect('' + err).to.contain('check is not a function') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting with a distance that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting with an angle that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting towards with a distance that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting towards with a target that is not a point", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting fraction towards with a distance that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting a fraction towards with a target that is not a point", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting outowards with a distance that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when shifting a outowards with a target that is not a point", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when translating with an X-delta that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when translating with an Y-delta that is not a number", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when sitsOn receives a non-point", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + expect(invalid).to.equal(true) + }) - it("Should raise a warning when sitsRoughlyOn receives a non-point", () => { + 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); + 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') } - catch (err) { - expect(''+err).to.contain("check is not a function") - } - expect(invalid).to.equal(true); - }); + 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 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-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'); - }); -}); + 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/snap.mjs b/packages/core/tests/snap.mjs index 1a22941d315..36de3dfbbc1 100644 --- a/packages/core/tests/snap.mjs +++ b/packages/core/tests/snap.mjs @@ -1,5 +1,5 @@ -import chai from "chai" -import freesewing from "../dist/index.js" +import chai from 'chai' +import freesewing from '../dist/index.js' const expect = chai.expect @@ -7,26 +7,29 @@ const measurements = { head: 400 } const toAbs = (val, { measurements }) => measurements.head * val describe('Snapped options', () => { - it("Should snap a percentage options to equal steps", () => { + it('Should snap a percentage options to equal steps', () => { const design = new freesewing.Design({ options: { - test: { pct: 30, min: 0, max: 100, snap: 12, toAbs } - } + test: { pct: 30, min: 0, max: 100, snap: 12, toAbs }, + }, }) const patternA = new design({ options: { test: 0.13 }, measurements }) const patternB = new design({ options: { test: 0.27 }, measurements }) expect(patternA.settings.absoluteOptions.test).to.equal(60) expect(patternB.settings.absoluteOptions.test).to.equal(108) - }); + }) - it("Should snap a percentage options to the Fibonacci sequence", () => { + it('Should snap a percentage options to the Fibonacci sequence', () => { const design = new freesewing.Design({ options: { test: { - pct: 30, min: 0, max: 100, toAbs, - snap: [ 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 ], - } - } + pct: 30, + min: 0, + max: 100, + toAbs, + snap: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144], + }, + }, }) const patternA = new design({ options: { test: 0.13 }, measurements }) const patternB = new design({ options: { test: 0.27 }, measurements }) @@ -34,50 +37,55 @@ describe('Snapped options', () => { expect(patternA.settings.absoluteOptions.test).to.equal(55) expect(patternB.settings.absoluteOptions.test).to.equal(89) expect(patternC.settings.absoluteOptions.test).to.equal(388) - }); + }) - it("Should snap a percentage options to imperial snaps", () => { + it('Should snap a percentage options to imperial snaps', () => { const design = new freesewing.Design({ options: { test: { - pct: 30, min: 0, max: 100, toAbs, + pct: 30, + min: 0, + max: 100, + toAbs, snap: { - metric: [ 25, 50, 75, 100 ], - imperial: [ 25.4, 50.8, 76.2, 101.6 ], - } - } - } + metric: [25, 50, 75, 100], + imperial: [25.4, 50.8, 76.2, 101.6], + }, + }, + }, }) - const patternA = new design({ options: { test: 0.13 }, measurements, units:'metric' }) - const patternB = new design({ options: { test: 0.27 }, measurements, units:'metric' }) - const patternC = new design({ options: { test: 0.97 }, measurements, units:'metric' }) - const patternD = new design({ options: { test: 0.01 }, measurements, units:'metric' }) + const patternA = new design({ options: { test: 0.13 }, measurements, units: 'metric' }) + const patternB = new design({ options: { test: 0.27 }, measurements, units: 'metric' }) + const patternC = new design({ options: { test: 0.97 }, measurements, units: 'metric' }) + const patternD = new design({ options: { test: 0.01 }, measurements, units: 'metric' }) expect(patternA.settings.absoluteOptions.test).to.equal(50) expect(patternB.settings.absoluteOptions.test).to.equal(100) expect(patternC.settings.absoluteOptions.test).to.equal(388) expect(patternD.settings.absoluteOptions.test).to.equal(4) - }); + }) - it("Should snap a percentage options to metrics snaps", () => { + it('Should snap a percentage options to metrics snaps', () => { const design = new freesewing.Design({ options: { test: { - pct: 30, min: 0, max: 100, toAbs, + pct: 30, + min: 0, + max: 100, + toAbs, snap: { - metric: [ 25, 50, 75, 100 ], - imperial: [ 25.4, 50.8, 76.2, 101.6 ], - } - } - } + metric: [25, 50, 75, 100], + imperial: [25.4, 50.8, 76.2, 101.6], + }, + }, + }, }) - const patternA = new design({ options: { test: 0.13 }, measurements, units:'imperial' }) - const patternB = new design({ options: { test: 0.27 }, measurements, units:'imperial' }) - const patternC = new design({ options: { test: 0.97 }, measurements, units:'imperial' }) - const patternD = new design({ options: { test: 0.01 }, measurements, units:'imperial' }) + const patternA = new design({ options: { test: 0.13 }, measurements, units: 'imperial' }) + const patternB = new design({ options: { test: 0.27 }, measurements, units: 'imperial' }) + const patternC = new design({ options: { test: 0.97 }, measurements, units: 'imperial' }) + const patternD = new design({ options: { test: 0.01 }, measurements, units: 'imperial' }) expect(patternA.settings.absoluteOptions.test).to.equal(50.8) expect(patternB.settings.absoluteOptions.test).to.equal(101.6) expect(patternC.settings.absoluteOptions.test).to.equal(388) expect(patternD.settings.absoluteOptions.test).to.equal(4) - }); -}); - + }) +}) diff --git a/packages/core/tests/snippet.test.mjs b/packages/core/tests/snippet.test.mjs index ad6b9734bb9..4bd3a46c335 100644 --- a/packages/core/tests/snippet.test.mjs +++ b/packages/core/tests/snippet.test.mjs @@ -1,33 +1,29 @@ -import chai from "chai" -import { Snippet, Point } from "./dist/index.mjs" +import chai from 'chai' +import { Snippet, Point } from '../src/index.mjs' const expect = chai.expect describe('Snippet', () => { - it("Should create a snippet", () => { - let snip1 = new Snippet("test", new Point(12, 34)); - expect(snip1.def).to.equal("test"); - expect(snip1.anchor.x).to.equal(12); - expect(snip1.anchor.y).to.equal(34); - }); + it('Should create a snippet', () => { + let snip1 = new Snippet('test', new Point(12, 34)) + expect(snip1.def).to.equal('test') + expect(snip1.anchor.x).to.equal(12) + expect(snip1.anchor.y).to.equal(34) + }) - it("Should clone a snippet", () => { - let snip3 = new Snippet("boo", new Point(56, 78)); - expect(snip3.clone().def).to.equal("boo"); - expect(snip3.clone().anchor.x).to.equal(56); - expect(snip3.clone().anchor.y).to.equal(78); - }); - - it("Should set an attribute", () => { - let s = new Snippet("test", new Point(12, -34)).attr( - "class", - "test" - ); - expect(s.attributes.get("class")).to.equal("test"); - s.attr("class", "more"); - expect(s.attributes.get("class")).to.equal("test more"); - s.attr("class", "less", true); - expect(s.attributes.get("class")).to.equal("less"); - }); -}); + it('Should clone a snippet', () => { + let snip3 = new Snippet('boo', new Point(56, 78)) + expect(snip3.clone().def).to.equal('boo') + expect(snip3.clone().anchor.x).to.equal(56) + expect(snip3.clone().anchor.y).to.equal(78) + }) + it('Should set an attribute', () => { + let s = new Snippet('test', new Point(12, -34)).attr('class', 'test') + expect(s.attributes.get('class')).to.equal('test') + s.attr('class', 'more') + expect(s.attributes.get('class')).to.equal('test more') + s.attr('class', 'less', true) + expect(s.attributes.get('class')).to.equal('less') + }) +}) diff --git a/packages/core/tests/store.test.mjs b/packages/core/tests/store.test.mjs index ab013d2dda3..6ca63afc802 100644 --- a/packages/core/tests/store.test.mjs +++ b/packages/core/tests/store.test.mjs @@ -1,97 +1,109 @@ -import chai from "chai" -import { Design, Store } from "./dist/index.mjs" +import chai from 'chai' +import { Design, Store } from '../src/index.mjs' const expect = chai.expect const store = new Store() describe('Store', () => { + it('Should set/get a top-level store value', () => { + store.set('foo', 'bar') + expect(store.get('foo')).to.equal('bar') + }) - it("Should set/get a top-level store value", () => { - store.set("foo", "bar"); - expect(store.get("foo")).to.equal("bar"); - }); + it('Should set/get a nested store value', () => { + store.set('some.nested.key.foo', 'bar') + expect(store.get('some.nested.key').foo).to.equal('bar') + }) - it("Should set/get a nested store value", () => { - store.set("some.nested.key.foo", "bar"); - expect(store.get("some.nested.key").foo).to.equal("bar"); - }); + it('Should set a store value only if unset', () => { + store.setIfUnset('dew.few', 'baz') + store.setIfUnset('dew.few', 'schmoo') + expect(store.get('dew').few).to.equal('baz') + }) - it("Should set a store value only if unset", () => { - store.setIfUnset("dew.few", "baz"); - store.setIfUnset("dew.few", "schmoo"); - expect(store.get("dew").few).to.equal("baz"); - }); - - it("Should push to an array value in the store", () => { - store.set("dew.few", ["baz", "bar"]); + it('Should push to an array value in the store', () => { + store.set('dew.few', ['baz', 'bar']) // store.push is variadic - store.push("dew.few", "boz", "bor"); - expect(store.get("dew").few.length).to.equal(4); - }); + store.push('dew.few', 'boz', 'bor') + expect(store.get('dew').few.length).to.equal(4) + }) - it("Should emit a warning when retrieving a invalid key", () => { - const warning = msg => events.push(msg) + it('Should emit a warning when retrieving a invalid key', () => { + const warning = (msg) => events.push(msg) const store = new Store() store.get('nope') expect(store.get('logs.warning').length).to.equal(1) - expect(store.get('logs.warning')[0]).to.equal('Store.get(key) on key `nope`, which is undefined') - }); + expect(store.get('logs.warning')[0]).to.equal( + 'Store.get(key) on key `nope`, which is undefined' + ) + }) - it("Should add methods to the store from a plugin", () => { + it('Should add methods to the store from a plugin', () => { const plugin = { name: 'test', version: 1, store: [ - ['test.example.warning', function(store, msg) { - store.set('test.message.warning', msg) - }], - ['test.example.info', function(store, msg) { - store.set('test.message.info', msg) - }], - ] + [ + 'test.example.warning', + function (store, msg) { + store.set('test.message.warning', msg) + }, + ], + [ + 'test.example.info', + function (store, msg) { + store.set('test.message.info', msg) + }, + ], + ], } const part = { name: 'example.part', - draft: part => { + draft: (part) => { const { store } = part.shorthand() store.test.example.warning('hello warning') store.test.example.info('hello info') - } + }, } - const Test = new Design({plugins: [plugin], parts: [ part ]}) + const Test = new Design({ plugins: [plugin], parts: [part] }) const pattern = new Test() pattern.draft() - expect(pattern.store.get("test.message.warning")).to.equal("hello warning") - expect(pattern.store.get("test.message.info")).to.equal("hello info") - }); + expect(pattern.store.get('test.message.warning')).to.equal('hello warning') + expect(pattern.store.get('test.message.info')).to.equal('hello info') + }) - it("Should make top-level plugin methods available via shorthand", () => { + it('Should make top-level plugin methods available via shorthand', () => { const plugin = { name: 'test', version: 1, store: [ - ['methodA', function(store, name, msg) { - store.set(['test', name, 'a'], msg) - }], - ['methodB', function(store, name, msg) { - store.set(['test', name, 'b'], msg) - }], - ] + [ + 'methodA', + function (store, name, msg) { + store.set(['test', name, 'a'], msg) + }, + ], + [ + 'methodB', + function (store, name, msg) { + store.set(['test', name, 'b'], msg) + }, + ], + ], } const part = { name: 'example_part', - draft: part => { + draft: (part) => { const { methodA, methodB } = part.shorthand() methodA('hello A') methodB('hello B') - } + }, } - const Test = new Design({plugins: [plugin], parts: [ part ]}) + const Test = new Design({ plugins: [plugin], parts: [part] }) const pattern = new Test() pattern.draft() - expect(pattern.store.get("test.example_part.a")).to.equal("hello A") - expect(pattern.store.get("test.example_part.b")).to.equal("hello B") - }); -}); - + expect(pattern.store.get('test.example_part.a')).to.equal('hello A') + expect(pattern.store.get('test.example_part.b')).to.equal('hello B') + }) +}) diff --git a/packages/core/tests/svg.test.mjs b/packages/core/tests/svg.test.mjs index 3818c3b749a..3b59dcb4773 100644 --- a/packages/core/tests/svg.test.mjs +++ b/packages/core/tests/svg.test.mjs @@ -1,282 +1,268 @@ -import chai from "chai" -import chaiString from "chai-string" -import { Pattern } from "./dist/index.mjs" +import chai from 'chai' +import chaiString from 'chai-string' +import { Pattern } from '../src/index.mjs' import pkg from '../package.json' assert { type: 'json' } -import render from "./fixtures/render.mjs" +import render from './fixtures/render.mjs' chai.use(chaiString) const expect = chai.expect const { version } = pkg describe('Svg', () => { - it("Svg constructor should initialize object", () => { - let pattern = new Pattern(); - pattern.render(); - let svg = pattern.svg; - expect(svg.openGroups).to.eql([]); - expect(svg.freeId).to.equal(0); - expect(svg.body).to.equal(""); - expect(svg.style).to.equal("") - expect(svg.script).to.equal(""); - expect(svg.defs).to.equal(""); - expect(svg.pattern).to.eql(pattern); - expect(svg.prefix).to.equal( - '' - ); - expect(svg.attributes.get("xmlns")).to.equal("http://www.w3.org/2000/svg"); - expect(svg.attributes.get("xmlns:svg")).to.equal( - "http://www.w3.org/2000/svg" - ); - expect(svg.attributes.get("xmlns:xlink")).to.equal( - "http://www.w3.org/1999/xlink" - ); - expect(svg.attributes.get("xmlns:freesewing")).to.equal( - "http://freesewing.org/namespaces/freesewing" - ); - expect(svg.attributes.get("freesewing")).to.equal(version); - }); + it('Svg constructor should initialize object', () => { + let pattern = new Pattern() + pattern.render() + let svg = pattern.svg + expect(svg.openGroups).to.eql([]) + expect(svg.freeId).to.equal(0) + expect(svg.body).to.equal('') + expect(svg.style).to.equal('') + expect(svg.script).to.equal('') + expect(svg.defs).to.equal('') + expect(svg.pattern).to.eql(pattern) + expect(svg.prefix).to.equal('') + expect(svg.attributes.get('xmlns')).to.equal('http://www.w3.org/2000/svg') + expect(svg.attributes.get('xmlns:svg')).to.equal('http://www.w3.org/2000/svg') + expect(svg.attributes.get('xmlns:xlink')).to.equal('http://www.w3.org/1999/xlink') + expect(svg.attributes.get('xmlns:freesewing')).to.equal( + 'http://freesewing.org/namespaces/freesewing' + ) + expect(svg.attributes.get('freesewing')).to.equal(version) + }) - it("Should render Svg boilerplate", () => { - let pattern = new Pattern(); - expect(pattern.render()).to.equalIgnoreSpaces(render.boilerplate); - }); + it('Should render Svg boilerplate', () => { + let pattern = new Pattern() + expect(pattern.render()).to.equalIgnoreSpaces(render.boilerplate) + }) - it("Should render language attribute", () => { - let pattern = new Pattern(); - pattern.settings.locale = "nl"; - expect(pattern.render()).to.equalIgnoreSpaces(render.boilerplateNl); - }); + it('Should render language attribute', () => { + let pattern = new Pattern() + pattern.settings.locale = 'nl' + expect(pattern.render()).to.equalIgnoreSpaces(render.boilerplateNl) + }) - it("Should render Svg boilerplate for embedding", () => { - let pattern = new Pattern(); - pattern.settings.embed = true; - expect(pattern.render()).to.equalIgnoreSpaces(render.embed); - }); + it('Should render Svg boilerplate for embedding', () => { + let pattern = new Pattern() + pattern.settings.embed = true + expect(pattern.render()).to.equalIgnoreSpaces(render.embed) + }) - it("Should render Svg part boilerplate", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - expect(pattern.render()).to.equalIgnoreSpaces(render.part); - pattern.parts.test.render = false; - expect(pattern.render()).to.equalIgnoreSpaces(render.boilerplate); - }); + it('Should render Svg part boilerplate', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + expect(pattern.render()).to.equalIgnoreSpaces(render.part) + pattern.parts.test.render = false + expect(pattern.render()).to.equalIgnoreSpaces(render.boilerplate) + }) - it("Should render Svg path", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg path', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.paths.test = new p.Path() .move(new p.Point(0, 0)) .line(new p.Point(40, 20)) .curve(new p.Point(12, 34), new p.Point(56, 78), new p.Point(21, 32)) .close() - .attr("id", "something") - .attr("class", "freesewing"); - expect(pattern.render()).to.equalIgnoreSpaces(render.path); - }); - it("Should not render Svg path when render property is false", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + .attr('id', 'something') + .attr('class', 'freesewing') + expect(pattern.render()).to.equalIgnoreSpaces(render.path) + }) + it('Should not render Svg path when render property is false', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.paths.test = new p.Path() .move(new p.Point(0, 0)) .line(new p.Point(40, 20)) .curve(new p.Point(12, 34), new p.Point(56, 78), new p.Point(21, 32)) .close() - .attr("id", "something") - .attr("class", "freesewing"); - p.paths.test.render = false; - expect(pattern.render()).to.equalIgnoreSpaces(render.part); - }); + .attr('id', 'something') + .attr('class', 'freesewing') + p.paths.test.render = false + expect(pattern.render()).to.equalIgnoreSpaces(render.part) + }) - it("Should render Svg text", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg text', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.points.test = new p.Point(20, 20) - .attr("data-text", "This is a test") - .attr("data-text-class", "text-lg"); - p.points.other = new p.Point(10, 10).attr("data-text", ""); - expect(pattern.render()).to.equalIgnoreSpaces(render.text); - }); + .attr('data-text', 'This is a test') + .attr('data-text-class', 'text-lg') + p.points.other = new p.Point(10, 10).attr('data-text', '') + expect(pattern.render()).to.equalIgnoreSpaces(render.text) + }) - it("Should render Svg multi-line text", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg multi-line text', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.points.test = new p.Point(20, 20) - .attr("data-text", "This is a test\nwith text on\nmultiple lines") - .attr("data-text-class", "text-lg") - .attr("data-text-lineheight", 8); - expect(pattern.render()).to.equalIgnoreSpaces(render.multiText); - }); + .attr('data-text', 'This is a test\nwith text on\nmultiple lines') + .attr('data-text-class', 'text-lg') + .attr('data-text-lineheight', 8) + expect(pattern.render()).to.equalIgnoreSpaces(render.multiText) + }) - it("Should render Svg multi-line text with default lineheight", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg multi-line text with default lineheight', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.points.test = new p.Point(20, 20) - .attr("data-text", "This is a test\nwith text on\nmultiple lines") - .attr("data-text-class", "text-lg"); - expect(pattern.render()).to.equalIgnoreSpaces(render.multiTextDflt); - }); + .attr('data-text', 'This is a test\nwith text on\nmultiple lines') + .attr('data-text-class', 'text-lg') + expect(pattern.render()).to.equalIgnoreSpaces(render.multiTextDflt) + }) - it("Should not render text when there is none", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; - p.points.test = new p.Point(20, 20); - expect(pattern.render()).to.equalIgnoreSpaces(render.part); - }); + it('Should not render text when there is none', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test + p.points.test = new p.Point(20, 20) + expect(pattern.render()).to.equalIgnoreSpaces(render.part) + }) - it("Should render Svg text on path", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg text on path', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.paths.test = new p.Path() .move(new p.Point(0, 0)) .line(new p.Point(40, 20)) .curve(new p.Point(12, 34), new p.Point(56, 78), new p.Point(21, 32)) .close() - .attr("data-text", "This is another test") - .attr("data-text-class", "text-sm") - .attr("class", "freesewing"); - expect(pattern.render()).to.equalIgnoreSpaces(render.textOnPath); - }); + .attr('data-text', 'This is another test') + .attr('data-text-class', 'text-sm') + .attr('class', 'freesewing') + expect(pattern.render()).to.equalIgnoreSpaces(render.textOnPath) + }) - it("Should render Svg text on path, center aligned", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg text on path, center aligned', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.paths.test = new p.Path() .move(new p.Point(0, 0)) .line(new p.Point(40, 20)) .curve(new p.Point(12, 34), new p.Point(56, 78), new p.Point(21, 32)) .close() - .attr("data-text", "This is another test") - .attr("data-text-class", "center") - .attr("class", "freesewing"); - expect(pattern.render()).to.equalIgnoreSpaces(render.textOnPathCenter); - }); + .attr('data-text', 'This is another test') + .attr('data-text-class', 'center') + .attr('class', 'freesewing') + expect(pattern.render()).to.equalIgnoreSpaces(render.textOnPathCenter) + }) - it("Should render Svg text on path, right aligned", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; + it('Should render Svg text on path, right aligned', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test p.paths.test = new p.Path() .move(new p.Point(0, 0)) .line(new p.Point(40, 20)) .curve(new p.Point(12, 34), new p.Point(56, 78), new p.Point(21, 32)) .close() - .attr("data-text", "This is another test") - .attr("data-text-class", "right") - .attr("class", "freesewing"); - expect(pattern.render()).to.equalIgnoreSpaces(render.textOnPathRight); - }); + .attr('data-text', 'This is another test') + .attr('data-text-class', 'right') + .attr('class', 'freesewing') + expect(pattern.render()).to.equalIgnoreSpaces(render.textOnPathRight) + }) - it("Should render an Svg circle", () => { - let pattern = new Pattern(); - pattern.render(); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; - p.points.test = new p.Point(20, 20).attr("data-circle", "50"); - expect(pattern.render()).to.equalIgnoreSpaces(render.circle); - }); + it('Should render an Svg circle', () => { + let pattern = new Pattern() + pattern.render() + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test + p.points.test = new p.Point(20, 20).attr('data-circle', '50') + expect(pattern.render()).to.equalIgnoreSpaces(render.circle) + }) - it("Should render an Svg snippet", () => { - let pattern = new 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" - ); - expect(pattern.render()).to.equalIgnoreSpaces(render.snippet); - }); + it('Should render an Svg snippet', () => { + let pattern = new 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') + expect(pattern.render()).to.equalIgnoreSpaces(render.snippet) + }) - it("Should render a rotated Svg snippet", () => { - let pattern = new 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 render a rotated Svg snippet', () => { + let pattern = new 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", () => { + it('Should replaced double quotes in Svg text', () => { const pattern = new Pattern() pattern.render() - expect( - pattern.svg.escapeText('This is a "test" message') - ).to.equal('This is a “test“ message') - }); + expect(pattern.svg.escapeText('This is a "test" message')).to.equal( + 'This is a “test“ message' + ) + }) - it("Should scale an Svg snippet", () => { - let pattern = new 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-scale", 2); - expect(pattern.render()).to.contain("scale(2)"); - }); - - it("Should run preRender hook", () => { - let pattern = new Pattern(); - pattern.on("preRender", svg => { - svg.attributes.set("data-hook", "preRender"); - }); - pattern.render(); - expect(pattern.svg.attributes.get("data-hook")).to.equal("preRender"); - }); - - it("Should run insertText hook", () => { - let pattern = new Pattern(); - pattern.on("insertText", (locale, text) => { - return text.toUpperCase(); - }); - pattern.parts.test = new pattern.Part(); - let p = pattern.parts.test; - p.points.test = new p.Point(20, 20) - .attr("data-text", "This is a test") - .attr("data-text-class", "text-lg"); - expect(pattern.render()).to.contain("THIS IS A TEST"); - }); - - it("Should run postRender hook", () => { + it('Should scale an Svg snippet', () => { let pattern = new Pattern() - pattern.on("postRender", svg => { - svg.svg = "test"; - }); - expect(pattern.render()).to.equal("test"); - }); + 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-scale', + 2 + ) + expect(pattern.render()).to.contain('scale(2)') + }) - it("Should tab in and out", () => { + it('Should run preRender hook', () => { + let pattern = new Pattern() + pattern.on('preRender', (svg) => { + svg.attributes.set('data-hook', 'preRender') + }) + pattern.render() + expect(pattern.svg.attributes.get('data-hook')).to.equal('preRender') + }) + + it('Should run insertText hook', () => { + let pattern = new Pattern() + pattern.on('insertText', (locale, text) => { + return text.toUpperCase() + }) + pattern.parts.test = new pattern.Part() + let p = pattern.parts.test + p.points.test = new p.Point(20, 20) + .attr('data-text', 'This is a test') + .attr('data-text-class', 'text-lg') + expect(pattern.render()).to.contain('THIS IS A TEST') + }) + + it('Should run postRender hook', () => { + let pattern = new Pattern() + pattern.on('postRender', (svg) => { + svg.svg = 'test' + }) + expect(pattern.render()).to.equal('test') + }) + + it('Should tab in and out', () => { let pattern = new Pattern() pattern.render() const svg = pattern.svg svg.tabs = 2 expect(svg.tab()).to.equal(' ') - }); -}); - - + }) +}) diff --git a/packages/core/tests/utils.test.mjs b/packages/core/tests/utils.test.mjs index 114e7133f68..9343e68464d 100644 --- a/packages/core/tests/utils.test.mjs +++ b/packages/core/tests/utils.test.mjs @@ -1,4 +1,4 @@ -import chai from "chai" +import chai from 'chai' import { Pattern, Point, @@ -30,568 +30,506 @@ import { Bezier, generatePartTransform, macroName, -} from "./dist/index.mjs" +} from '../src/index.mjs' const { expect } = chai describe('Utils', () => { - it("Should return the correct macro name", () => { - expect(macroName("test")).to.equal("_macro_test"); - }); + it('Should return the correct macro name', () => { + expect(macroName('test')).to.equal('_macro_test') + }) - it("Should find the intersection of two endless line segments", () => { - let a = new Point(10, 20); - let b = new Point(20, 24); - let c = new Point(90, 19); - let d = new Point(19, 70); - let X = beamsIntersect(a, b, c, d); - expect(round(X.x)).to.equal(60.49); - expect(round(X.y)).to.equal(40.2); - }); + it('Should find the intersection of two endless line segments', () => { + let a = new Point(10, 20) + let b = new Point(20, 24) + let c = new Point(90, 19) + let d = new Point(19, 70) + let X = beamsIntersect(a, b, c, d) + expect(round(X.x)).to.equal(60.49) + expect(round(X.y)).to.equal(40.2) + }) - it("Should detect parallel lines", () => { - let a = new Point(10, 20); - let b = new Point(20, 20); - let c = new Point(90, 40); - let d = new Point(19, 40); - expect(beamsIntersect(a, b, c, d)).to.equal(false); - expect(linesIntersect(a, b, c, d)).to.equal(false); - }); + it('Should detect parallel lines', () => { + let a = new Point(10, 20) + let b = new Point(20, 20) + let c = new Point(90, 40) + let d = new Point(19, 40) + expect(beamsIntersect(a, b, c, d)).to.equal(false) + expect(linesIntersect(a, b, c, d)).to.equal(false) + }) - it("Should detect vertical lines", () => { - let a = new Point(10, 20); - let b = new Point(10, 90); - let c = new Point(90, 40); - let d = new Point(19, 40); - let X = beamsIntersect(a, b, c, d); - expect(X.x).to.equal(10); - expect(X.y).to.equal(40); - X = beamsIntersect(c, d, a, b); - expect(X.x).to.equal(10); - }); + it('Should detect vertical lines', () => { + let a = new Point(10, 20) + let b = new Point(10, 90) + let c = new Point(90, 40) + let d = new Point(19, 40) + let X = beamsIntersect(a, b, c, d) + expect(X.x).to.equal(10) + expect(X.y).to.equal(40) + X = beamsIntersect(c, d, a, b) + expect(X.x).to.equal(10) + }) - it("Should swap direction prior to finding beam intersection", () => { - let a = new Point(10, 20); - let b = new Point(0, 90); - let c = new Point(90, 40); - let d = new Point(19, 40); - let X = beamsIntersect(a, b, c, d); - expect(round(X.x)).to.equal(7.14); - expect(round(X.y)).to.equal(40); - }); + it('Should swap direction prior to finding beam intersection', () => { + let a = new Point(10, 20) + let b = new Point(0, 90) + let c = new Point(90, 40) + let d = new Point(19, 40) + let X = beamsIntersect(a, b, c, d) + expect(round(X.x)).to.equal(7.14) + expect(round(X.y)).to.equal(40) + }) it("Should return false when two lines don't intersect", () => { - let a = new Point(10, 20); - let b = new Point(20, 24); - let c = new Point(90, 19); - let d = new Point(19, 70); - expect(linesIntersect(a, b, c, d)).to.equal(false); - }); + let a = new Point(10, 20) + let b = new Point(20, 24) + let c = new Point(90, 19) + let d = new Point(19, 70) + expect(linesIntersect(a, b, c, d)).to.equal(false) + }) - it("Should find the intersection of two line segments", () => { - let a = new Point(10, 10); - let b = new Point(90, 74); - let c = new Point(90, 19); - let d = new Point(11, 70); - let X = linesIntersect(a, b, c, d); - expect(round(X.x)).to.equal(51.95); - expect(round(X.y)).to.equal(43.56); - }); + it('Should find the intersection of two line segments', () => { + let a = new Point(10, 10) + let b = new Point(90, 74) + let c = new Point(90, 19) + let d = new Point(11, 70) + let X = linesIntersect(a, b, c, d) + expect(round(X.x)).to.equal(51.95) + expect(round(X.y)).to.equal(43.56) + }) - it("Should find the intersection of an endles line and a give X-value", () => { - let a = new Point(10, 10); - let b = new Point(90, 74); - let X = beamIntersectsX(a, b, 69); - expect(X.x).to.equal(69); - expect(X.y).to.equal(57.2); - }); + it('Should find the intersection of an endles line and a give X-value', () => { + let a = new Point(10, 10) + let b = new Point(90, 74) + let X = beamIntersectsX(a, b, 69) + expect(X.x).to.equal(69) + expect(X.y).to.equal(57.2) + }) - it("Should find the intersection of an endles line and a give Y-value", () => { - let a = new Point(10, 10); - let b = new Point(90, 74); - let X = beamIntersectsY(a, b, 69); - expect(X.x).to.equal(83.75); - expect(X.y).to.equal(69); - }); + it('Should find the intersection of an endles line and a give Y-value', () => { + let a = new Point(10, 10) + let b = new Point(90, 74) + let X = beamIntersectsY(a, b, 69) + expect(X.x).to.equal(83.75) + expect(X.y).to.equal(69) + }) - it("Should detect vertical lines never pass a give X-value", () => { - let a = new Point(10, 10); - let b = new Point(10, 90); - expect(beamIntersectsX(a, b, 69)).to.equal(false); - }); + it('Should detect vertical lines never pass a give X-value', () => { + let a = new Point(10, 10) + let b = new Point(10, 90) + expect(beamIntersectsX(a, b, 69)).to.equal(false) + }) - it("Should detect horizontal lines never pass a give Y-value", () => { - let a = new Point(10, 10); - let b = new Point(90, 10); - expect(beamIntersectsY(a, b, 69)).to.equal(false); - }); + it('Should detect horizontal lines never pass a give Y-value', () => { + let a = new Point(10, 10) + let b = new Point(90, 10) + expect(beamIntersectsY(a, b, 69)).to.equal(false) + }) - it("Should find no intersections between a curve and a line", () => { - let A = new Point(10, 10); - let Acp = new Point(310, 40); - let B = new Point(110, 70); - let Bcp = new Point(-210, 40); - let E = new Point(-20, -20); - let D = new Point(30, -85); + it('Should find no intersections between a curve and a line', () => { + let A = new Point(10, 10) + let Acp = new Point(310, 40) + let B = new Point(110, 70) + let Bcp = new Point(-210, 40) + let E = new Point(-20, -20) + let D = new Point(30, -85) - let hit = lineIntersectsCurve(E, D, A, Acp, Bcp, B); - expect(hit).to.equal(false); - }); + let hit = lineIntersectsCurve(E, D, A, Acp, Bcp, B) + expect(hit).to.equal(false) + }) - it("Should find 1 intersection between a curve and a line", () => { - let A = new Point(10, 10); - let Acp = new Point(310, 40); - let B = new Point(110, 70); - let Bcp = new Point(-210, 40); - let E = new Point(20, 20); - let D = new Point(30, -85); + it('Should find 1 intersection between a curve and a line', () => { + let A = new Point(10, 10) + let Acp = new Point(310, 40) + let B = new Point(110, 70) + let Bcp = new Point(-210, 40) + let E = new Point(20, 20) + let D = new Point(30, -85) - let hit = lineIntersectsCurve(E, D, A, Acp, Bcp, B); - expect(round(hit.x)).to.equal(20.85); - expect(round(hit.y)).to.equal(11.11); - }); + let hit = lineIntersectsCurve(E, D, A, Acp, Bcp, B) + expect(round(hit.x)).to.equal(20.85) + expect(round(hit.y)).to.equal(11.11) + }) - it("Should find 3 intersections between a curve and a line", () => { - let A = new Point(10, 10); - let Acp = new Point(310, 40); - let B = new Point(110, 70); - let Bcp = new Point(-210, 40); - let E = new Point(20, -5); - let D = new Point(100, 85); + it('Should find 3 intersections between a curve and a line', () => { + let A = new Point(10, 10) + let Acp = new Point(310, 40) + let B = new Point(110, 70) + let Bcp = new Point(-210, 40) + let E = new Point(20, -5) + let D = new Point(100, 85) - let hits = lineIntersectsCurve(E, D, A, Acp, Bcp, B); - expect(hits.length).to.equal(3); - }); + let hits = lineIntersectsCurve(E, D, A, Acp, Bcp, B) + expect(hits.length).to.equal(3) + }) - it("Should find 9 intersections between two curves", () => { - let A = new Point(10, 10); - let Acp = new Point(310, 40); - let B = new Point(110, 70); - let Bcp = new Point(-210, 40); - let C = new Point(20, -5); - let Ccp = new Point(60, 300); - let D = new Point(100, 85); - let Dcp = new Point(70, -220); + it('Should find 9 intersections between two curves', () => { + let A = new Point(10, 10) + let Acp = new Point(310, 40) + let B = new Point(110, 70) + let Bcp = new Point(-210, 40) + let C = new Point(20, -5) + let Ccp = new Point(60, 300) + let D = new Point(100, 85) + let Dcp = new Point(70, -220) - let hits = curvesIntersect(A, Acp, Bcp, B, C, Ccp, Dcp, D); - expect(hits.length).to.equal(9); - }); + let hits = curvesIntersect(A, Acp, Bcp, B, C, Ccp, Dcp, D) + expect(hits.length).to.equal(9) + }) - it("Should find 1 intersection between two curves", () => { - let A = new Point(10, 10); - let Acp = new Point(310, 40); - let B = new Point(110, 70); - let Bcp = new Point(-210, 40); - let C = new Point(20, -5); - let Ccp = new Point(-60, 300); - let D = new Point(-200, 85); - let Dcp = new Point(-270, -220); + it('Should find 1 intersection between two curves', () => { + let A = new Point(10, 10) + let Acp = new Point(310, 40) + let B = new Point(110, 70) + let Bcp = new Point(-210, 40) + let C = new Point(20, -5) + let Ccp = new Point(-60, 300) + let D = new Point(-200, 85) + let Dcp = new Point(-270, -220) - let hit = curvesIntersect(A, Acp, Bcp, B, C, Ccp, Dcp, D); - expect(round(hit.x)).to.equal(15.58); - expect(round(hit.y)).to.equal(10.56); - }); + let hit = curvesIntersect(A, Acp, Bcp, B, C, Ccp, Dcp, D) + expect(round(hit.x)).to.equal(15.58) + expect(round(hit.y)).to.equal(10.56) + }) - it("Should find no intersection between two curves", () => { - let A = new Point(10, 10); - let Acp = new Point(310, 40); - let B = new Point(110, 70); - let Bcp = new Point(-210, 40); - let C = new Point(20, -5); - let Ccp = new Point(-60, -300); - let D = new Point(-200, 85); - let Dcp = new Point(-270, -220); + it('Should find no intersection between two curves', () => { + let A = new Point(10, 10) + let Acp = new Point(310, 40) + let B = new Point(110, 70) + let Bcp = new Point(-210, 40) + let C = new Point(20, -5) + let Ccp = new Point(-60, -300) + let D = new Point(-200, 85) + let Dcp = new Point(-270, -220) - let hit = curvesIntersect(A, Acp, Bcp, B, C, Ccp, Dcp, D); - expect(hit).to.equal(false); - }); + let hit = curvesIntersect(A, Acp, Bcp, B, C, Ccp, Dcp, D) + expect(hit).to.equal(false) + }) - it("Should correctly format units", () => { - expect(units(123.456)).to.equal("12.35cm"); - expect(units(123.456, "imperial")).to.equal('4.86"'); - }); + it('Should correctly format units', () => { + expect(units(123.456)).to.equal('12.35cm') + expect(units(123.456, 'imperial')).to.equal('4.86"') + }) - it("Should find a start or end point on beam", () => { - let A = new Point(12, 34); - let B = new Point(56, 78); - let checkA = new Point(12, 34); - let checkB = new Point(56, 78); - expect(pointOnBeam(A, B, checkA)).to.equal(true); - expect(pointOnBeam(A, B, checkB)).to.equal(true); - }); + it('Should find a start or end point on beam', () => { + let A = new Point(12, 34) + let B = new Point(56, 78) + let checkA = new Point(12, 34) + let checkB = new Point(56, 78) + expect(pointOnBeam(A, B, checkA)).to.equal(true) + expect(pointOnBeam(A, B, checkB)).to.equal(true) + }) - it("Should find whether a point lies on a line segment", () => { - let A = new Point(12, 34); - let B = new Point(56, 78); - let check1 = A.shiftTowards(B, 10); - let check2 = A.shiftTowards(B, 210); - expect(pointOnLine(A, B, check1)).to.equal(true); - expect(pointOnLine(A, B, check2)).to.equal(false); - }); + it('Should find whether a point lies on a line segment', () => { + let A = new Point(12, 34) + let B = new Point(56, 78) + let check1 = A.shiftTowards(B, 10) + let check2 = A.shiftTowards(B, 210) + expect(pointOnLine(A, B, check1)).to.equal(true) + expect(pointOnLine(A, B, check2)).to.equal(false) + }) - it("Should find a start or end point on curve", () => { - let A = new Point(12, 34); - let Acp = new Point(123, 4); - let B = new Point(56, 78); - let Bcp = new Point(5, 678); - let checkA = new Point(12, 34); - let checkB = new Point(56, 78); - expect(pointOnCurve(A, Acp, Bcp, B, checkA)).to.equal(true); - expect(pointOnCurve(A, Acp, Bcp, B, checkB)).to.equal(true); - }); + it('Should find a start or end point on curve', () => { + let A = new Point(12, 34) + let Acp = new Point(123, 4) + let B = new Point(56, 78) + let Bcp = new Point(5, 678) + let checkA = new Point(12, 34) + let checkB = new Point(56, 78) + expect(pointOnCurve(A, Acp, Bcp, B, checkA)).to.equal(true) + expect(pointOnCurve(A, Acp, Bcp, B, checkB)).to.equal(true) + }) - it("Should find the intersections of a beam and circle", () => { - let A = new Point(45, 45).attr("data-circle", 35); - let B = new Point(5, 50); - let C = new Point(25, 30); - let intersections = beamIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C, - "y" - ); - expect(intersections.length).to.equal(2); - expect(round(intersections[0].x)).to.equal(45); - expect(round(intersections[0].y)).to.equal(10); - expect(round(intersections[1].x)).to.equal(10); - expect(round(intersections[1].y)).to.equal(45); - }); + it('Should find the intersections of a beam and circle', () => { + let A = new Point(45, 45).attr('data-circle', 35) + let B = new Point(5, 50) + let C = new Point(25, 30) + let intersections = beamIntersectsCircle(A, A.attributes.get('data-circle'), B, C, 'y') + expect(intersections.length).to.equal(2) + expect(round(intersections[0].x)).to.equal(45) + expect(round(intersections[0].y)).to.equal(10) + expect(round(intersections[1].x)).to.equal(10) + expect(round(intersections[1].y)).to.equal(45) + }) - it("Should not find the intersections of this beam and circle", () => { - let A = new Point(75, 75).attr("data-circle", 35); - let B = new Point(5, 5); - let C = new Point(10, 5); - let intersections = beamIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections).to.equal(false); - }); + it('Should not find the intersections of this beam and circle', () => { + let A = new Point(75, 75).attr('data-circle', 35) + let B = new Point(5, 5) + let C = new Point(10, 5) + let intersections = beamIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections).to.equal(false) + }) - it("Should find one intersections between this beam and circle", () => { - let A = new Point(5, 5).attr("data-circle", 5); - let B = new Point(0, 0); - let C = new Point(-10, 0); - let intersections = beamIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections.length).to.equal(1); - expect(intersections[0].x).to.equal(5); - expect(intersections[0].y).to.equal(0); - }); + it('Should find one intersections between this beam and circle', () => { + let A = new Point(5, 5).attr('data-circle', 5) + let B = new Point(0, 0) + let C = new Point(-10, 0) + let intersections = beamIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections.length).to.equal(1) + expect(intersections[0].x).to.equal(5) + expect(intersections[0].y).to.equal(0) + }) - it("Should find one intersections between this tangent and circle", () => { - let A = new Point(5, 5).attr("data-circle", 5); - let B = new Point(0, 0); - let C = new Point(10, 0); - let intersections = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections.length).to.equal(1); - expect(intersections[0].x).to.equal(5); - expect(intersections[0].y).to.equal(0); - }); + it('Should find one intersections between this tangent and circle', () => { + let A = new Point(5, 5).attr('data-circle', 5) + let B = new Point(0, 0) + let C = new Point(10, 0) + let intersections = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections.length).to.equal(1) + expect(intersections[0].x).to.equal(5) + expect(intersections[0].y).to.equal(0) + }) - it("Should find one intersection between this line and circle", () => { - let A = new Point(5, 5).attr("data-circle", 5); - let B = new Point(5, 5); - let C = new Point(26, 25); - let intersections = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections.length).to.equal(1); - expect(round(intersections[0].x)).to.equal(8.62); - expect(round(intersections[0].y)).to.equal(8.45); - }); + it('Should find one intersection between this line and circle', () => { + let A = new Point(5, 5).attr('data-circle', 5) + let B = new Point(5, 5) + let C = new Point(26, 25) + let intersections = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections.length).to.equal(1) + expect(round(intersections[0].x)).to.equal(8.62) + expect(round(intersections[0].y)).to.equal(8.45) + }) - it("Should not find an intersections between this line and circle", () => { - let A = new Point(5, 5).attr("data-circle", 5); - let B = new Point(0, 0); - let C = new Point(-10, 0); - let intersections = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections).to.equal(false); - }); + it('Should not find an intersections between this line and circle', () => { + let A = new Point(5, 5).attr('data-circle', 5) + let B = new Point(0, 0) + let C = new Point(-10, 0) + let intersections = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections).to.equal(false) + }) - it("Should find two intersections between this line and circle", () => { - let A = new Point(6, 7).attr("data-circle", 5); - let B = new Point(0, 10); - let C = new Point(10, 0); - let intersections1 = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C, - "foo" - ); - let intersections2 = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C, - "x" - ); - let intersections3 = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C, - "y" - ); - expect(intersections1.length).to.equal(2); - expect(intersections2.length).to.equal(2); - expect(intersections3.length).to.equal(2); - expect(intersections1[0].sitsOn(intersections2[1])).to.equal(true); - expect(intersections1[1].sitsOn(intersections2[0])).to.equal(true); - expect(intersections1[0].sitsOn(intersections3[0])).to.equal(true); - expect(intersections1[1].sitsOn(intersections3[1])).to.equal(true); - expect(round(intersections1[0].x)).to.equal(7.7); - expect(round(intersections1[0].y)).to.equal(2.3); - expect(round(intersections1[1].x)).to.equal(1.3); - expect(round(intersections1[1].y)).to.equal(8.7); - }); + it('Should find two intersections between this line and circle', () => { + let A = new Point(6, 7).attr('data-circle', 5) + let B = new Point(0, 10) + let C = new Point(10, 0) + let intersections1 = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C, 'foo') + let intersections2 = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C, 'x') + let intersections3 = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C, 'y') + expect(intersections1.length).to.equal(2) + expect(intersections2.length).to.equal(2) + expect(intersections3.length).to.equal(2) + expect(intersections1[0].sitsOn(intersections2[1])).to.equal(true) + expect(intersections1[1].sitsOn(intersections2[0])).to.equal(true) + expect(intersections1[0].sitsOn(intersections3[0])).to.equal(true) + expect(intersections1[1].sitsOn(intersections3[1])).to.equal(true) + expect(round(intersections1[0].x)).to.equal(7.7) + expect(round(intersections1[0].y)).to.equal(2.3) + expect(round(intersections1[1].x)).to.equal(1.3) + expect(round(intersections1[1].y)).to.equal(8.7) + }) - it("Should find the intersections of a line and circle", () => { - let A = new Point(45, 45).attr("data-circle", 35); - let B = new Point(5, 50); - let C = new Point(25, 30); - let intersections = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections.length).to.equal(1); - expect(round(intersections[0].x)).to.equal(10); - expect(round(intersections[0].y)).to.equal(45); - }); + it('Should find the intersections of a line and circle', () => { + let A = new Point(45, 45).attr('data-circle', 35) + let B = new Point(5, 50) + let C = new Point(25, 30) + let intersections = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections.length).to.equal(1) + expect(round(intersections[0].x)).to.equal(10) + expect(round(intersections[0].y)).to.equal(45) + }) - it("Should not find intersections of this line and circle", () => { - let A = new Point(75, 75).attr("data-circle", 35); - let B = new Point(5, 5); - let C = new Point(10, 5); - let intersections = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections).to.equal(false); - }); + it('Should not find intersections of this line and circle', () => { + let A = new Point(75, 75).attr('data-circle', 35) + let B = new Point(5, 5) + let C = new Point(10, 5) + let intersections = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections).to.equal(false) + }) - it("Should not find intersections of this line and circle", () => { - let A = new Point(45, 45).attr("data-circle", 35); - let B = new Point(40, 40); - let C = new Point(52, 50); - let intersections = lineIntersectsCircle( - A, - A.attributes.get("data-circle"), - B, - C - ); - expect(intersections).to.equal(false); - }); + it('Should not find intersections of this line and circle', () => { + let A = new Point(45, 45).attr('data-circle', 35) + let B = new Point(40, 40) + let C = new Point(52, 50) + let intersections = lineIntersectsCircle(A, A.attributes.get('data-circle'), B, C) + expect(intersections).to.equal(false) + }) - it("Should find intersections between circles", () => { - let A = new Point(10, 10).attr("data-circle", 15); - let B = new Point(30, 30).attr("data-circle", 35); + it('Should find intersections between circles', () => { + let A = new Point(10, 10).attr('data-circle', 15) + let B = new Point(30, 30).attr('data-circle', 35) let intersections1 = circlesIntersect( A, - A.attributes.get("data-circle"), + A.attributes.get('data-circle'), B, - B.attributes.get("data-circle") - ); + B.attributes.get('data-circle') + ) let intersections2 = circlesIntersect( A, - A.attributes.get("data-circle"), + A.attributes.get('data-circle'), B, - B.attributes.get("data-circle"), - "y" - ); - expect(intersections1.length).to.equal(2); - expect(intersections2.length).to.equal(2); - expect(round(intersections1[0].x)).to.equal(-2.81); - expect(round(intersections1[0].y)).to.equal(17.81); - expect(round(intersections1[1].x)).to.equal(17.81); - expect(round(intersections1[1].y)).to.equal(-2.81); - expect(round(intersections2[0].x)).to.equal(17.81); - expect(round(intersections2[0].y)).to.equal(-2.81); - expect(round(intersections2[1].x)).to.equal(-2.81); - expect(round(intersections2[1].y)).to.equal(17.81); - }); + B.attributes.get('data-circle'), + 'y' + ) + expect(intersections1.length).to.equal(2) + expect(intersections2.length).to.equal(2) + expect(round(intersections1[0].x)).to.equal(-2.81) + expect(round(intersections1[0].y)).to.equal(17.81) + expect(round(intersections1[1].x)).to.equal(17.81) + expect(round(intersections1[1].y)).to.equal(-2.81) + expect(round(intersections2[0].x)).to.equal(17.81) + expect(round(intersections2[0].y)).to.equal(-2.81) + expect(round(intersections2[1].x)).to.equal(-2.81) + expect(round(intersections2[1].y)).to.equal(17.81) + }) - it("Should not find intersections between non-overlapping circles", () => { - let A = new Point(10, 10).attr("data-circle", 15); - let B = new Point(90, 90).attr("data-circle", 35); + it('Should not find intersections between non-overlapping circles', () => { + let A = new Point(10, 10).attr('data-circle', 15) + let B = new Point(90, 90).attr('data-circle', 35) let intersections = circlesIntersect( A, - A.attributes.get("data-circle"), + A.attributes.get('data-circle'), B, - B.attributes.get("data-circle") - ); - expect(intersections).to.equal(false); - }); + B.attributes.get('data-circle') + ) + expect(intersections).to.equal(false) + }) - it("Should not find intersections between contained circles", () => { - let A = new Point(10, 10).attr("data-circle", 15); - let B = new Point(10, 10).attr("data-circle", 35); + it('Should not find intersections between contained circles', () => { + let A = new Point(10, 10).attr('data-circle', 15) + let B = new Point(10, 10).attr('data-circle', 35) let intersections = circlesIntersect( A, - A.attributes.get("data-circle"), + A.attributes.get('data-circle'), B, - B.attributes.get("data-circle") - ); - expect(intersections).to.equal(false); - }); + B.attributes.get('data-circle') + ) + expect(intersections).to.equal(false) + }) - it("Should not find intersections between identical circles", () => { - let A = new Point(10, 10).attr("data-circle", 35); - let B = new Point(10, 10).attr("data-circle", 35); + it('Should not find intersections between identical circles', () => { + let A = new Point(10, 10).attr('data-circle', 35) + let B = new Point(10, 10).attr('data-circle', 35) let intersections = circlesIntersect( A, - A.attributes.get("data-circle"), + A.attributes.get('data-circle'), B, - B.attributes.get("data-circle") - ); - expect(intersections).to.equal(false); - }); + B.attributes.get('data-circle') + ) + expect(intersections).to.equal(false) + }) - it("Should return scale for a given amount of stretch", () => { - expect(stretchToScale(0)).to.equal(1); - expect(stretchToScale(0.25)).to.equal(0.8); - }); + it('Should return scale for a given amount of stretch', () => { + expect(stretchToScale(0)).to.equal(1) + expect(stretchToScale(0.25)).to.equal(0.8) + }) - it("Should capitalize a string", () => { - expect(capitalize("test")).to.equal("Test"); - expect(capitalize("Freesewing")).to.equal("Freesewing"); - }); + it('Should capitalize a string', () => { + expect(capitalize('test')).to.equal('Test') + expect(capitalize('Freesewing')).to.equal('Freesewing') + }) - it("Should split a curve", () => { - let a = new Point(0, 0); - let b = new Point(50, 0); - let c = new Point(50, 100); - let d = new Point(100, 100); - let X = new Point(50, 50); - let [c1, c2] = splitCurve(a, b, c, d, X); - expect(round(c1.cp1.x)).to.equal(25); - expect(round(c1.cp1.y)).to.equal(0); - expect(round(c1.cp2.x)).to.equal(37.5); - expect(round(c1.cp2.y)).to.equal(25); - expect(round(c2.cp1.x)).to.equal(62.5); - expect(round(c2.cp1.y)).to.equal(75); - expect(round(c2.cp2.x)).to.equal(75); - expect(round(c2.cp2.y)).to.equal(100); - }); + it('Should split a curve', () => { + let a = new Point(0, 0) + let b = new Point(50, 0) + let c = new Point(50, 100) + let d = new Point(100, 100) + let X = new Point(50, 50) + let [c1, c2] = splitCurve(a, b, c, d, X) + expect(round(c1.cp1.x)).to.equal(25) + expect(round(c1.cp1.y)).to.equal(0) + expect(round(c1.cp2.x)).to.equal(37.5) + expect(round(c1.cp2.y)).to.equal(25) + expect(round(c2.cp1.x)).to.equal(62.5) + expect(round(c2.cp1.y)).to.equal(75) + expect(round(c2.cp2.x)).to.equal(75) + expect(round(c2.cp2.y)).to.equal(100) + }) - it("Should find where a curve intersects a given X-value", () => { - let a = new Point(0, 0); - let b = new Point(50, 0); - let c = new Point(50, 100); - let d = new Point(100, 100); - let i = curveIntersectsX(a, b, c, d, 30); - expect(round(i.x)).to.equal(30); - expect(round(i.y)).to.equal(16); - }); + it('Should find where a curve intersects a given X-value', () => { + let a = new Point(0, 0) + let b = new Point(50, 0) + let c = new Point(50, 100) + let d = new Point(100, 100) + let i = curveIntersectsX(a, b, c, d, 30) + expect(round(i.x)).to.equal(30) + expect(round(i.y)).to.equal(16) + }) - it("Should find where a curve intersects a given Y-value", () => { - let a = new Point(0, 0); - let b = new Point(50, 0); - let c = new Point(50, 100); - let d = new Point(100, 100); - let i = curveIntersectsY(a, b, c, d, 30); - expect(round(i.x)).to.equal(39.49); - expect(round(i.y)).to.equal(30); - }); + it('Should find where a curve intersects a given Y-value', () => { + let a = new Point(0, 0) + let b = new Point(50, 0) + let c = new Point(50, 100) + let d = new Point(100, 100) + let i = curveIntersectsY(a, b, c, d, 30) + expect(round(i.x)).to.equal(39.49) + expect(round(i.y)).to.equal(30) + }) // Recreate issue #1206 - it("Should find intersecting beams when a line is almost vertical", () => { - let a = new Point(225.72, 241); - let b = new Point(225.71999999999997, 600); - let i = beamIntersectsY(a, b, 400); - expect(round(i.y)).to.equal(400); - }); + it('Should find intersecting beams when a line is almost vertical', () => { + let a = new Point(225.72, 241) + let b = new Point(225.71999999999997, 600) + let i = beamIntersectsY(a, b, 400) + expect(round(i.y)).to.equal(400) + }) - it("Should check for valid coordinate", () => { - expect(isCoord(23423.23)).to.equal(true); - expect(isCoord(0)).to.equal(true); - expect(isCoord()).to.equal(false); - expect(isCoord(null)).to.equal(false); - expect(isCoord('hi')).to.equal(false); - expect(isCoord(NaN)).to.equal(false); - }); + it('Should check for valid coordinate', () => { + expect(isCoord(23423.23)).to.equal(true) + expect(isCoord(0)).to.equal(true) + expect(isCoord()).to.equal(false) + expect(isCoord(null)).to.equal(false) + expect(isCoord('hi')).to.equal(false) + expect(isCoord(NaN)).to.equal(false) + }) - it("Should return the correct sample style", () => { - expect(sampleStyle(0, 5)).to.equal("stroke: hsl(-66, 100%, 35%);") - expect(sampleStyle(1, 5)).to.equal("stroke: hsl(0, 100%, 35%);") - expect(sampleStyle(2, 5)).to.equal("stroke: hsl(66, 100%, 35%);") - expect(sampleStyle(3, 5)).to.equal("stroke: hsl(132, 100%, 35%);") - expect(sampleStyle(4, 5)).to.equal("stroke: hsl(198, 100%, 35%);") - }); + it('Should return the correct sample style', () => { + expect(sampleStyle(0, 5)).to.equal('stroke: hsl(-66, 100%, 35%);') + expect(sampleStyle(1, 5)).to.equal('stroke: hsl(0, 100%, 35%);') + expect(sampleStyle(2, 5)).to.equal('stroke: hsl(66, 100%, 35%);') + expect(sampleStyle(3, 5)).to.equal('stroke: hsl(132, 100%, 35%);') + expect(sampleStyle(4, 5)).to.equal('stroke: hsl(198, 100%, 35%);') + }) - it("Should return the correct sample styles", () => { + it('Should return the correct sample styles', () => { const styles = [ - "stroke: red;", - "stroke: blue;", - "stroke: green;", - "stroke: pink;", - "stroke: orange;", + 'stroke: red;', + 'stroke: blue;', + 'stroke: green;', + 'stroke: pink;', + 'stroke: orange;', ] - for (let i=0;i<5;i++) expect(sampleStyle(i, 5, styles)).to.equal(styles[i]) - }); + for (let i = 0; i < 5; i++) expect(sampleStyle(i, 5, styles)).to.equal(styles[i]) + }) - it("Should convert degrees to radians", () => { - expect(deg2rad(0)).to.equal(0); - expect(round(deg2rad(69))).to.equal(1.2); - }); + it('Should convert degrees to radians', () => { + expect(deg2rad(0)).to.equal(0) + expect(round(deg2rad(69))).to.equal(1.2) + }) - it("Should convert radians to degrees", () => { - expect(rad2deg(0)).to.equal(0); - expect(round(rad2deg(69))).to.equal(3953.41); - }); + it('Should convert radians to degrees', () => { + expect(rad2deg(0)).to.equal(0) + expect(round(rad2deg(69))).to.equal(3953.41) + }) - it("Should shoulder return two methods for pctBasedOn", () => { + it('Should shoulder return two methods for pctBasedOn', () => { const result = pctBasedOn('chest') - expect(typeof result.toAbs).to.equal("function"); - expect(typeof result.fromAbs).to.equal("function"); + 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 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 = generatePartTransform(30,60,90,true,true,part) - expect(transform.transform).to.equal(`translate(${30 + part.topLeft.x + part.bottomRight.x} ${60 + part.topLeft.y + part.bottomRight.y}) scale(-1 -1) rotate(90 ${part.topLeft.x + part.width/2} ${part.topLeft.y + part.height/2})`); - }); -}); - + }) + it('Should generate a part transform', () => { + let pattern = new 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 = generatePartTransform(30, 60, 90, true, true, part) + expect(transform.transform).to.equal( + `translate(${30 + part.topLeft.x + part.bottomRight.x} ${ + 60 + part.topLeft.y + part.bottomRight.y + }) scale(-1 -1) rotate(90 ${part.topLeft.x + part.width / 2} ${ + part.topLeft.y + part.height / 2 + })` + ) + }) +})