Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix toSVG for graphs that call Drawing.gradient #2914

Merged
merged 5 commits into from
Aug 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/snapshot/tosvg.js
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand Down
48 changes: 38 additions & 10 deletions tasks/noci_test.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
#! /bin/bash
#
# Run tests that aren't ran on CI (yet)
#
# to run all no-ci tests
# $ (plotly.js) ./tasks/noci_test.sh
#
# to run jasmine no-ci tests
# $ (plotly.js) ./tasks/noci_test.sh jasmine

# to run image no-ci tests
# $ (plotly.js) ./tasks/noci_test.sh image
#
# -----------------------------------------------

EXIT_STATE=0
root=$(dirname $0)/..

# tests that aren't run on CI (yet)

# jasmine specs with @noCI tag
npm run test-jasmine -- --tags=noCI,noCIdep --nowatch || EXIT_STATE=$?
test_jasmine () {
npm run test-jasmine -- --tags=noCI,noCIdep --nowatch || EXIT_STATE=$?
}

# mapbox image tests take too much resources on CI
#
Expand All @@ -15,12 +28,27 @@ npm run test-jasmine -- --tags=noCI,noCIdep --nowatch || EXIT_STATE=$?
# 'old' image server
#
# cone traces don't render correctly in the imagetest container
$root/../orca/bin/orca.js graph \
$root/test/image/mocks/mapbox_* \
$root/test/image/mocks/gl3d_cone* \
--plotly $root/build/plotly.js \
--mapbox-access-token "pk.eyJ1IjoiZXRwaW5hcmQiLCJhIjoiY2luMHIzdHE0MGFxNXVubTRxczZ2YmUxaCJ9.hwWZful0U2CQxit4ItNsiQ" \
--output-dir $root/test/image/baselines/ \
--verbose
test_image () {
$root/../orca/bin/orca.js graph \
$root/test/image/mocks/mapbox_* \
$root/test/image/mocks/gl3d_cone* \
--plotly $root/build/plotly.js \
--mapbox-access-token "pk.eyJ1IjoiZXRwaW5hcmQiLCJhIjoiY2luMHIzdHE0MGFxNXVubTRxczZ2YmUxaCJ9.hwWZful0U2CQxit4ItNsiQ" \
--output-dir $root/test/image/baselines/ \
--verbose || EXIT_STATE=$?
}

case $1 in
jasmine)
test_jasmine
;;
image)
test_image
;;
*)
test_jasmine
test_image
;;
esac

exit $EXIT_STATE
135 changes: 91 additions & 44 deletions test/jasmine/tests/snapshot_test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
var Plotly = require('@lib/index');
var Lib = require('@src/lib');

var d3 = require('d3');
var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
var fail = require('../assets/fail_test');
var failTest = require('../assets/fail_test');

var subplotMock = require('../../image/mocks/multiple_subplots.json');
var annotationMock = require('../../image/mocks/annotations.json');
Expand Down Expand Up @@ -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);

var textElements = svgDOM.getElementsByTagName('text');
expect(textElements.length).toEqual(12);
for(i = 0; i < pointElements.length; i++) {
checkURL(pointElements[i].style.fill);
}

for(i = 0; i < textElements.length; i++) {
expect(textElements[i].style.fontFamily).toEqual('\"Times New Roman\"');
}
var legendPointElements = svgDOM.getElementsByClassName('scatterpts');
expect(legendPointElements.length).toEqual(1);
checkURL(legendPointElements[0].style.fill);
})
.catch(failTest)
.then(done);
});

var pointElements = svgDOM.getElementsByClassName('point');
expect(pointElements.length).toEqual(3);
it('- legend with contour items case', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/contour_legend.json'));
var fillItemIndices = [0, 4, 5];

for(i = 0; i < pointElements.length; i++) {
expect(pointElements[i].style.fill.substr(0, 6)).toEqual('url(\"#');
}
Plotly.plot(gd, fig)
.then(function() { return Plotly.Snapshot.toSVG(gd); })
.then(function(svg) {
var svgDOM = parser.parseFromString(svg, 'image/svg+xml');

var legendPointElements = svgDOM.getElementsByClassName('scatterpts');
expect(legendPointElements.length).toEqual(1);
expect(legendPointElements[0].style.fill.substr(0, 6)).toEqual('url(\"#');
})
.catch(fail)
.then(done);
var fillItems = svgDOM.getElementsByClassName('legendfill');
for(var i = 0; i < fillItemIndices.length; i++) {
checkURL(fillItems[fillItemIndices[i]].firstChild.style.fill, 'fill gradient ' + i);
}

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) {
Expand All @@ -317,7 +364,7 @@ describe('Plotly.Snapshot', function() {
expect(el.getAttribute('height')).toBe('1000', 'height');
expect(el.getAttribute('viewBox')).toBe('0 0 300 400', 'viewbox');
})
.catch(fail)
.catch(failTest)
.then(done);
});
});
Expand Down