Improved interface testing

This commit is contained in:
Bán Dénes 2021-07-16 20:18:09 +02:00
parent 7d841b2f5f
commit 1f3ecb5c58
10 changed files with 407 additions and 120 deletions

45
package-lock.json generated
View file

@ -9,9 +9,9 @@
"license": "MIT",
"dependencies": {
"@jscad/openjscad": "github:mrzealot/oldjscad",
"chai-as-promised": "^7.1.1",
"fs-extra": "^9.0.1",
"js-yaml": "^3.14.0",
"json5": "^2.2.0",
"kle-serial": "github:mrzealot/kle-serial",
"makerjs": "github:mrzealot/maker.js-dist",
"mathjs": "^8.1.1",
@ -833,7 +833,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true,
"engines": {
"node": "*"
}
@ -970,7 +969,6 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz",
"integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==",
"dev": true,
"dependencies": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
@ -983,6 +981,17 @@
"node": ">=4"
}
},
"node_modules/chai-as-promised": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
"integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
"dependencies": {
"check-error": "^1.0.2"
},
"peerDependencies": {
"chai": ">= 2.1.2 < 5"
}
},
"node_modules/chalk": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
@ -1015,7 +1024,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true,
"engines": {
"node": "*"
}
@ -1217,7 +1225,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"dependencies": {
"type-detect": "^4.0.0"
},
@ -1486,7 +1493,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true,
"engines": {
"node": "*"
}
@ -2545,7 +2551,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
"dev": true,
"engines": {
"node": "*"
}
@ -2961,7 +2966,6 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
"dev": true,
"engines": {
"node": ">=4"
}
@ -3958,8 +3962,7 @@
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
},
"astring": {
"version": "1.7.5",
@ -4061,7 +4064,6 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz",
"integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
@ -4071,6 +4073,14 @@
"type-detect": "^4.0.5"
}
},
"chai-as-promised": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
"integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
"requires": {
"check-error": "^1.0.2"
}
},
"chalk": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
@ -4095,8 +4105,7 @@
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
},
"chokidar": {
"version": "3.5.1",
@ -4252,7 +4261,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"requires": {
"type-detect": "^4.0.0"
}
@ -4431,8 +4439,7 @@
"get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
},
"get-package-type": {
"version": "0.1.0",
@ -5237,8 +5244,7 @@
"pathval": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
"dev": true
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ=="
},
"picomatch": {
"version": "2.3.0",
@ -5545,8 +5551,7 @@
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
"dev": true
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
},
"type-fest": {
"version": "0.8.1",

View file

@ -11,15 +11,15 @@
"bin": "./src/cli.js",
"scripts": {
"build": "rollup -c",
"test": "mocha -r chai/register-should test/index.js",
"test": "mocha -r test/helpers/register test/index.js",
"coverage": "nyc --reporter=html --reporter=text npm test"
},
"dependencies": {
"kle-serial": "github:mrzealot/kle-serial",
"@jscad/openjscad": "github:mrzealot/oldjscad",
"chai-as-promised": "^7.1.1",
"fs-extra": "^9.0.1",
"js-yaml": "^3.14.0",
"json5": "^2.2.0",
"kle-serial": "github:mrzealot/kle-serial",
"makerjs": "github:mrzealot/maker.js-dist",
"mathjs": "^8.1.1",
"yargs": "^15.4.1"
@ -37,9 +37,6 @@
"all": true,
"include": [
"src/**/*.js"
],
"exclude": [
"src/cli.js"
]
}
}

View file

