react-factorial-test
Version:
Generate component test buy using multiplication on parameter sets
461 lines (392 loc) • 21.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _reactAutobind = require('react-autobind');
var _reactAutobind2 = _interopRequireDefault(_reactAutobind);
var _jsonStableStringify = require('json-stable-stringify');
var _jsonStableStringify2 = _interopRequireDefault(_jsonStableStringify);
var _FlagVariantIcon = require('mdi-react/FlagVariantIcon');
var _FlagVariantIcon2 = _interopRequireDefault(_FlagVariantIcon);
var _MagnifyIcon = require('mdi-react/MagnifyIcon');
var _MagnifyIcon2 = _interopRequireDefault(_MagnifyIcon);
var _CheckboxBlankOutlineIcon = require('mdi-react/CheckboxBlankOutlineIcon');
var _CheckboxBlankOutlineIcon2 = _interopRequireDefault(_CheckboxBlankOutlineIcon);
var _CheckboxBlankIcon = require('mdi-react/CheckboxBlankIcon');
var _CheckboxBlankIcon2 = _interopRequireDefault(_CheckboxBlankIcon);
var _CloseBoxIcon = require('mdi-react/CloseBoxIcon');
var _CloseBoxIcon2 = _interopRequireDefault(_CloseBoxIcon);
var _UnFilter = require('./buttons/UnFilter');
var _UnFilter2 = _interopRequireDefault(_UnFilter);
var _ArrowExpandAllIcon = require('mdi-react/ArrowExpandAllIcon');
var _ArrowExpandAllIcon2 = _interopRequireDefault(_ArrowExpandAllIcon);
var _ArrowCollapseAllIcon = require('mdi-react/ArrowCollapseAllIcon');
var _ArrowCollapseAllIcon2 = _interopRequireDefault(_ArrowCollapseAllIcon);
var _TestItem = require('./TestItem');
var _TestItem2 = _interopRequireDefault(_TestItem);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
//import { observable, action, computed } from 'mobx';
//import { observer } from 'mobx-react';
// stable json for easy test name comparisons later.
// Given a set of parameters and rules for multiplying those objects togeter, generate
// TODO: PropTypes
var MultiTest = function (_React$Component) {
_inherits(MultiTest, _React$Component);
function MultiTest(props) {
_classCallCheck(this, MultiTest);
var _this = _possibleConstructorReturn(this, (MultiTest.__proto__ || Object.getPrototypeOf(MultiTest)).call(this, props));
(0, _reactAutobind2.default)(_this);
_this.id = '_' + (_this.props.id || '');
try {
// clear any bad data
var reactFactorialTest_filter = localStorage.getItem('reactFactorialTest_filter' + _this.id) || ''; // empty string implies false.
var reactFactorialTest_compsOnly = localStorage.getItem('reactFactorialTest_compsOnly' + _this.id) || '';
var reactFactorialTest_compList = JSON.parse(localStorage.getItem('reactFactorialTest_compList' + _this.id)) || [];
var reactFactorialTest_flagsOnly = localStorage.getItem('reactFactorialTest_flagsOnly' + _this.id) || '';
var reactFactorialTest_flagList = JSON.parse(localStorage.getItem('reactFactorialTest_flagList' + _this.id)) || [];
var reactFactorialTest_smallMode = localStorage.getItem('reactFactorialTest_smallMode' + _this.id) || ''; // empty string implies false.
} catch (e) {
localStorage.removeItem('reactFactorialTest_filter' + _this.id);
localStorage.removeItem('reactFactorialTest_compsOnly' + _this.id);
localStorage.removeItem('reactFactorialTest_compList' + _this.id);
localStorage.removeItem('reactFactorialTest_flagsOnly' + _this.id);
localStorage.removeItem('reactFactorialTest_flagList' + _this.id);
localStorage.removeItem('reactFactorialTest_smallMode' + _this.id);
}
_this.state = {
filter: localStorage.getItem("reactFactorialTest_filter" + _this.id) || '',
smallMode: localStorage.getItem('reactFactorialTest_smallMode' + _this.id) || _this.props.smallMode || '',
showCompsOnly: false,
showFlagsOnly: false
};
return _this;
}
// Flattens a JSON hierarchy to prepare for test discovery and multiplication.
// Expands each test group into individual test to muldiply.
// For Example
// testParams:{
// alphaTest: { a1Test:{a:1}, a2Test:{a:2}, a3Test:{a:3} },
// betaTest: { b1Test:{b:1}, b2Test:{b:2}, b3Test:{b:3} },
// }
// getAllWork(testParams.alphaTest.a1Test) --> [{a:1}]
// getAllWork(testParams.alphaTest) --> [{a:1},{a:2},{a:3}]
// getAllWork(testParams) --> [{a:1},{a:2},{a:3},{b:1},{b:2},{b:3}]
_createClass(MultiTest, [{
key: 'getAllWork',
value: function getAllWork(workObj, nameSoFar) {
if (!workObj) return [];
var results = [];
var keys = Object.keys(workObj);
for (var kctr = 0; kctr < keys.length; kctr++) {
var curKey = keys[kctr];
if (curKey.endsWith('Test')) {
results = results.concat(this.getAllWork(workObj[curKey], curKey));
} else if (curKey !== 'tstName' && curKey !== '_rft') {
results.push(workObj);
return results;
}
}
return results;
}
// Multiplies two arrays of objects
// Expands each test group into individual test to muldiply.
// For Example
// testParams:{
// alphaTest: { a1Test:{a:1}, a2Test:{a:2}, a3Test:{a:3} },
// betaTest: { b1Test:{b:1}, b2Test:{b:2}, b3Test:{b:3} },
// }
// var aList = getAllWork(testParams.alphaTest) --> [{a:1},{a:2},{a:3}]
// var bList = getAllWork(testParams.alphaTest) --> [{a:1},{a:2},{a:3}]
// multiplyObjects(aList,bList) --> [ {a:1,b:1} , {a:1,b:2} , {a:1,b:3} ,
// {a:2,b:1} , {a:2,b:2} , {a:2,b:3} ,
// {a:3,b:1} , {a:3,b:2} , {a:3,b:3} ]
}, {
key: 'multiplyObjects',
value: function multiplyObjects(left, right) {
var results = [];
for (var lctr = 0; lctr < left.length; lctr++) {
for (var rctr = 0; rctr < right.length; rctr++) {
var newName = left[lctr].tstName || '';
if (right[rctr].tstName) {
newName = (left[lctr].tstName || '') + ' | ' + right[rctr].tstName;
}
var test = Object.assign({}, left[lctr], right[rctr], { tstName: newName });
results.push(test);
}
}
return results;
}
// show only the given test name.
// save the information to a window variable so that it will survive reloading the page due the tested code being updated.
}, {
key: 'setFilter',
value: function setFilter(filterVal) {
localStorage.setItem('reactFactorialTest_filter' + this.id, filterVal);
localStorage.setItem('reactFactorialTest_compsOnly' + this.id, ''); // emptry string for false because local storage works on strings.
localStorage.setItem('reactFactorialTest_flagsOnly' + this.id, '');
this.setState({ filter: filterVal, showCompsOnly: '', showFlagsOnly: '' });
}
}, {
key: 'goSmall',
value: function goSmall() {
localStorage.setItem('reactFactorialTest_smallMode' + this.id, 'T'), this.setState({ smallMode: true });
}
}, {
key: 'goBig',
value: function goBig() {
localStorage.setItem('reactFactorialTest_smallMode' + this.id, ''), this.setState({ smallMode: false });
}
// toggle wether the system is showing all tests or just the comparison tests.
// save the information to a window variable so that it will survive reloading the page due the tested code being updated.
}, {
key: 'toggleCompVisible',
value: function toggleCompVisible() {
var showCompsOnly = localStorage.getItem('reactFactorialTest_compsOnly' + this.id) || '';
var compsOnly = '' === showCompsOnly ? 'T' : ''; // rigmaroll so I can store in local storage.
localStorage.setItem('reactFactorialTest_compsOnly' + this.id, compsOnly);
this.setState({ showCompsOnly: compsOnly });
}
// toggle wether the system is showing all tests or just the flagged tests.
// save the information to a window variable so that it will survive reloading the page due the tested code being updated.
}, {
key: 'toggleFlagVisible',
value: function toggleFlagVisible() {
var showFlagsOnly = localStorage.getItem('reactFactorialTest_flagsOnly' + this.id) || '';
var flagsOnly = '' === showFlagsOnly ? 'T' : ''; // rigmaroll so I can store in local storage.
localStorage.setItem('reactFactorialTest_flagsOnly' + this.id, flagsOnly);
this.setState({ showFlagsOnly: flagsOnly });
}
// Uses the getAllWork and multiplyObjects methods to generate a list of test parameters.
// renders this.props.targetTag once for each multiplied test parameter group in the list.
}, {
key: 'render',
value: function render() {
var _this2 = this;
// this is the input list of tests and test multiplications to perform
var testArray = this.props.test;
if (!testArray) {
return _react2.default.createElement(
'div',
null,
'you must specify an array of tests as the test paramter'
);
}
if ('object' !== _typeof(this.props.target)) {
return _react2.default.createElement(
'div',
{ style: { margin: '5px', padding: '5px', backgroundColor: 'red', border: '5px dashed black', fontSize: '2em' } },
_react2.default.createElement(
'b',
null,
'You have not passed a valid React element for testing.',
_react2.default.createElement('br', null),
'Instead of an object, you\'ve passed in a function.'
),
_react2.default.createElement('br', null),
'Most likely you typed something like:',
_react2.default.createElement('br', null),
'\xA0\xA0\xA0\xA0\xA0\xA0target={MyComponent}',
_react2.default.createElement('br', null),
'Instead, you need to type:',
_react2.default.createElement('br', null),
'\xA0\xA0\xA0\xA0\xA0\xA0target={<MyComponent/>}',
_react2.default.createElement('br', null)
);
}
//===== MULTIPLICATION PHASE =====
// testArray is an array or arrays.
// in the outer array, each item is a test to calculate,
// for the inner array, they are parameter sets to multiply
var allWork = []; // the final list of all test parameters to be rendered.
for (var tctr = 0; tctr < testArray.length; tctr++) {
// test counter
var curTest = testArray[tctr]; // take this item in the test array and expand it out.
// curTest is an array of parameter group objects.
if (curTest && curTest.length) {
// Each object has a field that is one test (recursively).
var lastSet = [{}]; // array with one empty object. Important! Multiply by 1, not 0
for (var pctr = 0; pctr < curTest.length; pctr++) {
// part counter
var part = curTest[pctr]; // part should be an object. Each member ending in Test is a parameter group
var curSet = this.getAllWork(part, ''); // returns an array of multiplicable objects.
// multiply all the work from the lastSet by all the work in the curSet
var thisSet = this.multiplyObjects(curSet, lastSet);
lastSet = thisSet.slice(0); // clone array so that we don't alter the sets
}
allWork = allWork.concat(lastSet); // add this multiplied group of tests to the list of all tests to run.
}
}
var reactFactorialTest_filter = localStorage.getItem('reactFactorialTest_filter' + this.id) || '';
var reactFactorialTest_compsOnly = localStorage.getItem('reactFactorialTest_compsOnly' + this.id) || ''; // empty string implies false.
var reactFactorialTest_flagsOnly = localStorage.getItem('reactFactorialTest_flagsOnly' + this.id) || '';
var reactFactorialTest_smallMode = localStorage.getItem('reactFactorialTest_smallMode' + this.id) || '';
var reactFactorialTest_compList = JSON.parse(localStorage.getItem('reactFactorialTest_compList' + this.id)) || [];
var reactFactorialTest_flagList = JSON.parse(localStorage.getItem('reactFactorialTest_flagList' + this.id)) || [];
var visibleTestCount = 0;
//===== FILTERING PHASE =====
var renderList = allWork.map(function (item, index) {
// check if rendering all, or only a specific test.
// This filtering has a couple of notable things:
// 1) test are filtered for focus so the user can make repairs to a specific mixture of text parameters
// 2) test filter state is copied into window variables and used from there instead of from state.
// That way, the tests can re-load without losing your test focus or comparisons
// 3) any number of tests can be set for comparison, again controlled by window variables.
// this renders each item in allwork to an array, filtering out items that are not supposed to be rendered.
var holdName = item.tstName;
// It seems like this logic has to be checked twice in order to have things be performant and also work while in focused mode
if (
// if there's no filter or this test matches a filter, include it.
(!reactFactorialTest_filter || holdName === reactFactorialTest_filter) && (
// if there's no comparison, or if there is comparison and this test is in the list.
!reactFactorialTest_compsOnly || reactFactorialTest_compsOnly && reactFactorialTest_compList && -1 !== reactFactorialTest_compList.indexOf(holdName)) && (
// if there's no comparison, or if there is comparison and this test is in the list.
!reactFactorialTest_flagsOnly || reactFactorialTest_flagsOnly && reactFactorialTest_flagList && -1 !== reactFactorialTest_flagList.indexOf(holdName))) {
visibleTestCount++;
return _react2.default.createElement(_TestItem2.default, { key: index, index: index, item: item, target: _this2.props.target, smallMode: _this2.state.smallMode, id: _this2.id,
focusToggle: function focusToggle() {
return _this2.setFilter(holdName);
}
});
}
});
var unFocusButton = '';
var unCompareButton = '';
var unFlagButton = '';
/*
<div style={{ display: 'inline-block', padding: '2px', height: '18px',backgroundColor: 'lightgreen', border: '1px solid black' }}
onClick={() => this.setFilter('')}
title='UnFocus / Show All Tests'
>
<UnFilter width={18} height={18} />
</div>
*/
if (reactFactorialTest_filter || reactFactorialTest_compsOnly || reactFactorialTest_flagsOnly) {
unFocusButton = _react2.default.createElement(_UnFilter2.default, { onClick: function onClick() {
return _this2.setFilter('');
}, title: 'UnFocus / Show All Tests' });
} else {
unCompareButton = _react2.default.createElement(
'div',
{ style: { display: 'inline-block', padding: '2px', height: '18px', backgroundColor: 'lightgreen', border: '1px solid black' },
onClick: function onClick() {
return _this2.toggleCompVisible();
}, title: 'Focus On Comparison Tests'
},
_react2.default.createElement(_MagnifyIcon2.default, { width: 18, height: 18 }),
_react2.default.createElement(_CheckboxBlankIcon2.default, { width: 18, height: 18 })
);
unFlagButton = _react2.default.createElement(
'div',
{ style: { display: 'inline-block', padding: '2px', height: '18px', backgroundColor: 'lightgreen', border: '1px solid black' },
onClick: function onClick() {
return _this2.toggleFlagVisible();
}, title: 'Focus On Flagged Tests'
},
_react2.default.createElement(_MagnifyIcon2.default, { width: 18, height: 18 }),
_react2.default.createElement(_FlagVariantIcon2.default, { width: 18, height: 18 })
);
}
var goBigButton = _react2.default.createElement(
'div',
{ key: 'goBig', id: 'reactFactorialTest_goBig' + this.id, style: { display: 'inline-block', padding: '2px', height: '18px', backgroundColor: 'lightgreen', border: '1px solid black' },
onClick: function onClick() {
return _this2.goBig();
}, title: 'Toggle: One Test Per Line' },
_react2.default.createElement(_ArrowExpandAllIcon2.default, { width: 18, height: 18 })
);
var goSmallButton = _react2.default.createElement(
'div',
{ key: 'goSmall', id: 'reactFactorialTest_goSmall' + this.id, style: { display: 'inline-block', padding: '2px', height: '18px', backgroundColor: 'lightgreen', border: '1px solid black' },
onClick: function onClick() {
return _this2.goSmall();
}, title: 'Toggle: Compact Mode' },
_react2.default.createElement(_ArrowCollapseAllIcon2.default, { width: 18, height: 18 })
);
if (reactFactorialTest_smallMode) {
return _react2.default.createElement(
'div',
{ style: { padding: '5px' } },
_react2.default.createElement(
'div',
null,
allWork.length,
' Tests ',
visibleTestCount < allWork.length && _react2.default.createElement(
'span',
null,
'(',
allWork.length - visibleTestCount,
' filtered out)'
)
),
_react2.default.createElement(
'div',
null,
'Mouse over each test for details. Click above the test to flag for review.'
),
_react2.default.createElement(
'div',
null,
goBigButton,
'\xA0',
unFocusButton,
'\xA0',
unFlagButton
),
renderList
);
}
// I have considered using a virutal list here, but that removes the ability to performance test a large number of renders.
// So far, I've decided to leave it as is.
return _react2.default.createElement(
'div',
{ style: { padding: '5px' } },
_react2.default.createElement(
'div',
{ style: { position: 'absolute', left: 0, right: 0, top: 0, height: 50, borderBottom: '3px solid grey', padding: '10px' } },
_react2.default.createElement(
'div',
{ style: { fontSize: '1.5em' } },
allWork.length,
' Tests ',
visibleTestCount < allWork.length && _react2.default.createElement(
'span',
null,
'(',
allWork.length - visibleTestCount,
' filtered out)'
)
),
_react2.default.createElement(
'div',
null,
goSmallButton,
'\xA0',
unFocusButton,
'\xA0',
unFlagButton,
'\xA0',
unCompareButton,
'\xA0'
)
),
_react2.default.createElement(
'div',
{ style: { position: 'absolute', left: 0, right: 0, top: 73, bottom: 0, overflow: 'auto', padding: '5px' } },
renderList
)
);
}
}]);
return MultiTest;
}(_react2.default.Component);
exports.default = MultiTest;
module.exports = exports['default'];