node-gerber-parser
Version:
Streaming Gerber/drill file parser
955 lines (817 loc) • 28.3 kB
JavaScript
// test suite for the top level gerber parser class
// test subset - parsing gerber files
var expect = require('chai').expect
var partial = require('lodash/partial')
var parser = require('..')
describe('gerber parser with gerber files', function() {
var p
var pFactory = partial(parser, {filetype: 'gerber'})
// convenience function to expect an array of results
var expectResults = function(expected, done) {
var handleData = function(res) {
expect(res).to.eql(expected.shift())
if (!expected.length) {
return done()
}
}
p.on('data', handleData)
}
beforeEach(function() {
p = pFactory()
})
afterEach(function() {
p.removeAllListeners('data')
p.removeAllListeners('warning')
p.removeAllListeners('error')
})
it('should do nothing with comments', function(done) {
p.once('data', function() {
p.removeAllListeners('warning').removeAllListeners('error')
throw new Error('should not have emitted from comments')
})
p.once('warning', function() {
p.removeAllListeners('data').removeAllListeners('error')
throw new Error('should not have warned from comments')
})
p.once('error', function() {
p.removeAllListeners('warning').removeAllListeners('data')
throw new Error('should not have errored from comments')
})
p.write('G04 MOIN*')
p.write('G04 this is a comment*')
p.write('G04 D03*')
p.write('G04 D02*')
p.write('G04 G36*')
p.write('G04 M02*')
setTimeout(done, 1)
})
it('should do nothing with "empty" blocks', function(done) {
p.once('data', function() {
p.removeAllListeners('warning').removeAllListeners('error')
throw new Error('should not have emitted from empty block')
})
p.once('warning', function() {
p.removeAllListeners('data').removeAllListeners('error')
throw new Error('should not have warned from empty block')
})
p.once('error', function() {
p.removeAllListeners('warning').removeAllListeners('data')
throw new Error('should not have errored from empty block')
})
p.write('*\n')
p.write('\n')
p.write('')
p.write('\n\n\n')
setTimeout(done, 1)
})
it('should warn if a block is unhandled', function(done) {
p.once('warning', function(w) {
expect(w.line).to.equal(0)
expect(w.message).to.match(/not recognized/)
done()
})
p.write('foobarbaz*\n')
})
it('should handle split blocks', function(done) {
p.once('data', function() {
p.removeAllListeners('warning').removeAllListeners('error')
throw new Error('should not have emitted from split comment')
})
p.once('warning', function() {
p.removeAllListeners('data').removeAllListeners('error')
throw new Error('should not have warned from split comment')
})
p.once('error', function() {
p.removeAllListeners('warning').removeAllListeners('data')
throw new Error('should not have errored from split comment')
})
p.write('G04 thi')
p.write('s is a comment*\n')
setTimeout(done, 1)
})
it('should end the file with a M02', function(done) {
var expected = [{type: 'done', line: 0}]
expectResults(expected, done)
p.write('M02*\n')
})
describe('general set commands (G-codes)', function() {
it('should set region mode on/off with G36/7', function(done) {
var expected = [
{type: 'set', prop: 'region', value: true, line: 0},
{type: 'set', prop: 'region', value: false, line: 1},
]
expectResults(expected, done)
p.write('G36*\nG37*\n')
})
it('should set interpolation mode with G01/2/3', function(done) {
var expected = [
{type: 'set', prop: 'mode', value: 'i', line: 0},
{type: 'set', prop: 'mode', value: 'cw', line: 1},
{type: 'set', prop: 'mode', value: 'ccw', line: 2},
{type: 'set', prop: 'mode', value: 'i', line: 3},
{type: 'set', prop: 'mode', value: 'cw', line: 4},
{type: 'set', prop: 'mode', value: 'ccw', line: 5},
]
expectResults(expected, done)
p.write('G01*\nG02*\nG03*\n')
p.write('G1*\nG2*\nG3*\n')
})
it('should set the arc mode with G74/5', function(done) {
var expected = [
{type: 'set', prop: 'arc', value: 's', line: 0},
{type: 'set', prop: 'arc', value: 'm', line: 1},
]
expectResults(expected, done)
p.write('G74*\nG75*\n')
})
})
describe('unit set commands (MO parameter)', function() {
it('should set units with %MOIN*% and %MOMM*%', function(done) {
var expected = [
{type: 'set', prop: 'units', value: 'in', line: 0},
{type: 'set', prop: 'units', value: 'mm', line: 1},
]
expectResults(expected, done)
p.write('%MOIN*%\n')
p.write('%MOMM*%\n')
})
// Special Case: Cadence Allegro
// The gerber spec says
// "There can be only one extended code command between each pair of ‘%’ delimiters"
// Cadence Allegro violates this rule by including the units after the format command
//
// Sample:
// G04 File Origin: Cadence Allegro 17.2-S032*
// ...
// %FSLAX25Y25*MOMM*%
// ...
//
describe('should set units if found in same line as format', function() {
it('should output notation and epsilion then units', function(done) {
var epsilon = 1.5 * Math.pow(10, -5)
var expected = [
{type: 'set', line: 0, prop: 'nota', value: 'A'},
{type: 'set', line: 0, prop: 'epsilon', value: epsilon},
{type: 'set', line: 0, prop: 'units', value: 'in'},
{type: 'set', line: 1, prop: 'nota', value: 'A'},
{type: 'set', line: 1, prop: 'epsilon', value: epsilon},
{type: 'set', line: 1, prop: 'units', value: 'mm'},
]
expectResults(expected, done)
p.write('%FSLAX25Y25*MOIN*%\n') // inches
p.write('%FSTAX25Y25*MOMM*%\n') // millimeters
})
it('should still parse format', function() {
// Inches
p.write('%FSLAX25Y25*MOIN*%\n')
expect(p.format.zero).to.equal('L')
expect(p.format.places).to.eql([2, 5])
// Millimeters
p.format.zero = null
p.format.places = null
p.write('%FSTAX37Y37*MOMM*%\n')
expect(p.format.zero).to.equal('T')
expect(p.format.places).to.eql([3, 7])
})
})
it('should set backup units with G70/1', function(done) {
var expected = [
{type: 'set', prop: 'backupUnits', value: 'in', line: 0},
{type: 'set', prop: 'backupUnits', value: 'mm', line: 1},
]
expectResults(expected, done)
p.write('G70*\nG71*\n')
})
})
describe('format block', function() {
it('should parse zero suppression', function() {
var format = '%FSLAX34Y34*%'
p.write(format)
expect(p.format.zero).to.equal('L')
p = pFactory()
format = '%FSTAX34Y34*%'
p.write(format)
expect(p.format.zero).to.equal('T')
})
it('should warn trailing suppression is deprected', function(done) {
p.once('warning', function(w) {
expect(w.line).to.equal(0)
expect(w.message).to.match(/trailing zero suppression/)
done()
})
p.write('%FSTAX34Y34*%\n')
})
it('should parse places format', function() {
var format = '%FSLAX34Y34*%'
p.write(format)
expect(p.format.places).to.eql([3, 4])
p = pFactory()
format = '%FSLAX77Y77*%'
p.write(format)
expect(p.format.places).to.eql([7, 7])
})
it('should not override user-set places or suppression', function() {
var format = '%FSLAX34Y34*%'
p.format.zero = 'T'
p.format.places = [7, 7]
p.write(format)
expect(p.format.zero).to.equal('T')
expect(p.format.places).to.eql([7, 7])
})
it('should set notation and epsilon', function(done) {
var format1 = '%FSLAX34Y34*%\n'
var format2 = '%FSLIX77Y77*%\n'
// ensure it parses if suppression is missing
var format3 = '%FSAX66Y66*%\n'
var expected = [
{type: 'set', line: 0, prop: 'nota', value: 'A'},
{type: 'set', line: 0, prop: 'epsilon', value: 1.5 * Math.pow(10, -4)},
{type: 'set', line: 1, prop: 'nota', value: 'I'},
{type: 'set', line: 1, prop: 'epsilon', value: 1.5 * Math.pow(10, -7)},
{type: 'set', line: 2, prop: 'nota', value: 'A'},
{type: 'set', line: 2, prop: 'epsilon', value: 1.5 * Math.pow(10, -6)},
]
expectResults(expected, done)
// clear places format between writes to simulate new parsers
p.write(format1)
p.format.places = null
p.write(format2)
p.format.places = null
p.write(format3)
})
it('should warn and set leading if suppression missing', function(done) {
var format = '%FSAX34Y34*%\n'
p.once('warning', function(w) {
expect(w.line).to.equal(0)
expect(w.message).to.match(/suppression missing/)
expect(p.format.zero).to.equal('L')
done()
})
p.write(format)
})
it('should be able to set backup notation with G90/1', function(done) {
var expected = [
{type: 'set', line: 0, prop: 'backupNota', value: 'A'},
{type: 'set', line: 1, prop: 'backupNota', value: 'I'},
]
expectResults(expected, done)
p.write('G90*\n')
p.write('G91*\n')
})
it('should warn but still set format if there are extra characters', function(done) {
var format = '%FSLAN2X34Y34*%\n'
p.once('warning', function(w) {
expect(w.line).to.equal(0)
expect(w.message).to.match(/unknown characters/)
expect(p.format.zero).to.equal('L')
expect(p.format.places).to.eql([3, 4])
done()
})
p.write(format)
})
})
describe('new level commands (SR/LP parameters)', function() {
it('should parse a new level polarity', function(done) {
var expected = [
{type: 'level', line: 0, level: 'polarity', value: 'D'},
{type: 'level', line: 1, level: 'polarity', value: 'C'},
]
expectResults(expected, done)
p.write('%LPD*%\n%LPC*%')
})
it('should parse a new step-repeat level', function(done) {
var expected = [
{
type: 'level',
line: 0,
level: 'stepRep',
value: {x: 1, y: 1, i: 0, j: 0},
},
{
type: 'level',
line: 1,
level: 'stepRep',
value: {x: 2, y: 3, i: 2, j: 3},
},
{
type: 'level',
line: 2,
level: 'stepRep',
value: {x: 1, y: 1, i: 0, j: 0},
},
]
expectResults(expected, done)
p.format.places = [2, 2]
p.write('%SRX1Y1I0J0*%\n')
p.write('%SRX2Y3I2.0J3.0*%\n')
p.write('%SR*%\n')
})
})
describe('tool changes and definitions', function() {
beforeEach(function() {
p.format.zero = 'L'
p.format.places = [2, 2]
})
it('should parse a tool change block', function(done) {
var expected = [
{type: 'set', line: 0, prop: 'tool', value: '10'},
{type: 'set', line: 1, prop: 'tool', value: '11'},
{type: 'set', line: 2, prop: 'tool', value: '12'},
]
expectResults(expected, done)
p.write('D10*\n')
p.write('G54D11*\n')
p.write('D00012*\n')
})
it('should handle standard circles', function(done) {
var expectedTools = [
{shape: 'circle', params: [1], hole: []},
{shape: 'circle', params: [1], hole: [0.1]},
{shape: 'circle', params: [1], hole: [0.2, 0.3]},
]
var expected = [
{type: 'tool', line: 0, code: '10', tool: expectedTools[0]},
{type: 'tool', line: 1, code: '11', tool: expectedTools[1]},
{type: 'tool', line: 2, code: '12', tool: expectedTools[2]},
]
expectResults(expected, done)
p.write('%ADD10C,1*%\n')
p.write('%ADD11C,1X0.1*%\n')
p.write('%ADD12C,1X0.2X0.3*%\n')
})
it('should handle standard rectangles/obrounds', function(done) {
var expectedTools = [
{shape: 'rect', params: [1, 2], hole: []},
{shape: 'obround', params: [3, 4], hole: [0.1]},
{shape: 'rect', params: [5, 6], hole: [0.2, 0.3]},
]
var expected = [
{type: 'tool', line: 0, code: '10', tool: expectedTools[0]},
{type: 'tool', line: 1, code: '11', tool: expectedTools[1]},
{type: 'tool', line: 2, code: '12', tool: expectedTools[2]},
]
expectResults(expected, done)
p.write('%ADD10R,1X2*%\n')
p.write('%ADD11O,3.0X4.0X0.1*%\n')
p.write('%ADD12R,5X6X0.2X0.3*%\n')
})
it('should handle standard polygons', function(done) {
var expectedTools = [
{shape: 'poly', params: [1, 5, 0], hole: []},
{shape: 'poly', params: [2, 6, 45], hole: []},
{shape: 'poly', params: [3, 7, 0], hole: [0.1]},
{shape: 'poly', params: [4, 8, 0], hole: [0.2, 0.3]},
]
var expected = [
{type: 'tool', line: 0, code: '10', tool: expectedTools[0]},
{type: 'tool', line: 1, code: '11', tool: expectedTools[1]},
{type: 'tool', line: 2, code: '12', tool: expectedTools[2]},
{type: 'tool', line: 3, code: '13', tool: expectedTools[3]},
]
expectResults(expected, done)
p.write('%ADD10P,1X5*%\n')
p.write('%ADD11P,2X6X45*%\n')
p.write('%ADD12P,3X7X0X0.1*%\n')
p.write('%ADD13P,4X8X0X0.2X0.3*%\n')
})
it('should handle aperture macro tools', function(done) {
var expectedTools = [
{shape: 'CIRC', params: [1, 0.5], hole: []},
{shape: 'RECT', params: [], hole: []},
]
var expected = [
{type: 'tool', line: 0, code: '10', tool: expectedTools[0]},
{type: 'tool', line: 1, code: '11', tool: expectedTools[1]},
]
expectResults(expected, done)
p.write('%ADD10CIRC,1X0.5*%\n')
p.write('%ADD11RECT*%\n')
})
it('should handle tool defs with leading zeros', function(done) {
var expectedTools = [{shape: 'circle', params: [1], hole: []}]
var expected = [
{type: 'tool', line: 0, code: '10', tool: expectedTools[0]},
]
expectResults(expected, done)
p.write('%ADD0010C,1*%\n')
})
it('should handle tool defs with negative modifiers', function(done) {
var expectedTools = [{shape: 'CIRC', params: [1, -0.5, 3], hole: []}]
var expected = [
{type: 'tool', line: 0, code: '10', tool: expectedTools[0]},
]
expectResults(expected, done)
p.write('%ADD10CIRC,1X-0.5X3*%\n')
})
})
describe('aperture macros', function() {
it('should parse the name of the macro properly', function(done) {
var expected = [
{type: 'macro', line: 0, name: 'NAME1', blocks: []},
{type: 'macro', line: 1, name: 'CRAZY8', blocks: []},
{type: 'macro', line: 2, name: 'NAME-1', blocks: []},
{type: 'macro', line: 3, name: 'Name1.0', blocks: []},
{type: 'macro', line: 4, name: '$Name1', blocks: []},
]
expectResults(expected, done)
p.write('%AMNAME1*%\n')
p.write('%AMCRAZY8*%\n')
p.write('%AMNAME-1*%\n')
p.write('%AMName1.0*%\n')
p.write('%AM$Name1*%\n')
})
it('should warn that hyphens in macro names are invalid', function(done) {
p.once('warning', function(w) {
expect(w.line).to.equal(0)
expect(w.message).to.match(/hyphen/)
done()
})
p.write('%AMNAME-1*%\n')
})
describe('primitive blocks', function() {
var exp = 1
it('should parse comments', function(done) {
var expectedBlocks = [{type: 'comment'}]
var expected = [
{type: 'macro', line: 1, name: 'NAME1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMNAME1*\n')
p.write('0 a comment*%\n')
})
it('should parse circle primitives', function(done) {
var expectedBlocks = [
{type: 'circle', exp: exp, dia: 5, cx: 1, cy: 2, rot: 0},
{type: 'circle', exp: exp, dia: 3, cx: 4, cy: 5, rot: 20},
]
var expected = [
{type: 'macro', line: 2, name: 'CIRC1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMCIRC1*\n')
p.write('1,1,5,1,2*\n')
p.write('1,1,3,4,5,20*%\n')
})
it('should parse vector primitives', function(done) {
var expectedBlocks = [
{
type: 'vect',
exp: exp,
width: 2,
x1: 3,
y1: 4,
x2: 5,
y2: 6,
rot: 7,
},
{
type: 'vect',
exp: exp,
width: 2,
x1: 3,
y1: 4,
x2: 5,
y2: 6,
rot: 7,
},
]
var expected = [
{type: 'macro', line: 2, name: 'VECT1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMVECT1*\n')
p.write('2,1,2,3,4,5,6,7*\n')
p.write('20,1,2,3,4,5,6,7*%\n')
})
it('should warn that primitive code 2 is deprecated', function(done) {
p.once('warning', function(w) {
expect(w.line).to.equal(1)
expect(w.message).to.match(/vector.*deprecated/)
done()
})
p.write('%AMVECT1*\n')
p.write('2,1,2,3,4,5,6,7*%\n')
})
it('should parse rectangle primitives', function(done) {
var expectedBlocks = [
{type: 'rect', exp: exp, width: 2, height: 3, cx: 4, cy: 5, rot: 6},
]
var expected = [
{type: 'macro', line: 1, name: 'RECT1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMRECT1*\n')
p.write('21,1,2,3,4,5,6*%\n')
})
it('should parse a lower left rectangle primitive', function(done) {
var expectedBlocks = [
{type: 'rectLL', exp: exp, width: 2, height: 3, x: 4, y: 5, rot: 6},
]
var expected = [
{type: 'macro', line: 1, name: 'RECTLL1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMRECTLL1*\n')
p.write('22,1,2,3,4,5,6*%\n')
})
it('should warn that primitive code 22 is deprecated', function(done) {
p.once('warning', function(w) {
expect(w.line).to.equal(1)
expect(w.message).to.match(/lower-left.*deprecated/)
done()
})
p.write('%AMRECTLL1*\n')
p.write('22,1,2,3,4,5,6*%\n')
})
it('should parse an outline polygon primitive', function(done) {
var expectedBlocks = [
{type: 'outline', exp: exp, points: [3, 4, 5, 6, 7, 8], rot: 9},
]
var expected = [
{type: 'macro', line: 1, name: 'OUT1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMOUT1*\n')
p.write('4,1,2,3,4,5,6,7,8,9*%\n')
})
it('should parse a regular polygon primitive', function(done) {
var expectedBlocks = [
{type: 'poly', exp: exp, vertices: 3, cx: 4, cy: 5, dia: 6, rot: 7},
]
var expected = [
{type: 'macro', line: 1, name: 'POLY1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMPOLY1*\n')
p.write('5,1,3,4,5,6,7*%\n')
})
it('should parse a moire primitive', function(done) {
var expectedBlocks = [
{
type: 'moire',
exp: 1,
cx: 1,
cy: 2,
dia: 3,
ringThx: 4,
ringGap: 5,
maxRings: 6,
crossThx: 7,
crossLen: 8,
rot: 9,
},
]
var expected = [
{type: 'macro', line: 1, name: 'MOIRE1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMMOIRE1*\n')
p.write('6,1,2,3,4,5,6,7,8,9*%\n')
})
it('should parse a thermal primitive', function(done) {
var expectedBlocks = [
{
type: 'thermal',
exp: 1,
cx: 1,
cy: 2,
outerDia: 3,
innerDia: 4,
gap: 5,
rot: 6,
},
]
var expected = [
{type: 'macro', line: 1, name: 'THERMAL1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMTHERMAL1*\n')
p.write('7,1,2,3,4,5,6*%\n')
})
it('should warn if the primitive is unrecognized', function(done) {
p.once('warning', function(w) {
expect(w.line).to.equal(1)
expect(w.message).to.match(/unrecognized primitive/)
done()
})
p.write('%AMNOTAREALPRIMITIVE*\n')
p.write('8,1,2,3,4,5,6,7*%\n')
})
it('should parse primitives with negative parameters', function(done) {
var expectedBlocks = [
{type: 'circle', exp: exp, dia: 5, cx: -1, cy: -2.5, rot: 0},
]
var expected = [
{type: 'macro', line: 1, name: 'CIRC1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMCIRC1*\n')
p.write('1,1,5,-1,-2.5*%\n')
})
it('should ignore empty blocks', function(done) {
var expectedBlocks = [
{type: 'circle', exp: exp, dia: 5, cx: 1, cy: 2, rot: 0},
]
var expected = [
{type: 'macro', line: 2, name: 'CIRC1', blocks: expectedBlocks},
]
expectResults(expected, done)
p.write('%AMCIRC1*\n')
p.write('1,1,5,1,2*\n')
p.write('*%\n')
})
})
describe('variable set blocks', function() {
var mods
beforeEach(function() {
mods = {$1: 42}
})
var expectExprResults = function(expected, done) {
p.once('data', function(res) {
expect(res.type).to.equal('macro')
expect(res.name).to.equal('MODS1')
res.blocks.forEach(function(v) {
var newMods = v.set(mods)
expect(v.type).to.equal('variable')
expect(newMods).to.eql(expected.shift())
})
done()
})
}
it('should return function that takes / returns mods', function(done) {
var expected = [{$1: 42, $2: 1}]
expectExprResults(expected, done)
p.write('%AMMODS1*\n')
p.write('$2=1*%\n')
})
it('should parse addition', function(done) {
var expected = [
{$1: 42, $2: 3},
{$1: 42, $2: 56},
]
expectExprResults(expected, done)
p.write('%AMMODS1*\n')
p.write('$2=1+2*\n')
p.write('$2=$1+14*%\n')
})
it('should parse subtraction', function(done) {
var expected = [
{$1: 42, $2: 3},
{$1: 42, $2: 21},
]
expectExprResults(expected, done)
p.write('%AMMODS1*\n')
p.write('$2=5-2*\n')
p.write('$2=63-$1*%\n')
})
it('should parse multiplication with x and X', function(done) {
var expected = [
{$1: 42, $2: 21},
{$1: 42, $2: 6},
]
expectExprResults(expected, done)
p.write('%AMMODS1*\n')
p.write('$2=$1x0.5*\n')
p.write('$2=2X3*%\n')
})
it('should warn that mult with X is incorrect', function(done) {
p.once('warning', function(w) {
expect(w.message).to.match(/multiplication/)
done()
})
p.write('%AMMODS1*\n')
p.write('$2=$1X1*%\n')
})
it('should parse division with /', function(done) {
var expected = [
{$1: 42, $2: 4},
{$1: 42, $2: 21},
]
expectExprResults(expected, done)
p.write('%AMMODS1*\n')
p.write('$2=12/3*\n')
p.write('$2=$1/2*%\n')
})
it('should handle expressions with parentheses', function(done) {
var expected = [{$1: 42, $2: 3}]
expectExprResults(expected, done)
p.write('%AMMODS1*\n')
p.write('$2=($1-30)x(2/(3+12-7))*%\n')
})
})
it('should parse params in circle primitives as expressions', function(done) {
p.once('data', function(d) {
expect(d.blocks[0].dia({$1: 4})).to.equal(5)
done()
})
p.write('%AMCIRC1*\n')
p.write('1,1,$1+1,1,2*%\n')
})
it('should parse params in outline primitives as expressions', function(done) {
p.once('data', function(d) {
var block = d.blocks[0]
var points = block.points
var rotation = block.rot
var mods = {
$1: 0,
$2: 1,
$3: 2,
$4: 3,
$5: 4,
$6: 5,
$7: 6,
$8: 7,
$9: 8,
}
points.forEach(function(p, i) {
expect(p(mods)).to.equal(i)
})
expect(rotation(mods)).to.equal(8)
done()
})
p.write('%AMOUT1*\n')
p.write('4,1,3,$1,$2,$3,$4,$5,$6,$7,$8,$9**%\n')
})
})
describe('operations', function() {
beforeEach(function() {
p.format.zero = 'L'
p.format.places = [2, 3]
})
it('should parse an interpolation command', function(done) {
var expected = [
{
type: 'op',
line: 0,
op: 'int',
coord: {x: 0.1, y: 0.2, i: 0.3, j: 0.4},
},
{type: 'op', line: 1, op: 'int', coord: {x: 0.11, y: 0}},
{type: 'op', line: 2, op: 'int', coord: {x: 0.22}},
{type: 'op', line: 3, op: 'int', coord: {y: 0.33}},
{type: 'op', line: 4, op: 'int', coord: {}},
]
expectResults(expected, done)
p.write('X100Y200I300J400D01*\n')
p.write('X110Y0D01*\n')
p.write('X220D1*\n')
p.write('Y330D1*\n')
p.write('D01*\n')
})
it('should parse a move command', function(done) {
var expected = [
{type: 'op', line: 0, op: 'move', coord: {x: 0.3, y: 0.001}},
{type: 'op', line: 1, op: 'move', coord: {x: -0.1}},
{type: 'op', line: 2, op: 'move', coord: {}},
]
expectResults(expected, done)
p.write('X300Y1D02*\n')
p.write('X-100D2*\n')
p.write('D02*\n')
})
it('should parse a flash command', function(done) {
var expected = [
{type: 'op', line: 0, op: 'flash', coord: {x: 0.3, y: 0.001}},
{type: 'op', line: 1, op: 'flash', coord: {x: -0.1}},
{type: 'op', line: 2, op: 'flash', coord: {}},
]
expectResults(expected, done)
p.write('X300Y1D03*\n')
p.write('X-100D3*\n')
p.write('D03*\n')
})
it('should send "last" operation if op code is missing', function(done) {
var expected = [
{type: 'op', line: 0, op: 'last', coord: {x: 0.3, y: 0.001}},
{type: 'op', line: 1, op: 'last', coord: {x: -0.1}},
]
expectResults(expected, done)
p.write('X300Y1*\n')
p.write('X-100*\n')
})
it('should interpolate with inline mode set', function(done) {
var expected = [
{type: 'set', line: 0, prop: 'mode', value: 'i'},
{type: 'op', line: 0, op: 'int', coord: {x: 0.001, y: 0.001}},
{type: 'set', line: 1, prop: 'mode', value: 'cw'},
{type: 'op', line: 1, op: 'int', coord: {x: 0.001, y: 0.001}},
{type: 'set', line: 2, prop: 'mode', value: 'ccw'},
{type: 'op', line: 2, op: 'int', coord: {x: 0.001, y: 0.001}},
]
expectResults(expected, done)
p.write('G01X01Y01D01*\n')
p.write('G02X01Y01D01*\n')
p.write('G03X01Y01D01*\n')
})
it('should be strict about what counts as a operation', function(done) {
p.once('readable', function() {
throw new Error('should not have operated')
})
p.write('somestuffX01Y01*\n')
p.write('X01Y01somestuff*\n')
p.write('%TF.GerberVersion,J1*%\n')
setTimeout(done, 10)
})
})
})