react-split-test
Version:
Split testing using React
130 lines (115 loc) • 3.83 kB
JavaScript
'use strict';
var React = require('react');
var SplitTestScript = require('./splitTestScript');
var cookie = require('react-cookie');
var _React$PropTypes = React.PropTypes;
var string = _React$PropTypes.string;
var node = _React$PropTypes.node;
var func = _React$PropTypes.func;
var Experiment = React.createClass({
displayName: 'Experiment',
propTypes: {
cookieName: string,
experimentWrappingClass: string,
children: node,
callBack: func
},
getDefaultProps: function getDefaultProps() {
return {
cookieName: 'variation'
};
},
getInitialState: function getInitialState() {
return {
variation: false
};
},
noVariations: function noVariations() {
this.setState({
variation: false
});
},
sortVariations: function sortVariations() {
var variations = this.getVariations();
var total = 0;
return variations.map(function (item) {
if (!Number(item.props.percent)) return false;
total += Number(item.props.percent) / 100; // Lets convert percent to Math.random
if (total > 1) total = 1; // Cant get more than 100% !
return {
name: item.props.name || '',
id: item.props.id || '',
percent: total
};
}).filter(function (item) {
return item;
}).sort(function (a, b) {
// Right now we want highest first
return a.percent < b.percent;
});
},
getVariations: function getVariations() {
var _this = this;
return React.Children.map(this.props.children, function (child) {
var parentProps = {};
for (var key in _this.props) {
if (key !== 'children') parentProps[key] = _this.props[key];
}
return React.cloneElement(child, parentProps);
});
},
getOriginal: function getOriginal() {
var _this2 = this;
var variations = this.getVariations();
return variations.reduce(function (total, item) {
if (item.props && item.props.id && _this2.convert(item.props.id) === 'original') return item;
if (!item.props.percent) return item;
}, []);
},
getVariation: function getVariation() {
var _this3 = this;
var variation = this.state.variation;
var variations = this.getVariations();
var winner = this.getOriginal();
variations.reduce(function (total, item) {
if (_this3.convert(item.props.id) === _this3.convert(variation)) winner = item;
}, []);
return winner;
},
convert: function convert(str) {
if (!str) return '';
return str.toString().toLowerCase();
},
componentDidMount: function componentDidMount() {
var htmlTag = document.getElementsByTagName('html')[0];
if (htmlTag) htmlTag.style.visibility = 'visible';
},
componentWillMount: function componentWillMount() {
var cookieName = this.props.cookieName;
this.state.variation = cookie.load(cookieName);
},
getWinner: function getWinner() {
var variation = this.state.variation;
var variations = this.sortVariations();
if (!variations.length || !variation || variation === 'false') return this.getOriginal();
return this.getVariation();
},
render: function render() {
var _props = this.props;
var cookieName = _props.cookieName;
var callBack = _props.callBack;
var experimentWrappingClass = _props.experimentWrappingClass;
var winner = this.getWinner();
if (!winner) {
throw 'ERROR: Experiments had no Variations in it.'; // No variations? Something went wrong
}
if (callBack instanceof Function) callBack(winner.props.name || winner.props.id);
return React.createElement(
'div',
{ className: experimentWrappingClass },
React.createElement(SplitTestScript, { cookieName: cookieName, variations: this.sortVariations() }),
winner
);
}
});
module.exports = Experiment;