Skip to content

Commit cd92fea

Browse files
committed
Add jasmine tests for legend title click
1 parent 2f934ad commit cd92fea

1 file changed

Lines changed: 247 additions & 0 deletions

File tree

test/jasmine/tests/legend_test.js

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2794,3 +2794,250 @@ describe('legend with custom legendwidth', function() {
27942794
}).then(done, done.fail);
27952795
});
27962796
});
2797+
2798+
describe('legend title click', function() {
2799+
"use strict";
2800+
2801+
var gd;
2802+
2803+
beforeEach(function() {
2804+
gd = createGraphDiv();
2805+
});
2806+
afterEach(destroyGraphDiv);
2807+
2808+
function clickTitle(legendId, clicks) {
2809+
return function() {
2810+
return new Promise(function(resolve) {
2811+
var selector = '.' + (legendId || 'legend') + 'titletoggle';
2812+
var item = d3Select(selector).node();
2813+
if(!item) {
2814+
fail('Could not find title toggle element: ' + selector);
2815+
return resolve();
2816+
}
2817+
for(var i = 0; i < (clicks || 1); i++) {
2818+
item.dispatchEvent(new MouseEvent('mousedown'));
2819+
item.dispatchEvent(new MouseEvent('mouseup'));
2820+
}
2821+
setTimeout(resolve, DBLCLICKDELAY + 100);
2822+
});
2823+
};
2824+
}
2825+
2826+
function extractVisibilities(data) {
2827+
return data.map(function(trace) { return trace.visible; });
2828+
}
2829+
2830+
function assertVisible(expectation) {
2831+
return function() {
2832+
var actual = extractVisibilities(gd._fullData);
2833+
expect(actual).toEqual(expectation);
2834+
};
2835+
}
2836+
2837+
function assertVisibleShapes(expectation) {
2838+
return function() {
2839+
var actual = extractVisibilities(gd._fullLayout.shapes);
2840+
expect(actual).toEqual(expectation);
2841+
};
2842+
}
2843+
2844+
describe('defaults', function() {
2845+
it('should disable title clicking by default for a single legend', function(done) {
2846+
Plotly.newPlot(gd, [
2847+
{ x: [1, 2], y: [1, 2] },
2848+
{ x: [1, 2], y: [2, 3] }
2849+
], {
2850+
legend: { title: { text: 'Legend' } }
2851+
}).then(function() {
2852+
expect(gd._fullLayout.legend.titleclick).toBe(false);
2853+
expect(gd._fullLayout.legend.titledoubleclick).toBe(false);
2854+
}).then(done, done.fail);
2855+
});
2856+
2857+
it('should enable title clicking by default for multiple legends', function(done) {
2858+
Plotly.newPlot(gd, [
2859+
{ x: [1, 2], y: [1, 2] },
2860+
{ x: [1, 2], y: [2, 3] },
2861+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
2862+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
2863+
], {
2864+
showlegend: true,
2865+
legend: { title: { text: 'Legend 1' } },
2866+
legend2: { title: { text: 'Legend 2' } }
2867+
}).then(function() {
2868+
expect(gd._fullLayout.legend.titleclick).toBe('toggle');
2869+
expect(gd._fullLayout.legend.titledoubleclick).toBe('toggleothers');
2870+
expect(gd._fullLayout.legend2.titleclick).toBe('toggle');
2871+
expect(gd._fullLayout.legend2.titledoubleclick).toBe('toggleothers');
2872+
}).then(done, done.fail);
2873+
});
2874+
2875+
it('should allow user to override titleclick and titledoubleclick', function(done) {
2876+
Plotly.newPlot(gd, [
2877+
{ x: [1, 2], y: [1, 2] },
2878+
{ x: [1, 2], y: [2, 3] }
2879+
], {
2880+
legend: {
2881+
title: { text: 'Legend' },
2882+
titleclick: 'toggle',
2883+
titledoubleclick: false
2884+
}
2885+
}).then(function() {
2886+
expect(gd._fullLayout.legend.titleclick).toBe('toggle');
2887+
expect(gd._fullLayout.legend.titledoubleclick).toBe(false);
2888+
}).then(done, done.fail);
2889+
});
2890+
});
2891+
2892+
describe('toggle interactions', function() {
2893+
beforeEach(function(done) {
2894+
Plotly.newPlot(gd, [
2895+
{ x: [1, 2], y: [1, 2] },
2896+
{ x: [1, 2], y: [2, 3] },
2897+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
2898+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
2899+
], {
2900+
showlegend: true,
2901+
legend: { title: { text: 'Legend 1' } },
2902+
legend2: { title: { text: 'Legend 2' }, y: 0.5 }
2903+
}).then(done);
2904+
});
2905+
2906+
it('should hide all traces in legend when clicking title (all visible)', function(done) {
2907+
Promise.resolve()
2908+
.then(assertVisible([true, true, true, true]))
2909+
.then(clickTitle('legend'))
2910+
.then(assertVisible(['legendonly', 'legendonly', true, true]))
2911+
.then(done, done.fail);
2912+
});
2913+
2914+
it('should show all traces in legend when clicking title (all hidden)', function(done) {
2915+
Plotly.restyle(gd, 'visible', 'legendonly', [0, 1])
2916+
.then(assertVisible(['legendonly', 'legendonly', true, true]))
2917+
.then(clickTitle('legend'))
2918+
.then(assertVisible([true, true, true, true]))
2919+
.then(done, done.fail);
2920+
});
2921+
2922+
it('should not affect traces with visible: false', function(done) {
2923+
Plotly.restyle(gd, 'visible', false, [0])
2924+
.then(assertVisible([false, true, true, true]))
2925+
.then(clickTitle('legend'))
2926+
.then(assertVisible([false, 'legendonly', true, true]))
2927+
.then(done, done.fail);
2928+
});
2929+
});
2930+
2931+
describe('toggleothers interactions', function() {
2932+
beforeEach(function(done) {
2933+
Plotly.newPlot(gd, [
2934+
{ x: [1, 2], y: [1, 2] },
2935+
{ x: [1, 2], y: [2, 3] },
2936+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
2937+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
2938+
], {
2939+
showlegend: true,
2940+
legend: { title: { text: 'Legend 1' } },
2941+
legend2: { title: { text: 'Legend 2' }, y: 0.5 }
2942+
}).then(done);
2943+
});
2944+
2945+
it('should isolate this legend (hide others)', function(done) {
2946+
Promise.resolve()
2947+
.then(assertVisible([true, true, true, true]))
2948+
.then(clickTitle('legend', 2))
2949+
.then(assertVisible([true, true, 'legendonly', 'legendonly']))
2950+
.then(done, done.fail);
2951+
});
2952+
2953+
it('should restore all when already isolated', function(done) {
2954+
Plotly.restyle(gd, 'visible', 'legendonly', [2, 3])
2955+
.then(assertVisible([true, true, 'legendonly', 'legendonly']))
2956+
.then(clickTitle('legend', 2))
2957+
.then(assertVisible([true, true, true, true]))
2958+
.then(done, done.fail);
2959+
});
2960+
});
2961+
2962+
describe('interactions with shapes', function() {
2963+
beforeEach(function(done) {
2964+
Plotly.newPlot(gd, [
2965+
{ x: [1, 2], y: [1, 2] },
2966+
{ x: [1, 2], y: [2, 3] },
2967+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
2968+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
2969+
], {
2970+
showlegend: true,
2971+
legend: { title: { text: 'Legend 1' } },
2972+
legend2: { title: { text: 'Legend 2' }, y: 0.5 },
2973+
shapes: [
2974+
{ showlegend: true, type: 'line', x0: 0, y0: 0, x1: 1, y1: 1 },
2975+
{ showlegend: true, type: 'rect', x0: 0, y0: 0, x1: 1, y1: 1, legend: 'legend2' }
2976+
]
2977+
}).then(done);
2978+
});
2979+
2980+
it('should toggle shapes with traces', function(done) {
2981+
Promise.resolve()
2982+
.then(assertVisible([true, true, true, true]))
2983+
.then(assertVisibleShapes([true, true]))
2984+
.then(clickTitle('legend'))
2985+
.then(assertVisible(['legendonly', 'legendonly', true, true]))
2986+
.then(assertVisibleShapes(['legendonly', true]))
2987+
.then(done, done.fail);
2988+
});
2989+
});
2990+
2991+
it('should not create click target when no title text', function(done) {
2992+
Plotly.newPlot(gd, [
2993+
{ x: [1, 2], y: [1, 2] },
2994+
{ x: [1, 2], y: [2, 3] },
2995+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
2996+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
2997+
], {
2998+
showlegend: true,
2999+
legend: {},
3000+
legend2: { y: 0.5 }
3001+
}).then(function() {
3002+
var titleToggle = d3Select('.legendtitletoggle');
3003+
expect(titleToggle.size()).toBe(0);
3004+
}).then(done, done.fail);
3005+
});
3006+
3007+
it('should have a pointer cursor on hover for clickable titles', function(done) {
3008+
Plotly.newPlot(gd, [
3009+
{ x: [1, 2], y: [1, 2] },
3010+
{ x: [1, 2], y: [2, 3] },
3011+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
3012+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
3013+
], {
3014+
showlegend: true,
3015+
legend: { title: { text: 'Legend 1' } },
3016+
legend2: { title: { text: 'Legend 2' }, y: 0.5 }
3017+
}).then(function() {
3018+
var titleToggle = d3Select('.legendtitletoggle').node();
3019+
expect(titleToggle.style.cursor).toBe('pointer');
3020+
}).then(done, done.fail);
3021+
});
3022+
3023+
it('should not have pointer cursor on static plots', function(done) {
3024+
Plotly.newPlot(gd, [
3025+
{ x: [1, 2], y: [1, 2] },
3026+
{ x: [1, 2], y: [2, 3] },
3027+
{ x: [1, 2], y: [3, 4], legend: 'legend2' },
3028+
{ x: [1, 2], y: [4, 5], legend: 'legend2' }
3029+
], {
3030+
showlegend: true,
3031+
legend: { title: { text: 'Legend 1' } },
3032+
legend2: { title: { text: 'Legend 2' }, y: 0.5 }
3033+
}, {
3034+
staticPlot: true
3035+
}).then(function() {
3036+
var titleToggle = d3Select('.legendtitletoggle').node();
3037+
// On static plots, the title toggle rect is created but without pointer cursor
3038+
if(titleToggle) {
3039+
expect(titleToggle.style.cursor).not.toBe('pointer');
3040+
}
3041+
}).then(done, done.fail);
3042+
});
3043+
});

0 commit comments

Comments
 (0)