2022-09-09 20:20:38 +02:00
|
|
|
import chai from 'chai'
|
2022-09-19 18:04:47 +02:00
|
|
|
import { Design, Part, pctBasedOn } from '../src/index.mjs'
|
2022-08-25 11:47:54 +02:00
|
|
|
|
|
|
|
const expect = chai.expect
|
2018-08-12 17:02:49 +02:00
|
|
|
|
2022-08-17 14:26:45 -05:00
|
|
|
describe('Part', () => {
|
2022-09-10 19:34:43 +02:00
|
|
|
it('Shorthand should contain the part itself', () => {
|
|
|
|
let dp
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ part }) => {
|
|
|
|
dp = part
|
|
|
|
return part
|
2022-09-11 18:00:41 +02:00
|
|
|
},
|
2022-09-10 19:34:43 +02:00
|
|
|
}
|
2022-09-11 18:00:41 +02:00
|
|
|
const design = new Design({ parts: [part] })
|
2022-09-10 19:34:43 +02:00
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
|
|
|
expect(typeof dp).to.equal('object')
|
|
|
|
expect(typeof dp.context).to.equal('object')
|
|
|
|
})
|
|
|
|
|
2022-09-18 15:11:10 +02:00
|
|
|
it('Should return a function from __macroClosure', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = new Part()
|
2022-09-18 15:11:10 +02:00
|
|
|
expect(typeof part.__macroClosure()).to.equal('function')
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-09 20:20:38 +02:00
|
|
|
it('Should not run an unknown macro', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = new Part()
|
2022-09-18 15:11:10 +02:00
|
|
|
const macro = part.__macroClosure()
|
2022-09-09 20:20:38 +02:00
|
|
|
expect(macro('unknown')).to.equal(undefined)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-09 20:20:38 +02:00
|
|
|
it('Should register and run a macro', () => {
|
2022-09-10 16:00:43 +02:00
|
|
|
const plugin = {
|
2022-09-09 20:20:38 +02:00
|
|
|
name: 'test',
|
|
|
|
version: '0.1-test',
|
2022-08-27 09:27:07 +02:00
|
|
|
macros: {
|
2022-09-09 20:20:38 +02:00
|
|
|
test: function (so) {
|
|
|
|
let points = this.points
|
|
|
|
points.macro = new this.Point(so.x, so.y)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2022-09-24 18:37:49 +02:00
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ part, Point, points, macro }) => {
|
|
|
|
points.example = new Point(12,34)
|
|
|
|
macro('test', { x: 123, y: 456 })
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
plugins: plugin,
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
2022-09-17 10:28:01 +02:00
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
|
|
|
expect(pattern.parts[0].test.points.macro.x).to.equal(123)
|
|
|
|
expect(pattern.parts[0].test.points.macro.y).to.equal(456)
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-09 20:20:38 +02:00
|
|
|
it('Should return a free ID', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = new Part()
|
2022-09-10 16:00:43 +02:00
|
|
|
const free = part.getId()
|
2022-09-09 20:20:38 +02:00
|
|
|
expect(part.getId()).to.equal('' + (parseInt(free) + 1))
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-18 15:11:10 +02:00
|
|
|
it('Should return a function from __unitsClosure', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = new Part()
|
2022-09-18 15:11:10 +02:00
|
|
|
expect(typeof part.__unitsClosure()).to.equal('function')
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-09 20:20:38 +02:00
|
|
|
it('Should convert units', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = new Part()
|
|
|
|
part.context = { settings: { units: 'metric' } }
|
2022-09-18 15:11:10 +02:00
|
|
|
const units = part.__unitsClosure()
|
2022-09-09 20:20:38 +02:00
|
|
|
expect(units(123.456)).to.equal('12.35cm')
|
2022-09-17 10:28:01 +02:00
|
|
|
expect(units(123.456)).to.equal('12.35cm')
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Should convert units directly', () => {
|
|
|
|
const part = new Part()
|
|
|
|
part.context = { settings: { units: 'metric' } }
|
|
|
|
expect(part.units(123.456)).to.equal('12.35cm')
|
|
|
|
expect(part.units(123.456)).to.equal('12.35cm')
|
|
|
|
})
|
|
|
|
|
2022-09-09 20:20:38 +02:00
|
|
|
it('Should set part attributes', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = new Part()
|
2022-09-09 20:20:38 +02:00
|
|
|
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')
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-24 18:37:49 +02:00
|
|
|
it('Should log a warning when setting a non-Point value in points', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ points, part }) => {
|
|
|
|
points.a = 'banana'
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
2022-09-10 16:00:43 +02:00
|
|
|
const pattern = new design()
|
2022-09-17 10:28:01 +02:00
|
|
|
pattern.draft()
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning.length).to.equal(4)
|
|
|
|
expect(pattern.setStores[0].logs.warning[0]).to.equal(
|
2022-09-09 20:20:38 +02:00
|
|
|
'`points.a` was set with a value that is not a `Point` object'
|
|
|
|
)
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning[1]).to.equal(
|
2022-09-09 20:20:38 +02:00
|
|
|
'`points.a` was set with a `x` parameter that is not a `number`'
|
|
|
|
)
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning[2]).to.equal(
|
2022-09-09 20:20:38 +02:00
|
|
|
'`points.a` was set with a `y` parameter that is not a `number`'
|
|
|
|
)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-24 18:37:49 +02:00
|
|
|
it('Should log a warning when setting a non-Snippet value in snippets', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ snippets, part }) => {
|
|
|
|
snippets.a = 'banana'
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
2022-09-10 16:00:43 +02:00
|
|
|
const pattern = new design()
|
2022-09-17 10:28:01 +02:00
|
|
|
pattern.draft()
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning.length).to.equal(4)
|
|
|
|
expect(pattern.setStores[0].logs.warning[0]).to.equal(
|
2022-09-09 20:20:38 +02:00
|
|
|
'`snippets.a` was set with a value that is not a `Snippet` object'
|
|
|
|
)
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning[1]).to.equal(
|
2022-09-09 20:20:38 +02:00
|
|
|
'`snippets.a` was set with a `def` parameter that is not a `string`'
|
|
|
|
)
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning[2]).to.equal(
|
2022-09-09 20:20:38 +02:00
|
|
|
'`snippets.a` was set with an `anchor` parameter that is not a `Point`'
|
|
|
|
)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-14 12:24:09 +02:00
|
|
|
it('Should calculate the part boundary', () => {
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ points, Point, paths, Path, part }) => {
|
|
|
|
points.from = new Point(123, 456)
|
2022-09-19 18:04:47 +02:00
|
|
|
points.to = new Point(19, 76).attr('data-circle', 12)
|
|
|
|
|
2022-09-17 10:28:01 +02:00
|
|
|
paths.test = new Path().move(points.from).line(points.to)
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
2022-09-10 16:00:43 +02:00
|
|
|
const pattern = new design()
|
2022-09-19 18:04:47 +02:00
|
|
|
pattern.draft().render()
|
2022-09-18 15:11:10 +02:00
|
|
|
const boundary = pattern.parts[0].test.__boundary()
|
2022-09-17 10:28:01 +02:00
|
|
|
const { topLeft, bottomRight, width, height } = boundary
|
2022-09-19 18:04:47 +02:00
|
|
|
expect(topLeft.x).to.equal(7)
|
|
|
|
expect(topLeft.y).to.equal(64)
|
|
|
|
// Cover the cached branch
|
|
|
|
pattern.parts[0].test.__boundary()
|
2022-09-17 10:28:01 +02:00
|
|
|
expect(bottomRight.x).to.equal(123)
|
|
|
|
expect(bottomRight.y).to.equal(456)
|
2022-09-19 18:04:47 +02:00
|
|
|
expect(width).to.equal(116)
|
|
|
|
expect(height).to.equal(392)
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Units closure should log a warning when passing a non-number', () => {
|
2022-09-10 16:00:43 +02:00
|
|
|
const part = {
|
|
|
|
name: 'test',
|
2022-09-19 18:04:47 +02:00
|
|
|
draft: ({ units, part }) => {
|
|
|
|
units('a')
|
|
|
|
return part
|
|
|
|
},
|
2022-09-10 16:00:43 +02:00
|
|
|
}
|
2022-09-19 18:04:47 +02:00
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
// Let's also cover the branch where complete is false
|
|
|
|
const pattern = new design({ complete: false} )
|
2022-09-10 16:00:43 +02:00
|
|
|
pattern.draft()
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning.length).to.equal(1)
|
|
|
|
expect(pattern.setStores[0].logs.warning[0]).to.equal(
|
2022-09-19 18:04:47 +02:00
|
|
|
'Calling `units(value)` but `value` is not a number (`string`)'
|
|
|
|
)
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Should (un)hide a part with hide()/unhide()', () => {
|
|
|
|
const part = new Part()
|
|
|
|
expect(part.hidden).to.equal(false)
|
|
|
|
part.hide()
|
|
|
|
expect(part.hidden).to.equal(true)
|
|
|
|
part.unhide()
|
|
|
|
expect(part.hidden).to.equal(false)
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-09-19 18:04:47 +02:00
|
|
|
|
|
|
|
it('Should (un)hide a part with setHidden()', () => {
|
|
|
|
const part = new Part()
|
|
|
|
expect(part.hidden).to.equal(false)
|
|
|
|
part.setHidden(true)
|
|
|
|
expect(part.hidden).to.equal(true)
|
|
|
|
part.setHidden(false)
|
|
|
|
expect(part.hidden).to.equal(false)
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Draft method should receive the Snippet constructor', () => {
|
|
|
|
let method
|
2022-09-17 10:28:01 +02:00
|
|
|
const part = {
|
|
|
|
name: 'test',
|
2022-09-19 18:04:47 +02:00
|
|
|
draft: ({ Point, snippets, Snippet, part }) => {
|
|
|
|
method = Snippet
|
|
|
|
snippets.test = new Snippet('notch', new Point(19,80))
|
2022-09-17 10:28:01 +02:00
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
2022-09-19 18:04:47 +02:00
|
|
|
expect(typeof method).to.equal('function')
|
|
|
|
expect(pattern.parts[0].test.snippets.test.def).to.equal('notch')
|
|
|
|
expect(pattern.parts[0].test.snippets.test.name).to.equal('test')
|
|
|
|
expect(pattern.parts[0].test.snippets.test.anchor.x).to.equal(19)
|
|
|
|
expect(pattern.parts[0].test.snippets.test.anchor.y).to.equal(80)
|
2022-09-09 20:20:38 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Measurments proxy should allow setting a measurement', () => {
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ measurements, part }) => {
|
|
|
|
measurements.head = 120
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
|
|
|
expect(pattern.settings[0].measurements.head).to.equal(120)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Options proxy should allow setting an option', () => {
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ options, part }) => {
|
|
|
|
options.test = 120
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
|
|
|
expect(pattern.settings[0].options.test).to.equal(120)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('AbsoluteOptions proxy should allow setting an absoluteOption', () => {
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ absoluteOptions, part }) => {
|
|
|
|
absoluteOptions.test = 120
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
|
|
|
expect(pattern.settings[0].absoluteOptions.test).to.equal(120)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Snapped percentage options should be available to the draft method', () => {
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
options: {
|
|
|
|
test: { pct: 10, min: 5, max: 25, snap: 5, ...pctBasedOn('head') }
|
|
|
|
},
|
|
|
|
draft: ({ paths, Path, Point, absoluteOptions, part }) => {
|
|
|
|
paths.test = new Path()
|
|
|
|
.move(new Point(0,0))
|
|
|
|
.line(new Point(absoluteOptions.test, 0))
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design({ measurements: { head: 200 } })
|
|
|
|
pattern.draft()
|
|
|
|
expect(pattern.parts[0].test.paths.test.ops[1].to.x).to.equal(20)
|
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Accessing unknown option should log a warning', () => {
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ options, part }) => {
|
|
|
|
if (options.test || true) return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning.length).to.equal(1)
|
|
|
|
expect(pattern.setStores[0].logs.warning[0]).to.equal('Tried to access `options.test` but it is `undefined`')
|
2022-09-19 18:04:47 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Accessing unknown absoluteOption should log a warning', () => {
|
|
|
|
const part = {
|
|
|
|
name: 'test',
|
|
|
|
draft: ({ absoluteOptions, part }) => {
|
|
|
|
if (absoluteOptions.test || true) return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [part] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
2022-09-24 18:37:49 +02:00
|
|
|
expect(pattern.setStores[0].logs.warning.length).to.equal(1)
|
|
|
|
expect(pattern.setStores[0].logs.warning[0]).to.equal('Tried to access `absoluteOptions.test` but it is `undefined`')
|
2022-09-19 18:04:47 +02:00
|
|
|
})
|
2022-08-27 09:27:07 +02:00
|
|
|
|
2022-09-19 18:04:47 +02:00
|
|
|
it('Injecting a part should contain all data', () => {
|
|
|
|
const from = {
|
|
|
|
name: 'from',
|
|
|
|
draft: ({ points, Point, paths, Path, snippets, Snippet, part }) => {
|
|
|
|
points.from = new Point(0,0)
|
|
|
|
points.to = new Point(19,80)
|
|
|
|
points.start = new Point(100,100)
|
|
|
|
points.cp1 = new Point(100,200)
|
|
|
|
points.cp2 = new Point(200,100)
|
|
|
|
points.end = new Point(200,200)
|
|
|
|
paths.line = new Path().move(points.from).line(points.to)
|
|
|
|
paths.curve = new Path().move(points.start).curve(points.cp1, points.cp2, points.end)
|
|
|
|
snippets.test = new Snippet('notch', points.end)
|
|
|
|
return part
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const to = {
|
|
|
|
from,
|
|
|
|
name: 'to',
|
|
|
|
draft: ({ part }) => part
|
|
|
|
}
|
|
|
|
const design = new Design({ parts: [from, to] })
|
|
|
|
const pattern = new design()
|
|
|
|
pattern.draft()
|
|
|
|
expect(pattern.parts[0].to.points.to.x).to.equal(19)
|
|
|
|
expect(pattern.parts[0].to.points.to.y).to.equal(80)
|
|
|
|
expect(typeof pattern.parts[0].to.paths.line).to.equal('object')
|
|
|
|
expect(pattern.parts[0].to.paths.curve.ops[1].cp2.x).to.equal(200)
|
2022-08-24 13:36:19 -05:00
|
|
|
})
|
2022-08-17 14:26:45 -05:00
|
|
|
})
|