
Note that the tests for Lumina are failing, but that's not related to the chai upgrade, rather it seems these tests fail because of issues in the design that we'll tackle later (it's a brand new design yet to be released).
432 lines
13 KiB
JavaScript
432 lines
13 KiB
JavaScript
import { expect } from 'chai'
|
|
import { Design, Part, pctBasedOn } from '../src/index.mjs'
|
|
|
|
describe('Part', () => {
|
|
it('Shorthand should contain the part itself', () => {
|
|
let dp
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ part }) => {
|
|
dp = part
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(typeof dp).to.equal('object')
|
|
expect(typeof dp.context).to.equal('object')
|
|
})
|
|
|
|
it('Should return a function from __macroClosure', () => {
|
|
const part = new Part()
|
|
expect(typeof part.__macroClosure()).to.equal('function')
|
|
})
|
|
|
|
it('Should not run an unknown macro', () => {
|
|
const part = new Part()
|
|
const macro = part.__macroClosure()
|
|
expect(macro('unknown')).to.equal(undefined)
|
|
})
|
|
|
|
it('Should return a valid ID with Part.getId()', () => {
|
|
const part = new Part()
|
|
const id = part.getId()
|
|
const prefixed = part.getId('orange')
|
|
expect(id).to.equal('1')
|
|
expect(prefixed).to.equal('orange2')
|
|
})
|
|
|
|
it('Should register and run a macro', () => {
|
|
const plugin = {
|
|
name: 'test',
|
|
version: '0.1-test',
|
|
macros: {
|
|
test: function (so) {
|
|
let points = this.points
|
|
points.macro = new this.Point(so.x, so.y)
|
|
},
|
|
},
|
|
}
|
|
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] })
|
|
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)
|
|
})
|
|
|
|
it('Should return a free ID in draft method', () => {
|
|
let id = null
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ getId, part }) => {
|
|
id = getId()
|
|
id = getId()
|
|
id = getId()
|
|
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
new design().draft()
|
|
expect(id).to.equal('3')
|
|
})
|
|
|
|
it('Should return a function from __unitsClosure', () => {
|
|
const part = new Part()
|
|
expect(typeof part.__unitsClosure()).to.equal('function')
|
|
})
|
|
|
|
it('Should convert units', () => {
|
|
const part = new Part()
|
|
part.context = { settings: { units: 'metric' } }
|
|
const units = part.__unitsClosure()
|
|
expect(units(123.456)).to.equal('12.35cm')
|
|
expect(units(123.456)).to.equal('12.35cm')
|
|
})
|
|
|
|
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')
|
|
})
|
|
|
|
it('Should set part attributes', () => {
|
|
const part = new 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 log a warning when setting a non-Point value in points', () => {
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ points, part }) => {
|
|
points.a = 'banana'
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(pattern.setStores[0].logs.warn.length).to.equal(4)
|
|
expect(pattern.setStores[0].logs.warn[0]).to.equal(
|
|
'`points.a` was set with a value that is not a `Point` object'
|
|
)
|
|
expect(pattern.setStores[0].logs.warn[1]).to.equal(
|
|
'`points.a` was set with a `x` parameter that is not a `number`'
|
|
)
|
|
expect(pattern.setStores[0].logs.warn[2]).to.equal(
|
|
'`points.a` was set with a `y` parameter that is not a `number`'
|
|
)
|
|
})
|
|
|
|
it('Should log a warning when setting a non-Snippet value in snippets', () => {
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ snippets, part }) => {
|
|
snippets.a = 'banana'
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(pattern.setStores[0].logs.warn.length).to.equal(4)
|
|
expect(pattern.setStores[0].logs.warn[0]).to.equal(
|
|
'`snippets.a` was set with a value that is not a `Snippet` object'
|
|
)
|
|
expect(pattern.setStores[0].logs.warn[1]).to.equal(
|
|
'`snippets.a` was set with a `def` parameter that is not a `string`'
|
|
)
|
|
expect(pattern.setStores[0].logs.warn[2]).to.equal(
|
|
'`snippets.a` was set with an `anchor` parameter that is not a `Point`'
|
|
)
|
|
})
|
|
|
|
it('Should calculate the part boundary', () => {
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ points, Point, paths, Path, part }) => {
|
|
points.from = new Point(123, 456)
|
|
points.to = new Point(19, 76).attr('data-circle', 12)
|
|
|
|
paths.test = new Path().move(points.from).line(points.to)
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft().render()
|
|
const boundary = pattern.parts[0].test.__boundary()
|
|
const { topLeft, bottomRight, width, height } = boundary
|
|
expect(topLeft.x).to.equal(7)
|
|
expect(topLeft.y).to.equal(64)
|
|
// Cover the cached branch
|
|
pattern.parts[0].test.__boundary()
|
|
expect(bottomRight.x).to.equal(123)
|
|
expect(bottomRight.y).to.equal(456)
|
|
expect(width).to.equal(116)
|
|
expect(height).to.equal(392)
|
|
})
|
|
|
|
it('Units closure should log a warning when passing a non-number', () => {
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ units, part }) => {
|
|
units('a')
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
// Let's also cover the branch where complete is false
|
|
const pattern = new design({ complete: false })
|
|
pattern.draft()
|
|
expect(pattern.setStores[0].logs.warn.length).to.equal(1)
|
|
expect(pattern.setStores[0].logs.warn[0]).to.equal(
|
|
'Calling `units(value)` but `value` is not a number (`string`)'
|
|
)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
it('Draft method should receive the Snippet constructor', () => {
|
|
let method
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ Point, snippets, Snippet, part }) => {
|
|
method = Snippet
|
|
snippets.test = new Snippet('notch', new Point(19, 80))
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
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)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
it('Accessing unknown option should log a warning', () => {
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ options, part }) => {
|
|
if (options.test === 'This should never match') return null
|
|
else return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(pattern.setStores[0].logs.warn.length).to.equal(1)
|
|
expect(pattern.setStores[0].logs.warn[0]).to.equal(
|
|
'Tried to access `options.test` but it is `undefined`'
|
|
)
|
|
})
|
|
|
|
it('Accessing unknown absoluteOption should log a warning', () => {
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ absoluteOptions, part }) => {
|
|
if (absoluteOptions.test === 'this check should always fail') return null
|
|
else return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(pattern.setStores[0].logs.warn.length).to.equal(1)
|
|
expect(pattern.setStores[0].logs.warn[0]).to.equal(
|
|
'Tried to access `absoluteOptions.test` but it is `undefined`'
|
|
)
|
|
})
|
|
|
|
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)
|
|
})
|
|
|
|
it('Should set/unset the name of the active macro', () => {
|
|
const activeMacro = []
|
|
const plugin = {
|
|
name: 'testplugin',
|
|
version: '0.0.1',
|
|
macros: {
|
|
macro1: (config, { part, store }) => {
|
|
activeMacro.push(store.activeMacro)
|
|
return part
|
|
},
|
|
},
|
|
}
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ macro, part }) => {
|
|
activeMacro.push(part.activeMacro)
|
|
macro('macro1')
|
|
activeMacro.push(part.activeMacro)
|
|
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part], plugins: [plugin] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(activeMacro[0]).to.equal(undefined)
|
|
expect(activeMacro[1]).to.equal('macro1')
|
|
expect(activeMacro[2]).to.equal(undefined)
|
|
})
|
|
|
|
it('Should set/unset the name of the active macro in a nested macro', () => {
|
|
const activeMacro = []
|
|
const plugin = {
|
|
name: 'testplugin',
|
|
version: '0.0.1',
|
|
macros: {
|
|
macro1: (config, { macro, part, store }) => {
|
|
activeMacro.push(store.activeMacro)
|
|
macro('macro2')
|
|
activeMacro.push(store.activeMacro)
|
|
return part
|
|
},
|
|
macro2: (config, { part, store }) => {
|
|
activeMacro.push(store.activeMacro)
|
|
return part
|
|
},
|
|
},
|
|
}
|
|
const part = {
|
|
name: 'test',
|
|
draft: ({ macro, part }) => {
|
|
activeMacro.push(part.activeMacro)
|
|
macro('macro1')
|
|
activeMacro.push(part.activeMacro)
|
|
|
|
return part
|
|
},
|
|
}
|
|
const design = new Design({ parts: [part], plugins: [plugin] })
|
|
const pattern = new design()
|
|
pattern.draft()
|
|
expect(activeMacro[0]).to.equal(undefined)
|
|
expect(activeMacro[1]).to.equal('macro1')
|
|
expect(activeMacro[2]).to.equal('macro2')
|
|
expect(activeMacro[3]).to.equal('macro1')
|
|
expect(activeMacro[4]).to.equal(undefined)
|
|
})
|
|
})
|