Skip to content

Instantly share code, notes, and snippets.

@aethant
Forked from iammerrick/README.md
Created January 6, 2016 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aethant/f135b9746ea25cedc37a to your computer and use it in GitHub Desktop.
Save aethant/f135b9746ea25cedc37a to your computer and use it in GitHub Desktop.

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'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment