UNPKG

react-factorial-test

Version:

Generate component test buy using multiplication on parameter sets

461 lines (392 loc) 21.3 kB
'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'];