From b494e3c501262d9ccc3b70827b527019a12fab34 Mon Sep 17 00:00:00 2001 From: Joseph Thomas Date: Thu, 30 Aug 2018 17:52:31 -0700 Subject: [PATCH] Adds machineDidUpdate utility and same-state transition+action tests --- src/utils.js | 9 +++++++++ src/withStateMachine.js | 6 +++--- test/withStateMachine.spec.js | 25 +++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/utils.js b/src/utils.js index b25e948..37f3a84 100644 --- a/src/utils.js +++ b/src/utils.js @@ -30,3 +30,12 @@ export const matches = (patterns, value) => { return patterns.some(pattern => values.some(val => pattern.test(val))) } + +export const machineDidUpdate = (oldMachine, newMachine) => { + // Compare the value + if (oldMachine.value !== newMachine.value) return true + // Compare the actions + // /* WIP - + if (oldMachine.actions !== newMachine.actions) return true + return false +} diff --git a/src/withStateMachine.js b/src/withStateMachine.js index 64cc863..938464e 100644 --- a/src/withStateMachine.js +++ b/src/withStateMachine.js @@ -10,6 +10,7 @@ import { getComponentName, isStateless, stringify, + machineDidUpdate } from './utils' const REDUX_DISPATCH = 'DISPATCH' @@ -118,7 +119,7 @@ const withStateMachine = (statechart, options = {}) => Component => { handleComponentDidUpdate(prevProps, prevState) { this.isTransitioning = false - + /* WIP - Should this logic be the same as what is used in handleTransition? */ if (prevState.machineState !== this.state.machineState) { this.runActions() @@ -176,9 +177,8 @@ const withStateMachine = (statechart, options = {}) => Component => { event, stateChange ) - if ( - machineState.value === prevState.machineState.value && + !machineDidUpdate(machineState, prevState.machineState) && (!stateChange || stateChange === prevState.componentState) ) { this.isTransitioning = false diff --git a/test/withStateMachine.spec.js b/test/withStateMachine.spec.js index 372881a..80bd3e0 100644 --- a/test/withStateMachine.spec.js +++ b/test/withStateMachine.spec.js @@ -4,6 +4,7 @@ import { Machine, State } from 'xstate' import { withStateMachine } from '../src' const actionFunction = jest.fn() +const sameStateFn = jest.fn() const statechart = { initial: 'a', @@ -16,6 +17,11 @@ const statechart = { b: { on: { EVENT: 'a', + SAME: { + b: { + actions: ['sameStateMethod', sameStateFn] + } + } }, onEntry: ['actionMethod', actionFunction], activities: ['activityMethod'], @@ -105,6 +111,7 @@ test('state', () => { test('actions', () => { const actionMethod = jest.fn() const activityMethod = jest.fn() + const sameStateMethod = jest.fn() class Component extends React.Component { actionMethod(...args) { @@ -115,6 +122,10 @@ test('actions', () => { activityMethod(...args) } + sameStateMethod(...args) { + sameStateMethod(...args) + } + render() { return
} @@ -131,6 +142,20 @@ test('actions', () => { expect(actionFunction).toHaveBeenCalledWith(undefined, 'EVENT') expect(activityMethod).toHaveBeenCalledTimes(1) expect(activityMethod).toHaveBeenCalledWith(true) + expect(sameStateFn).not.toHaveBeenCalled() + expect(sameStateMethod).not.toHaveBeenCalled() + + instance.handleTransition('SAME') + expect(actionMethod).toHaveBeenCalledTimes(2) + expect(actionMethod).toHaveBeenCalledWith(undefined, 'EVENT') + expect(actionFunction).toHaveBeenCalledTimes(2) + expect(actionFunction).toHaveBeenCalledWith(undefined, 'EVENT') + /* WIP - should the activity method have been called two or three times? */ + expect(activityMethod).toHaveBeenCalledTimes(3) + expect(activityMethod).toHaveBeenCalledWith(true) + + expect(sameStateFn).toHaveBeenCalledTimes(1) + expect(sameStateMethod).toHaveBeenCalledTimes(1) }) test('lifecycle hooks', () => {