Skip to content

Commit aa30ad6

Browse files
committed
update plot_api_test to 🔒 recent changes in react/transforms etc
1 parent e47e6a9 commit aa30ad6

File tree

1 file changed

+125
-78
lines changed

1 file changed

+125
-78
lines changed

test/jasmine/tests/plot_api_test.js

Lines changed: 125 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var helpers = require('@src/plot_api/helpers');
1212
var editTypes = require('@src/plot_api/edit_types');
1313
var annotations = require('@src/components/annotations');
1414
var images = require('@src/components/images');
15+
var Registry = require('@src/registry');
1516

1617
var d3 = require('d3');
1718
var createGraphDiv = require('../assets/create_graph_div');
@@ -1053,14 +1054,14 @@ describe('Test plot api', function() {
10531054
var mlcmax1 = 6;
10541055
var mlcscl1 = 'greens';
10551056

1056-
function check(auto, msg) {
1057+
function check(auto, autocolorscale, msg) {
10571058
expect(gd.data[0].marker.cauto).toBe(auto, msg);
10581059
expect(gd.data[0].marker.cmin).negateIf(auto).toBe(mcmin0);
1059-
expect(gd._fullData[0].marker.autocolorscale).toBe(auto, msg);
1060+
expect(gd._fullData[0].marker.autocolorscale).toBe(autocolorscale, msg);
10601061
expect(gd.data[0].marker.colorscale).toEqual(auto ? autocscale : mcscl0);
10611062
expect(gd.data[1].marker.line.cauto).toBe(auto, msg);
10621063
expect(gd.data[1].marker.line.cmax).negateIf(auto).toBe(mlcmax1);
1063-
expect(gd._fullData[1].marker.line.autocolorscale).toBe(auto, msg);
1064+
expect(gd._fullData[1].marker.line.autocolorscale).toBe(autocolorscale, msg);
10641065
expect(gd.data[1].marker.line.colorscale).toEqual(auto ? autocscale : mlcscl1);
10651066
}
10661067

@@ -1069,28 +1070,30 @@ describe('Test plot api', function() {
10691070
{y: [2, 1], mode: 'markers', marker: {line: {width: 2, color: [3, 4]}}}
10701071
])
10711072
.then(function() {
1072-
check(true, 'initial');
1073+
// autocolorscale is actually true after supplyDefaults, but during calc it's set
1074+
// to false when we push the resulting colorscale back to the input container
1075+
check(true, false, 'initial');
10731076
return Plotly.restyle(gd, {'marker.cmin': mcmin0, 'marker.colorscale': mcscl0}, null, [0]);
10741077
})
10751078
.then(function() {
10761079
return Plotly.restyle(gd, {'marker.line.cmax': mlcmax1, 'marker.line.colorscale': mlcscl1}, null, [1]);
10771080
})
10781081
.then(function() {
1079-
check(false, 'set min/max/scale');
1082+
check(false, false, 'set min/max/scale');
10801083
return Plotly.restyle(gd, {'marker.cauto': true, 'marker.autocolorscale': true}, null, [0]);
10811084
})
10821085
.then(function() {
10831086
return Plotly.restyle(gd, {'marker.line.cauto': true, 'marker.line.autocolorscale': true}, null, [1]);
10841087
})
10851088
.then(function() {
1086-
check(true, 'reset');
1089+
check(true, true, 'reset');
10871090
return Queue.undo(gd);
10881091
})
10891092
.then(function() {
10901093
return Queue.undo(gd);
10911094
})
10921095
.then(function() {
1093-
check(false, 'undo');
1096+
check(false, false, 'undo');
10941097
})
10951098
.catch(failTest)
10961099
.then(done);
@@ -3183,6 +3186,7 @@ describe('Test plot api', function() {
31833186
['cheater_smooth', require('@mocks/cheater_smooth.json')],
31843187
['finance_style', require('@mocks/finance_style.json')],
31853188
['geo_first', require('@mocks/geo_first.json')],
3189+
['gl2d_heatmapgl', require('@mocks/gl2d_heatmapgl.json')],
31863190
['gl2d_line_dash', require('@mocks/gl2d_line_dash.json')],
31873191
['gl2d_parcoords_2', require('@mocks/gl2d_parcoords_2.json')],
31883192
['gl2d_pointcloud-basic', require('@mocks/gl2d_pointcloud-basic.json')],
@@ -3196,12 +3200,14 @@ describe('Test plot api', function() {
31963200
['range_selector_style', require('@mocks/range_selector_style.json')],
31973201
['range_slider_multiple', require('@mocks/range_slider_multiple.json')],
31983202
['sankey_energy', require('@mocks/sankey_energy.json')],
3203+
['scattercarpet', require('@mocks/scattercarpet.json')],
31993204
['splom_iris', require('@mocks/splom_iris.json')],
32003205
['table_wrapped_birds', require('@mocks/table_wrapped_birds.json')],
32013206
['ternary_fill', require('@mocks/ternary_fill.json')],
32023207
['text_chart_arrays', require('@mocks/text_chart_arrays.json')],
3208+
['transforms', require('@mocks/transforms.json')],
32033209
['updatemenus', require('@mocks/updatemenus.json')],
3204-
['violins', require('@mocks/violins.json')],
3210+
['violin_side-by-side', require('@mocks/violin_side-by-side.json')],
32053211
['world-cals', require('@mocks/world-cals.json')],
32063212
['typed arrays', {
32073213
data: [{
@@ -3211,86 +3217,127 @@ describe('Test plot api', function() {
32113217
}]
32123218
];
32133219

3214-
mockList.forEach(function(mockSpec) {
3215-
it('can redraw "' + mockSpec[0] + '" with no changes as a noop', function(done) {
3216-
var mock = mockSpec[1];
3217-
var initialJson;
3218-
3219-
function fullJson() {
3220-
var out = JSON.parse(Plotly.Plots.graphJson({
3221-
data: gd._fullData,
3222-
layout: gd._fullLayout
3223-
}));
3224-
3225-
// TODO: does it matter that ax.tick0/dtick/range and zmin/zmax
3226-
// are often not regenerated without a calc step?
3227-
// in as far as editor and others rely on _full, I think the
3228-
// answer must be yes, but I'm not sure about within plotly.js
3229-
[
3230-
'xaxis', 'xaxis2', 'xaxis3', 'xaxis4', 'xaxis5',
3231-
'yaxis', 'yaxis2', 'yaxis3', 'yaxis4',
3232-
'zaxis'
3233-
].forEach(function(axName) {
3234-
var ax = out.layout[axName];
3220+
// make sure we've included every trace type in this suite
3221+
var typesTested = {};
3222+
var itemType;
3223+
for(itemType in Registry.modules) { typesTested[itemType] = 0; }
3224+
for(itemType in Registry.transformsRegistry) { typesTested[itemType] = 0; }
3225+
3226+
// Only include scattermapbox locally, see below
3227+
delete typesTested.scattermapbox;
3228+
3229+
// Not being supported? This isn't part of the main bundle, and it's pretty broken,
3230+
// but it gets registered and used by a couple of the gl2d tests.
3231+
delete typesTested.contourgl;
3232+
3233+
function _runReactMock(mockSpec, done) {
3234+
var mock = mockSpec[1];
3235+
var initialJson;
3236+
3237+
function fullJson() {
3238+
var out = JSON.parse(Plotly.Plots.graphJson({
3239+
data: gd._fullData.map(function(trace) { return trace._fullInput; }),
3240+
layout: gd._fullLayout
3241+
}));
3242+
3243+
// TODO: does it matter that ax.tick0/dtick/range and zmin/zmax
3244+
// are often not regenerated without a calc step?
3245+
// in as far as editor and others rely on _full, I think the
3246+
// answer must be yes, but I'm not sure about within plotly.js
3247+
[
3248+
'xaxis', 'xaxis2', 'xaxis3', 'xaxis4', 'xaxis5',
3249+
'yaxis', 'yaxis2', 'yaxis3', 'yaxis4',
3250+
'zaxis'
3251+
].forEach(function(axName) {
3252+
var ax = out.layout[axName];
3253+
if(ax) {
3254+
delete ax.dtick;
3255+
delete ax.tick0;
3256+
3257+
// TODO this one I don't understand and can't reproduce
3258+
// in the dashboard but it's needed here?
3259+
delete ax.range;
3260+
}
3261+
if(out.layout.scene) {
3262+
ax = out.layout.scene[axName];
32353263
if(ax) {
32363264
delete ax.dtick;
32373265
delete ax.tick0;
3238-
3239-
// TODO this one I don't understand and can't reproduce
3240-
// in the dashboard but it's needed here?
3266+
// TODO: this is the only one now that uses '_input_' + key
3267+
// as a hack to tell Plotly.react to ignore changes.
3268+
// Can we kill this?
32413269
delete ax.range;
32423270
}
3243-
if(out.layout.scene) {
3244-
ax = out.layout.scene[axName];
3245-
if(ax) {
3246-
delete ax.dtick;
3247-
delete ax.tick0;
3248-
// TODO: this is the only one now that uses '_input_' + key
3249-
// as a hack to tell Plotly.react to ignore changes.
3250-
// Can we kill this?
3251-
delete ax.range;
3252-
}
3253-
}
3254-
});
3255-
out.data.forEach(function(trace) {
3256-
if(trace.type === 'contourcarpet') {
3257-
delete trace.zmin;
3258-
delete trace.zmax;
3259-
}
3260-
});
3271+
}
3272+
});
3273+
out.data.forEach(function(trace) {
3274+
if(trace.type === 'contourcarpet') {
3275+
delete trace.zmin;
3276+
delete trace.zmax;
3277+
}
3278+
});
3279+
3280+
return out;
3281+
}
32613282

3262-
return out;
3283+
// Make sure we define `_length` in every trace *in supplyDefaults*.
3284+
// This is only relevant for traces that *have* a 1D concept of length,
3285+
// and in addition to simplifying calc/plot logic later on, ths serves
3286+
// as a signal to transforms about how they should operate. For traces
3287+
// that do NOT have a 1D length, `_length` should be `null`.
3288+
var mockGD = Lib.extendDeep({}, mock);
3289+
supplyAllDefaults(mockGD);
3290+
expect(mockGD._fullData.length).not.toBeLessThan((mock.data || []).length, mockSpec[0]);
3291+
mockGD._fullData.forEach(function(trace, i) {
3292+
var len = trace._length;
3293+
if(trace.visible !== false && len !== null) {
3294+
expect(typeof len).toBe('number', mockSpec[0] + ' trace ' + i + ': type=' + trace.type);
32633295
}
32643296

3265-
// Make sure we define `_length` in every trace *in supplyDefaults*.
3266-
// This is only relevant for traces that *have* a 1D concept of length,
3267-
// and in addition to simplifying calc/plot logic later on, ths serves
3268-
// as a signal to transforms about how they should operate. For traces
3269-
// that do NOT have a 1D length, `_length` should be `null`.
3270-
var mockGD = Lib.extendDeep({}, mock);
3271-
supplyAllDefaults(mockGD);
3272-
expect(mockGD._fullData.length).not.toBeLessThan((mock.data || []).length, mockSpec[0]);
3273-
mockGD._fullData.forEach(function(trace, i) {
3274-
var len = trace._length;
3275-
if(trace.visible !== false && len !== null) {
3276-
expect(typeof len).toBe('number', mockSpec[0] + ' trace ' + i + ': type=' + trace.type);
3277-
}
3278-
});
3297+
typesTested[trace.type]++;
32793298

3280-
Plotly.newPlot(gd, mock)
3281-
.then(countPlots)
3282-
.then(function() {
3283-
initialJson = fullJson();
3284-
3285-
return Plotly.react(gd, mock);
3286-
})
3287-
.then(function() {
3288-
expect(fullJson()).toEqual(initialJson);
3289-
countCalls({});
3290-
})
3291-
.catch(failTest)
3292-
.then(done);
3299+
if(trace.transforms) {
3300+
trace.transforms.forEach(function(transform) {
3301+
typesTested[transform.type]++;
3302+
});
3303+
}
32933304
});
3305+
3306+
Plotly.newPlot(gd, mock)
3307+
.then(countPlots)
3308+
.then(function() {
3309+
initialJson = fullJson();
3310+
3311+
return Plotly.react(gd, mock);
3312+
})
3313+
.then(function() {
3314+
expect(fullJson()).toEqual(initialJson);
3315+
countCalls({});
3316+
})
3317+
.catch(failTest)
3318+
.then(done);
3319+
}
3320+
3321+
mockList.forEach(function(mockSpec) {
3322+
it('can redraw "' + mockSpec[0] + '" with no changes as a noop', function(done) {
3323+
_runReactMock(mockSpec, done);
3324+
});
3325+
});
3326+
3327+
it('@noCI can redraw scattermapbox with no changes as a noop', function(done) {
3328+
typesTested.scattermapbox = 0;
3329+
3330+
Plotly.setPlotConfig({
3331+
mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN
3332+
});
3333+
3334+
_runReactMock(['scattermapbox', require('@mocks/mapbox_bubbles-text.json')], done);
3335+
});
3336+
3337+
it('tested every trace & transform type at least once', function() {
3338+
for(var itemType in typesTested) {
3339+
expect(typesTested[itemType]).toBeGreaterThan(0, itemType + ' was not tested');
3340+
}
32943341
});
32953342
});
32963343

0 commit comments

Comments
 (0)