MicheleBertoli / react-automata

A state machine abstraction for React
MIT License
1.34k stars 60 forks source link

How to test conditional transitions? #49

Closed hally9k closed 6 years ago

hally9k commented 6 years ago

How can I set the extendedState for a guarded transition in my testing fixtures?

davidkpiano commented 6 years ago

I'm working on a solution for that in xstate currently, so once that's done (likely in 3.3) I'll make a PR to upgrade the tests to handle conditional transitions in react-automata.

MicheleBertoli commented 6 years ago

Thank you very much @hally9k @davidkpiano.

react-automata is already passing the fixtures to xstate's transition as a third parameter (see here and here). However, xstate's getShortestPaths doesn't seem to return states guarded by conditions (see here).

For example:

const statechart = {
  initial: 'a',
  states: {
    a: {
      on: {
        EVENT: {
          b: {
            cond: extState => extState.shouldPass,
          },
        },
      },
    },
    b: {},
  },
}
const machine = Machine(statechart)
const paths = getShortestPaths(machine)

// { '"a"': [] }
davidkpiano commented 6 years ago

@MicheleBertoli Can you open an issue so I can track it?

MicheleBertoli commented 6 years ago

Sure @davidkpiano, here it is: https://github.com/davidkpiano/xstate/issues/100. Thank you very much!

MicheleBertoli commented 6 years ago

Given the following statechart:

const statechart = {
  initial: 'a',
  states: {
    a: {
      on: {
        EVENT: {
          b: {
            cond: extState => extState.shouldPass,
          },
        },
      },
    },
    b: {},
  },
}

and the following component:

const Cond = () => (
  <React.Fragment>
    <State value="a">A</State>
    <State value="b">B</State>
  </React.Fragment>
)

it's now possible to write a test that passes the condition:

test('pass', () => {
  const extendedState = {
    shouldPass: true,
  }
  const fixtures = {
    a: {
      EVENT: extendedState,
    },
  }

  testStatechart({ statechart, fixtures, extendedState }, Cond)
})
exports[`cond pass: a 1`] = `"A"`;
exports[`cond pass: b 1`] = `"B"`;

and one that doesn't:

test('fail', () => {
  testStatechart({ statechart }, Cond)
})
exports[`cond fail: a 1`] = `"A"`;

Thank you very much, @hally9k @davidkpiano.

hally9k commented 6 years ago

This is SUPER awesome. Go team!!! This was the one thing holding our project back from full adoption. Let's go!