From cc71a5f2e60e855ee9b25f5d3200cbca85b3df36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 15 Jun 2016 16:34:47 -0400 Subject: [PATCH 1/3] apply legend border styling on merge selection [fixes #649] - instead of just the enter selection. --- src/components/legend/draw.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 17d386288fb..4a81fb12f1d 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -62,14 +62,14 @@ module.exports = function draw(gd) { var bg = legend.selectAll('rect.bg') .data([0]); - bg.enter().append('rect') - .attr({ - 'class': 'bg', - 'shape-rendering': 'crispEdges' - }) - .call(Color.stroke, opts.bordercolor) - .call(Color.fill, opts.bgcolor) - .style('stroke-width', opts.borderwidth + 'px'); + bg.enter().append('rect').attr({ + 'class': 'bg', + 'shape-rendering': 'crispEdges' + }); + + bg.call(Color.stroke, opts.bordercolor); + bg.call(Color.fill, opts.bgcolor); + bg.style('stroke-width', opts.borderwidth + 'px'); var scrollBox = legend.selectAll('g.scrollbox') .data([0]); From d8d524117a78445fd65e710e465fce214f546c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 15 Jun 2016 16:39:25 -0400 Subject: [PATCH 2/3] flatten legend test suite --- test/jasmine/tests/legend_test.js | 561 +++++++++++++++--------------- 1 file changed, 284 insertions(+), 277 deletions(-) diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index f6bf87a045b..41bdd44a71f 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -7,112 +7,141 @@ var helpers = require('@src/components/legend/helpers'); var anchorUtils = require('@src/components/legend/anchor_utils'); -describe('Test legend:', function() { +describe('legend defaults', function() { 'use strict'; - describe('supplyLayoutDefaults', function() { - var supplyLayoutDefaults = Legend.supplyLayoutDefaults; + var supplyLayoutDefaults = Legend.supplyLayoutDefaults; - var layoutIn, layoutOut, fullData; + var layoutIn, layoutOut, fullData; - beforeEach(function() { - layoutIn = { - showlegend: true - }; - layoutOut = { - font: Plots.layoutAttributes.font, - bg_color: Plots.layoutAttributes.bg_color - }; - }); + beforeEach(function() { + layoutIn = { + showlegend: true + }; + layoutOut = { + font: Plots.layoutAttributes.font, + bg_color: Plots.layoutAttributes.bg_color + }; + }); - it('should default traceorder to reversed for stack bar charts', function() { - fullData = [ - { type: 'bar' }, - { type: 'bar' }, - { type: 'scatter' } - ]; + it('should default traceorder to reversed for stack bar charts', function() { + fullData = [ + { type: 'bar' }, + { type: 'bar' }, + { type: 'scatter' } + ]; - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut.legend.traceorder).toEqual('normal'); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.legend.traceorder).toEqual('normal'); - layoutOut.barmode = 'stack'; + layoutOut.barmode = 'stack'; - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut.legend.traceorder).toEqual('reversed'); - }); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.legend.traceorder).toEqual('reversed'); + }); - it('should default traceorder to reversed for filled tonext scatter charts', function() { - fullData = [ - { type: 'scatter' }, - { type: 'scatter', fill: 'tonexty' } - ]; + it('should default traceorder to reversed for filled tonext scatter charts', function() { + fullData = [ + { type: 'scatter' }, + { type: 'scatter', fill: 'tonexty' } + ]; - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut.legend.traceorder).toEqual('reversed'); - }); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.legend.traceorder).toEqual('reversed'); + }); - it('should default traceorder to grouped when a group is present', function() { - fullData = [ - { type: 'scatter', legendgroup: 'group' }, - { type: 'scatter'} - ]; + it('should default traceorder to grouped when a group is present', function() { + fullData = [ + { type: 'scatter', legendgroup: 'group' }, + { type: 'scatter'} + ]; - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut.legend.traceorder).toEqual('grouped'); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.legend.traceorder).toEqual('grouped'); - fullData[1].fill = 'tonextx'; + fullData[1].fill = 'tonextx'; - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut.legend.traceorder).toEqual('grouped+reversed'); - }); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.legend.traceorder).toEqual('grouped+reversed'); + }); - it('should default orientation to vertical', function() { - supplyLayoutDefaults(layoutIn, layoutOut, []); - expect(layoutOut.legend.orientation).toEqual('v'); - }); + it('should default orientation to vertical', function() { + supplyLayoutDefaults(layoutIn, layoutOut, []); + expect(layoutOut.legend.orientation).toEqual('v'); + }); + + describe('for horizontal legends', function() { + var layoutInForHorizontalLegends; - describe('for horizontal legends', function() { - var layoutInForHorizontalLegends; - - beforeEach(function() { - layoutInForHorizontalLegends = Lib.extendDeep({ - legend: { - orientation: 'h' - }, - xaxis: { - rangeslider: { - visible: false - } + beforeEach(function() { + layoutInForHorizontalLegends = Lib.extendDeep({ + legend: { + orientation: 'h' + }, + xaxis: { + rangeslider: { + visible: false } - }, layoutIn); - }); + } + }, layoutIn); + }); - it('should default position to bottom left', function() { - supplyLayoutDefaults(layoutInForHorizontalLegends, layoutOut, []); - expect(layoutOut.legend.x).toEqual(0); - expect(layoutOut.legend.xanchor).toEqual('left'); - expect(layoutOut.legend.y).toEqual(-0.1); - expect(layoutOut.legend.yanchor).toEqual('top'); - }); + it('should default position to bottom left', function() { + supplyLayoutDefaults(layoutInForHorizontalLegends, layoutOut, []); + expect(layoutOut.legend.x).toEqual(0); + expect(layoutOut.legend.xanchor).toEqual('left'); + expect(layoutOut.legend.y).toEqual(-0.1); + expect(layoutOut.legend.yanchor).toEqual('top'); + }); - it('should default position to top left if a range slider present', function() { - var mockLayoutIn = Lib.extendDeep({}, layoutInForHorizontalLegends); - mockLayoutIn.xaxis.rangeslider.visible = true; + it('should default position to top left if a range slider present', function() { + var mockLayoutIn = Lib.extendDeep({}, layoutInForHorizontalLegends); + mockLayoutIn.xaxis.rangeslider.visible = true; - supplyLayoutDefaults(mockLayoutIn, layoutOut, []); - expect(layoutOut.legend.x).toEqual(0); - expect(layoutOut.legend.xanchor).toEqual('left'); - expect(layoutOut.legend.y).toEqual(1.1); - expect(layoutOut.legend.yanchor).toEqual('bottom'); - }); + supplyLayoutDefaults(mockLayoutIn, layoutOut, []); + expect(layoutOut.legend.x).toEqual(0); + expect(layoutOut.legend.xanchor).toEqual('left'); + expect(layoutOut.legend.y).toEqual(1.1); + expect(layoutOut.legend.yanchor).toEqual('bottom'); }); }); +}); - describe('getLegendData', function() { - var calcdata, opts, legendData, expected; +describe('legend getLegendData', function() { + 'use strict'; + + var calcdata, opts, legendData, expected; + + it('should group legendgroup traces', function() { + calcdata = [ + [{trace: { + type: 'scatter', + visible: true, + legendgroup: 'group', + showlegend: true + + }}], + [{trace: { + type: 'bar', + visible: 'legendonly', + legendgroup: '', + showlegend: true + }}], + [{trace: { + type: 'scatter', + visible: true, + legendgroup: 'group', + showlegend: true + }}] + ]; + opts = { + traceorder: 'grouped' + }; - it('should group legendgroup traces', function() { - calcdata = [ + legendData = getLegendData(calcdata, opts); + + expected = [ + [ [{trace: { type: 'scatter', visible: true, @@ -120,57 +149,57 @@ describe('Test legend:', function() { showlegend: true }}], - [{trace: { - type: 'bar', - visible: 'legendonly', - legendgroup: '', - showlegend: true - }}], [{trace: { type: 'scatter', visible: true, legendgroup: 'group', showlegend: true }}] - ]; - opts = { - traceorder: 'grouped' - }; - - legendData = getLegendData(calcdata, opts); - - expected = [ - [ - [{trace: { - type: 'scatter', - visible: true, - legendgroup: 'group', - showlegend: true - - }}], - [{trace: { - type: 'scatter', - visible: true, - legendgroup: 'group', - showlegend: true - }}] - ], - [ - [{trace: { - type: 'bar', - visible: 'legendonly', - legendgroup: '', - showlegend: true - }}] - ] - ]; - - expect(legendData).toEqual(expected); - expect(opts._lgroupsLength).toEqual(2); - }); + ], + [ + [{trace: { + type: 'bar', + visible: 'legendonly', + legendgroup: '', + showlegend: true + }}] + ] + ]; + + expect(legendData).toEqual(expected); + expect(opts._lgroupsLength).toEqual(2); + }); - it('should collapse when data has only one group', function() { - calcdata = [ + it('should collapse when data has only one group', function() { + calcdata = [ + [{trace: { + type: 'scatter', + visible: true, + legendgroup: '', + showlegend: true + + }}], + [{trace: { + type: 'bar', + visible: 'legendonly', + legendgroup: '', + showlegend: true + }}], + [{trace: { + type: 'scatter', + visible: true, + legendgroup: '', + showlegend: true + }}] + ]; + opts = { + traceorder: 'grouped' + }; + + legendData = getLegendData(calcdata, opts); + + expected = [ + [ [{trace: { type: 'scatter', visible: true, @@ -190,74 +219,74 @@ describe('Test legend:', function() { legendgroup: '', showlegend: true }}] - ]; - opts = { - traceorder: 'grouped' - }; - - legendData = getLegendData(calcdata, opts); - - expected = [ - [ - [{trace: { - type: 'scatter', - visible: true, - legendgroup: '', - showlegend: true - - }}], - [{trace: { - type: 'bar', - visible: 'legendonly', - legendgroup: '', - showlegend: true - }}], - [{trace: { - type: 'scatter', - visible: true, - legendgroup: '', - showlegend: true - }}] - ] - ]; - - expect(legendData).toEqual(expected); - expect(opts._lgroupsLength).toEqual(1); - }); + ] + ]; - it('should return empty array when legend data has no traces', function() { - calcdata = [ - [{trace: { - type: 'histogram', - visible: true, - legendgroup: '', - showlegend: false + expect(legendData).toEqual(expected); + expect(opts._lgroupsLength).toEqual(1); + }); - }}], - [{trace: { - type: 'box', - visible: 'legendonly', - legendgroup: '', - showlegend: false - }}], - [{trace: { - type: 'heatmap', - visible: true, - legendgroup: '' - }}] - ]; - opts = { - traceorder: 'normal' - }; + it('should return empty array when legend data has no traces', function() { + calcdata = [ + [{trace: { + type: 'histogram', + visible: true, + legendgroup: '', + showlegend: false + + }}], + [{trace: { + type: 'box', + visible: 'legendonly', + legendgroup: '', + showlegend: false + }}], + [{trace: { + type: 'heatmap', + visible: true, + legendgroup: '' + }}] + ]; + opts = { + traceorder: 'normal' + }; + + legendData = getLegendData(calcdata, opts); + expect(legendData).toEqual([]); + }); - legendData = getLegendData(calcdata, opts); - expect(legendData).toEqual([]); - }); + it('should reverse the order when legend.traceorder is set', function() { + calcdata = [ + [{trace: { + type: 'scatter', + visible: true, + legendgroup: '', + showlegend: true - it('should reverse the order when legend.traceorder is set', function() { - calcdata = [ + }}], + [{trace: { + type: 'bar', + visible: 'legendonly', + legendgroup: '', + showlegend: true + }}], + [{trace: { + type: 'box', + visible: true, + legendgroup: '', + showlegend: true + }}] + ]; + opts = { + traceorder: 'reversed' + }; + + legendData = getLegendData(calcdata, opts); + + expected = [ + [ [{trace: { - type: 'scatter', + type: 'box', visible: true, legendgroup: '', showlegend: true @@ -270,106 +299,81 @@ describe('Test legend:', function() { showlegend: true }}], [{trace: { - type: 'box', + type: 'scatter', visible: true, legendgroup: '', showlegend: true }}] - ]; - opts = { - traceorder: 'reversed' - }; - - legendData = getLegendData(calcdata, opts); - - expected = [ - [ - [{trace: { - type: 'box', - visible: true, - legendgroup: '', - showlegend: true - - }}], - [{trace: { - type: 'bar', - visible: 'legendonly', - legendgroup: '', - showlegend: true - }}], - [{trace: { - type: 'scatter', - visible: true, - legendgroup: '', - showlegend: true - }}] - ] - ]; - - expect(legendData).toEqual(expected); - expect(opts._lgroupsLength).toEqual(1); - }); + ] + ]; + + expect(legendData).toEqual(expected); + expect(opts._lgroupsLength).toEqual(1); + }); - it('should reverse the trace order within groups when reversed+grouped', function() { - calcdata = [ + it('should reverse the trace order within groups when reversed+grouped', function() { + calcdata = [ + [{trace: { + type: 'scatter', + visible: true, + legendgroup: 'group', + showlegend: true + + }}], + [{trace: { + type: 'bar', + visible: 'legendonly', + legendgroup: '', + showlegend: true + }}], + [{trace: { + type: 'box', + visible: true, + legendgroup: 'group', + showlegend: true + }}] + ]; + opts = { + traceorder: 'reversed+grouped' + }; + + legendData = getLegendData(calcdata, opts); + + expected = [ + [ [{trace: { - type: 'scatter', + type: 'box', visible: true, legendgroup: 'group', showlegend: true }}], + [{trace: { + type: 'scatter', + visible: true, + legendgroup: 'group', + showlegend: true + }}] + ], + [ [{trace: { type: 'bar', visible: 'legendonly', legendgroup: '', showlegend: true - }}], - [{trace: { - type: 'box', - visible: true, - legendgroup: 'group', - showlegend: true }}] - ]; - opts = { - traceorder: 'reversed+grouped' - }; - - legendData = getLegendData(calcdata, opts); - - expected = [ - [ - [{trace: { - type: 'box', - visible: true, - legendgroup: 'group', - showlegend: true - - }}], - [{trace: { - type: 'scatter', - visible: true, - legendgroup: 'group', - showlegend: true - }}] - ], - [ - [{trace: { - type: 'bar', - visible: 'legendonly', - legendgroup: '', - showlegend: true - }}] - ] - ]; - - expect(legendData).toEqual(expected); - expect(opts._lgroupsLength).toEqual(2); - }); + ] + ]; + + expect(legendData).toEqual(expected); + expect(opts._lgroupsLength).toEqual(2); }); +}); - describe('legendGetsTraces helper', function() { +describe('legend helpers:', function() { + 'use strict'; + + describe('legendGetsTraces', function() { var legendGetsTrace = helpers.legendGetsTrace; it('should return true when trace is visible and supports legend', function() { @@ -380,7 +384,7 @@ describe('Test legend:', function() { }); }); - describe('isGrouped helper', function() { + describe('isGrouped', function() { var isGrouped = helpers.isGrouped; it('should return true when trace is visible and supports legend', function() { @@ -392,7 +396,7 @@ describe('Test legend:', function() { }); }); - describe('isReversed helper', function() { + describe('isReversed', function() { var isReversed = helpers.isReversed; it('should return true when trace is visible and supports legend', function() { @@ -403,8 +407,12 @@ describe('Test legend:', function() { expect(isReversed({ traceorder: 'reversed' })).toBe(true); }); }); +}); - describe('isRightAnchor anchor util', function() { +describe('legend anchor utils:', function() { + 'use strict'; + + describe('isRightAnchor', function() { var isRightAnchor = anchorUtils.isRightAnchor; var threshold = 2 / 3; @@ -425,7 +433,7 @@ describe('Test legend:', function() { }); }); - describe('isCenterAnchor anchor util', function() { + describe('isCenterAnchor', function() { var isCenterAnchor = anchorUtils.isCenterAnchor; var threshold0 = 1 / 3; var threshold1 = 2 / 3; @@ -447,7 +455,7 @@ describe('Test legend:', function() { }); }); - describe('isBottomAnchor anchor util', function() { + describe('isBottomAnchor', function() { var isBottomAnchor = anchorUtils.isBottomAnchor; var threshold = 1 / 3; @@ -468,7 +476,7 @@ describe('Test legend:', function() { }); }); - describe('isMiddleAnchor anchor util', function() { + describe('isMiddleAnchor', function() { var isMiddleAnchor = anchorUtils.isMiddleAnchor; var threshold0 = 1 / 3; var threshold1 = 2 / 3; @@ -489,5 +497,4 @@ describe('Test legend:', function() { }); }); }); - }); From 435408561dd5d4c3803cd3ed69fd678a43290587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 15 Jun 2016 17:02:05 -0400 Subject: [PATCH 3/3] update legend relayout update test --- test/jasmine/tests/legend_test.js | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index 41bdd44a71f..1e6b3490aa8 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -1,3 +1,4 @@ +var Plotly = require('@lib/index'); var Plots = require('@src/plots/plots'); var Lib = require('@src/lib'); @@ -6,6 +7,10 @@ var getLegendData = require('@src/components/legend/get_legend_data'); var helpers = require('@src/components/legend/helpers'); var anchorUtils = require('@src/components/legend/anchor_utils'); +var d3 = require('d3'); +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); + describe('legend defaults', function() { 'use strict'; @@ -498,3 +503,40 @@ describe('legend anchor utils:', function() { }); }); }); + +describe('legend relayout update', function() { + 'use strict'; + + afterEach(destroyGraphDiv); + + it('should update border styling', function(done) { + var mock = require('@mocks/0.json'), + mockCopy = Lib.extendDeep({}, mock), + gd = createGraphDiv(); + + function assertLegendStyle(bgColor, borderColor, borderWidth) { + var node = d3.select('g.legend').select('rect'); + + expect(node.style('fill')).toEqual(bgColor); + expect(node.style('stroke')).toEqual(borderColor); + expect(node.style('stroke-width')).toEqual(borderWidth + 'px'); + } + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + assertLegendStyle('rgb(255, 255, 255)', 'rgb(0, 0, 0)', 1); + + return Plotly.relayout(gd, { + 'legend.bordercolor': 'red', + 'legend.bgcolor': 'blue' + }); + }).then(function() { + assertLegendStyle('rgb(0, 0, 255)', 'rgb(255, 0, 0)', 1); + + return Plotly.relayout(gd, 'legend.borderwidth', 10); + }).then(function() { + assertLegendStyle('rgb(0, 0, 255)', 'rgb(255, 0, 0)', 10); + + done(); + }); + }); +});