diff --git a/src/snapshot/tosvg.js b/src/snapshot/tosvg.js index 51583764730..ae320d71ac7 100644 --- a/src/snapshot/tosvg.js +++ b/src/snapshot/tosvg.js @@ -116,15 +116,20 @@ module.exports = function toSVG(gd, format, scale) { } }); - svg.selectAll('.point,.scatterpts').each(function() { + svg.selectAll('.point, .scatterpts, .legendfill>path, .legendlines>path, .cbfill').each(function() { var pt = d3.select(this); - var fill = this.style.fill; // similar to font family styles above, // we must remove " after the SVG DOM has been serialized + var fill = this.style.fill; if(fill && fill.indexOf('url(') !== -1) { pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); } + + var stroke = this.style.stroke; + if(stroke && stroke.indexOf('url(') !== -1) { + pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } }); if(format === 'pdf' || format === 'eps') { diff --git a/test/jasmine/tests/snapshot_test.js b/test/jasmine/tests/snapshot_test.js index da84c2fd0d2..90c875e535d 100644 --- a/test/jasmine/tests/snapshot_test.js +++ b/test/jasmine/tests/snapshot_test.js @@ -1,4 +1,5 @@ var Plotly = require('@lib/index'); +var Lib = require('@src/lib'); var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); @@ -250,55 +251,101 @@ describe('Plotly.Snapshot', function() { }); }); - it('should handle quoted style properties', function(done) { - Plotly.plot(gd, [{ - y: [1, 2, 1], - marker: { - gradient: { - type: 'radial', - color: '#fff' - }, - color: ['red', 'blue', 'green'] - } - }], { - font: { family: 'Times New Roman' }, - showlegend: true - }) - .then(function() { - d3.selectAll('text').each(function() { - expect(this.style.fontFamily).toEqual('\"Times New Roman\"'); - }); + describe('should handle quoted style properties', function() { + function checkURL(actual, msg) { + // which is enough tot check that toSVG did its job right + expect((actual || '').substr(0, 6)).toBe('url(\"#', msg); + } - d3.selectAll('.point,.scatterpts').each(function() { - expect(this.style.fill.substr(0, 6)).toEqual('url(\"#'); - }); + it('- marker-gradient case', function(done) { + Plotly.plot(gd, [{ + y: [1, 2, 1], + marker: { + gradient: { + type: 'radial', + color: '#fff' + }, + color: ['red', 'blue', 'green'] + } + }], { + font: { family: 'Times New Roman' }, + showlegend: true + }) + .then(function() { + d3.selectAll('text').each(function() { + expect(this.style.fontFamily).toEqual('\"Times New Roman\"'); + }); + + d3.selectAll('.point,.scatterpts').each(function() { + checkURL(this.style.fill); + }); + + return Plotly.Snapshot.toSVG(gd); + }) + .then(function(svg) { + var svgDOM = parser.parseFromString(svg, 'image/svg+xml'); + var i; + + var textElements = svgDOM.getElementsByTagName('text'); + expect(textElements.length).toEqual(12); + + for(i = 0; i < textElements.length; i++) { + expect(textElements[i].style.fontFamily).toEqual('\"Times New Roman\"'); + } - return Plotly.Snapshot.toSVG(gd); - }) - .then(function(svg) { - var svgDOM = parser.parseFromString(svg, 'image/svg+xml'); - var i; + var pointElements = svgDOM.getElementsByClassName('point'); + expect(pointElements.length).toEqual(3); + + for(i = 0; i < pointElements.length; i++) { + checkURL(pointElements[i].style.fill); + } - var textElements = svgDOM.getElementsByTagName('text'); - expect(textElements.length).toEqual(12); + var legendPointElements = svgDOM.getElementsByClassName('scatterpts'); + expect(legendPointElements.length).toEqual(1); + checkURL(legendPointElements[0].style.fill); + }) + .catch(failTest) + .then(done); + }); - for(i = 0; i < textElements.length; i++) { - expect(textElements[i].style.fontFamily).toEqual('\"Times New Roman\"'); - } + it('- legend with contour items case', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/contour_legend.json')); + var fillItemIndices = [0, 4, 5]; - var pointElements = svgDOM.getElementsByClassName('point'); - expect(pointElements.length).toEqual(3); + Plotly.plot(gd, fig) + .then(function() { return Plotly.Snapshot.toSVG(gd); }) + .then(function(svg) { + var svgDOM = parser.parseFromString(svg, 'image/svg+xml'); - for(i = 0; i < pointElements.length; i++) { - expect(pointElements[i].style.fill.substr(0, 6)).toEqual('url(\"#'); - } + var fillItems = svgDOM.getElementsByClassName('legendfill'); + for(var i = 0; i < fillItemIndices.length; i++) { + checkURL(fillItems[fillItemIndices[i]].firstChild.style.fill, 'fill gradient ' + i); + } - var legendPointElements = svgDOM.getElementsByClassName('scatterpts'); - expect(legendPointElements.length).toEqual(1); - expect(legendPointElements[0].style.fill.substr(0, 6)).toEqual('url(\"#'); - }) - .catch(failTest) - .then(done); + var lineItems = svgDOM.getElementsByClassName('legendlines'); + checkURL(lineItems[1].firstChild.style.stroke, 'stroke gradient'); + }) + .catch(failTest) + .then(done); + }); + + it('- colorbar case', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/16.json')); + + Plotly.plot(gd, fig) + .then(function() { return Plotly.Snapshot.toSVG(gd); }) + .then(function(svg) { + var svgDOM = parser.parseFromString(svg, 'image/svg+xml'); + + var fillItems = svgDOM.getElementsByClassName('cbfill'); + expect(fillItems.length).toBe(1, '# of colorbars'); + for(var i = 0; i < fillItems.length; i++) { + checkURL(fillItems[i].style.fill, 'fill gradient ' + i); + } + }) + .catch(failTest) + .then(done); + }); }); it('should adapt *viewBox* attribute under *scale* option', function(done) {