From 28d073f9065ce115be776a5e0edd8f710291b999 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Mon, 2 Apr 2018 20:10:32 -0400 Subject: [PATCH 01/10] clean up catch/done in plot_api_test --- test/jasmine/tests/plot_api_test.js | 381 +++++++++++++++------------- 1 file changed, 200 insertions(+), 181 deletions(-) diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 1924111d1a0..20e735b769e 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -16,7 +16,7 @@ var images = require('@src/components/images'); var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); -var fail = require('../assets/fail_test'); +var failTest = require('../assets/fail_test'); var checkTicks = require('../assets/custom_assertions').checkTicks; var supplyAllDefaults = require('../assets/supply_defaults'); @@ -48,7 +48,9 @@ describe('Test plot api', function() { expect(gd.layout.height).toEqual(500); expect(gd.data.length).toEqual(1); expect(gd._context.editable).toBe(true); - }).catch(fail).then(done); + }) + .catch(failTest) + .then(done); }); it('accepts gd and an object as args', function(done) { @@ -63,7 +65,9 @@ describe('Test plot api', function() { expect(gd.data.length).toEqual(1); expect(gd._transitionData._frames.length).toEqual(1); expect(gd._context.editable).toBe(true); - }).catch(fail).then(done); + }) + .catch(failTest) + .then(done); }); it('allows adding more frames to the initial set', function(done) { @@ -88,7 +92,9 @@ describe('Test plot api', function() { expect(gd._transitionData._frames[0].name).toEqual('frame1'); expect(gd._transitionData._frames[1].name).toEqual('frame2'); expect(gd._transitionData._frames[2].name).toEqual('frame3'); - }).catch(fail).then(done); + }) + .catch(failTest) + .then(done); }); it('should emit afterplot event after plotting is done', function(done) { @@ -103,6 +109,7 @@ describe('Test plot api', function() { promise.then(function() { expect(afterPlot).toBe(true); }) + .catch(failTest) .then(done); }); }); @@ -128,70 +135,74 @@ describe('Test plot api', function() { it('should update the plot clipPath if the plot is resized', function(done) { Plotly.plot(gd, [{ x: [1, 2, 3], y: [1, 2, 3] }], { width: 500, height: 500 }) - .then(function() { - return Plotly.relayout(gd, { width: 400, height: 400 }); - }) - .then(function() { - var uid = gd._fullLayout._uid; - - var plotClip = document.getElementById('clip' + uid + 'xyplot'), - clipRect = plotClip.children[0], - clipWidth = +clipRect.getAttribute('width'), - clipHeight = +clipRect.getAttribute('height'); - - expect(clipWidth).toBe(240); - expect(clipHeight).toBe(220); - }) - .then(done); + .then(function() { + return Plotly.relayout(gd, { width: 400, height: 400 }); + }) + .then(function() { + var uid = gd._fullLayout._uid; + + var plotClip = document.getElementById('clip' + uid + 'xyplot'), + clipRect = plotClip.children[0], + clipWidth = +clipRect.getAttribute('width'), + clipHeight = +clipRect.getAttribute('height'); + + expect(clipWidth).toBe(240); + expect(clipHeight).toBe(220); + }) + .catch(failTest) + .then(done); }); it('sets null values to their default', function(done) { var defaultWidth; Plotly.plot(gd, [{ x: [1, 2, 3], y: [1, 2, 3] }]) - .then(function() { - defaultWidth = gd._fullLayout.width; - return Plotly.relayout(gd, { width: defaultWidth - 25}); - }) - .then(function() { - expect(gd._fullLayout.width).toBe(defaultWidth - 25); - return Plotly.relayout(gd, { width: null }); - }) - .then(function() { - expect(gd._fullLayout.width).toBe(defaultWidth); - }) - .then(done); + .then(function() { + defaultWidth = gd._fullLayout.width; + return Plotly.relayout(gd, { width: defaultWidth - 25}); + }) + .then(function() { + expect(gd._fullLayout.width).toBe(defaultWidth - 25); + return Plotly.relayout(gd, { width: null }); + }) + .then(function() { + expect(gd._fullLayout.width).toBe(defaultWidth); + }) + .catch(failTest) + .then(done); }); it('ignores undefined values', function(done) { var defaultWidth; Plotly.plot(gd, [{ x: [1, 2, 3], y: [1, 2, 3] }]) - .then(function() { - defaultWidth = gd._fullLayout.width; - return Plotly.relayout(gd, { width: defaultWidth - 25}); - }) - .then(function() { - expect(gd._fullLayout.width).toBe(defaultWidth - 25); - return Plotly.relayout(gd, { width: undefined }); - }) - .then(function() { - expect(gd._fullLayout.width).toBe(defaultWidth - 25); - }) - .then(done); + .then(function() { + defaultWidth = gd._fullLayout.width; + return Plotly.relayout(gd, { width: defaultWidth - 25}); + }) + .then(function() { + expect(gd._fullLayout.width).toBe(defaultWidth - 25); + return Plotly.relayout(gd, { width: undefined }); + }) + .then(function() { + expect(gd._fullLayout.width).toBe(defaultWidth - 25); + }) + .catch(failTest) + .then(done); }); it('can set items in array objects', function(done) { Plotly.plot(gd, [{ x: [1, 2, 3], y: [1, 2, 3] }]) - .then(function() { - return Plotly.relayout(gd, {rando: [1, 2, 3]}); - }) - .then(function() { - expect(gd.layout.rando).toEqual([1, 2, 3]); - return Plotly.relayout(gd, {'rando[1]': 45}); - }) - .then(function() { - expect(gd.layout.rando).toEqual([1, 45, 3]); - }) - .then(done); + .then(function() { + return Plotly.relayout(gd, {rando: [1, 2, 3]}); + }) + .then(function() { + expect(gd.layout.rando).toEqual([1, 2, 3]); + return Plotly.relayout(gd, {'rando[1]': 45}); + }) + .then(function() { + expect(gd.layout.rando).toEqual([1, 45, 3]); + }) + .catch(failTest) + .then(done); }); it('errors if child and parent are edited together', function(done) { @@ -200,34 +211,34 @@ describe('Test plot api', function() { var edit3 = {'rando[1].d': 4}; Plotly.plot(gd, [{ x: [1, 2, 3], y: [1, 2, 3] }]) - .then(function() { - return Plotly.relayout(gd, edit1); - }) - .then(function() { - expect(gd.layout.rando).toEqual([{a: 1}, {b: 2}]); - return Plotly.relayout(gd, edit2); - }) - .then(function() { - expect(gd.layout.rando).toEqual([{a: 1}, {c: 3}]); - return Plotly.relayout(gd, edit3); - }) - .then(function() { - expect(gd.layout.rando).toEqual([{a: 1}, {c: 3, d: 4}]); - - // OK, setup is done - test the failing combinations - [[edit1, edit2], [edit1, edit3], [edit2, edit3]].forEach(function(v) { - // combine properties in both orders - which results in the same object - // but the properties are iterated in opposite orders - expect(function() { - return Plotly.relayout(gd, Lib.extendFlat({}, v[0], v[1])); - }).toThrow(); - expect(function() { - return Plotly.relayout(gd, Lib.extendFlat({}, v[1], v[0])); - }).toThrow(); - }); - }) - .catch(fail) - .then(done); + .then(function() { + return Plotly.relayout(gd, edit1); + }) + .then(function() { + expect(gd.layout.rando).toEqual([{a: 1}, {b: 2}]); + return Plotly.relayout(gd, edit2); + }) + .then(function() { + expect(gd.layout.rando).toEqual([{a: 1}, {c: 3}]); + return Plotly.relayout(gd, edit3); + }) + .then(function() { + expect(gd.layout.rando).toEqual([{a: 1}, {c: 3, d: 4}]); + + // OK, setup is done - test the failing combinations + [[edit1, edit2], [edit1, edit3], [edit2, edit3]].forEach(function(v) { + // combine properties in both orders - which results in the same object + // but the properties are iterated in opposite orders + expect(function() { + return Plotly.relayout(gd, Lib.extendFlat({}, v[0], v[1])); + }).toThrow(); + expect(function() { + return Plotly.relayout(gd, Lib.extendFlat({}, v[1], v[0])); + }).toThrow(); + }); + }) + .catch(failTest) + .then(done); }); it('can set empty text nodes', function(done) { @@ -240,16 +251,17 @@ describe('Test plot api', function() { var scatter = null; var oldHeight = 0; Plotly.plot(gd, data) - .then(function() { - scatter = document.getElementsByClassName('scatter')[0]; - oldHeight = scatter.getBoundingClientRect().height; - return Plotly.relayout(gd, 'yaxis.range', [0.5, 0.5, 0.5]); - }) - .then(function() { - var newHeight = scatter.getBoundingClientRect().height; - expect(newHeight).toEqual(oldHeight); - }) - .then(done); + .then(function() { + scatter = document.getElementsByClassName('scatter')[0]; + oldHeight = scatter.getBoundingClientRect().height; + return Plotly.relayout(gd, 'yaxis.range', [0.5, 0.5, 0.5]); + }) + .then(function() { + var newHeight = scatter.getBoundingClientRect().height; + expect(newHeight).toEqual(oldHeight); + }) + .catch(failTest) + .then(done); }); it('should skip empty axis objects', function(done) { @@ -263,7 +275,7 @@ describe('Test plot api', function() { .then(function() { return Plotly.relayout(gd, { zaxis: {} }); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -336,7 +348,7 @@ describe('Test plot api', function() { expect(getShapePos()).toBeCloseToArray([350, 369]); expect(getImagePos()).toBeCloseToArray([170, 272.52]); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -375,7 +387,7 @@ describe('Test plot api', function() { expect(gd.layout.yaxis.autorange).toBe(false); expect(gd.layout.yaxis.range[1]).toBe(3); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -394,7 +406,7 @@ describe('Test plot api', function() { .then(function() { expect(gd.layout.scene.aspectmode).toBe('auto'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -419,7 +431,7 @@ describe('Test plot api', function() { expect(gd.layout.xaxis.tick0).toBeUndefined(); expect(gd.layout.yaxis.dtick).toBeUndefined(); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -441,7 +453,7 @@ describe('Test plot api', function() { expect(gd.layout.xaxis.range).toBeCloseToArray([1, 10], 5); expect(gd.layout.yaxis.range).toBeCloseToArray([0, 1], 5); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -467,7 +479,7 @@ describe('Test plot api', function() { // make sure it's a real loggy range expect(xRange[0]).toBeLessThan(1); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -492,7 +504,7 @@ describe('Test plot api', function() { expect(gd._fullLayout.xaxis.type).toBe('linear'); expect(gd.layout.xaxis.range).toEqual([0.6, 1.7]); }) - .catch(fail) + .catch(failTest) .then(done); }); }); @@ -913,7 +925,7 @@ describe('Test plot api', function() { expect(gd.data[0].contours).toEqual({start: 3, end: 9, size: 1}); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -923,34 +935,34 @@ describe('Test plot api', function() { var edit3 = {'rando[1].d': 4}; Plotly.plot(gd, [{x: [1, 2, 3], y: [1, 2, 3], type: 'scatter'}]) - .then(function() { - return Plotly.restyle(gd, edit1); - }) - .then(function() { - expect(gd.data[0].rando).toEqual([{a: 1}, {b: 2}]); - return Plotly.restyle(gd, edit2); - }) - .then(function() { - expect(gd.data[0].rando).toEqual([{a: 1}, {c: 3}]); - return Plotly.restyle(gd, edit3); - }) - .then(function() { - expect(gd.data[0].rando).toEqual([{a: 1}, {c: 3, d: 4}]); - - // OK, setup is done - test the failing combinations - [[edit1, edit2], [edit1, edit3], [edit2, edit3]].forEach(function(v) { - // combine properties in both orders - which results in the same object - // but the properties are iterated in opposite orders - expect(function() { - return Plotly.restyle(gd, Lib.extendFlat({}, v[0], v[1])); - }).toThrow(); - expect(function() { - return Plotly.restyle(gd, Lib.extendFlat({}, v[1], v[0])); - }).toThrow(); - }); - }) - .catch(fail) - .then(done); + .then(function() { + return Plotly.restyle(gd, edit1); + }) + .then(function() { + expect(gd.data[0].rando).toEqual([{a: 1}, {b: 2}]); + return Plotly.restyle(gd, edit2); + }) + .then(function() { + expect(gd.data[0].rando).toEqual([{a: 1}, {c: 3}]); + return Plotly.restyle(gd, edit3); + }) + .then(function() { + expect(gd.data[0].rando).toEqual([{a: 1}, {c: 3, d: 4}]); + + // OK, setup is done - test the failing combinations + [[edit1, edit2], [edit1, edit3], [edit2, edit3]].forEach(function(v) { + // combine properties in both orders - which results in the same object + // but the properties are iterated in opposite orders + expect(function() { + return Plotly.restyle(gd, Lib.extendFlat({}, v[0], v[1])); + }).toThrow(); + expect(function() { + return Plotly.restyle(gd, Lib.extendFlat({}, v[1], v[0])); + }).toThrow(); + }); + }) + .catch(failTest) + .then(done); }); it('turns off zauto when you edit zmin or zmax', function(done) { @@ -986,7 +998,7 @@ describe('Test plot api', function() { .then(function() { check(false, 'undo'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1037,7 +1049,7 @@ describe('Test plot api', function() { .then(function() { check(false, 'undo'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1077,7 +1089,7 @@ describe('Test plot api', function() { .then(function() { check(false, 'undo'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1114,7 +1126,7 @@ describe('Test plot api', function() { .then(function() { check(false, 'undo'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1141,7 +1153,7 @@ describe('Test plot api', function() { .then(function() { check(false, 'undo'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1180,7 +1192,7 @@ describe('Test plot api', function() { .then(function() { check(false, 'undo'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1201,7 +1213,7 @@ describe('Test plot api', function() { .then(function() { expect(d3.select('.cbaxis').size()).toBe(0); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1220,7 +1232,7 @@ describe('Test plot api', function() { .then(function() { expect(d3.select('.cbaxis').size()).toBe(0); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1244,7 +1256,7 @@ describe('Test plot api', function() { checkTicks('x', ['12', '12.5'], 'switched to numeric'); expect(gd._fullLayout.xaxis.type).toBe('linear'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1258,7 +1270,7 @@ describe('Test plot api', function() { .then(function() { expect(gd._fullLayout.scene.zaxis.type).toBe('category'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -1273,7 +1285,7 @@ describe('Test plot api', function() { expect(gd._fullLayout._axisConstraintGroups).toBeUndefined(); expect(gd._fullLayout.scene !== undefined).toBe(true); }) - .catch(fail) + .catch(failTest) .then(done); }); }); @@ -1327,7 +1339,6 @@ describe('Test plot api', function() { Plotly.deleteTraces(gd, -1); expect(gd.data).toEqual(expectedData); expect(plotApi.redraw).toHaveBeenCalled(); - }); it('should work when multiple traces are deleted', function() { @@ -1339,7 +1350,6 @@ describe('Test plot api', function() { Plotly.deleteTraces(gd, [0, 3]); expect(gd.data).toEqual(expectedData); expect(plotApi.redraw).toHaveBeenCalled(); - }); it('should work when indices are not sorted', function() { @@ -1351,7 +1361,6 @@ describe('Test plot api', function() { Plotly.deleteTraces(gd, [3, 0]); expect(gd.data).toEqual(expectedData); expect(plotApi.redraw).toHaveBeenCalled(); - }); it('should work with more than 10 indices', function() { @@ -1377,7 +1386,6 @@ describe('Test plot api', function() { Plotly.deleteTraces(gd, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); expect(gd.data).toEqual(expectedData); expect(plotApi.redraw).toHaveBeenCalled(); - }); }); @@ -2020,9 +2028,9 @@ describe('Test plot api', function() { expect(Object.keys(gd)).toEqual(initialKeys); expect(gd.innerHTML).toEqual(intialHTML); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -2056,9 +2064,11 @@ describe('Test plot api', function() { var newData = [trace1, trace2, trace3]; gd.data = newData; - Plotly.redraw(gd).then(function() { + Plotly.redraw(gd) + .then(function() { expect(d3.selectAll('g.trace.scatter').size()).toEqual(3); }) + .catch(failTest) .then(done); }); }); @@ -2284,18 +2294,21 @@ describe('Test plot api', function() { x: [1, 2], y: [1, 2] }]; + var height = 50; Plotly.plot(gd, data).then(function() { - var height = 50; - Plotly.newPlot(gd, data, { height: height }).then(function() { - var fullLayout = gd._fullLayout, - svg = document.getElementsByClassName('main-svg')[0]; + return Plotly.newPlot(gd, data, { height: height }); + }) + .then(function() { + var fullLayout = gd._fullLayout; + var svg = document.getElementsByClassName('main-svg')[0]; - expect(fullLayout.height).toBe(height); - expect(+svg.getAttribute('height')).toBe(height); - }).then(done); - }); + expect(fullLayout.height).toBe(height); + expect(+svg.getAttribute('height')).toBe(height); + }) + .catch(failTest) + .then(done); }); }); @@ -2314,8 +2327,9 @@ describe('Test plot api', function() { data = gd.data; layout = gd.layout; calcdata = gd.calcdata; - done(); - }); + }) + .catch(failTest) + .then(done); }); afterEach(destroyGraphDiv); @@ -2326,8 +2340,9 @@ describe('Test plot api', function() { Plotly.update(gd, { 'marker.color': 'blue' }).then(function() { expect(subroutines.doTraceStyle).toHaveBeenCalledTimes(1); expect(calcdata).toBe(gd.calcdata); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('clear calcdata on data updates', function(done) { @@ -2335,8 +2350,9 @@ describe('Test plot api', function() { expect(data).toBe(gd.data); expect(layout).toBe(gd.layout); expect(calcdata).not.toBe(gd.calcdata); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('clear calcdata on data + axis updates w/o extending current gd.data', function(done) { @@ -2354,9 +2370,9 @@ describe('Test plot api', function() { expect(calcdata).not.toBe(gd.calcdata); expect(gd.data.length).toEqual(1); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('call doLegend on legend updates', function(done) { @@ -2365,8 +2381,9 @@ describe('Test plot api', function() { Plotly.update(gd, {}, { 'showlegend': true }).then(function() { expect(subroutines.doLegend).toHaveBeenCalledTimes(1); expect(calcdata).toBe(gd.calcdata); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('call layoutReplot when adding update menu', function(done) { @@ -2384,8 +2401,9 @@ describe('Test plot api', function() { Plotly.update(gd, {}, layoutUpdate).then(function() { expect(subroutines.doLegend).toHaveBeenCalledTimes(1); expect(calcdata).toBe(gd.calcdata); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('call doModeBar when updating \'dragmode\'', function(done) { @@ -2394,8 +2412,9 @@ describe('Test plot api', function() { Plotly.update(gd, {}, { 'dragmode': 'pan' }).then(function() { expect(subroutines.doModeBar).toHaveBeenCalledTimes(1); expect(calcdata).toBe(gd.calcdata); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -2486,7 +2505,7 @@ describe('Test plot api', function() { countCalls({plot: 1}); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2516,7 +2535,7 @@ describe('Test plot api', function() { countCalls({plot: 1}); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2582,7 +2601,7 @@ describe('Test plot api', function() { .then(function() { countCalls({doColorBars: 1, plot: 1}); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2642,7 +2661,7 @@ describe('Test plot api', function() { countCalls({plot: 1}); expect(layout.yaxis.range[1]).toBeCloseTo(ymax, 0); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2697,7 +2716,7 @@ describe('Test plot api', function() { expect(n.attributes.y.value).not.toBe(y); expect(n.attributes.height.value).not.toBe(height); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2732,7 +2751,7 @@ describe('Test plot api', function() { expect(d3.selectAll('.gtitle').size()).toBe(0); countCalls({plot: 1}); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2758,7 +2777,7 @@ describe('Test plot api', function() { .then(function() { expect(d3.select(gd).selectAll('.drag').size()).toBe(3); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2783,7 +2802,7 @@ describe('Test plot api', function() { expect(frameData.length).toBe(1); expect(frameData[0].name).toBe('frame2'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2841,7 +2860,7 @@ describe('Test plot api', function() { .then(countPlots) .then(function() { return Plotly.react(gd, mock); }) .then(function() { countCalls({}); }) - .catch(fail) + .catch(failTest) .then(done); }); }); @@ -2879,7 +2898,7 @@ describe('Test plot api', function() { expect(gd.layout.xaxis.range).toBeCloseToArray([-0.53448, 1.53448], 3); expect(gd.layout.yaxis.range).toBeCloseToArray([0.46552, 2.53448], 3); }) - .catch(fail) + .catch(failTest) .then(done); }); }); From c802d794e1501b4b4c3d605b5aaafe7053900ce5 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Tue, 3 Apr 2018 15:09:33 -0400 Subject: [PATCH 02/10] non-attribute modifications to _fullData should be _private, in carpet & table --- src/traces/carpet/calc.js | 6 +++--- src/traces/carpet/calc_gridlines.js | 4 ++-- src/traces/carpet/set_convert.js | 12 ++++++------ src/traces/contour/empty_pathinfo.js | 2 +- src/traces/contourcarpet/calc.js | 4 ++-- src/traces/contourcarpet/plot.js | 2 +- src/traces/scattercarpet/calc.js | 2 +- src/traces/table/calc.js | 6 ++++-- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/traces/carpet/calc.js b/src/traces/carpet/calc.js index 0a87098ea42..aa5bf66639c 100644 --- a/src/traces/carpet/calc.js +++ b/src/traces/carpet/calc.js @@ -52,8 +52,8 @@ module.exports = function calc(gd, trace) { trace.setScale(); // Convert cartesian-space x/y coordinates to screen space pixel coordinates: - t.xp = trace.xp = map2dArray(trace.xp, x, xa.c2p); - t.yp = trace.yp = map2dArray(trace.yp, y, ya.c2p); + t.xp = trace._xp = map2dArray(trace._xp, x, xa.c2p); + t.yp = trace._yp = map2dArray(trace._yp, y, ya.c2p); // This is a rather expensive scan. Nothing guarantees monotonicity, // so we need to scan through all data to get proper ranges: @@ -88,7 +88,7 @@ module.exports = function calc(gd, trace) { // Tabulate points for the four segments that bound the axes so that we can // map to pixel coordinates in the plot function and create a clip rect: - t.clipsegments = calcClipPath(trace.xctrl, trace.yctrl, aax, bax); + t.clipsegments = calcClipPath(trace._xctrl, trace._yctrl, aax, bax); t.x = x; t.y = y; diff --git a/src/traces/carpet/calc_gridlines.js b/src/traces/carpet/calc_gridlines.js index 64006e071ab..af8d9c33907 100644 --- a/src/traces/carpet/calc_gridlines.js +++ b/src/traces/carpet/calc_gridlines.js @@ -30,8 +30,8 @@ module.exports = function calcGridlines(trace, cd, axisLetter, crossAxisLetter) axis.tickvals = data.slice(); } - var xcp = trace.xctrl; - var ycp = trace.yctrl; + var xcp = trace._xctrl; + var ycp = trace._yctrl; var nea = xcp[0].length; var neb = xcp.length; var na = trace.a.length; diff --git a/src/traces/carpet/set_convert.js b/src/traces/carpet/set_convert.js index f47cb0c52a3..eb742a0fbac 100644 --- a/src/traces/carpet/set_convert.js +++ b/src/traces/carpet/set_convert.js @@ -72,18 +72,18 @@ module.exports = function setConvert(trace) { // an expanded basis of control points. Note in particular that it overwrites the existing // basis without creating a new array since that would potentially thrash the garbage // collector. - var result = computeControlPoints(trace.xctrl, trace.yctrl, x, y, aax.smoothing, bax.smoothing); - trace.xctrl = result[0]; - trace.yctrl = result[1]; + var result = computeControlPoints(trace._xctrl, trace._yctrl, x, y, aax.smoothing, bax.smoothing); + trace._xctrl = result[0]; + trace._yctrl = result[1]; // This step is the second step in the process, but it's somewhat simpler. It just unrolls // some logic since it would be unnecessarily expensive to compute both interpolations // nearly identically but separately and to include a bunch of linear vs. bicubic logic in // every single call. - trace.evalxy = createSplineEvaluator([trace.xctrl, trace.yctrl], na, nb, aax.smoothing, bax.smoothing); + trace.evalxy = createSplineEvaluator([trace._xctrl, trace._yctrl], na, nb, aax.smoothing, bax.smoothing); - trace.dxydi = createIDerivativeEvaluator([trace.xctrl, trace.yctrl], aax.smoothing, bax.smoothing); - trace.dxydj = createJDerivativeEvaluator([trace.xctrl, trace.yctrl], aax.smoothing, bax.smoothing); + trace.dxydi = createIDerivativeEvaluator([trace._xctrl, trace._yctrl], aax.smoothing, bax.smoothing); + trace.dxydj = createJDerivativeEvaluator([trace._xctrl, trace._yctrl], aax.smoothing, bax.smoothing); }; /* diff --git a/src/traces/contour/empty_pathinfo.js b/src/traces/contour/empty_pathinfo.js index 2dffa586d5d..e6e186d5a28 100644 --- a/src/traces/contour/empty_pathinfo.js +++ b/src/traces/contour/empty_pathinfo.js @@ -21,7 +21,7 @@ module.exports = function emptyPathinfo(contours, plotinfo, cd0) { var pathinfo = []; var end = endPlus(contoursFinal); - var carpet = cd0.trace.carpetTrace; + var carpet = cd0.trace._carpetTrace; var basePathinfo = carpet ? { // store axes so we can convert to px diff --git a/src/traces/contourcarpet/calc.js b/src/traces/contourcarpet/calc.js index c8d05afffe6..ea2b46afe49 100644 --- a/src/traces/contourcarpet/calc.js +++ b/src/traces/contourcarpet/calc.js @@ -24,7 +24,7 @@ var setContours = require('../contour/set_contours'); // though a few things inside heatmap calc still look for // contour maps, because the makeBoundArray calls are too entangled module.exports = function calc(gd, trace) { - var carpet = trace.carpetTrace = lookupCarpet(gd, trace); + var carpet = trace._carpetTrace = lookupCarpet(gd, trace); if(!carpet || !carpet.visible || carpet.visible === 'legendonly') return; if(!trace.a || !trace.b) { @@ -54,7 +54,7 @@ module.exports = function calc(gd, trace) { function heatmappishCalc(gd, trace) { // prepare the raw data // run makeCalcdata on x and y even for heatmaps, in case of category mappings - var carpet = trace.carpetTrace; + var carpet = trace._carpetTrace; var aax = carpet.aaxis; var bax = carpet.baxis; var a, diff --git a/src/traces/contourcarpet/plot.js b/src/traces/contourcarpet/plot.js index b14b4b4db96..8ebfd7057b4 100644 --- a/src/traces/contourcarpet/plot.js +++ b/src/traces/contourcarpet/plot.js @@ -35,7 +35,7 @@ module.exports = function plot(gd, plotinfo, cdcontours) { function plotOne(gd, plotinfo, cd) { var trace = cd[0].trace; - var carpet = trace.carpetTrace = lookupCarpet(gd, trace); + var carpet = trace._carpetTrace = lookupCarpet(gd, trace); var carpetcd = gd.calcdata[carpet.index][0]; if(!carpet.visible || carpet.visible === 'legendonly') return; diff --git a/src/traces/scattercarpet/calc.js b/src/traces/scattercarpet/calc.js index 64d10706e06..3574a8e8189 100644 --- a/src/traces/scattercarpet/calc.js +++ b/src/traces/scattercarpet/calc.js @@ -18,7 +18,7 @@ var calcMarkerSize = require('../scatter/calc').calcMarkerSize; var lookupCarpet = require('../carpet/lookup_carpetid'); module.exports = function calc(gd, trace) { - var carpet = trace.carpetTrace = lookupCarpet(gd, trace); + var carpet = trace._carpetTrace = lookupCarpet(gd, trace); if(!carpet || !carpet.visible || carpet.visible === 'legendonly') return; var i; diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 7e94ccbe559..efe71bd7640 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -10,6 +10,8 @@ var wrap = require('../../lib/gup').wrap; -module.exports = function calc(gd, trace) { - return wrap(trace); +module.exports = function calc() { + // we don't actually need to include the trace here, since that will be added + // by Plots.doCalcdata, and that's all we actually need later. + return wrap({}); }; From 16a22f3d196e081122d368de31be5c4fcacc291d Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Tue, 3 Apr 2018 15:12:20 -0400 Subject: [PATCH 03/10] simplify convert_column_xyz API ...but we still need to make it NOT mutate the arrays it reshapes --- src/traces/heatmap/convert_column_xyz.js | 4 ---- test/jasmine/tests/heatmap_test.js | 12 ++++++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/traces/heatmap/convert_column_xyz.js b/src/traces/heatmap/convert_column_xyz.js index 162d8f94e6e..ca85f80e9f1 100644 --- a/src/traces/heatmap/convert_column_xyz.js +++ b/src/traces/heatmap/convert_column_xyz.js @@ -13,10 +13,6 @@ var Lib = require('../../lib'); var BADNUM = require('../../constants/numerical').BADNUM; module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, arrayVarNames) { - var1Name = var1Name || 'x'; - var2Name = var2Name || 'y'; - arrayVarNames = arrayVarNames || ['z']; - var col1 = trace[var1Name].slice(), col2 = trace[var2Name].slice(), textCol = trace.text, diff --git a/test/jasmine/tests/heatmap_test.js b/test/jasmine/tests/heatmap_test.js index c9bef41f48f..1471b42a4d3 100644 --- a/test/jasmine/tests/heatmap_test.js +++ b/test/jasmine/tests/heatmap_test.js @@ -181,7 +181,7 @@ describe('heatmap convertColumnXYZ', function() { z: [1, 2, 3, 4, 5, 6] }; - convertColumnXYZ(trace, xa, ya); + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); expect(trace.x).toEqual([1, 2]); expect(trace.y).toEqual([1, 2, 3]); expect(trace.z).toEqual([[1, 4], [2, 5], [3, 6]]); @@ -194,7 +194,7 @@ describe('heatmap convertColumnXYZ', function() { z: [1, 2, 4, 5, 6] }; - convertColumnXYZ(trace, xa, ya); + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); expect(trace.x).toEqual([1, 2]); expect(trace.y).toEqual([1, 2, 3]); expect(trace.z).toEqual([[1, 4], [2, 5], [, 6]]); @@ -207,7 +207,7 @@ describe('heatmap convertColumnXYZ', function() { z: [1, null, 4, 5, 6] }; - convertColumnXYZ(trace, xa, ya); + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); expect(trace.x).toEqual([1, 2]); expect(trace.y).toEqual([1, 2, 3]); expect(trace.z).toEqual([[1, 4], [null, 5], [, 6]]); @@ -221,7 +221,7 @@ describe('heatmap convertColumnXYZ', function() { text: ['a', 'b', 'c', 'd', 'e', 'f', 'g'] }; - convertColumnXYZ(trace, xa, ya); + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); expect(trace.text).toEqual([['a', 'd'], ['b', 'e'], ['c', 'f']]); }); @@ -253,7 +253,7 @@ describe('heatmap convertColumnXYZ', function() { ] }; - convertColumnXYZ(trace, xa, ya); + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); expect(trace.x).toEqual( [-88596, -65484, -42372, -19260, 3852, 26964, 50076, 73188]); expect(trace.y).toEqual( @@ -282,7 +282,7 @@ describe('heatmap convertColumnXYZ', function() { z: [0, 50, 100, 50, null, 255, 100, 510, 1010] }; - convertColumnXYZ(trace, xa, ya); + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); expect(trace.x).toEqual([0, 5, 10]); expect(trace.y).toEqual([0, 5, 10]); From 035c98d8ee0ec860041ba4cdabc30dee68609f08 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Tue, 3 Apr 2018 15:18:23 -0400 Subject: [PATCH 04/10] have Plotly.react diff _fullInput instead of the final trace --- src/plot_api/plot_api.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 283efa08ce2..b6aed6ba7d0 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -2429,8 +2429,14 @@ function diffData(gd, oldFullData, newFullData, immutable) { gd: gd }; + + var seenUIDs = {}; + for(i = 0; i < oldFullData.length; i++) { - trace = newFullData[i]; + trace = newFullData[i]._fullInput; + if(seenUIDs[trace.uid]) continue; + seenUIDs[trace.uid] = 1; + diffOpts.autoranged = trace.xaxis ? ( Axes.getFromId(gd, trace.xaxis).autorange || Axes.getFromId(gd, trace.yaxis).autorange From 95911da1176ee68e7035683176ae910b8122eb5e Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Tue, 3 Apr 2018 15:21:15 -0400 Subject: [PATCH 05/10] bug in relinkPrivateKeys condition ... that I thought might fix candlestick update bugs but there's more to that --- src/plots/plots.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index 08d311e6792..9d4d7ac07b4 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -380,7 +380,7 @@ plots.supplyDefaults = function(gd) { if(_module.cleanData) _module.cleanData(newFullData); } - if(oldFullData.length === newData.length) { + if(oldFullData.length === newFullData.length) { for(i = 0; i < newFullData.length; i++) { relinkPrivateKeys(newFullData[i], oldFullData[i]); } From 6b201a15985d7fc0d0219525d95a8f9235262f28 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Tue, 3 Apr 2018 23:57:48 -0400 Subject: [PATCH 06/10] stop overwriting fullTrace arrays in convert_column_xyz --- src/plots/plots.js | 16 ++++--- src/traces/carpet/axis_defaults.js | 3 ++ src/traces/carpet/calc.js | 30 +++++++++---- src/traces/carpet/calc_gridlines.js | 8 ++-- src/traces/carpet/defaults.js | 3 -- src/traces/carpet/index.js | 1 + src/traces/carpet/set_convert.js | 12 ++--- src/traces/carpet/xy_defaults.js | 21 +-------- src/traces/contourcarpet/calc.js | 8 ++-- src/traces/heatmap/calc.js | 10 +++-- src/traces/heatmap/convert_column_xyz.js | 12 ++--- test/jasmine/tests/heatmap_test.js | 57 +++++++++++------------- test/jasmine/tests/plot_api_test.js | 57 +++++++++++++++++++++++- 13 files changed, 142 insertions(+), 96 deletions(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index 9d4d7ac07b4..56c45fcdb17 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -2364,14 +2364,15 @@ plots.doCalcdata = function(gd, traces) { // clear stuff that should recomputed in 'regular' loop if(hasCalcTransform) clearAxesCalc(axList); - // 'regular' loop - for(i = 0; i < fullData.length; i++) { - var cd = []; - + function calci(i, isContainer) { trace = fullData[i]; + _module = trace._module; + + if(!!_module.isContainer !== isContainer) return; + + var cd = []; if(trace.visible === true) { - _module = trace._module; // keep ref of index-to-points map object of the *last* enabled transform, // this index-to-points map object is required to determine the calcdata indices @@ -2406,6 +2407,11 @@ plots.doCalcdata = function(gd, traces) { calcdata[i] = cd; } + // 'regular' loop - make sure container traces (eg carpet) calc before + // contained traces (eg contourcarpet) + for(i = 0; i < fullData.length; i++) calci(i, true); + for(i = 0; i < fullData.length; i++) calci(i, false); + Registry.getComponentMethod('fx', 'calc')(gd); }; diff --git a/src/traces/carpet/axis_defaults.js b/src/traces/carpet/axis_defaults.js index 1846a032cad..511428dc1ba 100644 --- a/src/traces/carpet/axis_defaults.js +++ b/src/traces/carpet/axis_defaults.js @@ -103,7 +103,10 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, options) handleCalendarDefaults(containerIn, containerOut, 'calendar', options.calendar); } + // we need some of the other functions setConvert attaches, but for + // path finding, override pixel scaling to simple passthrough (identity) setConvert(containerOut, options.fullLayout); + containerOut.c2p = Lib.identity; var dfltColor = coerce('color', options.dfltColor); // if axis.color was provided, use it for fonts too; otherwise, diff --git a/src/traces/carpet/calc.js b/src/traces/carpet/calc.js index aa5bf66639c..ad46dbe1c0b 100644 --- a/src/traces/carpet/calc.js +++ b/src/traces/carpet/calc.js @@ -17,25 +17,37 @@ var calcLabels = require('./calc_labels'); var calcClipPath = require('./calc_clippath'); var clean2dArray = require('../heatmap/clean_2d_array'); var smoothFill2dArray = require('./smooth_fill_2d_array'); +var hasColumns = require('./has_columns'); +var convertColumnData = require('../heatmap/convert_column_xyz'); +var setConvert = require('./set_convert'); module.exports = function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); + var xa = Axes.getFromId(gd, trace.xaxis); + var ya = Axes.getFromId(gd, trace.yaxis); var aax = trace.aaxis; var bax = trace.baxis; - var a = trace._a = trace.a; - var b = trace._b = trace.b; - var t = {}; - var x; + var x = trace.x; var y = trace.y; + var cols = []; + if(x && !hasColumns(x)) cols.push('x'); + if(y && !hasColumns(y)) cols.push('y'); + + if(cols.length) { + convertColumnData(trace, aax, bax, 'a', 'b', cols); + } + + var a = trace._a = trace._a || trace.a; + var b = trace._b = trace._b || trace.b; + x = trace._x || trace.x; + y = trace._y || trace.y; + + var t = {}; if(trace._cheater) { var avals = aax.cheatertype === 'index' ? a.length : a; var bvals = bax.cheatertype === 'index' ? b.length : b; x = cheaterBasis(avals, bvals, trace.cheaterslope); - } else { - x = trace.x; } trace._x = x = clean2dArray(x); @@ -48,6 +60,8 @@ module.exports = function calc(gd, trace) { smoothFill2dArray(x, a, b); smoothFill2dArray(y, a, b); + setConvert(trace); + // create conversion functions that depend on the data trace.setScale(); diff --git a/src/traces/carpet/calc_gridlines.js b/src/traces/carpet/calc_gridlines.js index af8d9c33907..146178ef6a0 100644 --- a/src/traces/carpet/calc_gridlines.js +++ b/src/traces/carpet/calc_gridlines.js @@ -16,14 +16,14 @@ module.exports = function calcGridlines(trace, cd, axisLetter, crossAxisLetter) var eps, bounds, n1, n2, n, value, v; var j1, v0, v1, d; - var data = trace[axisLetter]; + var data = trace['_' + axisLetter]; var axis = trace[axisLetter + 'axis']; var gridlines = axis._gridlines = []; var minorgridlines = axis._minorgridlines = []; var boundarylines = axis._boundarylines = []; - var crossData = trace[crossAxisLetter]; + var crossData = trace['_' + crossAxisLetter]; var crossAxis = trace[crossAxisLetter + 'axis']; if(axis.tickmode === 'array') { @@ -34,8 +34,8 @@ module.exports = function calcGridlines(trace, cd, axisLetter, crossAxisLetter) var ycp = trace._yctrl; var nea = xcp[0].length; var neb = xcp.length; - var na = trace.a.length; - var nb = trace.b.length; + var na = trace._a.length; + var nb = trace._b.length; Axes.prepTicks(axis); diff --git a/src/traces/carpet/defaults.js b/src/traces/carpet/defaults.js index a54efcff98c..da6373e69ea 100644 --- a/src/traces/carpet/defaults.js +++ b/src/traces/carpet/defaults.js @@ -12,7 +12,6 @@ var Lib = require('../../lib'); var handleXYDefaults = require('./xy_defaults'); var handleABDefaults = require('./ab_defaults'); -var setConvert = require('./set_convert'); var attributes = require('./attributes'); var colorAttrs = require('../../components/color/attributes'); @@ -49,8 +48,6 @@ module.exports = function supplyDefaults(traceIn, traceOut, dfltColor, fullLayou // and i goes from 0 to a.length - 1. var len = handleXYDefaults(traceIn, traceOut, coerce); - setConvert(traceOut); - if(traceOut._cheater) { coerce('cheaterslope'); } diff --git a/src/traces/carpet/index.js b/src/traces/carpet/index.js index e97fc2c1789..213d473b8f2 100644 --- a/src/traces/carpet/index.js +++ b/src/traces/carpet/index.js @@ -16,6 +16,7 @@ Carpet.supplyDefaults = require('./defaults'); Carpet.plot = require('./plot'); Carpet.calc = require('./calc'); Carpet.animatable = true; +Carpet.isContainer = true; // so carpet traces get `calc` before other traces Carpet.moduleType = 'trace'; Carpet.name = 'carpet'; diff --git a/src/traces/carpet/set_convert.js b/src/traces/carpet/set_convert.js index eb742a0fbac..c46b71fecb7 100644 --- a/src/traces/carpet/set_convert.js +++ b/src/traces/carpet/set_convert.js @@ -25,10 +25,10 @@ var createJDerivativeEvaluator = require('./create_j_derivative_evaluator'); * p: screen-space pixel coordinates */ module.exports = function setConvert(trace) { - var a = trace.a; - var b = trace.b; - var na = trace.a.length; - var nb = trace.b.length; + var a = trace._a; + var b = trace._b; + var na = a.length; + var nb = b.length; var aax = trace.aaxis; var bax = trace.baxis; @@ -60,10 +60,6 @@ module.exports = function setConvert(trace) { return a < amin || a > amax || b < bmin || b > bmax; }; - // XXX: ONLY PASSTHRU. ONLY. No, ONLY. - aax.c2p = function(v) { return v; }; - bax.c2p = function(v) { return v; }; - trace.setScale = function() { var x = trace._x; var y = trace._y; diff --git a/src/traces/carpet/xy_defaults.js b/src/traces/carpet/xy_defaults.js index adb9ec2cef1..4e046f8eb53 100644 --- a/src/traces/carpet/xy_defaults.js +++ b/src/traces/carpet/xy_defaults.js @@ -9,28 +9,11 @@ 'use strict'; -var hasColumns = require('./has_columns'); -var convertColumnData = require('../heatmap/convert_column_xyz'); - module.exports = function handleXYDefaults(traceIn, traceOut, coerce) { - var cols = []; var x = coerce('x'); - - var needsXTransform = x && !hasColumns(x); - if(needsXTransform) cols.push('x'); - - traceOut._cheater = !x; - var y = coerce('y'); - var needsYTransform = y && !hasColumns(y); - if(needsYTransform) cols.push('y'); - - if(!x && !y) return; - - if(cols.length) { - convertColumnData(traceOut, traceOut.aaxis, traceOut.baxis, 'a', 'b', cols); - } + traceOut._cheater = !x; - return true; + return !!x || !!y; }; diff --git a/src/traces/contourcarpet/calc.js b/src/traces/contourcarpet/calc.js index ea2b46afe49..f5f68ea5f4b 100644 --- a/src/traces/contourcarpet/calc.js +++ b/src/traces/contourcarpet/calc.js @@ -70,15 +70,17 @@ function heatmappishCalc(gd, trace) { bax._minDtick = 0; if(hasColumns(trace)) convertColumnData(trace, aax, bax, 'a', 'b', ['z']); + a = trace._a = trace._a || trace.a; + b = trace._b = trace._b || trace.b; - a = trace.a ? aax.makeCalcdata(trace, 'a') : []; - b = trace.b ? bax.makeCalcdata(trace, 'b') : []; + a = a ? aax.makeCalcdata(trace, '_a') : []; + b = b ? bax.makeCalcdata(trace, '_b') : []; a0 = trace.a0 || 0; da = trace.da || 1; b0 = trace.b0 || 0; db = trace.db || 1; - z = clean2dArray(trace.z, trace.transpose); + z = trace._z = clean2dArray(trace._z || trace.z, trace.transpose); trace._emptypoints = findEmpties(z); trace._interpz = interp2d(z, trace._emptypoints, trace._interpz); diff --git a/src/traces/heatmap/calc.js b/src/traces/heatmap/calc.js index a0736fd5722..7364a8bc88d 100644 --- a/src/traces/heatmap/calc.js +++ b/src/traces/heatmap/calc.js @@ -58,10 +58,12 @@ module.exports = function calc(gd, trace) { z = binned.z; } else { + var zIn = trace.z; if(hasColumns(trace)) { convertColumnData(trace, xa, ya, 'x', 'y', ['z']); - x = trace.x; - y = trace.y; + x = trace._x; + y = trace._y; + zIn = trace._z; } else { x = trace.x ? xa.makeCalcdata(trace, 'x') : []; y = trace.y ? ya.makeCalcdata(trace, 'y') : []; @@ -72,7 +74,7 @@ module.exports = function calc(gd, trace) { y0 = trace.y0 || 0; dy = trace.dy || 1; - z = clean2dArray(trace.z, trace.transpose); + z = clean2dArray(zIn, trace.transpose); if(isContour || trace.connectgaps) { trace._emptypoints = findEmpties(z); @@ -131,7 +133,7 @@ module.exports = function calc(gd, trace) { x: xArray, y: yArray, z: z, - text: trace.text + text: trace._text || trace.text }; if(xIn && xIn.length === xArray.length - 1) cd0.xCenter = xIn; diff --git a/src/traces/heatmap/convert_column_xyz.js b/src/traces/heatmap/convert_column_xyz.js index ca85f80e9f1..909fff986a8 100644 --- a/src/traces/heatmap/convert_column_xyz.js +++ b/src/traces/heatmap/convert_column_xyz.js @@ -66,14 +66,10 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, } } - // hack for Plotly.react - save the input arrays for diffing purposes - trace['_input_' + var1Name] = trace[var1Name]; - trace['_input_' + var2Name] = trace[var2Name]; - trace[var1Name] = col1vals; - trace[var2Name] = col2vals; + trace['_' + var1Name] = col1vals; + trace['_' + var2Name] = col2vals; for(j = 0; j < arrayVarNames.length; j++) { - trace['_input_' + arrayVarNames[j]] = trace[arrayVarNames[j]]; - trace[arrayVarNames[j]] = newArrays[j]; + trace['_' + arrayVarNames[j]] = newArrays[j]; } - if(hasColumnText) trace.text = text; + if(hasColumnText) trace._text = text; }; diff --git a/test/jasmine/tests/heatmap_test.js b/test/jasmine/tests/heatmap_test.js index 1471b42a4d3..8dbfd37920d 100644 --- a/test/jasmine/tests/heatmap_test.js +++ b/test/jasmine/tests/heatmap_test.js @@ -174,6 +174,13 @@ describe('heatmap convertColumnXYZ', function() { var xa = makeMockAxis(); var ya = makeMockAxis(); + function checkConverted(trace, x, y, z) { + convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); + expect(trace._x).toEqual(x); + expect(trace._y).toEqual(y); + expect(trace._z).toEqual(z); + } + it('should convert x/y/z columns to z(x,y)', function() { trace = { x: [1, 1, 1, 2, 2, 2], @@ -181,10 +188,7 @@ describe('heatmap convertColumnXYZ', function() { z: [1, 2, 3, 4, 5, 6] }; - convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); - expect(trace.x).toEqual([1, 2]); - expect(trace.y).toEqual([1, 2, 3]); - expect(trace.z).toEqual([[1, 4], [2, 5], [3, 6]]); + checkConverted(trace, [1, 2], [1, 2, 3], [[1, 4], [2, 5], [3, 6]]); }); it('should convert x/y/z columns to z(x,y) with uneven dimensions', function() { @@ -194,10 +198,7 @@ describe('heatmap convertColumnXYZ', function() { z: [1, 2, 4, 5, 6] }; - convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); - expect(trace.x).toEqual([1, 2]); - expect(trace.y).toEqual([1, 2, 3]); - expect(trace.z).toEqual([[1, 4], [2, 5], [, 6]]); + checkConverted(trace, [1, 2], [1, 2, 3], [[1, 4], [2, 5], [, 6]]); }); it('should convert x/y/z columns to z(x,y) with missing values', function() { @@ -207,10 +208,7 @@ describe('heatmap convertColumnXYZ', function() { z: [1, null, 4, 5, 6] }; - convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); - expect(trace.x).toEqual([1, 2]); - expect(trace.y).toEqual([1, 2, 3]); - expect(trace.z).toEqual([[1, 4], [null, 5], [, 6]]); + checkConverted(trace, [1, 2], [1, 2, 3], [[1, 4], [null, 5], [, 6]]); }); it('should convert x/y/z/text columns to z(x,y) and text(x,y)', function() { @@ -222,7 +220,7 @@ describe('heatmap convertColumnXYZ', function() { }; convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); - expect(trace.text).toEqual([['a', 'd'], ['b', 'e'], ['c', 'f']]); + expect(trace._text).toEqual([['a', 'd'], ['b', 'e'], ['c', 'f']]); }); it('should convert x/y/z columns to z(x,y) with out-of-order data', function() { @@ -253,20 +251,19 @@ describe('heatmap convertColumnXYZ', function() { ] }; - convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); - expect(trace.x).toEqual( - [-88596, -65484, -42372, -19260, 3852, 26964, 50076, 73188]); - expect(trace.y).toEqual( - [-78096.2, -52106.6, -26117, -127.4, 25862.2, 51851.8, 77841.4]); - expect(trace.z).toEqual([ - [,, 4.154291, 4.404264, 4.33847, 4.270931,,, ], - [, 4.339848, 4.39907, 4.345006, 4.315032, 4.295618, 4.262052,, ], - [3.908434, 4.433257, 4.364234, 4.308714, 4.275516, 4.126979, 4.296483, 4.320471], - [4.032226, 4.381492, 4.328922, 4.24046, 4.349151, 4.202861, 4.256402, 4.28972], - [3.956225, 4.337909, 4.31226, 4.259435, 4.146854, 4.235799, 4.238752, 4.299876], - [, 4.210373, 4.32009, 4.246728, 4.293992, 4.316364, 4.361856,, ], - [,, 4.234497, 4.321701, 4.450315, 4.416136,,, ] - ]); + checkConverted(trace, + [-88596, -65484, -42372, -19260, 3852, 26964, 50076, 73188], + [-78096.2, -52106.6, -26117, -127.4, 25862.2, 51851.8, 77841.4], + [ + [,, 4.154291, 4.404264, 4.33847, 4.270931,,, ], + [, 4.339848, 4.39907, 4.345006, 4.315032, 4.295618, 4.262052,, ], + [3.908434, 4.433257, 4.364234, 4.308714, 4.275516, 4.126979, 4.296483, 4.320471], + [4.032226, 4.381492, 4.328922, 4.24046, 4.349151, 4.202861, 4.256402, 4.28972], + [3.956225, 4.337909, 4.31226, 4.259435, 4.146854, 4.235799, 4.238752, 4.299876], + [, 4.210373, 4.32009, 4.246728, 4.293992, 4.316364, 4.361856,, ], + [,, 4.234497, 4.321701, 4.450315, 4.416136,,, ] + ] + ); }); it('should convert x/y/z columns with nulls to z(x,y)', function() { @@ -282,11 +279,7 @@ describe('heatmap convertColumnXYZ', function() { z: [0, 50, 100, 50, null, 255, 100, 510, 1010] }; - convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']); - - expect(trace.x).toEqual([0, 5, 10]); - expect(trace.y).toEqual([0, 5, 10]); - expect(trace.z).toEqual([ + checkConverted(trace, [0, 5, 10], [0, 5, 10], [ [0, 50, 100], [50, undefined, 510], [100, 255, 1010] diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 20e735b769e..367ce4dd881 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -2855,11 +2855,64 @@ describe('Test plot api', function() { mockList.forEach(function(mockSpec) { it('can redraw "' + mockSpec[0] + '" with no changes as a noop', function(done) { var mock = mockSpec[1]; + var initialJson; + + function fullJson() { + var out = JSON.parse(Plotly.Plots.graphJson({ + data: gd._fullData, + layout: gd._fullLayout + })); + + // TODO: does it matter that ax.tick0/dtick/range and zmin/zmax + // are often not regenerated without a calc step? + // in as far as editor and others rely on _full, I think the + // answer must be yes, but I'm not sure about within plotly.js + [ + 'xaxis', 'xaxis2', 'xaxis3', 'xaxis4', 'xaxis5', + 'yaxis', 'yaxis2', 'yaxis3', 'yaxis4', + 'zaxis' + ].forEach(function(axName) { + var ax = out.layout[axName]; + if(ax) { + delete ax.dtick; + delete ax.tick0; + + // TODO this one I don't understand and can't reproduce + // in the dashboard but it's needed here? + delete ax.range; + } + if(out.layout.scene) { + ax = out.layout.scene[axName]; + if(ax) { + delete ax.dtick; + delete ax.tick0; + // TODO: this is the only one now that uses '_input_' + key + // as a hack to tell Plotly.react to ignore changes. + // Can we kill this? + delete ax.range; + } + } + }); + out.data.forEach(function(trace) { + if(trace.type === 'contourcarpet') { + delete trace.zmin; + delete trace.zmax; + } + }); + + return out; + } Plotly.newPlot(gd, mock) .then(countPlots) - .then(function() { return Plotly.react(gd, mock); }) - .then(function() { countCalls({}); }) + .then(function() { + initialJson = fullJson(); + return Plotly.react(gd, mock); + }) + .then(function() { + expect(fullJson()).toEqual(initialJson); + countCalls({}); + }) .catch(failTest) .then(done); }); From 5546ec7057ad651d70c2cc561d6c00d7eda45903 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 4 Apr 2018 15:46:00 -0400 Subject: [PATCH 07/10] stop slicing finance input arrays during supplyDefaults --- src/traces/candlestick/defaults.js | 2 +- src/traces/candlestick/transform.js | 5 +++-- src/traces/ohlc/attributes.js | 4 ---- src/traces/ohlc/defaults.js | 2 +- src/traces/ohlc/ohlc_defaults.js | 16 +++++----------- src/traces/ohlc/transform.js | 8 +++++--- test/jasmine/tests/finance_test.js | 9 +++------ test/jasmine/tests/plot_api_test.js | 5 ++++- 8 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/traces/candlestick/defaults.js b/src/traces/candlestick/defaults.js index b9d6f42e96d..ee5dcdf7682 100644 --- a/src/traces/candlestick/defaults.js +++ b/src/traces/candlestick/defaults.js @@ -23,7 +23,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } var len = handleOHLC(traceIn, traceOut, coerce, layout); - if(len === 0) { + if(!len) { traceOut.visible = false; return; } diff --git a/src/traces/candlestick/transform.js b/src/traces/candlestick/transform.js index bd08e854fba..36b1e5de6c7 100644 --- a/src/traces/candlestick/transform.js +++ b/src/traces/candlestick/transform.js @@ -60,7 +60,8 @@ function makeTrace(traceIn, state, direction) { xaxis: traceIn.xaxis, yaxis: traceIn.yaxis, - transforms: helpers.makeTransform(traceIn, state, direction) + transforms: helpers.makeTransform(traceIn, state, direction), + _inputLength: traceIn._inputLength }; // the rest of below may not have been coerced @@ -99,7 +100,7 @@ exports.calcTransform = function calcTransform(gd, trace, opts) { low = trace.low, close = trace.close; - var len = open.length, + var len = trace._inputLength, x = [], y = []; diff --git a/src/traces/ohlc/attributes.js b/src/traces/ohlc/attributes.js index 016b1cb622d..6cb5b7a77e5 100644 --- a/src/traces/ohlc/attributes.js +++ b/src/traces/ohlc/attributes.js @@ -64,28 +64,24 @@ module.exports = { open: { valType: 'data_array', - dflt: [], editType: 'calc', description: 'Sets the open values.' }, high: { valType: 'data_array', - dflt: [], editType: 'calc', description: 'Sets the high values.' }, low: { valType: 'data_array', - dflt: [], editType: 'calc', description: 'Sets the low values.' }, close: { valType: 'data_array', - dflt: [], editType: 'calc', description: 'Sets the close values.' }, diff --git a/src/traces/ohlc/defaults.js b/src/traces/ohlc/defaults.js index 23b7bf34af3..ee9a9948ce4 100644 --- a/src/traces/ohlc/defaults.js +++ b/src/traces/ohlc/defaults.js @@ -23,7 +23,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout } var len = handleOHLC(traceIn, traceOut, coerce, layout); - if(len === 0) { + if(!len) { traceOut.visible = false; return; } diff --git a/src/traces/ohlc/ohlc_defaults.js b/src/traces/ohlc/ohlc_defaults.js index 2840b4245bf..261e92b7922 100644 --- a/src/traces/ohlc/ohlc_defaults.js +++ b/src/traces/ohlc/ohlc_defaults.js @@ -13,8 +13,6 @@ var Registry = require('../../registry'); module.exports = function handleOHLC(traceIn, traceOut, coerce, layout) { - var len; - var x = coerce('x'), open = coerce('open'), high = coerce('high'), @@ -24,17 +22,13 @@ module.exports = function handleOHLC(traceIn, traceOut, coerce, layout) { var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); handleCalendarDefaults(traceIn, traceOut, ['x'], layout); - len = Math.min(open.length, high.length, low.length, close.length); + if(!(open && high && low && close)) return; + + var len = Math.min(open.length, high.length, low.length, close.length); - if(x) { - len = Math.min(len, x.length); - if(len < x.length) traceOut.x = x.slice(0, len); - } + if(x) len = Math.min(len, x.length); - if(len < open.length) traceOut.open = open.slice(0, len); - if(len < high.length) traceOut.high = high.slice(0, len); - if(len < low.length) traceOut.low = low.slice(0, len); - if(len < close.length) traceOut.close = close.slice(0, len); + traceOut._inputLength = len; return len; }; diff --git a/src/traces/ohlc/transform.js b/src/traces/ohlc/transform.js index c569c6ede3d..af93b1d5946 100644 --- a/src/traces/ohlc/transform.js +++ b/src/traces/ohlc/transform.js @@ -53,6 +53,7 @@ exports.transform = function transform(dataIn, state) { }; function makeTrace(traceIn, state, direction) { + var len = traceIn._inputLength; var traceOut = { type: 'scatter', mode: 'lines', @@ -64,7 +65,8 @@ function makeTrace(traceIn, state, direction) { yaxis: traceIn.yaxis, hoverinfo: makeHoverInfo(traceIn), - transforms: helpers.makeTransform(traceIn, state, direction) + transforms: helpers.makeTransform(traceIn, state, direction), + _inputLength: len }; // the rest of below may not have been coerced @@ -79,7 +81,7 @@ function makeTrace(traceIn, state, direction) { xcalendar: traceIn.xcalendar, // concat low and high to get correct autorange - y: [].concat(traceIn.low).concat(traceIn.high), + y: traceIn.low.slice(0, len).concat(traceIn.high.slice(0, len)), text: traceIn.text, @@ -138,7 +140,7 @@ exports.calcTransform = function calcTransform(gd, trace, opts) { var lowName = _(gd, 'low:') + ' '; var closeName = _(gd, 'close:') + ' '; - var len = open.length, + var len = trace._inputLength, x = [], y = [], textOut = []; diff --git a/test/jasmine/tests/finance_test.js b/test/jasmine/tests/finance_test.js index aeddf64b1c2..770fe352dba 100644 --- a/test/jasmine/tests/finance_test.js +++ b/test/jasmine/tests/finance_test.js @@ -128,10 +128,7 @@ describe('finance charts defaults:', function() { function assertDataLength(fullTrace, len) { expect(fullTrace.visible).toBe(true); - expect(fullTrace.open.length).toEqual(len); - expect(fullTrace.high.length).toEqual(len); - expect(fullTrace.low.length).toEqual(len); - expect(fullTrace.close.length).toEqual(len); + expect(fullTrace._inputLength).toBe(len); } var trace0 = Lib.extendDeep({}, mock0, { type: 'ohlc' }); @@ -149,8 +146,8 @@ describe('finance charts defaults:', function() { expect(out._fullData[0]._fullInput.x).toBeUndefined(); expect(out._fullData[1]._fullInput.x).toBeUndefined(); - expect(out._fullData[2]._fullInput.x.length).toEqual(4); - expect(out._fullData[3]._fullInput.x.length).toEqual(4); + expect(out._fullData[2]._fullInput.x).toBeDefined(); + expect(out._fullData[3]._fullInput.x).toBeDefined(); }); it('should set visible to *false* when minimum supplied length is 0', function() { diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 367ce4dd881..96319a39fb2 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -2910,7 +2910,10 @@ describe('Test plot api', function() { return Plotly.react(gd, mock); }) .then(function() { - expect(fullJson()).toEqual(initialJson); + // TODO: remove this exemption once we fix finance + if(mockSpec[0] !== 'finance_style') { + expect(fullJson()).toEqual(initialJson); + } countCalls({}); }) .catch(failTest) From 0221510d0e1443aec95f7830659cfdffcd6e6772 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 4 Apr 2018 21:41:56 -0400 Subject: [PATCH 08/10] :hocho: obsolete _xp, _yp from carpet --- src/traces/carpet/calc.js | 8 ++------ src/traces/carpet/calc_gridlines.js | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/traces/carpet/calc.js b/src/traces/carpet/calc.js index ad46dbe1c0b..e2d7dd77530 100644 --- a/src/traces/carpet/calc.js +++ b/src/traces/carpet/calc.js @@ -65,10 +65,6 @@ module.exports = function calc(gd, trace) { // create conversion functions that depend on the data trace.setScale(); - // Convert cartesian-space x/y coordinates to screen space pixel coordinates: - t.xp = trace._xp = map2dArray(trace._xp, x, xa.c2p); - t.yp = trace._yp = map2dArray(trace._yp, y, ya.c2p); - // This is a rather expensive scan. Nothing guarantees monotonicity, // so we need to scan through all data to get proper ranges: var xrange = arrayMinmax(x); @@ -92,8 +88,8 @@ module.exports = function calc(gd, trace) { // Enumerate the gridlines, both major and minor, and store them on the trace // object: - calcGridlines(trace, t, 'a', 'b'); - calcGridlines(trace, t, 'b', 'a'); + calcGridlines(trace, 'a', 'b'); + calcGridlines(trace, 'b', 'a'); // Calculate the text labels for each major gridline and store them on the // trace object: diff --git a/src/traces/carpet/calc_gridlines.js b/src/traces/carpet/calc_gridlines.js index 146178ef6a0..a0c727fe829 100644 --- a/src/traces/carpet/calc_gridlines.js +++ b/src/traces/carpet/calc_gridlines.js @@ -11,7 +11,7 @@ var Axes = require('../../plots/cartesian/axes'); var extendFlat = require('../../lib/extend').extendFlat; -module.exports = function calcGridlines(trace, cd, axisLetter, crossAxisLetter) { +module.exports = function calcGridlines(trace, axisLetter, crossAxisLetter) { var i, j, j0; var eps, bounds, n1, n2, n, value, v; var j1, v0, v1, d; From b0af416a3561da25af1fa726da99be30de1b6c68 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 4 Apr 2018 21:52:24 -0400 Subject: [PATCH 09/10] even more became obsolete :tada: --- src/traces/carpet/calc.js | 1 - src/traces/carpet/map_2d_array.js | 45 ------------------------------- 2 files changed, 46 deletions(-) delete mode 100644 src/traces/carpet/map_2d_array.js diff --git a/src/traces/carpet/calc.js b/src/traces/carpet/calc.js index e2d7dd77530..50ebafff330 100644 --- a/src/traces/carpet/calc.js +++ b/src/traces/carpet/calc.js @@ -11,7 +11,6 @@ var Axes = require('../../plots/cartesian/axes'); var cheaterBasis = require('./cheater_basis'); var arrayMinmax = require('./array_minmax'); -var map2dArray = require('./map_2d_array'); var calcGridlines = require('./calc_gridlines'); var calcLabels = require('./calc_labels'); var calcClipPath = require('./calc_clippath'); diff --git a/src/traces/carpet/map_2d_array.js b/src/traces/carpet/map_2d_array.js deleted file mode 100644 index 172c1c6ab7f..00000000000 --- a/src/traces/carpet/map_2d_array.js +++ /dev/null @@ -1,45 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray; - -/* - * Map an array of x or y coordinates (c) to screen-space pixel coordinates (p). - * The output array is optional, but if provided, it will be reused without - * reallocation to the extent possible. - */ -module.exports = function mapArray(out, data, func) { - var i, j; - - if(!Array.isArray(out)) { - // If not an array, make it an array: - out = []; - } else if(out.length > data.length) { - // If too long, truncate. (If too short, it will grow - // automatically so we don't care about that case) - out = out.slice(0, data.length); - } - - for(i = 0; i < data.length; i++) { - if(!isArrayOrTypedArray(out[i])) { - // If not an array, make it an array: - out[i] = []; - } else if(out[i].length > data.length) { - // If too long, truncate. (If too short, it will grow - // automatically so we don't care about[i] that case) - out[i] = out[i].slice(0, data.length); - } - - for(j = 0; j < data[0].length; j++) { - out[i][j] = func(data[i][j]); - } - } - return out; -}; From c2b11dc5a8665c8c1e86b7f7fc969b15184e86f2 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 4 Apr 2018 22:00:24 -0400 Subject: [PATCH 10/10] failTest in transform_groupby_test --- test/jasmine/tests/transform_groupby_test.js | 82 ++++++++++---------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/test/jasmine/tests/transform_groupby_test.js b/test/jasmine/tests/transform_groupby_test.js index 8a41e03db95..5f6c564be5d 100644 --- a/test/jasmine/tests/transform_groupby_test.js +++ b/test/jasmine/tests/transform_groupby_test.js @@ -5,6 +5,7 @@ var Lib = require('@src/lib'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var customAssertions = require('../assets/custom_assertions'); +var failTest = require('../assets/fail_test'); var assertDims = customAssertions.assertDims; var assertStyle = customAssertions.assertStyle; @@ -72,9 +73,9 @@ describe('groupby', function() { expect(gd._fullData[1].transforms[0]._indexToPoints).toEqual({0: [2], 1: [4], 2: [5]}); assertDims([4, 3]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Accepts deprecated object notation for styles', function(done) { @@ -122,7 +123,9 @@ describe('groupby', function() { expect(gd._fullData[0].marker.opacity).toEqual(1); expect(gd._fullData[1].marker.opacity).toEqual(1); - }).then(done); + }) + .catch(failTest) + .then(done); // The final test for restyle updates using deprecated syntax // is ommitted since old style syntax is *only* sanitized on @@ -174,9 +177,9 @@ describe('groupby', function() { ['rgb(0, 128, 0)', 'rgb(255, 0, 0)'], [0.4, 0.4] ); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.extendTraces should work', function(done) { @@ -202,9 +205,9 @@ describe('groupby', function() { expect(gd._fullData[1].x.length).toEqual(5); assertDims([5, 5]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.deleteTraces should work', function(done) { @@ -222,9 +225,9 @@ describe('groupby', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { assertDims([]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('toggling trace visibility should work', function(done) { @@ -246,9 +249,9 @@ describe('groupby', function() { return Plotly.restyle(gd, 'visible', [true, true], [0, 1]); }).then(function() { assertDims([4, 3, 4, 3]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -359,9 +362,9 @@ describe('groupby', function() { expect(gd._fullData[1].y).toEqual([3, 2, 3]); assertDims([4, 3]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.plot should plot the transform traces', function(done) { @@ -376,9 +379,9 @@ describe('groupby', function() { expect(gd._fullData.length).toEqual(1); assertDims([7]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.plot should plot the transform traces', function(done) { @@ -396,9 +399,9 @@ describe('groupby', function() { expect(gd._fullData[0].y).toEqual([1, 2, 3, 1, 2, 3, 1]); assertDims([7]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.plot should plot the transform traces', function(done) { @@ -417,9 +420,9 @@ describe('groupby', function() { expect(gd._fullData[0].y).toEqual([1, 2, 3, 1, 2, 3, 1]); assertDims([7]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.plot should plot the transform traces', function(done) { @@ -438,9 +441,9 @@ describe('groupby', function() { expect(gd._fullData[0].y).toEqual([1, 2, 3, 1, 2, 3, 1]); assertDims([7]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -478,9 +481,9 @@ describe('groupby', function() { expect(gd._fullData[1].marker.line.width).toEqual([4, 2, 3]); assertDims([4, 3]); - - done(); - }); + }) + .catch(failTest) + .then(done); }; } @@ -611,8 +614,9 @@ describe('groupby', function() { Plotly.plot(gd, data).then(function() { expect(gd._fullData[0].marker.line.color).toEqual(['orange', 'red', 'cyan', 'pink']); expect(gd._fullData[1].marker.line.color).toEqual('yellow'); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('passes with no explicit styling for the individual group', test(mockData4)); @@ -649,9 +653,9 @@ describe('groupby', function() { expect(gd._fullData[0].marker.line.width).toEqual([4, 2, 4, 2, 2, 3, 3]); assertDims([7]); - - done(); - }); + }) + .catch(failTest) + .then(done); }; }