Skip to content
Permalink
Browse files

fix: Choice processor would fail on undefined or null input

This can happen if the input to a state machine is malformed
  • Loading branch information...
jezhiggins committed Dec 11, 2018
1 parent 9d101d5 commit 3d6e801b48e3c8fe54bc6a39bb7675272c296deb
Showing with 34 additions and 38 deletions.
  1. +17 −16 lib/Input-value-cache.js
  2. +14 −20 lib/index.js
  3. +3 −2 test/tests.js
@@ -1,34 +1,35 @@
'use strict'

const jp = require('jsonpath')
const _ = require('lodash')

class InputValueCache {
constructor () {
this.cache = {}
}

get (inputPath, values) {
if (!values) { return null }

if (this.cache.hasOwnProperty(inputPath)) {
return this.cache[inputPath]
} else {
let value = jp.query(values, inputPath)
}

let value = jp.query(values, inputPath)

if (_.isArray(value)) {
let l = value.length
switch (l) {
case 0:
value = undefined
break
case 1:
value = value[0]
break
}
if (Array.isArray(value)) {
let l = value.length
switch (l) {
case 0:
value = undefined
break
case 1:
value = value[0]
break
}
this.cache[inputPath] = value
return value
}
this.cache[inputPath] = value
return value
}
}
} // get

module.exports = InputValueCache
@@ -2,30 +2,24 @@

const InputValueCache = require('./Input-value-cache')
const getTopLevelChoices = require('./get-top-level-choices')
const _ = require('lodash')

module.exports = function (definition) {
const choices = getTopLevelChoices(definition.Choices)

return function calculateNextState (values) {
const inputCache = new InputValueCache()
let nextState
choices.forEach(
function (choice) {
if (_.isUndefined(nextState)) {
const inputValue = inputCache.get(choice.definition.Variable, values)
nextState = choice.operator(
inputValue,
choice.operatorValue,
choice.definition.Next,
inputCache
)
}
}
)
if (_.isUndefined(nextState) && _.isString(definition.Default)) {
nextState = definition.Default
for (const choice of choices) {
const inputValue = inputCache.get(choice.definition.Variable, values)
const nextState = choice.operator(
inputValue,
choice.operatorValue,
choice.definition.Next,
inputCache
)

if (nextState) return nextState
}
return nextState
}
}

return definition.Default ? definition.Default : null
} // calculateNextState
} //
@@ -31,8 +31,9 @@ describe('Choice tests', function () {
)
expect(calculateNextState({ foo: true })).to.equal('FirstMatchState')
expect(calculateNextState({ foo: false })).to.equal('SecondMatchState')
expect(calculateNextState({ foo: 'Unexpected!' })).to.equal(undefined)
expect(calculateNextState({})).to.equal(undefined)
expect(calculateNextState({ foo: 'Unexpected!' })).to.equal(null)
expect(calculateNextState({})).to.equal(null)
expect(calculateNextState(undefined)).to.equal(null)
})

it('Should pick a simple state using NumericEquals', function () {

0 comments on commit 3d6e801

Please sign in to comment.
You can’t perform that action at this time.