Skip to content

Commit 65f618d

Browse files
committed
Write failing tests for binding computation
1 parent f2d268d commit 65f618d

File tree

2 files changed

+141
-26
lines changed

2 files changed

+141
-26
lines changed

src/plots/command.js

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@
1010
'use strict';
1111

1212
var Plotly = require('../plotly');
13+
var Lib = require('../lib');
1314
var helpers = require('../plot_api/helpers');
1415

1516
exports.executeAPICommand = function(gd, method, args) {
1617
var apiMethod = Plotly[method];
1718

1819
var allArgs = [gd];
19-
for (var i = 0; i < args.length; i++) {
20+
for(var i = 0; i < args.length; i++) {
2021
allArgs.push(args[i]);
2122
}
2223

23-
if (!apiMethod) {
24+
if(!apiMethod) {
2425
return Promise.reject();
2526
}
2627

@@ -30,30 +31,49 @@ exports.executeAPICommand = function(gd, method, args) {
3031
exports.computeAPICommandBindings = function(gd, method, args) {
3132

3233
switch(method) {
33-
case 'restyle':
34-
var traces
34+
case 'restyle':
35+
var traces;
3536

3637
// Logic copied from Plotly.restyle:
37-
var astr = args[0];
38-
var val = args[1];
39-
var traces = args[2];
40-
var aobj = {};
41-
if(typeof astr === 'string') aobj[astr] = val;
42-
else if(Lib.isPlainObject(astr)) {
38+
var astr = args[0];
39+
var val = args[1];
40+
var traces = args[2];
41+
var aobj = {};
42+
if(typeof astr === 'string') aobj[astr] = val;
43+
else if(Lib.isPlainObject(astr)) {
4344
// the 3-arg form
44-
aobj = astr;
45-
if(traces === undefined) traces = val;
46-
} else {
45+
aobj = astr;
46+
if(traces === undefined) traces = val;
47+
} else {
4748
// This is the failure case, but it's not a concern of this method to fail
4849
// on bad input. This will just return no bindings:
49-
return [];
50-
}
50+
return [];
51+
}
5152

52-
console.log('aobj:', aobj);
53+
console.log('aobj:', aobj);
5354

54-
return ['data[0].marker.size'];
55-
break;
56-
default:
57-
throw new Error('Unimplemented');
55+
return ['data[0].marker.size'];
56+
break;
57+
default:
58+
// The unknown case. We'll elect to fail-non-fatal since this is a correct
59+
// answer and since this is not a validation method.
60+
return [];
5861
}
5962
};
63+
64+
function crawl(attrs, callback, path) {
65+
if(path === undefined) {
66+
path = '';
67+
}
68+
69+
Object.keys(attrs).forEach(function(attrName) {
70+
var attr = attrs[attrName];
71+
72+
if(exports.UNDERSCORE_ATTRS.indexOf(attrName) !== -1) return;
73+
74+
callback(attr, attrName, attrs, level);
75+
76+
if(isValObject(attr)) return;
77+
if(isPlainObject(attr)) crawl(attr, callback, level + 1);
78+
});
79+
}

test/jasmine/tests/command_test.js

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('Plots.executeAPICommand', function() {
2323
beforeEach(function() {
2424
spyOn(PlotlyInternal, 'restyle').and.callFake(function() {
2525
return Promise.resolve('resolution');
26-
})
26+
});
2727
});
2828

2929
it('calls the API method and resolves', function(done) {
@@ -43,7 +43,7 @@ describe('Plots.executeAPICommand', function() {
4343
beforeEach(function() {
4444
spyOn(PlotlyInternal, 'restyle').and.callFake(function() {
4545
return Promise.reject('rejection');
46-
})
46+
});
4747
});
4848

4949
it('calls the API method and rejects', function(done) {
@@ -68,7 +68,10 @@ describe('Plots.computeAPICommandBindings', function() {
6868
beforeEach(function() {
6969
gd = createGraphDiv();
7070

71-
Plotly.plot(gd, [{x: [1, 2, 3], y: [4, 5, 6]}]);
71+
Plotly.plot(gd, [
72+
{x: [1, 2, 3], y: [1, 2, 3]},
73+
{x: [1, 2, 3], y: [4, 5, 6]},
74+
]);
7275
});
7376

7477
afterEach(function() {
@@ -77,10 +80,102 @@ describe('Plots.computeAPICommandBindings', function() {
7780

7881
describe('restyle', function() {
7982
describe('astr + val notation', function() {
80-
it('computes the binding', function() {
81-
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', 7]);
83+
describe('with a single attribute', function() {
84+
it('with a scalar value', function() {
85+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', 7]);
86+
expect(result).toEqual(['data[0].marker.size', 'data[1].marker.size']);
87+
});
88+
89+
it('with an array value and no trace specified', function() {
90+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7]]);
91+
expect(result).toEqual(['data[0].marker.size', 'data[1].marker.size']);
92+
});
93+
94+
it('with trace specified', function() {
95+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', 7, [0]]);
96+
expect(result).toEqual(['data[0].marker.size']);
97+
});
98+
99+
it('with a different trace specified', function() {
100+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', 7, [1]]);
101+
expect(result).toEqual(['data[1].marker.size']);
102+
});
103+
104+
it('with an array value', function() {
105+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7], [0]]);
106+
expect(result).toEqual(['data[1].marker.size']);
107+
});
108+
109+
it('with two array values and two traces specified', function() {
110+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [0, 1]]);
111+
expect(result).toEqual(['data[0].marker.size', 'data[1].marker.size']);
112+
});
113+
114+
it('with traces specified in reverse order', function() {
115+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [1, 0]]);
116+
expect(result).toEqual(['data[1].marker.size', 'data[0].marker.size']);
117+
});
118+
119+
it('with two values and a single trace specified', function() {
120+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [0]]);
121+
expect(result).toEqual(['data[0].marker.size']);
122+
});
123+
124+
it('with two values and a different trace specified', function() {
125+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [1]]);
126+
expect(result).toEqual(['data[1].marker.size']);
127+
});
128+
});
129+
});
130+
131+
describe('aobj notation', function() {
132+
describe('with a single attribute', function() {
133+
it('with a scalar value', function() {
134+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': 7}]);
135+
expect(result).toEqual(['data[0].marker.size', 'data[1].marker.size']);
136+
});
137+
138+
it('with trace specified', function() {
139+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': 7}, [0]]);
140+
expect(result).toEqual(['data[0].marker.size']);
141+
});
142+
143+
it('with a different trace specified', function() {
144+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': 7}, [1]]);
145+
expect(result).toEqual(['data[1].marker.size']);
146+
});
147+
148+
it('with an array value', function() {
149+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': [7]}, [0]]);
150+
expect(result).toEqual(['data[1].marker.size']);
151+
});
152+
153+
it('with two array values and two traces specified', function() {
154+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': [7, 5]}, [0, 1]]);
155+
expect(result).toEqual(['data[0].marker.size', 'data[1].marker.size']);
156+
});
157+
158+
it('with traces specified in reverse order', function() {
159+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': [7, 5]}, [1, 0]]);
160+
expect(result).toEqual(['data[1].marker.size', 'data[0].marker.size']);
161+
});
162+
163+
it('with two values and a single trace specified', function() {
164+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': [7, 5]}, [0]]);
165+
expect(result).toEqual(['data[0].marker.size']);
166+
});
167+
168+
it('with two values and a different trace specified', function() {
169+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': [7, 5]}, [1]]);
170+
expect(result).toEqual(['data[1].marker.size']);
171+
});
172+
});
82173

83-
expect(result).toEqual(['data[0].marker.size']);
174+
describe('with multiple attributes', function() {
175+
it('with a scalar value', function() {
176+
var result = Plots.computeAPICommandBindings(gd, 'restyle', [{'marker.size': 7, 'text.color': 'blue'}]);
177+
expect(result).toEqual(['data[0].marker.size', 'data[1].marker.size', 'data[0].text.color', 'data[1].text.color']);
178+
});
84179
});
85180
});
86181
});

0 commit comments

Comments
 (0)