@ -4,7 +4,7 @@ import replace from '@rollup/plugin-replace'
export default {
input: 'src/ergogen.js',
external: ['makerjs', 'js-yaml', 'mathjs', 'json5'],
external: ['makerjs', 'js-yaml', 'mathjs'],
output: {
name: 'ergogen',
file: 'dist/ergogen.js',
@ -13,8 +13,7 @@ export default {
globals: {
'makerjs': 'makerjs',
'js-yaml': 'jsyaml',
'mathjs': 'math',
'json5': 'json5'
'mathjs': 'math'
}
},
plugins: [

View file

@ -1,4 +1,3 @@
const json5 = require('json5')
const yaml = require('js-yaml')
const makerjs = require('makerjs')
const jscad = require('@jscad/openjscad')
@ -10,38 +9,43 @@ const kle = require('./kle')
exports.interpret = (raw, logger) => {
let config = raw
let format = 'OBJ'
if (a.type(raw)() != 'object') {
if (a.type(raw)() == 'string') {
try {
config = yaml.safeLoad(raw)
format = 'YAML'
} catch (yamlex) {
try {
config = json5.parse(raw)
format = 'JSON'
} catch (jsonex) {
try {
config = new Function(raw)()
format = 'JS Code'
a.assert(
a.type(config)() == 'object',
'Input JS Code doesn\'t resolve into an object!'
)
format = 'JS'
} catch (codeex) {
logger('YAML exception:', yamlex)
logger('JSON exception:', jsonex)
logger('Code exception:', codeex)
throw new Error('Input is not valid YAML, JSON, or JS Code!')
}
}
}
if (!config) {
throw new Error('Input appears to be empty!')
}
}
try {
// assume it's KLE and try to convert it
// if it's not, it'll throw anyway
return kle.convert(config, logger)
config = kle.convert(config, logger)
format = 'KLE'
} catch (kleex) {
return [config, format]
// nope... nevermind
}
if (a.type(config)() != 'object') {
throw new Error('Input doesn\'t resolve into an object!')
}
if (!Object.keys(config).length) {
throw new Error('Input appears to be empty!')
}
return [config, format]
}
exports.twodee = (model, debug) => {

View file

@ -1,18 +1,19 @@
const u = require('./utils')
const kle = require('kle-serial')
const json5 = require('json5')
const yaml = require('js-yaml')
exports.convert = (config, logger) => {
const keyboard = kle.Serial.deserialize(config)
const result = {points: {zones: {}}, pcbs: {main: {}}}
// if the keyboard notes are valid JSON, they get added to each key as metadata
let meta = {}
// if the keyboard notes are valid YAML/JSON, they get added to each key as metadata
let meta
try {
meta = json5.parse(keyboard.meta.notes)
meta = yaml.load(keyboard.meta.notes)
} catch (ex) {
// notes were not valid JSON, oh well...
// notes were not valid YAML/JSON, oh well...
}
meta = meta || {}
let index = 1
for (const key of keyboard.keys) {
@ -68,5 +69,5 @@ exports.convert = (config, logger) => {
result.points.zones[id] = converted
}
return [result, 'KLE']
return result
}

271
test/fixtures/atreus_kle.json vendored Normal file
View file

@ -0,0 +1,271 @@
[
[
{
"r": 10,
"rx": 1,
"y": -0.09999999999999998,
"x": 2
},
"E"
],
[
{
"y": -0.65,
"x": 1
},
"W",
{
"x": 1
},
"R"
],
[
{
"y": -0.75
},
"Q"
],
[
{
"y": -0.9,
"x": 4
},
"T"
],
[
{
"y": -0.7000000000000001,
"x": 2
},
"D"
],
[
{
"y": -0.6499999999999999,
"x": 1
},
"S",
{
"x": 1
},
"F"
],
[
{
"y": -0.75
},
"A"
],
[
{
"y": -0.8999999999999999,
"x": 4
},
"G"
],
[
{
"y": -0.7000000000000002,
"x": 2
},
"C"
],
[
{
"y": -0.6499999999999999,
"x": 1
},
"X",
{
"x": 1
},
"V"
],
[
{
"y": -0.75
},
"Z"
],
[
{
"y": -0.8999999999999999,
"x": 4
},
"B"
],
[
{
"y": -0.75,
"x": 5,
"h": 1.5
},
"Ctrl"
],
[
{
"y": -0.9500000000000002,
"x": 2
},
"super"
],
[
{
"y": -0.6499999999999999,
"x": 1
},
"Tab",
{
"x": 1
},
"Shift"
],
[
{
"y": -0.75
},
"Esc"
],
[
{
"y": -0.8999999999999999,
"x": 4
},
"Bksp"
],
[
{
"r": -10,
"rx": 7,
"ry": 0.965,
"y": -0.20000000000000018,
"x": 2
},
"I"
],
[
{
"y": -0.6499999999999999,
"x": 1
},
"U",
{
"x": 1
},
"O"
],
[
{
"y": -0.75,
"x": 4
},
"P"
],
[
{
"y": -0.8999999999999999
},
"Y"
],
[
{
"y": -0.7000000000000002,
"x": 2
},
"K"
],
[
{
"y": -0.6499999999999999,
"x": 1
},
"J",
{
"x": 1
},
"L"
],
[
{
"y": -0.75,
"x": 4
},
":\n;"
],
[
{
"y": -0.8999999999999999
},
"H"
],
[
{
"y": -0.7000000000000002,
"x": 2
},
"<\n,"
],
[
{
"y": -0.6499999999999999,
"x": 1
},
"M",
{
"x": 1
},
">\n."
],
[
{
"y": -0.7500000000000004,
"x": 4
},
"?\n/"
],
[
{
"y": -0.9000000000000004
},
"N"
],
[
{
"y": -0.7499999999999996,
"x": -1,
"h": 1.5
},
"Alt"
],
[
{
"y": -0.9499999999999997,
"x": 2
},
"_\n-"
],
[
{
"y": -0.6500000000000004,
"x": 1
},
"fn",
{
"x": 1
},
"\"\n'"
],
[
{
"y": -0.75,
"x": 4
},
"Enter"
],
[
{
"y": -0.9000000000000004
},
"Space"
]
]

24
test/fixtures/big.yaml vendored Normal file
View file

@ -0,0 +1,24 @@
units:
a: 28 + u
points.zones.matrix:
columns.col: {}
rows.row: {}
outlines.exports:
export:
- type: 'keys'
side: 'left'
size: 18
_export:
- type: 'keys'
side: 'left'
size: 18
cases:
export:
- name: 'export'
extrude: 1
_export:
- name: 'export'
extrude: 1
pcbs:
export: {}
_export: {}

3
test/fixtures/minimal.yaml vendored Normal file
View file

@ -0,0 +1,3 @@
points.zones.matrix:
columns.col: {}
rows.row: {}

4
test/helpers/register.js Normal file
View file

@ -0,0 +1,4 @@
global.chai = require('chai')
global.chai.use(require('chai-as-promised'))
global.expect = global.chai.expect
global.should = global.chai.should()

View file

@ -1,76 +1,55 @@
const u = require('../../src/utils')
const fs = require('fs')
const path = require('path')
const yaml = require('js-yaml')
const ergogen = require('../../src/ergogen')
const minimal = {
'points.zones.matrix': {
columns: {col: {}},
rows: {row: {}}
}
}
// fixtures
const load = name => yaml.safeLoad(fs.readFileSync(
path.join(__dirname, `../fixtures/${name}`)
).toString())
const minimal = load('minimal.yaml')
const big = load('big.yaml')
const kle = load('atreus_kle.json')
const full = {
'points.zones.matrix': {
columns: {col: {}},
rows: {row: {}}
},
'outlines.exports': {
export: [{
type: 'keys',
side: 'left',
size: 18
}],
_export: [{
type: 'keys',
side: 'left',
size: 18
}]
},
cases: {
export: [{
name: 'export',
extrude: 1
}],
_export: [{
name: 'export',
extrude: 1
}]
},
pcbs: {
export: {},
_export: {}
}
}
describe('Interface', function() {
// to check whether the output has "private" exports
const underscore = obj => {
it('debug', async function() {
// to check whether the output has "private" exports
const underscore = obj => {
for (const val of Object.values(obj)) {
for (const key of Object.keys(val)) {
if (key.startsWith('_')) return true
}
}
return false
}
describe('Interface', function() {
it('minimal', async function() {
}
underscore(await ergogen.process(minimal)).should.be.false
underscore(await ergogen.process(big, false)).should.be.false
underscore(await ergogen.process(big, true)).should.be.true
})
it('production', async function() {
underscore(await ergogen.process(full, false)).should.be.false
})
it('debug', async function() {
underscore(await ergogen.process(full, true)).should.be.true
})
it('logging', async function() {
const flag = {value: false}
const logger = msg => { flag.value = true }
await ergogen.process(full, false, logger)
flag.value.should.be.true
it('formats', async function() {
const logger = msg => {
if (msg.startsWith('Interpreting format:')) {
throw msg.split(':')[1].trim()
}
}
return Promise.all([
ergogen.process(minimal, true, logger).should.be.rejectedWith('OBJ'),
ergogen.process(yaml.dump(minimal), true, logger).should.be.rejectedWith('YAML'),
ergogen.process(`
//:
return {points: {}}
`, true, logger).should.be.rejectedWith('JS'),
ergogen.process(`
//:
return 'not an object';
`, true, logger).should.be.rejectedWith('not valid'),
ergogen.process(kle, true, logger).should.be.rejectedWith('KLE'),
ergogen.process('not an object', true, logger).should.be.rejectedWith('object'),
ergogen.process({}, true, logger).should.be.rejectedWith('empty'),
ergogen.process({not_points: {}}, true, () => {}).should.be.rejectedWith('any points')
])
})
})