diff --git a/test/jasmine/tests/pikul_test.js b/test/jasmine/tests/pikul_test.js index 4227fdc8611..097be31f3ff 100644 --- a/test/jasmine/tests/pikul_test.js +++ b/test/jasmine/tests/pikul_test.js @@ -4,6 +4,10 @@ var Plotly = require('../../../lib/index'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); +function makeSet(data) { // Returns array of only unique values from array + if(data === undefined || data.length === undefined || data.length === 0) return []; + return data.filter(function(value, index, array) { return array.indexOf(value) === index; }); +} // Boilerplate taken from axes_test.js describe('Generating ticks with `tickmode`,', function() { var gd; @@ -21,12 +25,12 @@ describe('Generating ticks with `tickmode`,', function() { // Passed as tickLen argument to specify a major or minor tick config var MAJOR = 10; var MINOR = 5; + function ticksOff() { return {ticklen: 0, showticklabels: false, nticks: 0}; } // es5 neither has copy() nor const function generateTickConfig(tickLen, tickmode, nticks) { if(tickmode === undefined) tickmode = 'domain array'; // Intentionally configure to produce a single `(x|y)tick` class per tick // labels and tick marks each produce one, so one or the other var standardConfig = {tickmode: tickmode, ticklen: tickLen, showticklabels: false}; - // Tick values will be random: if(tickmode === 'domain array') { var n = Math.floor(Math.random() * 100); @@ -40,10 +44,15 @@ describe('Generating ticks with `tickmode`,', function() { } else if(tickmode === 'full domain') { standardConfig.nticks = nticks; } + console.log("Generated Config:"); + console.log(standardConfig); return standardConfig; } + function areTicks(config) { + return (config !== undefined && config.ticklen !== undefined && config.ticklen !== 0); + } - // See comment below for explanation of parameterization + // numbers 0 through 15 are all possible combination of 4 boolean values (0001, 0010, 0011, 0100, 0101 ,etc) var XMAJOR = 1;// 0b0001; var XMINOR = 2;// 0b0010; var YMAJOR = 4;// 0b0100; @@ -74,170 +83,36 @@ describe('Generating ticks with `tickmode`,', function() { function getParameters(op) { // the var `tickConfig` represents every possible configuration. It is in an int 0-15. // The binary is 0001, 0010, 0011, etc. IE every possible combination of 4 booleans. - if (op === undefined) return {tickConfig: 0, graphTypeIndex: 0}; - if (++op.tickConfig > 15) op.tickConfig = 0; + if(op === undefined) return {tickConfig: 15, graphTypeIndex: 4}; // only run one parameterization + if(++op.tickConfig > 15) op.tickConfig = 0; else return op; - if (++op.graphTypeIndex >= graphTypes.length) return false; + if(++op.graphTypeIndex >= graphTypes.length) return false; return op; } // DO TESTS it('"domain array" and config', function(done) { for(var parameters = getParameters(); parameters; parameters = getParameters(parameters)) { - //console.log(parameters); view parameterization + console.log("domain array"); + console.log(parameters); //view parameterization var xGraphType = graphTypes[parameters.graphTypeIndex]; var tickConfig = parameters.tickConfig; - var xMajor = tickConfig & XMAJOR; // does this config include xmajor? - var xMinor = tickConfig & XMINOR; // does this config include xminor? - var yMajor = tickConfig & YMAJOR; // ... etc - var yMinor = tickConfig & YMINOR; - var ticksOff = {ticklen: 0, showticklabels: false}; - var xMajorConfig = xMajor ? generateTickConfig(MAJOR) : ticksOff; // generate configs - var xMinorConfig = xMinor ? generateTickConfig(MINOR) : ticksOff; - var yMajorConfig = yMajor ? generateTickConfig(MAJOR) : ticksOff; - var yMinorConfig = yMinor ? generateTickConfig(MINOR) : ticksOff; - var configInfo = ''; // for debugging - /* configInfo += xMajor ? '\n ' + 'xMajor: ' + new Set(xMajorConfig.tickvals).length + ' unique vals' : ''; - configInfo += xMinor ? '\n ' + 'xMinor: ' + new Set(xMinorConfig.tickvals).length + ' unique vals' : ''; - configInfo += yMajor ? '\n ' + 'yMajor: ' + new Set(yMajorConfig.tickvals).length + ' unique vals' : ''; - configInfo += yMinor ? '\n ' + 'yMinor: ' + new Set(yMinorConfig.tickvals).length + ' unique vals' : '';*/ - // TODO no set? - - var plotlyDict = { - data: [{ - x: [0, 1], - y: [0, 1] - }], - layout: { - width: 400, - height: 400, - margin: { t: 40, b: 40, l: 40, r: 40, }, - type: xGraphType, - xaxis: { - ...xMajorConfig, // explode config into this key - minor: xMinorConfig, - }, - yaxis: { - ...yMajorConfig, - minor: yMinorConfig, - }, - } - }; - // stolen from axes_test.js - Plotly.newPlot(gd, plotlyDict).then(function() { - // This regex is for extracting geometric position of a tick - // regex: `.source` converts to string, laid out this way to make for easier reading - var funcName = 'translate' + /\(/.source; // literally simplest way to regex '(' - var integerPart = /\d+/.source; // numbers left of decimal - var fractionalPart = /(?:\.\d+)?/.source; // decimal + numbers to right - var floatNum = integerPart + fractionalPart; // all together - var any = /.+/.source; - var close = /\)/.source; - var reX = new RegExp(funcName + '(' + floatNum + '),' + any + close); // parens () are capture not fn() - var reY = new RegExp(funcName + any + ',(' + floatNum + ')' + close); - - for(var runNumber = 1; runNumber <= 8; runNumber <<= 1) { // Check all ticks on all axes ☺ - var runInfo = '\n Checking: ' + binaryToTickType(runNumber); - var elementName = ''; - var targetConfig; - var re; - if(runNumber & xMajor) { // ie. (this run wants xMajor) & (xMajor was set in config above) - elementName = 'xtick'; - targetConfig = xMajorConfig; - re = reX; - } else if(runNumber & xMinor) { - elementName = 'xtick'; - targetConfig = xMinorConfig; - re = reX; - } else if(runNumber & yMajor) { - elementName = 'ytick'; - targetConfig = yMajorConfig; - re = reY; - } else if(runNumber & yMinor) { - elementName = 'ytick'; - targetConfig = yMinorConfig; - re = reY; - } else continue; // This run would have been to check ticks that don't exist - - var tickElements = document.getElementsByClassName(elementName); - var tickValsUnique = targetConfig.tickvals.filter(function(value, index, data) { return data.indexOf(value) === index; }); - var expectedTickLen = String(targetConfig.ticklen); - - - // Filter out major/minor and grab geometry - var transformVals = []; // "transform" ie the positional property - for(var i = 0; i < tickElements.length; i++) { - if(!tickElements[i].getAttribute('d').endsWith(expectedTickLen)) continue; - var translate = tickElements[i].getAttribute('transform'); - transformVals.push(Number(translate.match(re)[1])); - } - var debugInfo = '\n ' + 'tickElements: (' + tickElements.length + ') ' + tickElements + '\n ' + - 'tickVals/Unique: (' + targetConfig.tickvals.length + '/' + tickValsUnique.length + ') ' + tickValsUnique; + var xConfig = (tickConfig & XMAJOR) ? generateTickConfig(MAJOR) : ticksOff(); // generate configs + xConfig.minor = (tickConfig & XMINOR) ? generateTickConfig(MINOR) : ticksOff(); - expect(transformVals.length).toBe(tickValsUnique.length, - 'filtered tick elements vs tickvals failed' + runInfo + configInfo + debugInfo); + var yConfig = (tickConfig & MAJOR) ? generateTickConfig(MAJOR) : ticksOff(); + yConfig.minor = (tickConfig & YMINOR) ? generateTickConfig(MINOR) : ticksOff(); - if(transformVals.length < 2) return; // Can't test proportions with < 2 ticks (since no fixed reference) - - - // To test geometries without using fixed point or data values... - // we can check consistency of y = mx+b! (y is DOM position, x is proportion) - // If x = 0 then y = b, but we may not have a 0 valued x - // m = (y1 - y2) / (x1 - x2) - // b = y1 - mx1 - var y = transformVals; - var x = tickValsUnique; - var m, b; - var bIndex = x.indexOf(0); - - m = (y[0] - y[1]) / (x[0] - x[1]); - b = (bIndex !== -1) ? b = y[bIndex] : y[0] - m * x[0]; - - var calculatedY = []; - for(var k = 0; k < x.length; k++) { // linter didn't like I being here - calculatedY.push(m * x[k] + b); - } - - /* **** Close this comment line to manually inspect output --> - yout = []; - ycalcout = []; - for (i = 0; i < Math.min(x.length, 10); i++) { - yout.push(Number.parseFloat(y[i]).toFixed(2)); - ycalcout.push(Number.parseFloat(calculatedY[i]).toFixed(2)); - } - console.log(yout); - console.log(ycalcout);/* */ - expect(y).toBeCloseToArray(calculatedY, 'y=mx+b test failed comparing\n' + y + '\n' + calculatedY); - } - }).then(done, done.fail); - } - }); - it('"full domain" and config ', function(done) { - for(var parameters = getParameters(); parameters; parameters = getParameters(parameters)) { - //console.log(parameters); // view parameterization - var xGraphType = graphTypes[parameters.graphTypeIndex]; - var tickConfig = parameters.tickConfig; + var configInfo = ''; // for debugging + configInfo += areTicks(xConfig) ? '\n ' + 'xMajor: ' + makeSet(xConfig.tickvals).length + ' unique vals' : ''; + configInfo += areTicks(xConfig.minor) ? '\n ' + 'xMinor: ' + makeSet(xConfig.minor.tickvals).length + ' unique vals' : ''; + configInfo += areTicks(yConfig) ? '\n ' + 'yMajor: ' + makeSet(yConfig.tickvals).length + ' unique vals' : ''; + configInfo += areTicks(yConfig.minor) ? '\n ' + 'yMinor: ' + makeSet(yConfig.minor.tickvals).length + ' unique vals' : ''; - for(var nticks_param = 0; nticks_param < 5; nticks_param++) { // TODO: We've removed the closure function, move this INSIDE, then move graphtypes inside, then move tickconfig inside - // console.log(parameters); // for viewing parameterization - // console.log(" " + nticks_param); // for viewing parameterization - var xMajor = tickConfig & XMAJOR; // does this config include xmajor? - var xMinor = tickConfig & XMINOR; // does this config include xminor? - var yMajor = tickConfig & YMAJOR; // ... etc - var yMinor = tickConfig & YMINOR; - ticksOff = {ticklen: 0, showticklabels: false}; - var xMajorConfig = xMajor ? generateTickConfig(MAJOR, 'full domain', nticks_param) : ticksOff; // generate configs - var xMinorConfig = xMinor ? generateTickConfig(MINOR, 'full domain', nticks_param) : ticksOff; - var yMajorConfig = yMajor ? generateTickConfig(MAJOR, 'full domain', nticks_param) : ticksOff; - var yMinorConfig = yMinor ? generateTickConfig(MINOR, 'full domain', nticks_param) : ticksOff; - var configInfo = "" // for debugging - configInfo += xMajor ? "\n " + `xMajor nticks: ${xMajorConfig['nticks']}` : ""; - configInfo += xMinor ? "\n " + `xMinor nticks: ${xMinorConfig['nticks']}` : ""; - configInfo += yMajor ? "\n " + `yMajor nticks: ${yMajorConfig['nticks']}` : ""; - configInfo += yMinor ? "\n " + `yMinor nticks: ${yMinorConfig['nticks']}` : ""; - - // stolen from axes_test.js - Plotly.newPlot(gd, { + var variablesToInject = {configInfo: configInfo, gd: gd, parameters: parameters, xconfig: xConfig, yconfig: yConfig, xGraphType: xGraphType}; + (function(scopeLock) { + // stolen from axes_test.js + Plotly.newPlot(scopeLock.gd, { data: [{ x: [0, 1], y: [0, 1] @@ -246,21 +121,20 @@ describe('Generating ticks with `tickmode`,', function() { width: 400, height: 400, margin: { t: 40, b: 40, l: 40, r: 40, }, - ...xGraphType, - xaxis: { - autorange: true, - ...xMajorConfig, // explode config into this key - minor: xMinorConfig, // set config to this key - }, - yaxis: { // same as above - autorange: true, - ...yMajorConfig, - minor: yMinorConfig, - }, - }}).then(function() { + type: scopelock.xGraphType, + xaxis: scopelock.xConfig, // explode config into this key + yaxis: yConfig, + } + } + + ).then(function() { + var tickConfig = scopeLock.parameters.tickConfig; + var xConfig = scopeLock.parameters.xConfig; + var yConfig = scopeLock.parameters.yConfig; + var configInfo = scopeLock.configInfo; // This regex is for extracting geometric position of a tick // regex: `.source` converts to string, laid out this way to make for easier reading - var funcName = "translate" + /\(/.source; // literally simplest way to regex '(' + var funcName = 'translate' + /\(/.source; // literally simplest way to regex '(' var integerPart = /\d+/.source; // numbers left of decimal var fractionalPart = /(?:\.\d+)?/.source; // decimal + numbers to right var floatNum = integerPart + fractionalPart; // all together @@ -269,62 +143,54 @@ describe('Generating ticks with `tickmode`,', function() { var reX = new RegExp(funcName + '(' + floatNum + '),' + any + close); // parens () are capture not fn() var reY = new RegExp(funcName + any + ',(' + floatNum + ')' + close); - for(var runNumber = 1; runNumber <= 15; runNumber <<= 1) { // Check all ticks on all axes ☺ - var runInfo = "\n Checking: " + binaryToTickType(runNumber); - var elementName = ""; + for(var runNumber = 1; runNumber <= 8; runNumber <<= 1) { // Check all ticks on all axes ☺ + if(!(runNumber & tickConfig)) { + console.log("Continuing because..." + String(runNumber) + " & " + String(tickConfig)) + continue; + } + var runInfo = '\n Checking: ' + binaryToTickType(runNumber); + var elementName = ''; var targetConfig; var re; - if(runNumber & xMajor) { // ie. (this run wants xMajor) & (xMajor was set in config above) - elementName = "xtick"; - targetConfig = xMajorConfig; + if(runNumber & XMAJOR) { // ie. (this run wants xMajor) & (xMajor was set in config above) + elementName = 'xtick'; + targetConfig = xConfig; re = reX; - } else if(runNumber & xMinor) { - elementName = "xtick"; - targetConfig = xMinorConfig; + } else if(runNumber & XMINOR) { + elementName = 'xtick'; + targetConfig = xConfig.minor; re = reX; - } else if(runNumber & yMajor) { - elementName = "ytick"; - targetConfig = yMajorConfig; + } else if(runNumber & YMAJOR) { + elementName = 'ytick'; + targetConfig = yConfig; re = reY; - } else if(runNumber & yMinor) { - elementName = "ytick"; - targetConfig = yMinorConfig; + } else if(runNumber & YMINOR) { + elementName = 'ytick'; + targetConfig = yConfig.minor; re = reY; - } else continue; // This run would have been to check ticks that don't exist - - var tickElements = document.getElementsByClassName(elementName); - var nt = targetConfig['nticks']; - var expectedTickLen = String(targetConfig['ticklen']) - var tickValsUnique = new Array(); - if (nt == 0) { - // pass - } else if (nt == 1) { - tickValsUnique = [0]; - } else if (nt == 2) { - tickValsUnique = [0, 1]; } else { - var increment = 1/(nt-1); // (nt-2) + 1 - tickValsUnique.push(0); - for (var i = 0; i < nt-2; i++) { - tickValsUnique.push((i+1)*increment); - } - tickValsUnique.push(1); + console.log("Shouldn't have gotten here"); + continue; // This run would have been to check ticks that don't exist } + + var tickElements = document.getElementsByClassName(elementName); + var tickValsUnique = makeSet(targetConfig.tickvals); + var expectedTickLen = String(targetConfig.ticklen); + + // Filter out major/minor and grab geometry - transformVals = []; // "transform" ie the positional property + var transformVals = []; // "transform" ie the positional property for(var i = 0; i < tickElements.length; i++) { - if(!tickElements[i].getAttribute("d").endsWith(expectedTickLen)) continue; - var translate = tickElements[i].getAttribute("transform"); - var match = translate.match(re); - if (match === null) continue; - transformVals.push(Number(match[1])); + if(!tickElements[i].getAttribute('d').endsWith(expectedTickLen)) continue; + var translate = tickElements[i].getAttribute('transform'); + transformVals.push(Number(translate.match(re)[1])); } - var debugInfo = "\n " + `tickElements: (${tickElements.length}) ${tickElements}` + "\n " + - `nticks: ${tickValsUnique.length}`; + var debugInfo = '\n ' + 'tickElements: (' + tickElements.length + ') ' + tickElements + '\n ' + + 'tickVals/Unique: (' + targetConfig.tickvals.length + '/' + tickValsUnique.length + ') ' + tickValsUnique; expect(transformVals.length).toBe(tickValsUnique.length, - "filtered tick elements vs tickvals failed" + runInfo + configInfo + debugInfo); + 'filtered tick elements vs tickvals failed' + runInfo + configInfo + debugInfo); if(transformVals.length < 2) return; // Can't test proportions with < 2 ticks (since no fixed reference) @@ -334,29 +200,200 @@ describe('Generating ticks with `tickmode`,', function() { // If x = 0 then y = b, but we may not have a 0 valued x // m = (y1 - y2) / (x1 - x2) // b = y1 - mx1 - y = transformVals; - x = tickValsUnique; + var y = transformVals; + var x = tickValsUnique; var m, b; var bIndex = x.indexOf(0); m = (y[0] - y[1]) / (x[0] - x[1]); - b = (bIndex != -1) ? b = y[bIndex] : y[0] - m*x[0]; - - calculatedY = []; - for(var i = 0; i < x.length; i++) calculatedY.push(m*x[i] + b); - - /* **** Close this comment line to manually inspect output --> - yout = []; - ycalcout = []; - for (i = 0; i < Math.min(x.length, 10); i++) { - yout.push(Number.parseFloat(y[i]).toFixed(2)); - ycalcout.push(Number.parseFloat(calculatedY[i]).toFixed(2)); - } - console.log(yout); - console.log(ycalcout);/**/ - expect(y).toBeCloseToArray(calculatedY, 1, `y=mx+b test failed comparing\n${y}\n${calculatedY}`); + b = (bIndex !== -1) ? b = y[bIndex] : y[0] - m * x[0]; + + var calculatedY = []; + for(var k = 0; k < x.length; k++) { // linter didn't like I being here + calculatedY.push(m * x[k] + b); + } + + /* THIS WOULD BE TO MANUALLY INSPECT OUTPUT */ + // yout = []; + // ycalcout = []; + // for (i = 0; i < Math.min(x.length, 10); i++) { + // yout.push(Number.parseFloat(y[i]).toFixed(2)); + // ycalcout.push(Number.parseFloat(calculatedY[i]).toFixed(2)); + // } + // console.log(yout); + // console.log(ycalcout); + expect(y).toBeCloseToArray(calculatedY, 'y=mx+b test failed comparing\n' + y + '\n' + calculatedY); } }).then(done, done.fail); + })(variablesToInject); + } + }); + fit('"full domain" and config ', function(done) { + for(var parameters = getParameters(); parameters; parameters = getParameters(parameters)) { + console.log("\nMain Loop Start:"); + console.log(parameters); // for viewing parameterization + var xGraphType = graphTypes[parameters.graphTypeIndex]; + var tickConfig = parameters.tickConfig; + for(var nTicksParameter = 1; nTicksParameter < 3; nTicksParameter++) { // TODO + console.log("Nticks loop start:"); + console.log(" " + String(nTicksParameter)); // for viewing parameterization + + console.log("xConfig"); + var xConfig = (tickConfig & XMAJOR) ? generateTickConfig(MAJOR, 'full domain', nTicksParameter) : ticksOff(); + xConfig.minor = (tickConfig & XMINOR) ? generateTickConfig(MINOR, 'full domain', nTicksParameter) : ticksOff(); + console.log("returned"); + console.log(xConfig); + console.log("yConfig"); + var yConfig = (tickConfig & MAJOR) ? generateTickConfig(MAJOR, 'full domain', nTicksParameter) : ticksOff(); + yConfig.minor = (tickConfig & YMINOR) ? generateTickConfig(MINOR, 'full domain', nTicksParameter) : ticksOff(); + console.log("returned"); + console.log(yConfig); + var variablesToInject = {gd: JSON.parse(JSON.stringify(gd)), xConfig: xConfig, yConfig: yConfig, xGraphType: xGraphType, tickConfig: tickConfig, nTicksParameter: nTicksParameter}; + (function(scopeLock) { + console.log("Variables received by scope locking function:"); + console.log(" nTicks "+ scopeLock.nTicksParameter); + console.log(" xConfig "); + console.log(scopeLock.xConfig); + console.log(" yConfig ") + console.log(scopeLock.yConfig); + console.log(" xGraphType "+ scopeLock.xGraphType); + console.log(" tickConfig "+ scopeLock.tickConfig); + Plotly.newPlot(scopeLock.gd, { + data: [{ + x: [0, 1], + y: [0, 1] + }], + layout: { + width: 400, + height: 400, + margin: { t: 40, b: 40, l: 40, r: 40, }, + type: scopeLock.xGraphType, + xaxis: scopeLock.xConfig, + yaxis: scopeLock.yConfig, + } + }).then(function() { + console.log("\n-full domain"); + console.log("tickConfig: " + String(scopeLock.tickConfig)); // view parameterization + console.log("nTicks: " + String(scopeLock.nTicksParameter)); + var tickConfig = scopeLock.tickConfig; + var xConfig = scopeLock.xConfig; + var yConfig = scopeLock.yConfig; + var configInfo = scopeLock.configInfo; + // This regex is for extracting geometric position of a tick + // regex: `.source` converts to string, laid out this way to make for easier reading + var funcName = 'translate' + /\(/.source; // literally simplest way to regex '(' + var integerPart = /\d+/.source; // numbers left of decimal + var fractionalPart = /(?:\.\d+)?/.source; // decimal + numbers to right + var floatNum = integerPart + fractionalPart; // all together + var any = /.+/.source; + var close = /\)/.source; + var reX = new RegExp(funcName + '(' + floatNum + '),' + any + close); // parens () are capture not fn() + var reY = new RegExp(funcName + any + ',(' + floatNum + ')' + close); + + for(var runNumber = 1; runNumber <= 15; runNumber <<= 1) { // Check all ticks on all axes ☺ + if(!(runNumber & tickConfig)) { + console.log("Skipping a run number " + String(runNumber) + " because config doesn't include it"); + continue; + } + var runInfo = '\n Checking: ' + binaryToTickType(runNumber); + var elementName = ''; + var targetConfig; + var re; + if(runNumber & XMAJOR) { // ie. (this run wants xMajor) & (xMajor was set in config above) + elementName = 'xtick'; + targetConfig = xConfig; + re = reX; + } else if(runNumber & XMINOR) { + elementName = 'xtick'; + targetConfig = xConfig.minor; + re = reX; + } else if(runNumber & YMAJOR) { + elementName = 'ytick'; + targetConfig = yConfig; + re = reY; + } else if(runNumber & YMINOR) { + elementName = 'ytick'; + targetConfig = yConfig.minor; + re = reY; + } else { + console.log("Shouldn't reach this continue"); + continue; + } + + var tickElements = scopeLock.gd.getElementsByClassName(elementName); // Document may have changed and there is nothing we can do about that. + console.log("Found elements"); + console.log("For run: " + String(runNumber) + " " + runInfo); + console.log(targetConfig); + var nt = targetConfig.nticks; + var expectedTickLen = String(targetConfig.ticklen); + var tickValsUnique = new Array(); + if(nt === 0) { + // pass + } else if(nt === 1) { + tickValsUnique = [0]; + } else if(nt === 2) { + tickValsUnique = [0, 1]; + } else { + var increment = 1 / (nt - 1); // (nt-2) + 1 + tickValsUnique.push(0); + for(var i = 0; i < nt - 2; i++) { + tickValsUnique.push((i + 1) * increment); + } + tickValsUnique.push(1); + } + console.log("Expecting tick vals: " + String(tickValsUnique)); + console.log("Length: " + String(tickValsUnique.length)); + // Filter out major/minor and grab geometry + var transformVals = []; // "transform" ie the positional property + console.log("Found ticks: " + String(tickElements.length)); + for(var i = 0; i < tickElements.length; i++) { + if(!tickElements[i].getAttribute('d').endsWith(expectedTickLen)) continue; + console.log("Found a relevant tick:"); + console.log(tickElements[i]); + var translate = tickElements[i].getAttribute('transform'); + var match = translate.match(re); + if(match === null) continue; + transformVals.push(Number(match[1])); + } + console.log("Found filtered ticks: " + String(transformVals.length)); + var debugInfo = '\n ' + 'tickElements: (' + tickElements.length + ') ' + tickElements + '\n ' + + 'nticks: ' + tickValsUnique.length; // Why is this 0 + + expect(transformVals.length).toBe(tickValsUnique.length, + 'filtered tick elements vs tickvals failed' + runInfo + configInfo + debugInfo); + + if(transformVals.length < 2) return; // Can't test proportions with < 2 ticks (since no fixed reference) + + + // To test geometries without using fixed point or data values... + // we can check consistency of y = mx+b! (y is DOM position, x is proportion) + // If x = 0 then y = b, but we may not have a 0 valued x + // m = (y1 - y2) / (x1 - x2) + // b = y1 - mx1 + var y = transformVals; + var x = tickValsUnique; + var m, b; + var bIndex = x.indexOf(0); + + m = (y[0] - y[1]) / (x[0] - x[1]); + b = (bIndex != -1) ? b = y[bIndex] : y[0] - m * x[0]; + + calculatedY = []; + for(var i = 0; i < x.length; i++) calculatedY.push(m * x[i] + b); + + /* **** Close this comment line to manually inspect output --> */ + // yout = []; + // ycalcout = []; + // for (i = 0; i < Math.min(x.length, 10); i++) { + // yout.push(Number.parseFloat(y[i]).toFixed(2)); + // ycalcout.push(Number.parseFloat(calculatedY[i]).toFixed(2)); + // } + // console.log(yout); + // console.log(ycalcout); + expect(y).toBeCloseToArray(calculatedY, 1, 'y=mx+b test failed comparing\n' + y + '\n' + calculatedY); + } + }).then(done, done.fail); + }(variablesToInject)); } } });