From 7cf69e26488bcd5bdce158904399b8a5e76796a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= <etienne@plot.ly>
Date: Thu, 13 Apr 2017 17:55:32 -0400
Subject: [PATCH 1/2] pass context mapbox access token during cloneplot

- so that toImage works when token is set in config
  argument.
---
 src/snapshot/cloneplot.js           | 4 +++-
 test/jasmine/tests/snapshot_test.js | 3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/snapshot/cloneplot.js b/src/snapshot/cloneplot.js
index bb44098caae..a03e2667b6c 100644
--- a/src/snapshot/cloneplot.js
+++ b/src/snapshot/cloneplot.js
@@ -70,6 +70,7 @@ module.exports = function clonePlot(graphObj, options) {
     var oldLayout = graphObj.layout;
     var newData = extendDeep([], oldData);
     var newLayout = extendDeep({}, oldLayout, cloneLayoutOverride(options.tileClass));
+    var context = graphObj._context || {};
 
     if(options.width) newLayout.width = options.width;
     if(options.height) newLayout.height = options.height;
@@ -153,7 +154,8 @@ module.exports = function clonePlot(graphObj, options) {
                 options.plotGlPixelRatio,
             displaylogo: options.displaylogo || false,
             showLink: options.showLink || false,
-            showTips: options.showTips || false
+            showTips: options.showTips || false,
+            mapboxAccessToken: context.mapboxAccessToken
         }
     };
 
diff --git a/test/jasmine/tests/snapshot_test.js b/test/jasmine/tests/snapshot_test.js
index 72c01d2a8ab..cd712b5a1b0 100644
--- a/test/jasmine/tests/snapshot_test.js
+++ b/test/jasmine/tests/snapshot_test.js
@@ -80,7 +80,8 @@ describe('Plotly.Snapshot', function() {
                 displaylogo: false,
                 showLink: false,
                 showTips: false,
-                setBackground: 'opaque'
+                setBackground: 'opaque',
+                mapboxAccessToken: undefined
             };
 
             var themeTile = Plotly.Snapshot.clone(dummyGraphObj, themeOptions);

From 6dd25e2ab5f2c2f63b6f2d212ba96caf1abf23d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= <etienne@plot.ly>
Date: Thu, 13 Apr 2017 17:55:41 -0400
Subject: [PATCH 2/2] add mapbox to image tests

---
 test/jasmine/tests/mapbox_test.js        | 73 ++++++++++++++++++++++++
 test/jasmine/tests/scattermapbox_test.js | 13 +++--
 2 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/test/jasmine/tests/mapbox_test.js b/test/jasmine/tests/mapbox_test.js
index d494573ecb2..ae866723a75 100644
--- a/test/jasmine/tests/mapbox_test.js
+++ b/test/jasmine/tests/mapbox_test.js
@@ -964,5 +964,78 @@ describe('@noCI, mapbox plots', function() {
             }, MOUSE_DELAY);
         });
     }
+});
+
+describe('@noCI, mapbox toImage', function() {
+    var MINIMUM_LENGTH = 1e5;
+
+    var gd;
+
+    beforeEach(function() {
+        gd = createGraphDiv();
+    });
+
+    afterEach(function() {
+        Plotly.purge(gd);
+        Plotly.setPlotConfig({ mapboxAccessToken: null });
+        destroyGraphDiv();
+    });
+
+    it('should generate image data with global credentials', function(done) {
+        Plotly.setPlotConfig({
+            mapboxAccessToken: MAPBOX_ACCESS_TOKEN
+        });
+
+        Plotly.newPlot(gd, [{
+            type: 'scattermapbox',
+            lon: [0, 10, 20],
+            lat: [-10, 10, -10]
+        }])
+        .then(function() {
+            return Plotly.toImage(gd);
+        })
+        .then(function(imgData) {
+            expect(imgData.length).toBeGreaterThan(MINIMUM_LENGTH);
+        })
+        .catch(failTest)
+        .then(done);
+    }, LONG_TIMEOUT_INTERVAL);
+
+    it('should generate image data with config credentials', function(done) {
+        Plotly.newPlot(gd, [{
+            type: 'scattermapbox',
+            lon: [0, 10, 20],
+            lat: [-10, 10, -10]
+        }], {}, {
+            mapboxAccessToken: MAPBOX_ACCESS_TOKEN
+        })
+        .then(function() {
+            return Plotly.toImage(gd);
+        })
+        .then(function(imgData) {
+            expect(imgData.length).toBeGreaterThan(MINIMUM_LENGTH);
+        })
+        .catch(failTest)
+        .then(done);
+    }, LONG_TIMEOUT_INTERVAL);
 
+    it('should generate image data with layout credentials', function(done) {
+        Plotly.newPlot(gd, [{
+            type: 'scattermapbox',
+            lon: [0, 10, 20],
+            lat: [-10, 10, -10]
+        }], {
+            mapbox: {
+                accesstoken: MAPBOX_ACCESS_TOKEN
+            }
+        })
+        .then(function() {
+            return Plotly.toImage(gd);
+        })
+        .then(function(imgData) {
+            expect(imgData.length).toBeGreaterThan(MINIMUM_LENGTH);
+        })
+        .catch(failTest)
+        .then(done);
+    }, LONG_TIMEOUT_INTERVAL);
 });
diff --git a/test/jasmine/tests/scattermapbox_test.js b/test/jasmine/tests/scattermapbox_test.js
index 1a2b84d05e5..7670ca1d8f2 100644
--- a/test/jasmine/tests/scattermapbox_test.js
+++ b/test/jasmine/tests/scattermapbox_test.js
@@ -24,11 +24,6 @@ function move(fromX, fromY, toX, toY, delay) {
     });
 }
 
-Plotly.setPlotConfig({
-    mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN
-});
-
-
 describe('scattermapbox defaults', function() {
     'use strict';
 
@@ -341,6 +336,10 @@ describe('@noCI scattermapbox hover', function() {
     beforeAll(function(done) {
         jasmine.addMatchers(customMatchers);
 
+        Plotly.setPlotConfig({
+            mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN
+        });
+
         gd = createGraphDiv();
 
         var data = [{
@@ -520,6 +519,10 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() {
     beforeAll(function(done) {
         jasmine.addMatchers(customMatchers);
 
+        Plotly.setPlotConfig({
+            mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN
+        });
+
         gd = createGraphDiv();
         mockCopy = Lib.extendDeep({}, mock);