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 + })` + ) + }) +})