Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Redux Chaos Monkey

This is a proof of concept which allows you to replay system events in a random order each time to make sure your UI can tolerate variable states.

I'm not sure if this is worthy of its on open source project with additional features like changing play back time, whitelisting/blacklisting actions etc but figured I'd put this out there to see if it piques anyones interest.

See a video of this in action here: [https://www.youtube.com/watch?v=wkoukONfwmA](Video on YouTube).

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, compose } from 'redux';
import { connect, Provider} from 'react-redux';
import { createDevTools, ActionCreators } from 'redux-devtools';
const { reset, performAction } = ActionCreators;
/**
* Developer Tools
*/
const Havoc = connect((state) => state, {
reset,
performAction
})(class extends React.Component {
constructor(){
super(...arguments);
this.havoc = this.havoc.bind(this);
}
havoc() {
const goHam = (list) => {
const keys = Object.keys(list);
const random = keys[Math.floor(Math.random() * keys.length)];
if (keys.length === 0) return null;
if (list[random].action.type !== '@@INIT') {
this.props.performAction(list[random].action);
}
const remaining = keys.reduce((acc, key) => {
if (key === random) return acc;
acc[key] = list[key];
return acc;
}, {});
setTimeout(() => goHam(remaining), 500);
};
this.props.reset();
goHam(this.props.actionsById);
}
render() {
return (
<div style={{ backgroundColor: '#eee' }}>
<button onClick={this.havoc}>Wreak Chaos</button>
{Object.keys(this.props.actionsById).map((action) => {
return <div key={action}>{this.props.actionsById[action].action.type}</div>;
})}
</div>
);
}
});
Havoc.update = () => {};
const DeveloperTools = createDevTools(<Havoc />);
const finalCreateStore = compose(
DeveloperTools.instrument()
)(createStore);
/**
* Constants
*/
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
/**
* Store
*/
const store = finalCreateStore((state = { count: 0 }, action) => {
switch (action.type) {
case INCREMENT:
return { count: state.count + 1 };
case DECREMENT:
return { count: state.count - 1 };
default:
return state;
}
});
/**
* Actions
*/
const increment = () => {
return {
type: INCREMENT
};
};
const decrement = () => {
return {
type: DECREMENT
};
};
/**
* Selectors
*/
const selectCount = (state) => {
return state.count;
};
/**
* Components
*/
const Counter = connect((state) => ({
count: selectCount(state)
}), {
increment,
decrement
})(class extends React.Component {
render() {
return (
<div>
<button onClick={this.props.increment}>+</button>
<button onClick={this.props.decrement}>-</button>
{this.props.count}
</div>
);
}
});
ReactDOM.render(
<Provider store={store}>
<div>
<Counter />
<DeveloperTools />
</div>
</Provider>
, document.getElementById('viewport'));
@ccorcos

This comment has been minimized.

Copy link

@ccorcos ccorcos commented Jan 7, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment