From 55e5dc3d0c657047e772ec4916edfceef96f1a41 Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Wed, 7 Sep 2022 21:16:44 +0200 Subject: [PATCH] feat(plugin-cutlist): New plugin to manage cutlist This also removed the cutlist-related functionality that was added to core as an early v3 feature. --- config/software/plugins.json | 1 + packages/core/src/part.mjs | 56 ---- packages/core/tests/part.test.mjs | 126 -------- plugins/plugin-cutlist/CHANGELOG.md | 9 + plugins/plugin-cutlist/README.md | 287 +++++++++++++++++++ plugins/plugin-cutlist/build.mjs | 50 ++++ plugins/plugin-cutlist/data.mjs | 4 + plugins/plugin-cutlist/package.json | 65 +++++ plugins/plugin-cutlist/src/index.mjs | 71 +++++ plugins/plugin-cutlist/tests/plugin.test.mjs | 170 +++++++++++ plugins/plugin-cutlist/tests/shared.test.mjs | 7 + 11 files changed, 664 insertions(+), 182 deletions(-) create mode 100644 plugins/plugin-cutlist/CHANGELOG.md create mode 100644 plugins/plugin-cutlist/README.md create mode 100644 plugins/plugin-cutlist/build.mjs create mode 100644 plugins/plugin-cutlist/data.mjs create mode 100644 plugins/plugin-cutlist/package.json create mode 100644 plugins/plugin-cutlist/src/index.mjs create mode 100644 plugins/plugin-cutlist/tests/plugin.test.mjs create mode 100644 plugins/plugin-cutlist/tests/shared.test.mjs diff --git a/config/software/plugins.json b/config/software/plugins.json index 202ab1dbb30..267d4ce7eb1 100644 --- a/config/software/plugins.json +++ b/config/software/plugins.json @@ -4,6 +4,7 @@ "plugin-bundle": "An umbrella package of 8 essential FreeSewing build-time plugins", "plugin-bust": "A FreeSewing plugin that helps with bust-adjusting menswear patterns", "plugin-buttons": "A FreeSewing plugin that provides button, buttonhole, and snap snippets", + "plugin-cutlist": "A FreeSewing plugin to store data regarding a pattern's cutlist", "plugin-cutonfold": "A FreeSewing plugin to add cut-on-fold indicators on your patterns", "plugin-dimension": "A FreeSewing plugin to add dimensions to your (paperless) pattern", "plugin-flip": "A FreeSewing plugin to flip parts horizontally", diff --git a/packages/core/src/part.mjs b/packages/core/src/part.mjs index 212235ffaba..c3693cc1be3 100644 --- a/packages/core/src/part.mjs +++ b/packages/core/src/part.mjs @@ -354,62 +354,6 @@ Part.prototype.generateTransform = function(transforms) { } } -/** Chainable way to add the cut info */ -Part.prototype.addCut = function (cut=2, material='fabric', identical=false) { - if (cut === false) { - if (this.cut.materials[material]) delete this.cut.materials[material] - else this.context.raise.warning(`Tried to remove a material that is not set`) - return this - } - if (typeof this.cut.materials[material] === 'undefined') this.cut.materials[material] = {} - if (!(Number.isInteger(cut) && cut > -1)) { - this.context.raise.error(`Tried to set cut to a value that is not a positive integer`) - return this - } - if (typeof material !== 'string') { - this.context.raise.warning(`Tried to set material to a value that is not a string`) - return this - } - this.cut.materials[material].cut = cut - this.cut.materials[material].identical = identical - - return this -} - -/** Chainable way to remove (some) cut info */ -Part.prototype.removeCut = function (material=false) { - return this.addCut(false, material) -} - -/** Chainable way to add the grain info */ -Part.prototype.setGrain = function (grain=false) { - if (grain === false) { - this.cut.grain = false - return this - } - if (typeof grain !== 'number') { - this.context.raise.error('Called part.setGrain() with a value that is not a number') - return this - } - this.cut.grain = grain - - return this -} - -/** Chainable way to add the cutOnFold info */ -Part.prototype.setCutOnFold = function (p1, p2) { - if (p1 === false && typeof p2 === 'undefined') { - delete this.cut.cutOnFold - return this - } - if (p1 instanceof Point && p2 instanceof Point) { - this.cut.cutOnFold = [p1, p2] - } - else this.context.raise.error('Called part.setCutOnFold() but at least one parameter is not a Point instance') - - return this -} - Part.prototype.isEmpty = function() { if (Object.keys(this.snippets).length > 0) return false diff --git a/packages/core/tests/part.test.mjs b/packages/core/tests/part.test.mjs index 7fe51cfec79..f39d9bdc6f8 100644 --- a/packages/core/tests/part.test.mjs +++ b/packages/core/tests/part.test.mjs @@ -276,132 +276,6 @@ describe('Part', () => { expect(part.attributes.list.transform[0]).to.equal('translate(10 20)') }); - - it("Should add the part cut", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - expect(part.cut.materials.fabric.cut).to.equal(4) - expect(part.cut.materials.fabric.identical).to.equal(true) - part.addCut() - expect(part.cut.materials.fabric.cut).to.equal(2) - expect(part.cut.materials.fabric.identical).to.equal(false) - }); - - it("Should generate an error if cut is not a number", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut('a', 'fabric', true) - expect(pattern.events.error.length).to.equal(1) - expect(pattern.events.error[0]).to.equal('Tried to set cut to a value that is not a positive integer') - }); - - it("Should generate an warning if material is not a string", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(3, 4) - expect(pattern.events.warning.length).to.equal(1) - expect(pattern.events.warning[0]).to.equal('Tried to set material to a value that is not a string') - }); - - it("Should generate an error when removing a material that is not set (through addCut)", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - part.addCut(false, 'lining') - expect(pattern.events.warning.length).to.equal(1) - expect(pattern.events.warning[0]).to.equal('Tried to remove a material that is not set') - }); - - it("Should remove the part cut through addCut", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - part.addCut(false, 'fabric') - expect(typeof part.cut.materials.fabric).to.equal('undefined') - }); - - it("Should remove the part cut through removeCut", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - part.removeCut('fabric') - expect(typeof part.cut.materials.fabric).to.equal('undefined') - }); - - it("Should generate an error when removing a material that is not set (through removeCut)", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - part.removeCut('lining') - expect(pattern.events.warning.length).to.equal(1) - expect(pattern.events.warning[0]).to.equal('Tried to remove a material that is not set') - }); - - it("Should generate an error when removing a material that is not a string (through removeCut)", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - part.removeCut(23) - expect(pattern.events.warning.length).to.equal(1) - expect(pattern.events.warning[0]).to.equal('Tried to remove a material that is not set') - }); - - it("Should generate a warning when calling removeCut without parameters", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.addCut(4, 'fabric', true) - part.removeCut() - expect(pattern.events.warning.length).to.equal(1) - expect(pattern.events.warning[0]).to.equal('Tried to remove a material that is not set') - }); - - it("Should set the part grainline", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - expect(part.cut.grain).to.equal(90) - part.setGrain(123) - expect(part.cut.grain).to.equal(123) - }); - - it("Should raise a warning when calling part.setGrain() without any parameters", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.setGrain() - expect(part.cut.grain).to.equal(false) - }); - - it("Should raise an error when calling part.setGrain() with a value that is not a number", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - part.setGrain('a') - expect(part.cut.grain).to.equal(90) - expect(pattern.events.error.length).to.equal(1) - expect(pattern.events.error[0]).to.equal('Called part.setGrain() with a value that is not a number') - }); - - it("Should set and then remove the cutOnFold", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const { Point } = part.shorthand() - part.setCutOnFold(new Point(2,3), new Point(100,200)) - expect(part.cut.cutOnFold[0].x).to.equal(2) - expect(part.cut.cutOnFold[0].y).to.equal(3) - expect(part.cut.cutOnFold[1].x).to.equal(100) - expect(part.cut.cutOnFold[1].y).to.equal(200) - part.setCutOnFold(false) - expect(typeof part.cut.cutOnFold).to.equal('undefined') - }); - - it("Should raise an error when setting the cutOnFold with a non-Point value", () => { - let pattern = new Pattern(); - let part = new pattern.Part(); - const { Point } = part.shorthand() - part.setCutOnFold(new Point(2,3), 12) - expect(pattern.events.error.length).to.equal(1) - expect(pattern.events.error[0]).to.equal('Called part.setCutOnFold() but at least one parameter is not a Point instance') - }); - describe('isEmpty', () => { it("Should return true if the part has no paths or snippets", () => { let pattern = new Pattern(); diff --git a/plugins/plugin-cutlist/CHANGELOG.md b/plugins/plugin-cutlist/CHANGELOG.md new file mode 100644 index 00000000000..ab19f198610 --- /dev/null +++ b/plugins/plugin-cutlist/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change log for: @freesewing/plugin-cutlist + + + +This is the **initial release**, and the start of this change log. + +> Prior to version 2, FreeSewing was not a JavaScript project. +> As such, that history is out of scope for this change log. + diff --git a/plugins/plugin-cutlist/README.md b/plugins/plugin-cutlist/README.md new file mode 100644 index 00000000000..4ca4339fd03 --- /dev/null +++ b/plugins/plugin-cutlist/README.md @@ -0,0 +1,287 @@ +![FreeSewing](https://static.freesewing.org/banner.png) +

@freesewing/plugin-cutlist on NPM + License: MIT + Code quality on DeepScan + Open issues tagged pkg:plugin-cutlist + All Contributors +

Follow @freesewing_org on Twitter + Chat with us on Discord + Become a FreeSewing Patron + Follow @freesewing_org on Twitter +

+ +# @freesewing/plugin-cutlist + +A FreeSewing plugin to store a pattern's cutlist + + + + +> #### Note: Version 3 is a work in progress +> +> We are working on a new major version (v3) but it is not ready for prime-time. +> For production use, please refer to our v2 packages (the `latest` on NPM) +> or [the `v2` branch in our monorepo](https://github.com/freesewing/freesewing/tree/v2). + +## What am I looking at? πŸ€” + +This repository is our *monorepo* holding all our NPM designs, plugins, other NPM packages, and (web)sites. + +This folder holds: @freesewing/plugin-cutlist + +If you're not entirely sure what to do or how to start, type this command: + +``` +npm run tips +``` + +> If you don't want to set up a dev environment, you can run it in your browser: +> +> [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/freesewing/freesewing) +> +> We recommend that you fork our repository and then +> put `gitpod.io/# to start up a browser-based dev environment of your own. + +## About FreeSewing πŸ’€ + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate +our sewing patterns adapted to your measurements. + +If you're a developer, our documentation is on [freesewing.dev](https://freesewing.dev/). +Our [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox +for parametric design of sewing patterns. But we also provide a range +of [plugins](https://freesewing.dev/reference/plugins/) that further extend the +functionality of the platform. + +If you have NodeJS installed, you can try it right now by running: + +```bash +npx create-freesewing-pattern +``` + +Or, consult our getting started guides +for [Linux](https://freesewing.dev/tutorials/getting-started-linux/), +[MacOS](https://freesewing.dev/tutorials/getting-started-mac/), +or [Windows](https://freesewing.dev/tutorials/getting-started-windows/). + +We also have a [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) that +walks you through your first parametric design, +and [a friendly community](https://freesewing.org/community/where/) with +people who can help you when you get stuck. + +## Support FreeSewing: Become a patron πŸ₯° + +FreeSewing is an open source project run by a community, +and financially supported by our patrons. + +If you feel what we do is worthwhile, and you can spend a few coind without +hardship, then you should [join us and become a patron](https://freesewing.org/community/join). + +## Links πŸ‘©β€πŸ’» + + - πŸ’» Makers website: [freesewing.org](https://freesewing.org) + - πŸ’» Developers website: [freesewing.dev](https://freesewing.dev) + - πŸ’¬ Chat: On Discord via [discord.freesewing.org](https://discord.freesewing.org/) + - βœ… Todo list/Kanban board: On Github via [todo.freesewing.org](https://todo.freesewing.org/) + - 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org) + - πŸ“· Instagram: [@freesewing_org](https://instagram.com/freesewing_org) + +## License: MIT πŸ€“ + +Β© [Joost De Cock](https://github.com/joostdecock). +See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details. + +## Where to get help 🀯 + +Our [chatrooms on Discord](https://chat.freesewing.org/) are the best place to ask questions, +share your feedback, or just hang out. + +If you want to report a problem, please [create an issue](https://github.com/freesewing/freesewing/issues/new). + + + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Adam Tomkins

πŸ“–

Alexandre Ignjatovic

πŸ’»

AlfaLyr

πŸ’» πŸ”Œ 🎨

Andrew James

πŸ“–

Anneke

πŸ“– 🌍

Annie Kao

πŸ“–

Anternative

πŸ“–

Anthony

πŸ’¬

Ari Grayzel-student

πŸ’»

Bart

πŸ“–

BenJamesBen

πŸ’» πŸ“–

Cameron Dubas

πŸ“–

Carsten Biebricher

πŸ“–

Cathy Zoller

πŸ“–

Chantal Lapointe

🌍

Damien PIQUET

πŸ’»

Darigov Research

πŸ“– πŸ€”

Elena FdR

πŸ“– πŸ“

Emmanuel Nyachoke

πŸ’» πŸ“–

Enoch Riese

πŸ’»

EvEkSwed

🌍

Fantastik-Maman

🌍

Forrest O.

πŸ“–

FrΓ©dΓ©ric

🌍

Glenn Matthews

πŸ“–

Greg Sadetsky

πŸ“–

Igor Couto

πŸ›

Ikko Ashimine

πŸ“–

Irapeke

🌍

Jacek Sawoszczuk

πŸ“–

Jason Williams

πŸ“–

Jeremy Jackson

πŸ’»

Joe Schofield

πŸ“–

Joebidido

🌍

Joost De Cock

🚧

Josh Essman

πŸ“–

Kake

πŸ“–

Kapunahele Wong

πŸ“–

Karen

πŸ“– πŸ“‹

Katie McGinley

πŸ“–

Kieran Klaassen

πŸ’»

Kittycatou

🌍

Kris

πŸ“–

Kristin Ruben

πŸ’»

Loudepeuter

🌍

Lucian

πŸ“‹

Marcus

🌍

Martin Tribo

πŸ“–

Nadege Michel

⚠️ πŸ“–

Natalia

πŸ’» 🎨 πŸ“

Nathan Yergler

πŸ“–

Nick Dower

πŸ“– πŸ’» πŸ›

Nikhil Chelliah

πŸ“–

OysteinHoiby

πŸ’»

Patrick Forringer

πŸ”Œ

Paul

πŸ“– πŸ“ 🌍

Phillip Thelen

πŸ’»

Pixieish

πŸ“–

Prof. dr. Sorcha NΓ­ Dhubhghaill

πŸ“–

Quentin FELIX

πŸ’» 🎨

Rik Hekker

πŸ›

Sam Livingston-Gray

πŸ“–

Sanne

πŸ’» πŸ“–

Sara Latorre

🌍

SeaZeeZee

πŸ“– πŸ’»

SimonbJohnson

πŸ›

Slylele

πŸ“– 🌍

Soazillon

🌍

SoneaTheBest

🌍

Stefan Sydow

🌍 πŸ“– πŸ’»

TrΓ­ona

πŸ“–

Unmutual

πŸ“–

Wouter van Wageningen

πŸ’» 🎨 πŸ”§

amysews

πŸ“–

anna-puk

πŸ’»

beautifulsummermoon

🌍

berce

πŸ“–

biou

πŸ’»

bobgeorgethe3rd

πŸ’» πŸ“– 🎨

brmlyklr

πŸ“–

chri5b

πŸ’» ⚠️

dingcycle

🌍

drowned-in-books

πŸ’¬

econo202

πŸ“–

ericamattos

🌍

fightingrabbit

πŸ’»

gaylyndie

πŸ“–

grimlokason

πŸ’»

hellgy

🎨

jackseye

πŸ“–

marckiesel

🌍

mesil

πŸ›

starfetch

πŸ’» πŸ“– 🌍 🎨

ttimearl

πŸ–‹

tuesgloomsday

πŸ“–

valadaptive

πŸ’»

viocky

🌍

woolishboy

πŸ’»

yc

🌍
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! + diff --git a/plugins/plugin-cutlist/build.mjs b/plugins/plugin-cutlist/build.mjs new file mode 100644 index 00000000000..c5581c1e4a2 --- /dev/null +++ b/plugins/plugin-cutlist/build.mjs @@ -0,0 +1,50 @@ +/* This script will build the package with esbuild */ +import esbuild from 'esbuild' +import pkg from './package.json' assert { type: 'json' } + +// Create banner based on package info +const banner = `/** + * ${pkg.name} | v${pkg.version} + * ${pkg.description} + * (c) ${new Date().getFullYear()} ${pkg.author} + * @license ${pkg.license} + */` + +// Shared esbuild options +const options = { + banner: { js: banner }, + bundle: true, + entryPoints: ['src/index.mjs'], + format: 'esm', + outfile: 'dist/index.mjs', + external: ["@freesewing"], + metafile: process.env.VERBOSE ? true : false, + minify: process.env.NO_MINIFY ? false : true, + sourcemap: true, +} + +// Let esbuild generate the build +let result +(async () => { + result = await esbuild.build(options).catch(() => process.exit(1)) + + if (process.env.VERBOSE) { + const info = await esbuild.analyzeMetafile(result.metafile) + console.log(info) + } + + // Also build a version that has all dependencies bundled + // This makes it easy to run tests + await esbuild + .build({ + ...options, + minify: false, + keepNames: true, + sourcemap: false, + outfile: 'tests/dist/index.mjs', + format: 'esm', + external: [], + }) + .catch(() => process.exit(1)) + +})() diff --git a/plugins/plugin-cutlist/data.mjs b/plugins/plugin-cutlist/data.mjs new file mode 100644 index 00000000000..9d228c3bd8d --- /dev/null +++ b/plugins/plugin-cutlist/data.mjs @@ -0,0 +1,4 @@ +// This file is auto-generated | All changes you make will be overwritten. +export const name = "@freesewing/plugin-cutlist" +export const version = "3.0.0-alpha.0" +export const data = { name, version } diff --git a/plugins/plugin-cutlist/package.json b/plugins/plugin-cutlist/package.json new file mode 100644 index 00000000000..a4d1a9300df --- /dev/null +++ b/plugins/plugin-cutlist/package.json @@ -0,0 +1,65 @@ +{ + "name": "@freesewing/plugin-cutlist", + "version": "3.0.0-alpha.0", + "description": "A FreeSewing plugin to store a pattern's cutlist", + "author": "Joost De Cock (https://github.com/joostdecock)", + "homepage": "https://freesewing.org/", + "repository": "github:freesewing/freesewing", + "license": "MIT", + "bugs": { + "url": "https://github.com/freesewing/freesewing/issues" + }, + "funding": { + "type": "individual", + "url": "https://freesewing.org/patrons/join" + }, + "keywords": [ + "freesewing", + "plugin", + "sewing pattern", + "sewing", + "design", + "parametric design", + "made to measure", + "diy", + "fashion" + ], + "type": "module", + "module": "dist/index.mjs", + "exports": { + ".": "./dist/index.mjs" + }, + "scripts": { + "build": "node build.mjs", + "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": "npx mocha tests/*.test.mjs", + "vbuild": "VERBOSE=1 node build.mjs", + "lab": "cd ../../sites/lab && yarn start", + "tips": "node ../../scripts/help.mjs", + "prettier": "npx prettier --write 'src/*.mjs' 'tests/*.mjs'", + "testci": "npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js", + "cibuild_step1": "node build.mjs" + }, + "peerDependencies": { + "@freesewing/core": "^3.0.0-alpha.0" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "^10.0.0", + "chai": "^4.2.0" + }, + "files": [ + "dist/*", + "README.md" + ], + "publishConfig": { + "access": "public", + "tag": "next" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8" + } +} diff --git a/plugins/plugin-cutlist/src/index.mjs b/plugins/plugin-cutlist/src/index.mjs new file mode 100644 index 00000000000..428fca79fb9 --- /dev/null +++ b/plugins/plugin-cutlist/src/index.mjs @@ -0,0 +1,71 @@ +import { name, version } from '../package.json' +import { Point } from '@freesewing/core' + +export const plugin = { + name, + version, + store: [ + ['addCut', addCut], + ['removeCut', removeCut], + ['setGrain', setGrain], + ['setCutOnFold', setCutOnFold], + ] +} + +// More specifically named exports +export const cutlistPlugin = plugin +export const pluginCutlist = plugin + +/** Method to add the cut info */ +function addCut(store, partName, cut=2, material='fabric', identical=false) { + if (cut === false) { + if (material === false) store.unset(['cutlist', partName, 'materials']) + else store.unset(['cutlist', partName, 'materials', material]) + return store + } + if (!(Number.isInteger(cut) && cut > -1)) { + store.log.error(`Tried to set cut to a value that is not a positive integer`) + return store + } + if (typeof material !== 'string') { + store.log.warning(`Tried to set material to a value that is not a string`) + return store + } + const path = ['cutlist', partName, 'materials', material] + store.set([...path, 'cut'], cut) + store.set([...path, 'identical'], identical) + + return store +} + +/** Method to remove the cut info */ +function removeCut(store, partName, material=false) { + return addCut(store, partName, false, material) +} + +/** Method to add the grain info */ +function setGrain(store, partName, grain=false) { + const path = ['cutlist', partName, 'grain'] + if (grain === false) return store.unset(path) + if (typeof grain !== 'number') { + store.log.error('Called part.setGrain() with a value that is not a number') + return store + } + return store.set(path, grain) + + return store +} + +/** Method to add the cutOnFold info */ +function setCutOnFold(store, partName, p1, p2) { + const path = ['cutlist', partName, 'cutOnFold'] + if (p1 === false && typeof p2 === 'undefined') { + return store.unset(path) + } + if (p1 instanceof Point && p2 instanceof Point) { + store.set(path, [p1, p2]) + } + else store.log.error('Called part.setCutOnFold() but at least one parameter is not a Point instance') + + return store +} diff --git a/plugins/plugin-cutlist/tests/plugin.test.mjs b/plugins/plugin-cutlist/tests/plugin.test.mjs new file mode 100644 index 00000000000..9ff7a086c86 --- /dev/null +++ b/plugins/plugin-cutlist/tests/plugin.test.mjs @@ -0,0 +1,170 @@ +import chai from 'chai' +import { Design, Point } from '@freesewing/core' +import { plugin } from '../dist/index.mjs' + +const expect = chai.expect + +describe('Cutlist Plugin Tests', () => { + + it("Should make methods available through part.shorthand()", () => { + let methods + const part = { + name: 'example_part', + draft: part => { + const { addCut, removeCut, setGrain, setCutOnFold } = part.shorthand() + methods = { addCut, removeCut, setGrain, setCutOnFold } + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(typeof methods.addCut).to.equal("function") + expect(typeof methods.removeCut).to.equal("function") + expect(typeof methods.setGrain).to.equal("function") + expect(typeof methods.setCutOnFold).to.equal("function") + }) + + it("Should handle addCut() with defaults", () => { + const part = { + name: 'example_part', + draft: part => { + const { addCut } = part.shorthand() + addCut() + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(pattern.store.cutlist.example_part.materials.fabric.cut).to.equal(2) + expect(pattern.store.cutlist.example_part.materials.fabric.identical).to.equal(false) + }) + + it("Should handle addCut() with non-defaults", () => { + const part = { + name: 'example_part', + draft: part => { + const { addCut } = part.shorthand() + addCut(3, 'lining', true) + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(pattern.store.cutlist.example_part.materials.lining.cut).to.equal(3) + expect(pattern.store.cutlist.example_part.materials.lining.identical).to.equal(true) + }) + + it("Should remove cut info via addCut(false)", () => { + const part = { + name: 'example_part', + draft: part => { + const { addCut } = part.shorthand() + addCut(2, 'fabric') + addCut(4, 'lining', true) + addCut(false, 'lining') + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(typeof pattern.store.cutlist.example_part.materials.lining).to.equal('undefined') + }) + + it("Should remove cut info for a material via removeCut()", () => { + const part = { + name: 'example_part', + draft: part => { + const { addCut, removeCut } = part.shorthand() + addCut(2, 'fabric') + addCut(4, 'lining', true) + removeCut('lining') + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(typeof pattern.store.cutlist.example_part.materials.lining).to.equal('undefined') + expect(pattern.store.cutlist.example_part.materials.fabric.cut).to.equal(2) + }) + + it("Should remove cut info for all materials via removeCut(true)", () => { + const part = { + name: 'example_part', + draft: part => { + const { addCut, removeCut } = part.shorthand() + addCut(2, 'fabric') + addCut(4, 'lining', true) + removeCut() + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(typeof pattern.store.cutlist.example_part.materials).to.equal('undefined') + }) + + it("Should set the grain via setGrain()", () => { + const part = { + name: 'example_part', + draft: part => { + const { setGrain } = part.shorthand() + setGrain(45) + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(pattern.store.cutlist.example_part.grain).to.equal(45) + }) + + it("Should remove the grain via setGrain(false)", () => { + const part = { + name: 'example_part', + draft: part => { + const { setGrain } = part.shorthand() + setGrain(45) + setGrain(false) + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(typeof pattern.store.cutlist.example_part.grain).to.equal('undefined') + }) + + it("Should set the cutOnFold via setCutOnFold(p1, p2)", () => { + const part = { + name: 'example_part', + draft: part => { + const { Point, setCutOnFold } = part.shorthand() + try { + setCutOnFold(new Point(2,2), new Point(200,200)) + } catch(err){ console.log(err)} + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(pattern.store.cutlist.example_part.cutOnFold[0].x).to.equal(2) + expect(pattern.store.cutlist.example_part.cutOnFold[0].y).to.equal(2) + expect(pattern.store.cutlist.example_part.cutOnFold[1].x).to.equal(200) + expect(pattern.store.cutlist.example_part.cutOnFold[1].y).to.equal(200) + }) + + it("Should removet the cutOnFold via setCutOnFold(false)", () => { + const part = { + name: 'example_part', + draft: part => { + const { Point, setCutOnFold } = part.shorthand() + try { + setCutOnFold(new Point(2,2), new Point(200,200)) + setCutOnFold(false) + } catch(err){ console.log(err)} + } + } + const Test = new Design({plugins: [plugin], parts: [ part ]}) + const pattern = new Test() + pattern.draft() + expect(typeof pattern.store.cutlist.example_part.cutOnFold).to.equal('undefined') + }) +}) diff --git a/plugins/plugin-cutlist/tests/shared.test.mjs b/plugins/plugin-cutlist/tests/shared.test.mjs new file mode 100644 index 00000000000..fdf846844b0 --- /dev/null +++ b/plugins/plugin-cutlist/tests/shared.test.mjs @@ -0,0 +1,7 @@ +// This file is auto-generated | Any changes you make will be overwritten. +import { plugin } from './dist/index.mjs' +import { sharedPluginTests } from '../../../tests/plugins/shared.mjs' + +// Run shared tests +sharedPluginTests(plugin) +