From 40dd784546bbc41f8a1e874bd737135ff235cdb9 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Sat, 24 Feb 2018 21:16:49 -0500 Subject: [PATCH] validate info_array, make grid defaults work better with validate --- src/plot_api/validate.js | 56 ++++++++++++++++++++++--- src/plots/grid.js | 3 ++ test/jasmine/tests/validate_test.js | 65 +++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 5 deletions(-) diff --git a/src/plot_api/validate.js b/src/plot_api/validate.js index 8f163fb92c9..0b77146a4e1 100644 --- a/src/plot_api/validate.js +++ b/src/plot_api/validate.js @@ -164,9 +164,10 @@ function crawl(objIn, objOut, schema, list, base, path) { var valIn = objIn[k], valOut = objOut[k]; - var nestedSchema = getNestedSchema(schema, k), - isInfoArray = (nestedSchema || {}).valType === 'info_array', - isColorscale = (nestedSchema || {}).valType === 'colorscale'; + var nestedSchema = getNestedSchema(schema, k); + var isInfoArray = (nestedSchema || {}).valType === 'info_array'; + var isColorscale = (nestedSchema || {}).valType === 'colorscale'; + var items = (nestedSchema || {}).items; if(!isInSchema(schema, k)) { list.push(format('schema', base, p)); @@ -174,9 +175,54 @@ function crawl(objIn, objOut, schema, list, base, path) { else if(isPlainObject(valIn) && isPlainObject(valOut)) { crawl(valIn, valOut, nestedSchema, list, base, p); } + else if(isInfoArray && isArray(valIn)) { + if(valIn.length > valOut.length) { + list.push(format('unused', base, p.concat(valOut.length))); + } + var len = valOut.length; + var arrayItems = Array.isArray(items); + if(arrayItems) len = Math.min(len, items.length); + var m, n, item, valInPart, valOutPart; + if(nestedSchema.dimensions === 2) { + for(n = 0; n < len; n++) { + if(isArray(valIn[n])) { + if(valIn[n].length > valOut[n].length) { + list.push(format('unused', base, p.concat(n, valOut[n].length))); + } + var len2 = valOut[n].length; + for(m = 0; m < (arrayItems ? Math.min(len2, items[n].length) : len2); m++) { + item = arrayItems ? items[n][m] : items; + valInPart = valIn[n][m]; + valOutPart = valOut[n][m]; + if(!Lib.validate(valInPart, item)) { + list.push(format('value', base, p.concat(n, m), valInPart)); + } + else if(valOutPart !== valInPart && valOutPart !== +valInPart) { + list.push(format('dynamic', base, p.concat(n, m), valInPart, valOutPart)); + } + } + } + else { + list.push(format('array', base, p.concat(n), valIn[n])); + } + } + } + else { + for(n = 0; n < len; n++) { + item = arrayItems ? items[n] : items; + valInPart = valIn[n]; + valOutPart = valOut[n]; + if(!Lib.validate(valInPart, item)) { + list.push(format('value', base, p.concat(n), valInPart)); + } + else if(valOutPart !== valInPart && valOutPart !== +valInPart) { + list.push(format('dynamic', base, p.concat(n), valInPart, valOutPart)); + } + } + } + } else if(nestedSchema.items && !isInfoArray && isArray(valIn)) { - var items = nestedSchema.items, - _nestedSchema = items[Object.keys(items)[0]], + var _nestedSchema = items[Object.keys(items)[0]], indexList = []; var j, _p; diff --git a/src/plots/grid.js b/src/plots/grid.js index 0943f0a6dbd..030022e196c 100644 --- a/src/plots/grid.js +++ b/src/plots/grid.js @@ -276,6 +276,8 @@ exports.contentDefaults = function(layoutIn, layoutOut) { } else subplotId = rowIn[j]; + rowOut[j] = ''; + if(subplots.cartesian.indexOf(subplotId) !== -1) { yPos = subplotId.indexOf('y'); xId = subplotId.slice(0, yPos); @@ -390,6 +392,7 @@ function fillGridAxes(axesIn, axesAllowed, len, axisMap, axLetter) { out[i] = axisId; axisMap[axisId] = i; } + else out[i] = ''; } if(Array.isArray(axesIn)) { diff --git a/test/jasmine/tests/validate_test.js b/test/jasmine/tests/validate_test.js index 3014e3540a3..ad12aeefd50 100644 --- a/test/jasmine/tests/validate_test.js +++ b/test/jasmine/tests/validate_test.js @@ -440,4 +440,69 @@ describe('Plotly.validate', function() { 'In layout, key yaxis2.overlaying (set to \'x\') got reset to \'false\' during defaults.' ); }); + + it('catches bad axes in grid definitions', function() { + var out = Plotly.validate([ + {y: [1, 2]}, + {y: [1, 2], xaxis: 'x2', yaxis: 'y2'} + ], { + grid: {xaxes: ['x3', '', 'x2', 4], yaxes: ['y', 3, '', 'y4']}, + // while we're at it check on another info_array + xaxis: {range: [5, 'lots']} + }); + + expect(out.length).toBe(5); + assertErrorContent( + out[0], 'dynamic', 'layout', null, + ['grid', 'xaxes', 0], 'grid.xaxes[0]', + 'In layout, key grid.xaxes[0] (set to \'x3\') got reset to \'\' during defaults.' + ); + assertErrorContent( + out[1], 'value', 'layout', null, + ['grid', 'xaxes', 3], 'grid.xaxes[3]', + 'In layout, key grid.xaxes[3] is set to an invalid value (4)' + ); + assertErrorContent( + out[2], 'value', 'layout', null, + ['grid', 'yaxes', 1], 'grid.yaxes[1]', + 'In layout, key grid.yaxes[1] is set to an invalid value (3)' + ); + assertErrorContent( + out[3], 'dynamic', 'layout', null, + ['grid', 'yaxes', 3], 'grid.yaxes[3]', + 'In layout, key grid.yaxes[3] (set to \'y4\') got reset to \'\' during defaults.' + ); + assertErrorContent( + out[4], 'dynamic', 'layout', null, + ['xaxis', 'range', 1], 'xaxis.range[1]', + 'In layout, key xaxis.range[1] (set to \'lots\') got reset to \'50\' during defaults.' + ); + }); + + it('catches bad subplots in grid definitions', function() { + var out = Plotly.validate([ + {y: [1, 2]}, + {y: [1, 2], xaxis: 'x2', yaxis: 'y2'}, + {y: [1, 2], xaxis: 'x2'} + ], { + grid: {subplots: [['xy', 'x2y3'], ['x2y', 'x2y2'], [5, '']]}, + }); + + expect(out.length).toBe(3); + assertErrorContent( + out[0], 'dynamic', 'layout', null, + ['grid', 'subplots', 0, 1], 'grid.subplots[0][1]', + 'In layout, key grid.subplots[0][1] (set to \'x2y3\') got reset to \'\' during defaults.' + ); + assertErrorContent( + out[1], 'dynamic', 'layout', null, + ['grid', 'subplots', 1, 0], 'grid.subplots[1][0]', + 'In layout, key grid.subplots[1][0] (set to \'x2y\') got reset to \'\' during defaults.' + ); + assertErrorContent( + out[2], 'value', 'layout', null, + ['grid', 'subplots', 2, 0], 'grid.subplots[2][0]', + 'In layout, key grid.subplots[2][0] is set to an invalid value (5)' + ); + }); });