diff --git a/.circleci/config.yml b/.circleci/config.yml
index 008e8c1bea5..0d7242171ea 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,6 +1,6 @@
version: 2.1
orbs:
- browser-tools: circleci/browser-tools@1.4.8
+ browser-tools: circleci/browser-tools@1.5.1
# Inspired by:
# https://github.com/CircleCI-Public/circleci-demo-workflows/blob/workspace-forwarding/.circleci/config.yml
diff --git a/test/image/baselines/map_layers.png b/test/image/baselines/map_layers.png
index f49b75ca990..75ee5b12958 100644
Binary files a/test/image/baselines/map_layers.png and b/test/image/baselines/map_layers.png differ
diff --git a/test/image/baselines/pattern_fgcolor_overlay_fillmode.png b/test/image/baselines/pattern_fgcolor_overlay_fillmode.png
index af59862d58a..6c6b5fbb821 100644
Binary files a/test/image/baselines/pattern_fgcolor_overlay_fillmode.png and b/test/image/baselines/pattern_fgcolor_overlay_fillmode.png differ
diff --git a/test/image/baselines/sunburst_coffee.png b/test/image/baselines/sunburst_coffee.png
index 590edb08ba9..523744ad90d 100644
Binary files a/test/image/baselines/sunburst_coffee.png and b/test/image/baselines/sunburst_coffee.png differ
diff --git a/test/image/baselines/treemap_sunburst_marker_colors.png b/test/image/baselines/treemap_sunburst_marker_colors.png
index 209427c1b2a..beebd418791 100644
Binary files a/test/image/baselines/treemap_sunburst_marker_colors.png and b/test/image/baselines/treemap_sunburst_marker_colors.png differ
diff --git a/test/image/compare_pixels_test.js b/test/image/compare_pixels_test.js
index ad47a502173..75aba5fc7af 100644
--- a/test/image/compare_pixels_test.js
+++ b/test/image/compare_pixels_test.js
@@ -63,15 +63,11 @@ argv._.forEach(function(pattern) {
var blacklist = [
'map_angles',
'map_stamen-style',
- 'mapbox_stamen-style',
- 'mapbox_custom-style',
- 'mapbox_density0-legend',
- 'mapbox_osm-style',
];
if(virtualWebgl) {
allMockList = allMockList.filter(function(a) {
- return a.slice(0, 2) === 'gl' || a.slice(0, 6) === 'mapbox';
+ return a.slice(0, 2) === 'gl';
});
}
@@ -108,23 +104,12 @@ for(var i = 0; i < allMockList.length; i++) {
// skip blacklist
if(blacklist.indexOf(mockName) !== -1) continue;
- var isMapbox = mockName.substr(0, 7) === 'mapbox_';
-
- // We have to skip mapbox since Aug 2024
- // See https://github.com/plotly/plotly.js/issues/7075
- if(isMapbox) continue;
-
var flakyMap = [
// more flaky
'map_density0-legend',
'map_osm-style',
'map_predefined-styles1',
'map_predefined-styles2',
-
- 'mapbox_angles',
- 'mapbox_layers',
- 'mapbox_custom-style',
- 'mapbox_geojson-attributes'
].indexOf(mockName) !== -1;
var otherFlaky = [
diff --git a/test/image/export_test.js b/test/image/export_test.js
index 47a06ef06cd..d5caded09ad 100644
--- a/test/image/export_test.js
+++ b/test/image/export_test.js
@@ -26,7 +26,6 @@ var DEFAULT_LIST = [
'image_astronaut_source',
'gl2d_no-clustering2',
'gl3d_surface-heatmap-treemap_transparent-colorscale',
- 'mapbox_density-multiple_legend',
'map_density-multiple_legend',
'smith_modes',
'zsmooth_methods',
diff --git a/test/image/make_baseline.py b/test/image/make_baseline.py
index 8c260fb658a..519335d31cd 100644
--- a/test/image/make_baseline.py
+++ b/test/image/make_baseline.py
@@ -55,10 +55,6 @@
pio.kaleido.scope.plotlyjs = plotlyjs
pio.templates.default = 'none'
-_credentials = open(os.path.join(root, 'build', 'credentials.json'), 'r')
-pio.kaleido.scope.mapbox_access_token = json.load(_credentials)['MAPBOX_ACCESS_TOKEN']
-_credentials.close()
-
ALL_MOCKS = [os.path.splitext(a)[0] for a in os.listdir(dirIn) if a.endswith('.json')]
ALL_MOCKS.sort()
@@ -70,10 +66,6 @@
# unable to generate baselines for the following mocks
blacklist = [
'map_stamen-style',
- 'mapbox_density0-legend',
- 'mapbox_osm-style',
- 'mapbox_stamen-style', # Could pass by setting mapboxAccessToken to a stadiamaps.com token
- 'mapbox_custom-style' # Figure out why needed this in https://github.com/plotly/plotly.js/pull/6610
]
allNames = [a for a in allNames if a not in blacklist]
diff --git a/test/image/make_exports.py b/test/image/make_exports.py
index ddf12072968..ea8a4efe7f1 100644
--- a/test/image/make_exports.py
+++ b/test/image/make_exports.py
@@ -10,10 +10,6 @@
pio.templates.default = 'none'
pio.kaleido.scope.plotlyjs = os.path.join(root, 'build', 'plotly.js')
-_credentials = open(os.path.join(root, 'build', 'credentials.json'), 'r')
-pio.kaleido.scope.mapbox_access_token = json.load(_credentials)['MAPBOX_ACCESS_TOKEN']
-_credentials.close()
-
allFormats = ['svg', 'jpg', 'jpeg', 'webp', 'eps', 'pdf']
# 'png' is tested by image-test
@@ -27,7 +23,6 @@
'image_astronaut_source',
'gl2d_no-clustering2',
'gl3d_surface-heatmap-treemap_transparent-colorscale',
- 'mapbox_density-multiple_legend',
'map_density-multiple_legend',
'smith_modes',
'zsmooth_methods',
diff --git a/test/image/mocks/map_layers.json b/test/image/mocks/map_layers.json
index 10a6f3ff6ea..308b0c26c09 100644
--- a/test/image/mocks/map_layers.json
+++ b/test/image/mocks/map_layers.json
@@ -189,7 +189,7 @@
{
"sourcetype": "raster",
"source": [
- "https://img.nj.gov/imagerywms/Natural2015?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:3857&transparent=true&width=256&height=256&layers=Natural2015"
+ "https://basemap.nationalmap.gov/arcgis/services/USGSImageryOnly/MapServer/WMSServer?bbox={bbox-epsg-3857}&format=image/png&service=WMS&request=GetMap&crs=EPSG:3857&transparent=true&width=256&height=256&version=1.3.0&layers=0&styles=default"
],
"below": "aeroway-line"
},
diff --git a/test/jasmine/assets/mock_lists.js b/test/jasmine/assets/mock_lists.js
index 05375108c8d..bf93191c0c3 100644
--- a/test/jasmine/assets/mock_lists.js
+++ b/test/jasmine/assets/mock_lists.js
@@ -68,12 +68,6 @@ var glMockList = [
['gl3d_volume_multiple-traces', require('../../image/mocks/gl3d_volume_multiple-traces.json')]
];
-var mapboxMockList = [
- ['scattermapbox', require('../../image/mocks/mapbox_bubbles-text.json')],
- ['choroplethmapbox', require('../../image/mocks/mapbox_choropleth0.json')],
- ['densitymapbox', require('../../image/mocks/mapbox_density0.json')]
-];
-
var mapMockList = [
['scattermap', require('../../image/mocks/map_bubbles-text.json')],
['choroplethmap', require('../../image/mocks/map_choropleth0.json')],
@@ -83,7 +77,6 @@ var mapMockList = [
module.exports = {
svg: svgMockList,
gl: glMockList,
- mapbox: mapboxMockList,
map: mapMockList,
- all: svgMockList.concat(glMockList).concat(mapboxMockList).concat(mapMockList)
+ all: svgMockList.concat(glMockList).concat(mapMockList)
};
diff --git a/test/jasmine/tests/choroplethmapbox_test.js b/test/jasmine/tests/choroplethmapbox_test.js
deleted file mode 100644
index c9133894265..00000000000
--- a/test/jasmine/tests/choroplethmapbox_test.js
+++ /dev/null
@@ -1,794 +0,0 @@
-var Plotly = require('../../../lib/index');
-var Plots = require('../../../src/plots/plots');
-var Lib = require('../../../src/lib');
-var loggers = require('../../../src/lib/loggers');
-
-var convertModule = require('../../../src/traces/choroplethmapbox/convert');
-var MAPBOX_ACCESS_TOKEN = require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN;
-
-var createGraphDiv = require('../assets/create_graph_div');
-var destroyGraphDiv = require('../assets/destroy_graph_div');
-var failTest = require('../assets/fail_test');
-var mouseEvent = require('../assets/mouse_event');
-var supplyAllDefaults = require('../assets/supply_defaults');
-
-var assertHoverLabelContent = require('../assets/custom_assertions').assertHoverLabelContent;
-
-describe('Test choroplethmapbox defaults:', function() {
- var gd;
- var fullData;
-
- function _supply(opts, layout) {
- gd = {};
- opts = Array.isArray(opts) ? opts : [opts];
-
- gd.data = opts.map(function(o) {
- return Lib.extendFlat({type: 'choroplethmapbox'}, o || {});
- });
- gd.layout = layout || {};
-
- supplyAllDefaults(gd);
- fullData = gd._fullData;
- }
-
- function expectVisibleFalse(msg) {
- fullData.forEach(function(trace, i) {
- expect(trace.visible).toBe(false, 'visible |trace #' + i + '- ' + msg);
- expect(trace._length).toBe(undefined, '_length |trace #' + i + '- ' + msg);
- });
- }
-
- it('should set *visible:false* when locations or z or geojson is missing', function() {
- _supply([
- {z: [1], geojson: 'url'},
- {locations: ['a'], geojson: 'url'},
- {locations: ['a'], z: [1]}
- ]);
- expectVisibleFalse();
- });
-
- it('should set *visible:false* when locations or z is empty', function() {
- _supply([
- {locations: [], z: [1], geojson: 'url'},
- {locations: ['a'], z: [], geojson: 'url'},
- {locations: [], z: [], geojson: 'url'}
- ]);
- expectVisibleFalse();
- });
-
- it('should accept string (URL) and object *geojson*', function() {
- _supply([
- {name: 'ok during defaults, will fail later', locations: ['a'], z: [1], geojson: 'url'},
- {name: 'ok during defaults, will fail later', locations: ['a'], z: [1], geojson: {}},
- ]);
- fullData.forEach(function(trace, i) {
- expect(trace.visible).toBe(true, 'visible |trace #' + i);
- expect(trace._length).toBe(1, '_length |trace #' + i);
- });
-
- _supply([
- {name: 'no', locations: ['a'], z: [1], geojson: ''},
- {name: 'no', locations: ['a'], z: [1], geojson: []},
- {name: 'no', locations: ['a'], z: [1], geojson: true}
- ]);
- expectVisibleFalse();
- });
-
- it('should not coerce *marker.line.color* when *marker.line.width* is *0*', function() {
- _supply([{
- locations: ['CAN', 'USA'],
- z: [1, 2],
- geojson: 'url',
- marker: {
- line: {
- color: 'red',
- width: 0
- }
- }
- }]);
-
- expect(fullData[0].marker.line.width).toBe(0, 'mlw');
- expect(fullData[0].marker.line.color).toBe(undefined, 'mlc');
- });
-});
-
-describe('Test choroplethmapbox convert:', function() {
- var geojson0 = function() {
- return {
- type: 'FeatureCollection',
- features: [
- {type: 'Feature', id: 'a', geometry: {type: 'Polygon', coordinates: []}},
- {type: 'Feature', id: 'b', geometry: {type: 'Polygon', coordinates: []}},
- {type: 'Feature', id: 'c', geometry: {type: 'Polygon', coordinates: []}}
- ]
- };
- };
-
- var base = function() {
- return {
- locations: ['a', 'b', 'c'],
- z: [10, 20, 5],
- geojson: geojson0()
- };
- };
-
- function pre(trace, layout) {
- var gd = {data: [Lib.extendFlat({type: 'choroplethmapbox'}, trace)]};
- if(layout) gd.layout = layout;
-
- supplyAllDefaults(gd);
- Plots.doCalcdata(gd, gd._fullData[0]);
-
- return gd.calcdata[0];
- }
-
- function _convert(trace) {
- return convertModule.convert(pre(trace));
- }
-
- function expectBlank(opts, msg) {
- expect(opts.fill.layout.visibility).toBe('none', msg);
- expect(opts.line.layout.visibility).toBe('none', msg);
- expect(opts.geojson).toEqual({type: 'Point', coordinates: []}, msg);
- }
-
- function extract(opts, k) {
- return opts.geojson.features.map(function(f) { return f.properties[k]; });
- }
-
- it('should return early when trace is *visible:false*', function() {
- var opts = _convert(Lib.extendFlat(base(), {visible: false}));
- expectBlank(opts);
- });
-
- it('should return early when trace is has no *_length*', function() {
- var opts = _convert({
- locations: [],
- z: [],
- geojson: geojson0
- });
- expectBlank(opts);
- });
-
- it('should return early if something goes wrong while fetching a GeoJSON', function() {
- spyOn(loggers, 'error');
-
- var opts = _convert({
- locations: ['a'], z: [1],
- geojson: 'url'
- });
-
- expect(loggers.error).toHaveBeenCalledWith('Oops ... something went wrong when fetching url');
- expectBlank(opts);
- });
-
- describe('should warn when set GeoJSON is not a *FeatureCollection* or a *Feature* type and return early', function() {
- beforeEach(function() { spyOn(loggers, 'warn'); });
-
- it('- case missing *type* key', function() {
- var opts = _convert({
- locations: ['a'], z: [1],
- geojson: {
- missingType: ''
- }
- });
- expectBlank(opts);
- expect(loggers.warn).toHaveBeenCalledWith([
- 'Invalid GeoJSON type none.',
- 'Traces with locationmode *geojson-id* only support *FeatureCollection* and *Feature* types.'
- ].join(' '));
- });
-
- it('- case invalid *type*', function() {
- var opts = _convert({
- locations: ['a'], z: [1],
- geojson: {
- type: 'nop!'
- }
- });
- expectBlank(opts);
- expect(loggers.warn).toHaveBeenCalledWith([
- 'Invalid GeoJSON type nop!.',
- 'Traces with locationmode *geojson-id* only support *FeatureCollection* and *Feature* types.'
- ].join(' '));
- });
- });
-
- describe('should log when crossing a GeoJSON geometry that is not a *Polygon* or a *MultiPolygon* type', function() {
- beforeEach(function() { spyOn(loggers, 'log'); });
-
- it('- case missing geometry *type*', function() {
- var trace = base();
- delete trace.geojson.features[1].geometry.type;
-
- var opts = _convert(trace);
- expect(opts.geojson.features.length).toBe(2, '# of feature to be rendered');
- expect(loggers.log).toHaveBeenCalledWith([
- 'Location b does not have a valid GeoJSON geometry.',
- 'Traces with locationmode *geojson-id* only support *Polygon* and *MultiPolygon* geometries.'
- ].join(' '));
- });
-
- it('- case invalid geometry *type*', function() {
- var trace = base();
- trace.geojson.features[2].geometry.type = 'not-gonna-work';
-
- var opts = _convert(trace);
- expect(opts.geojson.features.length).toBe(2, '# of feature to be rendered');
- expect(loggers.log).toHaveBeenCalledWith([
- 'Location c does not have a valid GeoJSON geometry.',
- 'Traces with locationmode *geojson-id* only support *Polygon* and *MultiPolygon* geometries.'
- ].join(' '));
- });
- });
-
- it('should log when an entry set in *locations* does not a matching feature in the GeoJSON', function() {
- spyOn(loggers, 'log');
-
- var trace = base();
- trace.locations = ['a', 'b', 'c', 'd'];
- trace.z = [1, 2, 3, 1];
-
- var opts = _convert(trace);
- expect(opts.geojson.features.length).toBe(3, '# of features to be rendered');
- expect(loggers.log).toHaveBeenCalledWith('Location *d* does not have a matching feature with id-key *id*.');
- });
-
- describe('should accept numbers as *locations* items', function() {
- function _assert(act) {
- expect(act.fill.layout.visibility).toBe('visible', 'fill layer visibility');
- expect(act.line.layout.visibility).toBe('visible', 'line layer visibility');
- expect(act.geojson.features.length).toBe(3, '# of visible features');
- expect(extract(act, 'fc'))
- .toEqual(['rgb(178, 10, 28)', 'rgb(220, 220, 220)', 'rgb(240, 149, 99)']);
- }
-
- it('- regular array case', function() {
- var trace = {
- locations: [1, 2, 3],
- z: [20, 10, 2],
- geojson: {
- type: 'FeatureCollection',
- features: [
- {type: 'Feature', id: '1', geometry: {type: 'Polygon', coordinates: []}},
- {type: 'Feature', id: '3', geometry: {type: 'Polygon', coordinates: []}},
- {type: 'Feature', id: '2', geometry: {type: 'Polygon', coordinates: []}}
- ]
- }
- };
- _assert(_convert(trace));
- });
-
- it('- typed array case', function() {
- var trace = {
- locations: new Float32Array([1, 2, 3]),
- z: new Float32Array([20, 10, 2]),
- geojson: {
- type: 'FeatureCollection',
- features: [
- {type: 'Feature', id: 1, geometry: {type: 'Polygon', coordinates: []}},
- {type: 'Feature', id: 3, geometry: {type: 'Polygon', coordinates: []}},
- {type: 'Feature', id: 2, geometry: {type: 'Polygon', coordinates: []}}
- ]
- }
- };
- _assert(_convert(trace));
- });
- });
-
- it('should handle *Feature* on 1-item *FeatureCollection* the same way', function() {
- var locations = ['a'];
- var z = [1];
-
- var feature = {
- type: 'Feature',
- id: 'a',
- geometry: {type: 'Polygon', coordinates: []}
- };
-
- var opts = _convert({
- locations: locations,
- z: z,
- geojson: feature
- });
-
- var opts2 = _convert({
- locations: locations,
- z: z,
- geojson: {
- type: 'FeatureCollection',
- features: [feature]
- }
- });
-
- expect(opts).toEqual(opts2);
- });
-
- it('should fill stuff in corresponding calcdata items', function() {
- var calcTrace = pre(base());
- var opts = convertModule.convert(calcTrace);
-
- var fullTrace = calcTrace[0].trace;
- expect(fullTrace._opts).toBe(opts, 'opts ref');
-
- for(var i = 0; i < calcTrace.length; i++) {
- var cdi = calcTrace[i];
- expect(typeof cdi._polygons).toBe('object', '_polygons |' + i);
- expect(Array.isArray(cdi.ct)).toBe(true, 'ct|' + i);
- expect(typeof cdi.fIn).toBe('object', 'fIn |' + i);
- expect(typeof cdi.fOut).toBe('object', 'fOut |' + i);
- }
- });
-
- describe('should fill *fill-color* correctly', function() {
- function _assert(act, exp) {
- expect(act.fill.paint['fill-color'])
- .toEqual({type: 'identity', property: 'fc'});
- expect(extract(act, 'fc')).toEqual(exp);
- }
-
- it('- base case', function() {
- _assert(_convert(base()), [
- 'rgb(245, 172, 122)',
- 'rgb(178, 10, 28)',
- 'rgb(220, 220, 220)'
- ]);
- });
-
- it('- custom colorscale case', function() {
- var trace = base();
- trace.colorscale = [[0, 'rgb(0, 255, 0)'], [1, 'rgb(0, 0, 255)']];
- trace.zmid = 10;
-
- _assert(_convert(trace), [
- 'rgb(0, 128, 128)',
- 'rgb(0, 0, 255)',
- 'rgb(0, 191, 64)'
- ]);
- });
- });
-
- describe('should fill *fill-opacity* correctly', function() {
- function _assertScalar(act, exp) {
- expect(act.fill.paint['fill-opacity']).toBe(exp);
- expect(act.line.paint['line-opacity']).toBe(exp);
- expect(extract(act, 'mo')).toEqual([undefined, undefined, undefined]);
- }
-
- function _assertArray(act, k, exp) {
- expect(act.fill.paint['fill-opacity']).toEqual({type: 'identity', property: k});
- expect(act.line.paint['line-opacity']).toEqual({type: 'identity', property: k});
- expect(extract(act, k)).toBeCloseToArray(exp, 2);
- }
-
- function fakeSelect(calcTrace, selectedpoints) {
- if(selectedpoints === null) {
- delete calcTrace[0].trace.selectedpoints;
- } else {
- calcTrace[0].trace.selectedpoints = selectedpoints;
- }
-
- for(var i = 0; i < calcTrace.length; i++) {
- var cdi = calcTrace[i];
- if(selectedpoints) {
- if(selectedpoints.indexOf(i) !== -1) {
- cdi.selected = 1;
- } else {
- cdi.selected = 0;
- }
- } else {
- delete cdi.selected;
- }
- }
- }
-
- it('- base case', function() {
- var trace = base();
- trace.marker = {opacity: 0.4};
- _assertScalar(_convert(trace), 0.4);
- });
-
- it('- arrayOk case', function() {
- var trace = base();
- trace.marker = {opacity: [null, 0.2, -10]};
- _assertArray(_convert(trace), 'mo', [0, 0.2, 0]);
- });
-
- it('- arrayOk case + bad coordinates', function() {
- var trace = base();
- trace.locations = ['a', null, 'c'];
- trace.marker = {opacity: [-1, 0.2, 0.9]};
- _assertArray(_convert(trace), 'mo', [0, 0.9]);
- });
-
- it('- selection (base)', function() {
- var trace = base();
- trace.selectedpoints = [1];
-
- var calcTrace = pre(trace);
- _assertArray(convertModule.convert(calcTrace), 'mo2', [0.2, 1, 0.2]);
-
- fakeSelect(calcTrace, [1, 2]);
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0.2, 1, 1]);
-
- fakeSelect(calcTrace, []);
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0.2, 0.2, 0.2]);
-
- calcTrace[0].trace.unselected = {marker: {opacity: 0}};
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0, 0, 0]);
-
- fakeSelect(calcTrace, null);
- _assertScalar(convertModule.convertOnSelect(calcTrace), 1);
- });
-
- it('- selection of arrayOk marker.opacity', function() {
- var trace = base();
- trace.marker = {opacity: [0.4, 1, 0.8]};
- trace.selectedpoints = [1];
-
- var calcTrace = pre(trace);
- _assertArray(convertModule.convert(calcTrace), 'mo2', [0.08, 1, 0.16]);
-
- fakeSelect(calcTrace, [1, 2]);
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0.08, 1, 0.8]);
-
- calcTrace[0].trace.selected = {marker: {opacity: 1}};
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0.08, 1, 1]);
-
- fakeSelect(calcTrace, []);
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0.08, 0.2, 0.16]);
-
- calcTrace[0].trace.unselected = {marker: {opacity: 0}};
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo2', [0, 0, 0]);
-
- fakeSelect(calcTrace, null);
- _assertArray(convertModule.convertOnSelect(calcTrace), 'mo', [0.4, 1, 0.8]);
- });
- });
-
- describe('should fill *line-color*, *line-width* correctly', function() {
- it('- base case', function() {
- var trace = base();
- trace.marker = {line: {color: 'blue', width: 3}};
-
- var opts = _convert(trace);
- expect(opts.line.paint['line-color']).toBe('blue');
- expect(opts.line.paint['line-width']).toBe(3);
- expect(extract(opts, 'mlc')).toEqual([undefined, undefined, undefined]);
- expect(extract(opts, 'mlw')).toEqual([undefined, undefined, undefined]);
- });
-
- it('- arrayOk case', function() {
- var trace = base();
- trace.marker = {
- line: {
- color: ['blue', 'red', 'black'],
- width: [0.1, 2, 10]
- }
- };
-
- var opts = _convert(trace);
- expect(opts.line.paint['line-color']).toEqual({type: 'identity', property: 'mlc'});
- expect(opts.line.paint['line-width']).toEqual({type: 'identity', property: 'mlw'});
- expect(extract(opts, 'mlc')).toEqual(['blue', 'red', 'black']);
- expect(extract(opts, 'mlw')).toEqual([0.1, 2, 10]);
- });
- });
-
- it('should find correct centroid (single polygon case)', function() {
- var trace = base();
-
- var coordsIn = [
- [
- [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
- [100.0, 1.0], [100.0, 0.0]
- ]
- ];
-
- trace.geojson.features[0].geometry.coordinates = coordsIn;
- var calcTrace = pre(trace);
- var opts = convertModule.convert(calcTrace);
-
- expect(opts.geojson.features[0].geometry.coordinates).toBe(coordsIn);
- expect(calcTrace[0].ct).toEqual([100.5, 0.5]);
- });
-
- it('should find correct centroid (multi-polygon case)', function() {
- var trace = base();
-
- var coordsIn = [
- [
- // this one has the bigger area
- [[30, 20], [47, 40], [10, 33], [30, 20]]
- ],
- [
- [[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]]
- ]
- ];
-
- trace.geojson.features[0].geometry.type = 'MultiPolygon';
- trace.geojson.features[0].geometry.coordinates = coordsIn;
- var calcTrace = pre(trace);
- var opts = convertModule.convert(calcTrace);
-
- expect(opts.geojson.features[0].geometry.coordinates).toBe(coordsIn);
- expect(calcTrace[0].ct).toEqual([29, 31]);
- });
-});
-
-describe('Test choroplethmapbox hover:', function() {
- var gd;
-
- afterEach(function(done) {
- Plotly.purge(gd);
- destroyGraphDiv();
- setTimeout(done, 200);
- });
-
- function transformPlot(gd, transformString) {
- gd.style.webkitTransform = transformString;
- gd.style.MozTransform = transformString;
- gd.style.msTransform = transformString;
- gd.style.OTransform = transformString;
- gd.style.transform = transformString;
- }
-
- function run(hasCssTransform, s, done) {
- gd = createGraphDiv();
- var scale = 1;
- if(hasCssTransform) {
- scale = 0.5;
- }
-
- var fig = Lib.extendDeep({},
- s.mock || require('../../image/mocks/mapbox_choropleth0.json')
- );
-
- if(s.patch) {
- fig = s.patch(fig);
- }
-
- if(!fig.layout) fig.layout = {};
- if(!fig.layout.mapbox) fig.layout.mapbox = {};
- fig.layout.mapbox.accesstoken = MAPBOX_ACCESS_TOKEN;
-
- var pos = s.pos || [270, 220];
-
- return Plotly.newPlot(gd, fig).then(function() {
- if(hasCssTransform) transformPlot(gd, 'translate(-25%, -25%) scale(0.5)');
-
- var to = setTimeout(function() {
- failTest('no event data received');
- done();
- }, 100);
-
- gd.on('plotly_hover', function(d) {
- clearTimeout(to);
- assertHoverLabelContent(s);
-
- var msg = ' - event data ' + s.desc;
- var actual = d.points || [];
- var exp = s.evtPts;
- expect(actual.length).toBe(exp.length, 'pt length' + msg);
- for(var i = 0; i < exp.length; i++) {
- for(var k in exp[i]) {
- var m = 'key ' + k + ' in pt ' + i + msg;
- var matcher = k === 'properties' ? 'toEqual' : 'toBe';
- expect(actual[i][k])[matcher](exp[i][k], m);
- }
- }
-
- // w/o this purge gets called before
- // hover throttle is complete
- setTimeout(done, 0);
- });
-
- mouseEvent('mousemove', scale * pos[0], scale * pos[1]);
- })
- .catch(failTest);
- }
-
- var specs = [{
- desc: 'basic',
- nums: '10',
- name: 'NY',
- evtPts: [{location: 'NY', z: 10, pointNumber: 0, curveNumber: 0, properties: {name: 'New York'}}]
- }, {
- desc: 'with a hovertemplate using values in *properties*',
- patch: function(fig) {
- fig.data.forEach(function(t) {
- t.hovertemplate = '%{z:.3f}PROP::%{properties.name}';
- });
- return fig;
- },
- nums: '10.000',
- name: 'PROP::New York',
- evtPts: [{location: 'NY', z: 10, pointNumber: 0, curveNumber: 0, properties: {name: 'New York'}}]
- }, {
- desc: 'with "typeof number" locations[i] and feature id (in *name* label case)',
- patch: function() {
- var fig = Lib.extendDeep({}, require('../../image/mocks/mapbox_choropleth-raw-geojson.json'));
- fig.data = [fig.data[1]];
- fig.data[0].locations = [100];
- fig.data[0].geojson.id = 100;
- return fig;
- },
- nums: '10',
- name: '100',
- evtPts: [{location: 100, z: 10, pointNumber: 0, curveNumber: 0}]
- }, {
- desc: 'with "typeof number" locations[i] and feature id (in *nums* label case)',
- patch: function() {
- var fig = Lib.extendDeep({}, require('../../image/mocks/mapbox_choropleth-raw-geojson.json'));
- fig.data = [fig.data[1]];
- fig.data[0].locations = [100];
- fig.data[0].geojson.id = 100;
- fig.data[0].hoverinfo = 'location+name';
- return fig;
- },
- nums: '100',
- name: 'trace 0',
- evtPts: [{location: 100, z: 10, pointNumber: 0, curveNumber: 0}]
- }, {
- desc: 'with "typeof number" locations[i] and feature id (hovertemplate case)',
- patch: function() {
- var fig = Lib.extendDeep({}, require('../../image/mocks/mapbox_choropleth-raw-geojson.json'));
- fig.data = [fig.data[1]];
- fig.data[0].locations = [100];
- fig.data[0].geojson.id = 100;
- fig.data[0].hovertemplate = '### %{location}%{ct[0]:.1f} | %{ct[1]:.1f} ###';
- return fig;
- },
- nums: '### 100',
- name: '-86.7 | 31.9 ###',
- evtPts: [{location: 100, z: 10, pointNumber: 0, curveNumber: 0}]
- }];
-
- specs.forEach(function(s) {
- [false, true].forEach(function(hasCssTransform) {
- it('@gl should generate correct hover labels ' + s.desc + ', hasCssTransform: ' + hasCssTransform, function(done) {
- run(hasCssTransform, s, done);
- });
- });
- });
-});
-
-describe('Test choroplethmapbox interactions:', function() {
- var gd;
-
- var geojson = {
- type: 'Feature',
- id: 'AL',
- geometry: {
- type: 'Polygon',
- coordinates: [[
- [-87.359296, 35.00118 ], [-85.606675, 34.984749 ], [-85.431413, 34.124869 ], [-85.184951, 32.859696 ],
- [-85.069935, 32.580372 ], [-84.960397, 32.421541 ], [-85.004212, 32.322956 ], [-84.889196, 32.262709 ],
- [-85.058981, 32.13674 ], [-85.053504, 32.01077 ], [-85.141136, 31.840985 ], [-85.042551, 31.539753 ],
- [-85.113751, 31.27686 ], [-85.004212, 31.003013 ], [-85.497137, 30.997536 ], [-87.600282, 30.997536 ],
- [-87.633143, 30.86609 ], [-87.408589, 30.674397 ], [-87.446927, 30.510088 ], [-87.37025, 30.427934 ],
- [-87.518128, 30.280057 ], [-87.655051, 30.247195 ], [-87.90699, 30.411504 ], [-87.934375, 30.657966 ],
- [-88.011052, 30.685351 ], [-88.10416, 30.499135 ], [-88.137022, 30.318396 ], [-88.394438, 30.367688 ],
- [-88.471115, 31.895754 ], [-88.241084, 33.796253 ], [-88.098683, 34.891641 ], [-88.202745, 34.995703 ],
- [-87.359296, 35.00118 ]
- ]]
- }
- };
-
- beforeEach(function() {
- gd = createGraphDiv();
- });
-
- afterEach(function(done) {
- Plotly.purge(gd);
- destroyGraphDiv();
- setTimeout(done, 200);
- });
-
- it('@gl should be able to add and remove traces', function(done) {
- function _assert(msg, exp) {
- var map = gd._fullLayout.mapbox._subplot.map;
- var layers = map.getStyle().layers;
-
- expect(layers.length).toBe(exp.layerCnt, 'total # of layers |' + msg);
- }
-
- var trace0 = {
- type: 'choroplethmapbox',
- locations: ['AL'],
- z: [10],
- geojson: geojson
- };
-
- var trace1 = {
- type: 'choroplethmapbox',
- locations: ['AL'],
- z: [1],
- geojson: geojson,
- marker: {opacity: 0.3}
- };
-
- Plotly.newPlot(gd,
- [trace0, trace1],
- {mapbox: {style: 'basic'}},
- {mapboxAccessToken: MAPBOX_ACCESS_TOKEN}
- )
- .then(function() {
- _assert('base', { layerCnt: 24 });
- })
- .then(function() { return Plotly.deleteTraces(gd, [0]); })
- .then(function() {
- _assert('w/o trace0', { layerCnt: 22 });
- })
- .then(function() { return Plotly.addTraces(gd, [trace0]); })
- .then(function() {
- _assert('after adding trace0', { layerCnt: 24 });
- })
- .then(done, done.fail);
- });
-
- it('@gl should be able to restyle *below*', function(done) {
- function getLayerIds() {
- var subplot = gd._fullLayout.mapbox._subplot;
- var layers = subplot.map.getStyle().layers;
- var layerIds = layers.map(function(l) { return l.id; });
- return layerIds;
- }
-
- Plotly.newPlot(gd, [{
- type: 'choroplethmapbox',
- locations: ['AL'],
- z: [10],
- geojson: geojson,
- uid: 'a'
- }], {}, {mapboxAccessToken: MAPBOX_ACCESS_TOKEN})
- .then(function() {
- expect(getLayerIds()).withContext('default *below*').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'plotly-trace-layer-a-fill', 'plotly-trace-layer-a-line',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country', 'poi_label', 'road_major_label',
- 'place_label_other', 'place_label_city', 'country_label'
- ]);
- })
- .then(function() { return Plotly.restyle(gd, 'below', ''); })
- .then(function() {
- expect(getLayerIds()).withContext('*below* set to \'\'').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country', 'poi_label', 'road_major_label',
- 'place_label_other', 'place_label_city', 'country_label',
- 'plotly-trace-layer-a-fill', 'plotly-trace-layer-a-line'
- ]);
- })
- .then(function() { return Plotly.restyle(gd, 'below', 'place_label_other'); })
- .then(function() {
- expect(getLayerIds()).withContext('*below* set to same base layer').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country', 'poi_label', 'road_major_label',
- 'plotly-trace-layer-a-fill', 'plotly-trace-layer-a-line',
- 'place_label_other', 'place_label_city', 'country_label',
- ]);
- })
- .then(function() { return Plotly.restyle(gd, 'below', null); })
- .then(function() {
- expect(getLayerIds()).withContext('back to default *below*').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'plotly-trace-layer-a-fill', 'plotly-trace-layer-a-line',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country', 'poi_label', 'road_major_label',
- 'place_label_other', 'place_label_city', 'country_label'
- ]);
- })
- .then(done, done.fail);
- }, 5 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
-});
diff --git a/test/jasmine/tests/densitymapbox_test.js b/test/jasmine/tests/densitymapbox_test.js
deleted file mode 100644
index c8cadd7cefb..00000000000
--- a/test/jasmine/tests/densitymapbox_test.js
+++ /dev/null
@@ -1,523 +0,0 @@
-var Plotly = require('../../../lib/index');
-var Plots = require('../../../src/plots/plots');
-var Lib = require('../../../src/lib');
-
-var convert = require('../../../src/traces/densitymapbox/convert');
-var MAPBOX_ACCESS_TOKEN = require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN;
-
-var createGraphDiv = require('../assets/create_graph_div');
-var destroyGraphDiv = require('../assets/destroy_graph_div');
-var failTest = require('../assets/fail_test');
-var mouseEvent = require('../assets/mouse_event');
-var supplyAllDefaults = require('../assets/supply_defaults');
-
-var assertHoverLabelContent = require('../assets/custom_assertions').assertHoverLabelContent;
-
-describe('Test densitymapbox defaults:', function() {
- var gd;
- var fullData;
-
- function _supply(opts, layout) {
- gd = {};
- opts = Array.isArray(opts) ? opts : [opts];
-
- gd.data = opts.map(function(o) {
- return Lib.extendFlat({type: 'densitymapbox'}, o || {});
- });
- gd.layout = layout || {};
-
- supplyAllDefaults(gd);
- fullData = gd._fullData;
- }
-
- it('should set *visible:false* when *lon* and/or *lat* is missing or empty', function() {
- _supply([
- {},
- {lon: [1]},
- {lat: [1]},
- {lon: [], lat: []},
- {lon: [1], lat: []},
- {lon: [], lat: [1]}
- ]);
-
- fullData.forEach(function(trace, i) {
- expect(trace.visible).toBe(false, 'visible |trace #' + i);
- expect(trace._length).toBe(undefined, '_length |trace #' + i);
- });
- });
-});
-
-describe('Test densitymapbox convert:', function() {
- var base = function() {
- return {
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- z: [1, 20, 5],
- };
- };
-
- function pre(trace, layout) {
- var gd = {data: [Lib.extendFlat({type: 'densitymapbox'}, trace)]};
- if(layout) gd.layout = layout;
-
- supplyAllDefaults(gd);
- Plots.doCalcdata(gd, gd._fullData[0]);
-
- return gd.calcdata[0];
- }
-
- function _convert(trace) {
- return convert(pre(trace));
- }
-
- function expectBlank(opts, msg) {
- expect(opts.heatmap.layout.visibility).toBe('none', msg);
- expect(opts.geojson).toEqual({type: 'Point', coordinates: []}, msg);
- }
-
- function extract(opts, k) {
- return opts.geojson.features.map(function(f) { return f.properties[k]; });
- }
-
- it('should return early when trace is *visible:false*', function() {
- var opts = _convert(Lib.extendFlat(base(), {visible: false}));
- expectBlank(opts);
- });
-
- it('should return early when trace is has no *_length*', function() {
- var opts = _convert({
- lon: [],
- lat: [],
- z: [],
- });
- expectBlank(opts);
- });
-
- describe('should fill in *z* in GeoJSON properties', function() {
- function _assert(act, prop, paint) {
- expect(extract(act, 'z')).toEqual(prop);
- expect(act.heatmap.paint['heatmap-weight']).toEqual(paint);
- }
-
- it('- base', function() {
- var opts = _convert(base());
- _assert(opts, [1, 20, 5], [
- 'interpolate', ['linear'],
- ['get', 'z'],
- 1, 0,
- 20, 1
- ]);
- });
-
- it('- with BADNUMs', function() {
- var opts = _convert({
- lon: [10, null, 30, 40],
- lat: [null, 25, 35, 45],
- z: [1, 20, null, 10]
- });
- _assert(opts, [0, 10], [
- 'interpolate', ['linear'],
- ['get', 'z'],
- 1, 0,
- 20, 1
- ]);
- });
-
- it('- w/ set zmin/zmax', function() {
- var opts = _convert(Lib.extendFlat({}, base(), {zmin: 0, zmax: 100}));
- _assert(opts, [1, 20, 5], [
- 'interpolate', ['linear'],
- ['get', 'z'],
- 0, 0,
- 100, 1
- ]);
- });
-
- it('- w/o z', function() {
- var opts = _convert({
- lon: [10, 20, 30, 40],
- lat: [15, 25, 35, 45],
- });
- _assert(opts, [undefined, undefined, undefined, undefined], 1);
- });
- });
-
- describe('should fill in *radius* settings', function() {
- function _assert(act, prop, paint) {
- expect(extract(act, 'r')).toEqual(prop);
- expect(act.heatmap.paint['heatmap-radius']).toEqual(paint);
- }
-
- it('- base', function() {
- var opts = _convert(base());
- _assert(opts, [undefined, undefined, undefined], 30);
- });
-
- it('- arrayOk', function() {
- var opts = _convert({
- lon: [10, 20, 30, 40],
- lat: [15, 25, 35, 45],
- z: [1, 20, 5, 10],
- radius: [20, '2', -100, 'not-gonna-work']
- });
- _assert(opts, [20, 2, 0, 0], {type: 'identity', property: 'r'});
- });
- });
-
- it('should propagate the trace opacity', function() {
- var opts = _convert(Lib.extendFlat({}, base(), {opacity: 0.2}));
- expect(opts.heatmap.paint['heatmap-opacity']).toBe(0.2);
- });
-
- describe('should propagate colorscale settings', function() {
- function _assert(act, exp) {
- expect(act.heatmap.paint['heatmap-color']).toEqual(exp);
- }
-
- it('- base', function() {
- var opts = _convert(Lib.extendFlat(base(), {
- colorscale: [
- [0, 'rgb(0, 0, 0)'],
- [1, 'rgb(255, 255, 255)']
- ]
- }));
- _assert(opts, [
- 'interpolate', ['linear'],
- ['heatmap-density'],
- 0, 'rgba(0, 0, 0, 0)',
- 1, 'rgb(255, 255, 255)'
- ]);
- });
-
- it('- with rgba in colorscale[0][1]', function() {
- var opts = _convert(Lib.extendFlat(base(), {
- colorscale: [
- [0, 'rgba(0, 0, 0, 0.2)'],
- [1, 'rgb(255, 255, 255)']
- ]
- }));
- _assert(opts, [
- 'interpolate', ['linear'],
- ['heatmap-density'],
- 0, 'rgba(0, 0, 0, 0.2)',
- 1, 'rgb(255, 255, 255)'
- ]);
- });
-
- it('- w/ reversescale:true', function() {
- var opts = _convert(Lib.extendFlat(base(), {
- colorscale: [
- [0, 'rgb(0, 0, 0)'],
- [1, 'rgb(255, 255, 255)']
- ],
- reversescale: true
- }));
- _assert(opts, [
- 'interpolate', ['linear'],
- ['heatmap-density'],
- 0, 'rgba(255, 255, 255, 0)',
- 1, 'rgb(0, 0, 0)'
- ]);
- });
-
- it('- with rgba in colorscale[0][1] and reversescale:true', function() {
- var opts = _convert(Lib.extendFlat(base(), {
- colorscale: [
- [0, 'rgba(0, 0, 0, 0.2)'],
- [1, 'rgba(255, 255, 255, 0.2)']
- ],
- reversescale: true
- }));
- _assert(opts, [
- 'interpolate', ['linear'],
- ['heatmap-density'],
- 0, 'rgba(255, 255, 255, 0.2)',
- 1, 'rgba(0, 0, 0, 0.2)'
- ]);
- });
- });
-
- it('should work with typed array', function() {
- var opts = _convert({
- lon: new Float32Array([10, 20, 30]),
- lat: new Float32Array([15, 25, 35]),
- z: new Float32Array([1, 20, 5]),
- radius: new Float32Array([30, 20, 25])
- });
-
- var coords = opts.geojson.features.map(function(f) { return f.geometry.coordinates; });
- expect(coords).toEqual([ [10, 15], [20, 25], [30, 35] ]);
-
- expect(extract(opts, 'z')).toEqual([1, 20, 5]);
- expect(extract(opts, 'r')).toEqual([30, 20, 25]);
-
- var paint = opts.heatmap.paint;
- expect(paint['heatmap-weight']).toEqual([
- 'interpolate', ['linear'],
- ['get', 'z'],
- 1, 0,
- 20, 1
- ]);
- expect(paint['heatmap-radius']).toEqual({type: 'identity', property: 'r'});
- expect(paint['heatmap-color']).toEqual([
- 'interpolate', ['linear'],
- ['heatmap-density'],
- 0, 'rgba(220, 220, 220, 0)',
- 0.2, 'rgb(245,195,157)',
- 0.4, 'rgb(245,160,105)',
- 1, 'rgb(178,10,28)'
- ]);
- });
-});
-
-describe('Test densitymapbox hover:', function() {
- var gd;
-
- afterEach(function(done) {
- Plotly.purge(gd);
- destroyGraphDiv();
- setTimeout(done, 200);
- });
-
- function run(s, done) {
- gd = createGraphDiv();
-
- var fig = Lib.extendDeep({},
- s.mock || require('../../image/mocks/mapbox_density0.json')
- );
-
- if(s.patch) {
- fig = s.patch(fig);
- }
-
- if(!fig.layout) fig.layout = {};
- if(!fig.layout.mapbox) fig.layout.mapbox = {};
- fig.layout.mapbox.accesstoken = MAPBOX_ACCESS_TOKEN;
-
- var pos = s.pos || [353, 143];
-
- return Plotly.newPlot(gd, fig).then(function() {
- var to = setTimeout(function() {
- failTest('no event data received');
- done();
- }, 100);
-
- gd.on('plotly_hover', function(d) {
- clearTimeout(to);
- assertHoverLabelContent(s);
-
- var msg = ' - event data ' + s.desc;
- var actual = d.points || [];
- var exp = s.evtPts;
- expect(actual.length).toBe(exp.length, 'pt length' + msg);
- for(var i = 0; i < exp.length; i++) {
- for(var k in exp[i]) {
- var m = 'key ' + k + ' in pt ' + i + msg;
- var matcher = k === 'properties' ? 'toEqual' : 'toBe';
- expect(actual[i][k])[matcher](exp[i][k], m);
- }
- }
-
- // w/o this purge gets called before
- // hover throttle is complete
- setTimeout(done, 0);
- });
-
- mouseEvent('mousemove', pos[0], pos[1]);
- })
- .catch(failTest);
- }
-
- var specs = [{
- desc: 'basic',
- nums: '3\n(25°, 20°)',
- name: '',
- evtPts: [{lon: 20, lat: 25, z: 3, pointNumber: 1, curveNumber: 0}]
- }, {
- desc: 'with a hovertemplate',
- patch: function(fig) {
- fig.data.forEach(function(t) {
- t.hovertemplate = '%{z:.3f}%{lon} || %{lat}';
- });
- return fig;
- },
- nums: '3.000',
- name: '20 || 25',
- evtPts: [{lon: 20, lat: 25, z: 3, pointNumber: 1, curveNumber: 0}]
- }, {
- desc: 'w/o z flag',
- patch: function(fig) {
- fig.data.forEach(function(t) {
- t.hoverinfo = 'lon+lat+name';
- });
- return fig;
- },
- nums: '(25°, 20°)',
- name: 'trace 0',
- evtPts: [{lon: 20, lat: 25, z: 3, pointNumber: 1, curveNumber: 0}]
- }, {
- desc: 'w/o z data',
- patch: function(fig) {
- fig.data.forEach(function(t) {
- delete t.z;
- });
- return fig;
- },
- nums: '(25°, 20°)',
- name: '',
- evtPts: [{lon: 20, lat: 25, pointNumber: 1, curveNumber: 0}]
- }];
-
- specs.forEach(function(s) {
- it('@gl should generate correct hover labels ' + s.desc, function(done) {
- run(s, done);
- });
- });
-});
-
-describe('Test densitymapbox interactions:', function() {
- var gd;
-
- beforeEach(function() {
- gd = createGraphDiv();
- });
-
- afterEach(function(done) {
- Plotly.purge(gd);
- destroyGraphDiv();
- setTimeout(done, 200);
- });
-
- it('@gl should be able to add and remove traces', function(done) {
- function _assert(msg, exp) {
- var map = gd._fullLayout.mapbox._subplot.map;
- var layers = map.getStyle().layers;
-
- expect(layers.length).toBe(exp.layerCnt, 'total # of layers |' + msg);
- }
-
- var trace0 = {
- type: 'densitymapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- z: [1, 20, 5],
- };
-
- var trace1 = {
- type: 'densitymapbox',
- lon: [-10, -20, -30],
- lat: [15, 25, 35],
- z: [1, 20, 5],
- };
-
- Plotly.newPlot(gd,
- [trace0, trace1],
- {mapbox: {style: 'basic'}},
- {mapboxAccessToken: MAPBOX_ACCESS_TOKEN}
- )
- .then(function() {
- _assert('base', { layerCnt: 22 });
- })
- .then(function() { return Plotly.deleteTraces(gd, [0]); })
- .then(function() {
- _assert('w/o trace0', { layerCnt: 21 });
- })
- .then(function() { return Plotly.addTraces(gd, [trace0]); })
- .then(function() {
- _assert('after adding trace0', { layerCnt: 22 });
- })
- .then(done, done.fail);
- });
-
- it('@gl should be able to restyle *below*', function(done) {
- function getLayerIds() {
- var subplot = gd._fullLayout.mapbox._subplot;
- var layers = subplot.map.getStyle().layers;
- var layerIds = layers.map(function(l) { return l.id; });
- return layerIds;
- }
-
- Plotly.newPlot(gd, [{
- type: 'densitymapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- z: [1, 20, 5],
- uid: 'a'
- }], {}, {mapboxAccessToken: MAPBOX_ACCESS_TOKEN})
- .then(function() {
- expect(getLayerIds()).withContext('default *below*').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country',
- 'plotly-trace-layer-a-heatmap',
- 'poi_label', 'road_major_label',
- 'place_label_other', 'place_label_city', 'country_label'
- ]);
- })
- .then(function() { return Plotly.restyle(gd, 'below', ''); })
- .then(function() {
- expect(getLayerIds()).withContext('default *below*').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country', 'poi_label', 'road_major_label',
- 'place_label_other', 'place_label_city', 'country_label',
- 'plotly-trace-layer-a-heatmap'
- ]);
- })
- .then(function() { return Plotly.restyle(gd, 'below', 'place_label_other'); })
- .then(function() {
- expect(getLayerIds()).withContext('default *below*').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country', 'poi_label', 'road_major_label',
- 'plotly-trace-layer-a-heatmap',
- 'place_label_other', 'place_label_city', 'country_label',
- ]);
- })
- .then(function() { return Plotly.restyle(gd, 'below', null); })
- .then(function() {
- expect(getLayerIds()).withContext('back to default *below*').toEqual([
- 'background', 'landuse_overlay_national_park', 'landuse_park',
- 'waterway', 'water',
- 'building', 'tunnel_minor', 'tunnel_major', 'road_minor', 'road_major',
- 'bridge_minor case', 'bridge_major case', 'bridge_minor', 'bridge_major',
- 'admin_country',
- 'plotly-trace-layer-a-heatmap',
- 'poi_label', 'road_major_label',
- 'place_label_other', 'place_label_city', 'country_label'
- ]);
- })
- .then(done, done.fail);
- }, 5 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
-
- it('@gl should be able to restyle from and to *scattermapbox*', function(done) {
- function _assert(msg, exp) {
- var traceHash = gd._fullLayout.mapbox._subplot.traceHash;
- expect(Object.keys(traceHash).length).toBe(1, 'one visible trace| ' + msg);
- for(var k in traceHash) {
- expect(traceHash[k].type).toBe(exp, 'trace type| ' + msg);
- }
- }
-
- Plotly.newPlot(gd, [{
- type: 'densitymapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- z: [1, 20, 5]
- }], {}, {
- mapboxAccessToken: MAPBOX_ACCESS_TOKEN
- })
- .then(function() { _assert('after first', 'densitymapbox'); })
- .then(function() { return Plotly.restyle(gd, 'type', 'scattermapbox'); })
- .then(function() { _assert('after restyle to scattermapbox', 'scattermapbox'); })
- .then(function() { return Plotly.restyle(gd, 'type', 'densitymapbox'); })
- .then(function() { _assert('back to densitymapbox', 'densitymapbox'); })
- .then(done, done.fail);
- }, 5 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
-});
diff --git a/test/jasmine/tests/draw_newshape_test.js b/test/jasmine/tests/draw_newshape_test.js
index f0ea4d2b809..657df5b2c0f 100644
--- a/test/jasmine/tests/draw_newshape_test.js
+++ b/test/jasmine/tests/draw_newshape_test.js
@@ -679,70 +679,6 @@ describe('Draw new shapes to layout', function() {
}
]
},
- {
- name: 'mapbox',
- json: require('../../image/mocks/mapbox_angles'),
- testPos: [
- function(pos) {
- return assertPos(pos,
- 'M0.2076923076923077,0.8725490196078431L0.2846153846153846,0.9705882352941176L0.33076923076923076,0.9705882352941176L0.2076923076923077,0.8725490196078431'
- );
- },
- function(pos) {
- return assertPos(pos,
- 'M0.09230769230769231,0.9215686274509804L0.24615384615384617,0.9215686274509804L0.24615384615384617,0.7254901960784313L0.09230769230769231,0.7254901960784313Z'
- );
- },
- function(pos) {
- return assertPos(pos, {
- x0: 0.2076923076923077,
- y0: 0.7745098039215687,
- x1: 0.36153846153846153,
- y1: 0.5784313725490196
- });
- },
- function(pos) {
- return assertPos(pos, {
- x0: 0.13076923076923078,
- y0: 0.8725490196078431,
- x1: 0.05384615384615385,
- y1: 0.9705882352941176
- });
- },
- function(pos) {
- return assertPos(pos, {
- x0: 0.021983572125146553,
- y0: 0.6358614154536182,
- x1: 0.23955488941331504,
- y1: 0.9131581923895189
- });
- },
- function(pos) {
- return assertPos(pos, {
- x0: 0.2076923076923077,
- y0: 0.6764705882352943,
- x1: 0.053846153846153794,
- y1: 0.872549019607843
- });
- },
- function(pos) {
- return assertPos(pos, {
- x0: 0.053846153846153835,
- y0: 0.872549019607843,
- x1: 0.2076923076923078,
- y1: 0.6764705882352943
- });
- },
- function(pos) {
- return assertPos(pos, {
- x0: 0.1851620600912729,
- y0: 0.3862943162113073,
- x1: 0.07637640144718866,
- y1: 1.1627252916318298
- });
- }
- ]
- },
{
name: 'map',
json: require('../../image/mocks/map_angles'),
diff --git a/test/jasmine/tests/mapbox_test.js b/test/jasmine/tests/mapbox_test.js
deleted file mode 100644
index 0432710fade..00000000000
--- a/test/jasmine/tests/mapbox_test.js
+++ /dev/null
@@ -1,2242 +0,0 @@
-var Plotly = require('../../../lib/index');
-var Lib = require('../../../src/lib');
-var Fx = require('../../../src/components/fx');
-
-var constants = require('../../../src/plots/mapbox/constants');
-var supplyLayoutDefaults = require('../../../src/plots/mapbox/layout_defaults');
-
-var d3Select = require('../../strict-d3').select;
-var d3SelectAll = require('../../strict-d3').selectAll;
-var createGraphDiv = require('../assets/create_graph_div');
-var destroyGraphDiv = require('../assets/destroy_graph_div');
-var mouseEvent = require('../assets/mouse_event');
-var click = require('../assets/click');
-var delay = require('../assets/delay');
-
-var supplyAllDefaults = require('../assets/supply_defaults');
-
-var customAssertions = require('../assets/custom_assertions');
-var assertHoverLabelStyle = customAssertions.assertHoverLabelStyle;
-var assertHoverLabelContent = customAssertions.assertHoverLabelContent;
-
-var SORTED_EVENT_KEYS = [
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
- 'lon', 'lat',
- 'bbox'
-].sort();
-
-var MAPBOX_ACCESS_TOKEN = require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN;
-var TRANSITION_DELAY = 500;
-var MOUSE_DELAY = 100;
-var LONG_TIMEOUT_INTERVAL = 5 * jasmine.DEFAULT_TIMEOUT_INTERVAL;
-
-var noop = function() {};
-
-Plotly.setPlotConfig({
- mapboxAccessToken: MAPBOX_ACCESS_TOKEN
-});
-
-describe('mapbox defaults', function() {
- var layoutIn, layoutOut, fullData;
-
- beforeEach(function() {
- layoutOut = { font: { color: 'red' }, _subplots: {mapbox: ['mapbox']} };
-
- // needs a mapbox-ref in a trace in order to be detected
- fullData = [{ type: 'scattermapbox', subplot: 'mapbox' }];
- });
-
- it('should fill empty containers', function() {
- layoutIn = {};
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutIn).toEqual({ mapbox: {} });
- });
-
- it('should copy ref to input container in full (for updating on map move)', function() {
- var mapbox = { style: 'light '};
-
- layoutIn = { mapbox: mapbox };
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.mapbox._input).toBe(mapbox);
- });
-
- it('should accept both string and object style', function() {
- var mapboxStyleJSON = {
- id: 'cdsa213wqdsa',
- owner: 'johnny'
- };
-
- layoutIn = {
- mapbox: { style: 'light' },
- mapbox2: { style: mapboxStyleJSON }
- };
-
- fullData.push({ type: 'scattermapbox', subplot: 'mapbox2' });
- layoutOut._subplots.mapbox.push('mapbox2');
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.mapbox.style).toEqual('light');
- expect(layoutOut.mapbox2.style).toBe(mapboxStyleJSON);
- });
-
- it('should fill layer containers', function() {
- layoutIn = {
- mapbox: {
- layers: [{}, {}]
- }
- };
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.mapbox.layers[0].sourcetype).toEqual('geojson');
- expect(layoutOut.mapbox.layers[1].sourcetype).toEqual('geojson');
- });
-
- it('should skip over non-object layer containers', function() {
- layoutIn = {
- mapbox: {
- layers: [{}, null, 'remove', {}]
- }
- };
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.mapbox.layers).toEqual([jasmine.objectContaining({
- sourcetype: 'geojson',
- _index: 0
- }), jasmine.objectContaining({
- visible: false
- }), jasmine.objectContaining({
- visible: false
- }), jasmine.objectContaining({
- sourcetype: 'geojson',
- _index: 3
- })]);
- });
-
- it('should coerce \'sourcelayer\' only for *vector* \'sourcetype\'', function() {
- layoutIn = {
- mapbox: {
- layers: [{
- sourcetype: 'vector',
- sourcelayer: 'layer0'
- }, {
- sourcetype: 'geojson',
- sourcelayer: 'layer0'
- }]
- }
- };
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.mapbox.layers[0].sourcelayer).toEqual('layer0');
- expect(layoutOut.mapbox.layers[1].sourcelayer).toBeUndefined();
- });
-
- it('should only coerce relevant layer style attributes', function() {
- var base = {
- line: { width: 3 },
- fill: { outlinecolor: '#d3d3d3' },
- circle: { radius: 20 },
- symbol: { icon: 'monument' }
- };
-
- layoutIn = {
- mapbox: {
- layers: [
- Lib.extendFlat({}, base, {
- type: 'line',
- color: 'red'
- }),
- Lib.extendFlat({}, base, {
- type: 'fill',
- color: 'blue'
- }),
- Lib.extendFlat({}, base, {
- type: 'circle',
- color: 'green'
- }),
- Lib.extendFlat({}, base, {
- type: 'symbol',
- color: 'yellow'
- })
- ]
- }
- };
-
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
-
- expect(layoutOut.mapbox.layers[0].color).toEqual('red');
- expect(layoutOut.mapbox.layers[0].line.width).toEqual(3);
- expect(layoutOut.mapbox.layers[0].fill).toBeUndefined();
- expect(layoutOut.mapbox.layers[0].circle).toBeUndefined();
- expect(layoutOut.mapbox.layers[0].symbol).toBeUndefined();
-
- expect(layoutOut.mapbox.layers[1].color).toEqual('blue');
- expect(layoutOut.mapbox.layers[1].fill.outlinecolor).toEqual('#d3d3d3');
- expect(layoutOut.mapbox.layers[1].line).toBeUndefined();
- expect(layoutOut.mapbox.layers[1].circle).toBeUndefined();
- expect(layoutOut.mapbox.layers[1].symbol).toBeUndefined();
-
- expect(layoutOut.mapbox.layers[2].color).toEqual('green');
- expect(layoutOut.mapbox.layers[2].circle.radius).toEqual(20);
- expect(layoutOut.mapbox.layers[2].line).toBeUndefined();
- expect(layoutOut.mapbox.layers[2].fill).toBeUndefined();
- expect(layoutOut.mapbox.layers[2].symbol).toBeUndefined();
-
- expect(layoutOut.mapbox.layers[3].color).toEqual('yellow');
- expect(layoutOut.mapbox.layers[3].symbol.icon).toEqual('monument');
- expect(layoutOut.mapbox.layers[3].line).toBeUndefined();
- expect(layoutOut.mapbox.layers[3].fill).toBeUndefined();
- expect(layoutOut.mapbox.layers[3].circle).toBeUndefined();
- });
-
- it('should not allow to set layer type other than *raster* for sourcetype value *raster* and *image*', function() {
- spyOn(Lib, 'log');
-
- layoutIn = {
- mapbox: {
- layers: [{
- sourcetype: 'raster',
- source: 'url',
- type: 'circle'
- }, {
- sourcetype: 'image',
- source: 'url',
- type: 'fill'
- }]
- }
- };
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
-
- expect(Lib.log).toHaveBeenCalledTimes(2);
- expect(Lib.log).toHaveBeenCalledWith('Source types *raster* and *image* must drawn *raster* layer type.');
-
- expect(layoutOut.mapbox.layers[0].type).toBe('raster');
- expect(layoutOut.mapbox.layers[1].type).toBe('raster');
- });
-
- it('should default layer with sourcetype *raster* and *image* to type *raster', function() {
- spyOn(Lib, 'log');
-
- layoutIn = {
- mapbox: {
- layers: [{
- sourcetype: 'raster',
- source: 'url'
- }, {
- sourcetype: 'image',
- source: 'url'
- }]
- }
- };
- supplyLayoutDefaults(layoutIn, layoutOut, fullData);
-
- expect(Lib.log).toHaveBeenCalledTimes(0);
- expect(layoutOut.mapbox.layers[0].type).toBe('raster');
- expect(layoutOut.mapbox.layers[1].type).toBe('raster');
- });
-
- it('should set *layout.dragmode* to pan while zoom is not available', function() {
- var gd = {
- data: fullData,
- layout: {}
- };
-
- supplyAllDefaults(gd);
- expect(gd._fullLayout.dragmode).toBe('pan');
- });
-});
-
-describe('mapbox credentials', function() {
- var gd;
-
- var dummyToken = 'asfdsa124331wersdsa1321q3';
-
- var osmStyle = {
- id: 'osm',
- version: 8,
- sources: {
- 'osm-tiles': {
- type: 'raster',
- tiles: [
- 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
- 'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png'
- ],
- tileSize: 256
- }
- },
- layers: [{
- id: 'osm-tiles',
- type: 'raster',
- source: 'osm-tiles',
- minzoom: 0,
- maxzoom: 22
- }]
- };
-
- beforeEach(function() {
- gd = createGraphDiv();
-
- Plotly.setPlotConfig({
- mapboxAccessToken: null
- });
- });
-
- afterEach(function() {
- Plotly.purge(gd);
- destroyGraphDiv();
-
- Plotly.setPlotConfig({
- mapboxAccessToken: MAPBOX_ACCESS_TOKEN
- });
- });
-
- it('@gl should throw error when no non-mapbox style is set and missing a mapbox access token token', function() {
- spyOn(Lib, 'error');
-
- expect(function() {
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }]);
- }).toThrow(new Error(constants.missingStyleErrorMsg));
-
- expect(Lib.error).toHaveBeenCalledWith(constants.missingStyleErrorMsg);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should throw error when setting a Mapbox style w/o a registered token', function() {
- spyOn(Lib, 'error');
-
- expect(function() {
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {
- mapbox: {style: 'basic'}
- });
- }).toThrow(new Error(constants.noAccessTokenErrorMsg));
-
- expect(Lib.error).toHaveBeenCalledWith('Uses Mapbox map style, but did not set an access token.');
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should throw error if token is invalid', function(done) {
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {}, {
- mapboxAccessToken: dummyToken
- })
- .catch(function(err) {
- cnt++;
- expect(err).toEqual(new Error(constants.mapOnErrorMsg));
- })
- .then(function() {
- expect(cnt).toEqual(1);
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should use access token in mapbox layout options if present', function(done) {
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {
- mapbox: {
- accesstoken: MAPBOX_ACCESS_TOKEN
- }
- }, {
- mapboxAccessToken: dummyToken
- }).catch(function() {
- cnt++;
- }).then(function() {
- expect(cnt).toEqual(0);
- expect(gd._fullLayout.mapbox.accesstoken).toEqual(MAPBOX_ACCESS_TOKEN);
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should warn when multiple tokens in mapbox layout options are present', function(done) {
- spyOn(Lib, 'warn');
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }, {
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30],
- subplot: 'mapbox2'
- }], {
- mapbox: { accesstoken: MAPBOX_ACCESS_TOKEN },
- mapbox2: { accesstoken: dummyToken }
- }).catch(function() {
- cnt++;
- }).then(function() {
- expect(cnt).toEqual(0);
- expect(gd._fullLayout.mapbox.accesstoken).toEqual(MAPBOX_ACCESS_TOKEN);
- expect(Lib.warn).toHaveBeenCalledWith(constants.multipleTokensErrorMsg);
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should not throw when using a custom non-mapbox style', function(done) {
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {
- mapbox: { style: osmStyle }
- }).catch(function() {
- cnt++;
- }).then(function() {
- expect(cnt).toEqual(0);
- expect(gd._fullLayout.mapbox.accesstoken).toBe(undefined);
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@noCI @gl should not throw when using a custom mapbox style URL with an access token in the layout', function(done) {
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {
- mapbox: {
- accesstoken: MAPBOX_ACCESS_TOKEN,
- style: 'mapbox://styles/plotly-js-tests/ck4og36lx0vnj1cpdl8y0cr8m'
- }
- }).catch(function() {
- cnt++;
- }).then(function() {
- expect(cnt).toEqual(0);
- expect(gd._fullLayout.mapbox.accesstoken).toBe(MAPBOX_ACCESS_TOKEN);
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should log when an access token is set while using a custom non-mapbox style', function(done) {
- spyOn(Lib, 'log');
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {
- mapbox: {
- style: osmStyle,
- accesstoken: MAPBOX_ACCESS_TOKEN
- }
- }).catch(function() {
- cnt++;
- }).then(function() {
- expect(cnt).toEqual(0);
- expect(Lib.log).toHaveBeenCalledWith([
- 'Listed mapbox access token(s)',
- MAPBOX_ACCESS_TOKEN,
- 'but did not use a Mapbox map style, ignoring token(s).'
- ].join(' '));
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should bypass access token in mapbox layout options when config points to an Atlas server', function(done) {
- var cnt = 0;
- var msg = [
- 'An API access token is required to use Mapbox GL.',
- 'See https://www.mapbox.com/api-documentation/#access-tokens-and-token-scopes'
- ].join(' ');
-
- // TODO potential new way of doing this:
- // https://github.com/mapbox/mapbox-gl-js/pull/7594
- //
- // https://www.mapbox.com/atlas/#developing-with-atlas
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- }], {
- mapbox: {
- accesstoken: MAPBOX_ACCESS_TOKEN
- }
- }, {
- mapboxAccessToken: ''
- })
- .catch(function(err) {
- cnt++;
- // Note that we get an error here on `new mapboxgl.Map`
- // as we don't have an Atlas server running.
- //
- // In essence, we test that the `new mapboxgl.Map` throws
- // as oppose to `findAccessToken`
- expect(err).toEqual(new Error(msg));
- })
- .then(function() {
- expect(cnt).toEqual(1);
- done();
- });
- }, LONG_TIMEOUT_INTERVAL);
-});
-
-describe('mapbox plots', function() {
- var mock = require('../../image/mocks/mapbox_0.json');
- var gd;
-
- var pointPos = [579, 276];
- var blankPos = [650, 120];
-
- beforeEach(function(done) {
- gd = createGraphDiv();
-
- var mockCopy = Lib.extendDeep({}, mock);
-
- Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done);
- });
-
- afterEach(function() {
- Plotly.purge(gd);
- destroyGraphDiv();
- });
-
- it('@gl should be able to toggle trace visibility', function(done) {
- var modes = ['line', 'circle'];
-
- expect(countVisibleTraces(gd, modes)).toEqual(2);
-
- Plotly.restyle(gd, 'visible', false).then(function() {
- expect(gd._fullLayout.mapbox === undefined).toBe(false);
-
- expect(countVisibleTraces(gd, modes)).toEqual(0);
-
- return Plotly.restyle(gd, 'visible', true);
- })
- .then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(2);
-
- return Plotly.restyle(gd, 'visible', 'legendonly', [1]);
- })
- .then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(1);
-
- return Plotly.restyle(gd, 'visible', true);
- })
- .then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(2);
-
- var mockCopy = Lib.extendDeep({}, mock);
- mockCopy.data[0].visible = false;
-
- return Plotly.newPlot(gd, mockCopy.data, mockCopy.layout);
- })
- .then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(1);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to delete and add traces', function(done) {
- var modes = ['line', 'circle'];
-
- expect(countVisibleTraces(gd, modes)).toEqual(2);
-
- Plotly.deleteTraces(gd, [0]).then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(1);
-
- var trace = {
- type: 'scattermapbox',
- mode: 'markers+lines',
- lon: [-10, -20, -10],
- lat: [-10, 20, -10]
- };
-
- return Plotly.addTraces(gd, [trace]);
- })
- .then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(2);
-
- var trace = {
- type: 'scattermapbox',
- mode: 'markers+lines',
- lon: [10, 20, 10],
- lat: [10, -20, 10]
- };
-
- return Plotly.addTraces(gd, [trace]);
- })
- .then(function() {
- expect(countVisibleTraces(gd, modes)).toEqual(3);
-
- return Plotly.deleteTraces(gd, [0, 1, 2]);
- })
- .then(function() {
- expect(gd._fullLayout.mapbox === undefined).toBe(true);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should not update center while dragging', function(done) {
- var map = gd._fullLayout.mapbox._subplot.map;
- spyOn(map, 'setCenter').and.callThrough();
-
- var p1 = [pointPos[0] + 50, pointPos[1] - 20];
-
- _mouseEvent('mousemove', pointPos, noop).then(function() {
- return Plotly.relayout(gd, {'mapbox.center': {lon: 13.5, lat: -19.5}});
- }).then(function() {
- // First relayout on mapbox.center results in setCenter call
- expect(map.setCenter).toHaveBeenCalledWith([13.5, -19.5]);
- expect(map.setCenter).toHaveBeenCalledTimes(1);
- }).then(function() {
- return _mouseEvent('mousedown', pointPos, noop);
- }).then(function() {
- return _mouseEvent('mousemove', p1, noop);
- }).then(function() {
- return Plotly.relayout(gd, {'mapbox.center': {lat: 0, lon: 0}});
- }).then(function() {
- return _mouseEvent('mouseup', p1, noop);
- }).then(function() {
- // Second relayout on mapbox.center does not result in a setCenter
- // call since map drag is underway
- expect(map.setCenter).toHaveBeenCalledTimes(1);
- }).then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should not update zoom while scroll wheeling', function(done) {
- var map = gd._fullLayout.mapbox._subplot.map;
- spyOn(map, 'setZoom').and.callThrough();
-
- _mouseEvent('mousemove', pointPos, noop).then(function() {
- return Plotly.relayout(gd, {'mapbox.zoom': 5});
- }).then(function() {
- // First relayout on mapbox.zoom results in setZoom call
- expect(map.setZoom).toHaveBeenCalledWith(5);
- expect(map.setZoom).toHaveBeenCalledTimes(1);
- }).then(function() {
- mouseEvent('scroll', pointPos[0], pointPos[1], {deltaY: -400});
- return Plotly.relayout(gd, {'mapbox.zoom': 2}).then(function() {
- // Second relayout on mapbox.zoom does not result in setZoom
- // call since a scroll wheel zoom is underway
- expect(map.setZoom).toHaveBeenCalledTimes(1);
- });
- }).then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to restyle', function(done) {
- var restyleCnt = 0;
- var relayoutCnt = 0;
-
- gd.on('plotly_restyle', function() {
- restyleCnt++;
- });
-
- gd.on('plotly_relayout', function() {
- relayoutCnt++;
- });
-
- function assertMarkerColor(expectations) {
- return new Promise(function(resolve) {
- setTimeout(function() {
- var objs = getStyle(gd, 'circle', 'circle-color');
-
- expectations.forEach(function(expected, i) {
- var obj = objs[i];
- var rgba = [obj.r, obj.g, obj.b, obj.a];
- expect(rgba).toBeCloseToArray(expected);
- });
-
- resolve();
- }, TRANSITION_DELAY);
- });
- }
-
- assertMarkerColor([
- [0.121, 0.466, 0.705, 1],
- [1, 0.498, 0.0549, 1]
- ])
- .then(function() {
- return Plotly.restyle(gd, 'marker.color', 'green');
- })
- .then(function() {
- expect(restyleCnt).toEqual(1);
- expect(relayoutCnt).toEqual(0);
-
- return assertMarkerColor([
- [0, 0.5019, 0, 1],
- [0, 0.5019, 0, 1]
- ]);
- })
- .then(function() {
- return Plotly.restyle(gd, 'marker.color', 'red', [1]);
- })
- .then(function() {
- expect(restyleCnt).toEqual(2);
- expect(relayoutCnt).toEqual(0);
-
- return assertMarkerColor([
- [0, 0.5019, 0, 1],
- [1, 0, 0, 1]
- ]);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to relayout', function(done) {
- var restyleCnt = 0;
- var relayoutCnt = 0;
-
- gd.on('plotly_restyle', function() {
- restyleCnt++;
- });
-
- gd.on('plotly_relayout', function() {
- relayoutCnt++;
- });
-
- function assertLayout(center, zoom, dims) {
- var mapInfo = getMapInfo(gd);
-
- expect([mapInfo.center.lng, mapInfo.center.lat])
- .toBeCloseToArray(center);
- expect(mapInfo.zoom).toBeCloseTo(zoom);
-
- var divStyle = mapInfo.div.style;
- ['left', 'top', 'width', 'height'].forEach(function(p, i) {
- expect(parseFloat(divStyle[p])).toBeWithin(dims[i], 8);
- });
- }
-
- assertLayout([-4.710, 19.475], 1.234, [80, 100, 908, 270]);
-
- Plotly.relayout(gd, 'mapbox.center', { lon: 0, lat: 0 })
- .then(function() {
- expect(restyleCnt).toEqual(0);
- expect(relayoutCnt).toEqual(1);
-
- assertLayout([0, 0], 1.234, [80, 100, 908, 270]);
-
- return Plotly.relayout(gd, 'mapbox.zoom', '6');
- })
- .then(function() {
- expect(restyleCnt).toEqual(0);
- expect(relayoutCnt).toEqual(2);
-
- assertLayout([0, 0], 6, [80, 100, 908, 270]);
-
- return Plotly.relayout(gd, 'mapbox.domain.x', [0, 0.5]);
- })
- .then(function() {
- expect(restyleCnt).toEqual(0);
- expect(relayoutCnt).toEqual(3);
-
- assertLayout([0, 0], 6, [80, 100, 454, 270]);
-
- return Plotly.relayout(gd, 'mapbox.domain.y[0]', 0.5);
- })
- .then(function() {
- expect(restyleCnt).toEqual(0);
- expect(relayoutCnt).toEqual(4);
-
- assertLayout([0, 0], 6, [80, 100, 454, 135]);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to relayout the map style', function(done) {
- function assertLayout(style) {
- var mapInfo = getMapInfo(gd);
- expect(mapInfo.style.name).toEqual(style);
- }
-
- // TODO
- // this one now logs:
- // 'Unable to perform style diff: Unimplemented: setSprite.. Rebuilding the style from scratch.'
- // https://github.com/mapbox/mapbox-gl-js/issues/6933
-
- assertLayout('Mapbox Dark');
-
- Plotly.relayout(gd, 'mapbox.style', 'light')
- .then(function() {
- assertLayout('Mapbox Light');
-
- return Plotly.relayout(gd, 'mapbox.style', 'dark');
- })
- .then(function() {
- assertLayout('Mapbox Dark');
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to add, update and remove layers', function(done) {
- var mockWithLayers = require('../../image/mocks/mapbox_layers');
-
- var layer0 = Lib.extendDeep({}, mockWithLayers.layout.mapbox.layers[0]);
- var layer1 = Lib.extendDeep({}, mockWithLayers.layout.mapbox.layers[1]);
-
- var mapUpdate = {
- 'mapbox.zoom': mockWithLayers.layout.mapbox.zoom,
- 'mapbox.center.lon': mockWithLayers.layout.mapbox.center.lon,
- 'mapbox.center.lat': mockWithLayers.layout.mapbox.center.lat
- };
-
- var styleUpdate0 = {
- 'mapbox.layers[0].color': 'red',
- 'mapbox.layers[0].fill.outlinecolor': 'blue',
- 'mapbox.layers[0].opacity': 0.3
- };
-
- var styleUpdate1 = {
- 'mapbox.layers[1].color': 'blue',
- 'mapbox.layers[1].line.width': 3,
- 'mapbox.layers[1].opacity': 0.6
- };
-
- function countVisibleLayers(gd) {
- var mapInfo = getMapInfo(gd);
-
- var sourceLen = mapInfo.layoutSources.length;
- var layerLen = mapInfo.layoutLayers.length;
-
- if(sourceLen !== layerLen) return null;
-
- return layerLen;
- }
-
- function getLayerLength(gd) {
- return Lib.filterVisible(gd._fullLayout.mapbox.layers || []).length;
- }
-
- function assertLayerStyle(gd, expectations, index) {
- var mapInfo = getMapInfo(gd);
- var layers = mapInfo.layers;
- var layerNames = mapInfo.layoutLayers;
-
- var layer = layers[layerNames[index]];
- expect(layer).toBeDefined(layerNames[index]);
-
- return new Promise(function(resolve) {
- setTimeout(function() {
- Object.keys(expectations).forEach(function(k) {
- try {
- var obj = layer.paint._values[k].value.value;
- expect(String(obj)).toBe(String(expectations[k]), k);
- } catch(e) {
- fail('could not find paint values in layer');
- }
- });
- resolve();
- }, TRANSITION_DELAY);
- });
- }
-
- expect(countVisibleLayers(gd)).toEqual(0);
-
- Plotly.relayout(gd, 'mapbox.layers[0]', layer0)
- .then(function() {
- expect(getLayerLength(gd)).toEqual(1);
- expect(countVisibleLayers(gd)).toEqual(1);
-
- // add a new layer at the beginning
- return Plotly.relayout(gd, 'mapbox.layers[1]', layer1);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- // hide a layer
- return Plotly.relayout(gd, 'mapbox.layers[0].visible', false);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(1);
- expect(countVisibleLayers(gd)).toEqual(1);
-
- // re-show it
- return Plotly.relayout(gd, 'mapbox.layers[0].visible', true);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- return Plotly.relayout(gd, mapUpdate);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- return Plotly.relayout(gd, styleUpdate0);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- return assertLayerStyle(gd, {
- 'fill-color': 'rgba(255,0,0,1)',
- 'fill-outline-color': 'rgba(0,0,255,1)',
- 'fill-opacity': 0.3
- }, 0);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- return Plotly.relayout(gd, styleUpdate1);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- return assertLayerStyle(gd, {
- 'line-width': 3,
- 'line-color': 'rgba(0,0,255,1)',
- 'line-opacity': 0.6
- }, 1);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(2);
- expect(countVisibleLayers(gd)).toEqual(2);
-
- // delete the first layer
- return Plotly.relayout(gd, 'mapbox.layers[0]', null);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(1);
- expect(countVisibleLayers(gd)).toEqual(1);
-
- return Plotly.relayout(gd, 'mapbox.layers[0]', null);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(0);
- expect(countVisibleLayers(gd)).toEqual(0);
-
- return Plotly.relayout(gd, 'mapbox.layers[0]', {});
- })
- .then(function() {
- expect(gd.layout.mapbox.layers).toEqual([{}]);
- expect(countVisibleLayers(gd)).toEqual(0);
-
- // layer with no source are not drawn
-
- return Plotly.relayout(gd, 'mapbox.layers[0].source', layer0.source);
- })
- .then(function() {
- expect(getLayerLength(gd)).toEqual(1);
- expect(countVisibleLayers(gd)).toEqual(1);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to update layer image', function(done) {
- var coords = [
- [-80.425, 46.437],
- [-71.516, 46.437],
- [-71.516, 37.936],
- [-80.425, 37.936]
- ];
- function makeFigure(source) {
- return {
- data: [{type: 'scattermapbox'}],
- layout: {
- mapbox: {
- layers: [{
- sourcetype: 'raster',
- source: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],
- below: 'traces',
- }, {
- sourcetype: 'image',
- coordinates: coords,
- source: source,
- below: 'traces',
- }],
- }
- }
- };
- }
-
- var map = null;
- var layerSource = null;
-
- // Single pixel PNGs generated with http://png-pixel.com/
- var prefix = 'data:image/png;base64,';
- var redImage = prefix + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42m' +
- 'P8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==';
- var greenImage = prefix + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42m' +
- 'Nk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg==';
-
- Plotly.react(gd, makeFigure(redImage)).then(function() {
- var mapbox = gd._fullLayout.mapbox._subplot;
- map = mapbox.map;
- layerSource = map.getSource(mapbox.layerList[1].idSource);
-
- spyOn(layerSource, 'updateImage').and.callThrough();
- spyOn(map, 'removeSource').and.callThrough();
- return Plotly.react(gd, makeFigure(greenImage));
- })
- .then(function() {
- expect(layerSource.updateImage).toHaveBeenCalledWith(
- {url: greenImage, coordinates: coords}
- );
- expect(map.removeSource).not.toHaveBeenCalled();
-
- // Check order of layers
- var mapbox = gd._fullLayout.mapbox._subplot;
- var mapboxLayers = mapbox.getMapLayers();
- var plotlyjsLayers = mapbox.layerList;
-
- var indexLower = mapboxLayers.findIndex(function(layer) {
- return layer.id === 'plotly-layout-layer-' + plotlyjsLayers[0].uid;
- });
-
- var indexUpper = mapboxLayers.findIndex(function(layer) {
- return layer.id === 'plotly-layout-layer-' + plotlyjsLayers[1].uid;
- });
-
- expect(indexLower).toBeGreaterThan(-1);
- expect(indexUpper).toBeGreaterThan(0);
- expect(indexUpper).toBe(indexLower + 1);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to react to layer changes', function(done) {
- function makeFigure(color) {
- return {
- data: [{type: 'scattermapbox'}],
- layout: {
- mapbox: {
- layers: [{
- color: color,
- sourcetype: 'geojson',
- type: 'fill',
- source: {
- type: 'Feature',
- properties: {},
- geometry: {
- type: 'Polygon',
- coordinates: [[
- [174.7447586059570, -36.86533886128865],
- [174.7773742675781, -36.86533886128865],
- [174.7773742675781, -36.84913134182603],
- [174.7447586059570, -36.84913134182603],
- [174.7447586059570, -36.86533886128865]
- ]]
- }
- }
- }]
- }
- }
- };
- }
-
- function _assert(color) {
- var mapInfo = getMapInfo(gd);
- var layer = mapInfo.layers[mapInfo.layoutLayers[0]];
-
- expect(mapInfo.layoutLayers.length).toBe(1, 'one layer');
- expect(mapInfo.layoutSources.length).toBe(1, 'one layer source');
- expect(String(layer.paint._values['fill-color'].value.value)).toBe(color, 'layer color');
- }
-
- // TODO
- // this one now logs:
- // 'Unable to perform style diff: Unimplemented: setSprite, setLayerProperty.. Rebuilding the style from scratch.'
- // github.com/mapbox/mapbox-gl-js/issues/6933/
-
- Plotly.react(gd, makeFigure('blue')).then(function() {
- _assert('rgba(0,0,255,1)');
- return Plotly.react(gd, makeFigure('red'));
- })
- .then(function() {
- _assert('rgba(255,0,0,1)');
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should not wedge graph after reacting to invalid layer', function(done) {
- Plotly.react(gd, [{type: 'scattermapbox'}], {
- mapbox: {
- layers: [{ source: 'invalid' }]
- }
- })
- .then(function() {
- fail('The above Plotly.react promise should be rejected');
- })
- .catch(function() {
- expect(gd._promises.length).toBe(1, 'has 1 rejected promise in queue');
- })
- .then(function() {
- return Plotly.react(gd, [{type: 'scattermapbox'}], {
- mapbox: {
- layers: [{
- sourcetype: 'vector',
- sourcelayer: 'contour',
- source: 'mapbox://mapbox.mapbox-terrain-v2'
- }]
- }
- });
- })
- .then(function() {
- expect(gd._promises.length).toBe(0, 'rejected promise has been cleared');
-
- var mapInfo = getMapInfo(gd);
- expect(mapInfo.layoutLayers.length).toBe(1, 'one layer');
- expect(mapInfo.layoutSources.length).toBe(1, 'one layer source');
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should not attempt to remove non-existing layer sources', function(done) {
- function _assert(msg, exp) {
- return function() {
- var layerList = gd._fullLayout.mapbox._subplot.layerList;
- expect(layerList.length).toBe(exp, msg);
- };
- }
-
- Plotly.react(gd, [{type: 'scattermapbox'}], {
- mapbox: { layers: [{}] }
- })
- .then(_assert('1 visible:false layer', 1))
- .then(function() {
- return Plotly.react(gd, [{type: 'scattermapbox'}], {
- mapbox: { layers: [] }
- });
- })
- .then(_assert('no layers', 0))
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should validate layout layer input', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], {
- mapbox: {
- layers: [{
- sourcetype: 'raster',
- source: ['']
- }]
- }
- })
- .then(function() {
- var mapInfo = getMapInfo(gd);
- expect(mapInfo.layoutLayers.length).toBe(0, 'no on-map layer');
- expect(mapInfo.layoutSources.length).toBe(0, 'no map source');
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to update the access token', function(done) {
- Plotly.relayout(gd, 'mapbox.accesstoken', 'wont-work')
- .catch(function(err) {
- expect(gd._fullLayout.mapbox.accesstoken).toEqual('wont-work');
- expect(err).toEqual(new Error(constants.mapOnErrorMsg));
- expect(gd._promises.length).toEqual(1);
-
- return Plotly.relayout(gd, 'mapbox.accesstoken', MAPBOX_ACCESS_TOKEN);
- })
- .then(function() {
- expect(gd._fullLayout.mapbox.accesstoken).toEqual(MAPBOX_ACCESS_TOKEN);
- expect(gd._promises.length).toEqual(0);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should be able to update traces', function(done) {
- function assertDataPts(lengths) {
- var lines = getGeoJsonData(gd, 'lines');
- var markers = getGeoJsonData(gd, 'markers');
-
- lines.forEach(function(obj, i) {
- expect(obj.coordinates[0].length).toEqual(lengths[i]);
- });
-
- markers.forEach(function(obj, i) {
- expect(obj.features.length).toEqual(lengths[i]);
- });
- }
-
- assertDataPts([3, 3]);
-
- var update = {
- lon: [[10, 20]],
- lat: [[-45, -20]]
- };
-
- Plotly.restyle(gd, update, [1]).then(function() {
- assertDataPts([3, 2]);
-
- var update = {
- lon: [ [10, 20], [30, 40, 20] ],
- lat: [ [-10, 20], [10, 20, 30] ]
- };
-
- return Plotly.extendTraces(gd, update, [0, 1]);
- })
- .then(function() {
- assertDataPts([5, 5]);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should display to hover labels on mouse over', function(done) {
- function assertMouseMove(pos, len) {
- return _mouseEvent('mousemove', pos, function() {
- var hoverLabels = d3Select('.hoverlayer').selectAll('g');
-
- expect(hoverLabels.size()).toEqual(len);
- });
- }
-
- assertMouseMove(blankPos, 0).then(function() {
- return assertMouseMove(pointPos, 1);
- })
- .then(function() {
- return Plotly.restyle(gd, {
- 'hoverlabel.bgcolor': 'yellow',
- 'hoverlabel.font.size': [[20, 10, 30]]
- });
- })
- .then(function() {
- return assertMouseMove(pointPos, 1);
- })
- .then(function() {
- assertHoverLabelStyle(d3Select('g.hovertext'), {
- bgcolor: 'rgb(255, 255, 0)',
- bordercolor: 'rgb(68, 68, 68)',
- fontSize: 20,
- fontFamily: 'Arial',
- fontColor: 'rgb(68, 68, 68)'
- });
- assertHoverLabelContent({
- nums: '(10°, 10°)',
- name: 'trace 0'
- });
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should respond to hover interactions by', function(done) {
- var hoverCnt = 0;
- var unhoverCnt = 0;
-
- var hoverData, unhoverData;
-
- gd.on('plotly_hover', function(eventData) {
- hoverCnt++;
- hoverData = eventData.points[0];
- });
-
- gd.on('plotly_unhover', function(eventData) {
- unhoverCnt++;
- unhoverData = eventData.points[0];
- });
-
- _mouseEvent('mousemove', blankPos, function() {
- expect(hoverData).toBe(undefined, 'not firing on blank points');
- expect(unhoverData).toBe(undefined, 'not firing on blank points');
- })
- .then(function() {
- return _mouseEvent('mousemove', pointPos, function() {
- expect(hoverData).not.toBe(undefined, 'firing on data points');
- expect(Object.keys(hoverData).sort()).toEqual(SORTED_EVENT_KEYS, 'returning the correct event data keys');
- expect(hoverData.curveNumber).toEqual(0, 'returning the correct curve number');
- expect(hoverData.pointNumber).toEqual(0, 'returning the correct point number');
- });
- })
- .then(function() {
- return _mouseEvent('mousemove', blankPos, function() {
- expect(unhoverData).not.toBe(undefined, 'firing on data points');
- expect(Object.keys(unhoverData).sort()).toEqual(SORTED_EVENT_KEYS, 'returning the correct event data keys');
- expect(unhoverData.curveNumber).toEqual(0, 'returning the correct curve number');
- expect(unhoverData.pointNumber).toEqual(0, 'returning the correct point number');
- });
- })
- .then(function() {
- expect(hoverCnt).toEqual(1);
- expect(unhoverCnt).toEqual(1);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should not attempt to rehover over exiting subplots', function(done) {
- spyOn(Fx, 'hover').and.callThrough();
-
- function countHoverLabels() {
- return d3Select('.hoverlayer').selectAll('g').size();
- }
-
- Promise.resolve()
- .then(function() {
- return _mouseEvent('mousemove', pointPos, function() {
- expect(countHoverLabels()).toEqual(1);
- expect(Fx.hover).toHaveBeenCalledTimes(1);
- expect(Fx.hover.calls.argsFor(0)[2]).toBe('mapbox');
- Fx.hover.calls.reset();
- });
- })
- .then(function() { return Plotly.deleteTraces(gd, [0, 1]); })
- .then(delay(10))
- .then(function() {
- return _mouseEvent('mousemove', pointPos, function() {
- expect(countHoverLabels()).toEqual(0);
- // N.B. no additional calls from Plots.rehover()
- // (as 'mapbox' subplot is gone),
- // just one on the fallback xy subplot
- expect(Fx.hover).toHaveBeenCalledTimes(1);
- expect(Fx.hover.calls.argsFor(0)[2]).toBe('xy');
- });
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@noCI @gl should respond drag / scroll / double-click interactions', function(done) {
- var relayoutCnt = 0;
- var doubleClickCnt = 0;
- var relayoutingCnt = 0;
- var evtData;
-
- gd.on('plotly_relayout', function(d) {
- relayoutCnt++;
- evtData = d;
- });
-
- gd.on('plotly_relayouting', function() {
- relayoutingCnt++;
- });
-
- gd.on('plotly_doubleclick', function() {
- doubleClickCnt++;
- });
-
- function _scroll(p) {
- return new Promise(function(resolve) {
- mouseEvent('mousemove', p[0], p[1]);
- mouseEvent('scroll', p[0], p[1], {deltaY: -400});
- setTimeout(resolve, 1000);
- });
- }
-
- function _assertLayout(center, zoom) {
- var mapInfo = getMapInfo(gd);
- var layout = gd.layout.mapbox;
-
- expect([mapInfo.center.lng, mapInfo.center.lat]).toBeCloseToArray(center);
- expect(mapInfo.zoom).toBeCloseTo(zoom);
-
- expect([layout.center.lon, layout.center.lat]).toBeCloseToArray(center);
- expect(layout.zoom).toBeCloseTo(zoom);
- }
-
- function _assert(center, zoom, lon0, lat0, lon1, lat1) {
- _assertLayout(center, zoom);
-
- expect([evtData['mapbox.center'].lon, evtData['mapbox.center'].lat]).toBeCloseToArray(center);
- expect(evtData['mapbox.zoom']).toBeCloseTo(zoom);
- expect(Object.keys(evtData['mapbox._derived'])).toEqual(['coordinates']);
- expect(evtData['mapbox._derived'].coordinates).toBeCloseTo2DArray([
- [lon0, lat1],
- [lon1, lat1],
- [lon1, lat0],
- [lon0, lat0]
- ], -0.1);
- }
-
- _assertLayout([-4.710, 19.475], 1.234);
-
- var p1 = [pointPos[0] + 50, pointPos[1] - 20];
-
- _drag(pointPos, p1, function() {
- expect(relayoutCnt).toBe(1, 'relayout cnt');
- expect(relayoutingCnt).toBe(1, 'relayouting cnt');
- expect(doubleClickCnt).toBe(0, 'double click cnt');
- _assert([-19.651, 13.751], 1.234,
- -155.15981291032617, -25.560300274373148,
- 115.85734493011842, 47.573988219006424);
-
- return _doubleClick(p1);
- })
- .then(function() {
- expect(relayoutCnt).toBe(2, 'relayout cnt');
- expect(relayoutingCnt).toBe(1, 'relayouting cnt');
- expect(doubleClickCnt).toBe(1, 'double click cnt');
- _assert([-4.710, 19.475], 1.234,
- -140.21950652441467, -20.054298691163496,
- 130.79765131602989, 51.4513888208798);
-
- return _scroll(pointPos);
- })
- .then(function() {
- expect(relayoutCnt).toBe(3, 'relayout cnt');
- expect(relayoutingCnt).toBeCloseTo(10, -1, 'relayouting cnt');
- expect(doubleClickCnt).toBe(1, 'double click cnt');
- expect(getMapInfo(gd).zoom).toBeGreaterThan(1.234);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl should respond to click interactions by', function(done) {
- var ptData;
-
- gd.on('plotly_click', function(eventData) {
- ptData = eventData.points[0];
- });
-
- Promise.resolve()
- .then(function() { return click(blankPos[0], blankPos[1]); })
- .then(delay(100))
- .then(function() {
- expect(ptData).toBe(undefined, 'not firing on blank points');
- })
- .then(delay(100))
- .then(function() { return click(pointPos[0], pointPos[1]); })
- .then(function() {
- expect(ptData).not.toBe(undefined, 'firing on data points');
- expect(Object.keys(ptData).sort()).toEqual(SORTED_EVENT_KEYS, 'returning the correct event data keys');
- expect(ptData.curveNumber).toEqual(0, 'returning the correct curve number');
- expect(ptData.pointNumber).toEqual(0, 'returning the correct point number');
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@noCI @gl should respect scrollZoom config option', function(done) {
- var mockCopy2 = Lib.extendDeep({}, mock);
- mockCopy2.config = {scrollZoom: false};
-
- var relayoutCnt = 0;
- var addOnGd = function() {
- gd.on('plotly_relayout', function() { relayoutCnt++; });
- };
-
- function _scroll() {
- relayoutCnt = 0;
- return new Promise(function(resolve) {
- mouseEvent('mousemove', pointPos[0], pointPos[1]);
- mouseEvent('scroll', pointPos[0], pointPos[1], {deltaY: -400});
- setTimeout(resolve, 500);
- });
- }
-
- var zoom = getMapInfo(gd).zoom;
- expect(zoom).toBeCloseTo(1.234);
- var zoom0 = zoom;
-
- addOnGd();
-
- _scroll().then(function() {
- expect(relayoutCnt).toBe(1, 'scroll relayout cnt');
-
- var zoomNew = getMapInfo(gd).zoom;
- expect(zoomNew).toBeGreaterThan(zoom);
- zoom = zoomNew;
- })
- .then(function() { return Plotly.newPlot(gd, gd.data, gd.layout, {scrollZoom: false}); })
- .then(addOnGd)
- .then(_scroll)
- .then(function() {
- expect(relayoutCnt).toBe(0, 'no additional relayout call');
-
- var zoomNew = getMapInfo(gd).zoom;
- expect(zoomNew).toBe(zoom);
- zoom = zoomNew;
- })
- .then(function() { return Plotly.newPlot(gd, gd.data, gd.layout, {scrollZoom: true}); })
- .then(addOnGd)
- .then(_scroll)
- .then(function() {
- expect(relayoutCnt).toBe(1, 'scroll relayout cnt');
-
- var zoomNew = getMapInfo(gd).zoom;
- expect(zoomNew).toBeGreaterThan(zoom);
- })
- .then(function() { return Plotly.newPlot(gd, mockCopy2); })
- .then(addOnGd)
- .then(_scroll)
- .then(function() {
- // see https://github.com/plotly/plotly.js/issues/3738
- var zoomNew = getMapInfo(gd).zoom;
- expect(zoomNew).toBe(zoom0);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- describe('attributions', function() {
- function assertLinks(s, exp) {
- var elements = s[0][0].getElementsByTagName('a');
- expect(elements.length).toEqual(exp.length);
- for(var i = 0; i < elements.length; i++) {
- var e = elements[i];
- expect(e.href).toEqual(exp[i]);
- expect(e.target).toEqual('_blank');
- }
- }
-
- it('@gl should be displayed for style "Carto"', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], {mapbox: {style: 'carto-darkmatter'}})
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual('© Carto © OpenStreetMap contributors');
- assertLinks(s, [
- 'https://carto.com/',
- 'https://www.openstreetmap.org/copyright'
- ]);
- })
- .then(done, done.fail);
- });
-
- ['stamen-terrain', 'stamen-toner'].forEach(function(style) {
- it('@noCI @gl should be displayed for style "' + style + '"', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], {mapbox: {style: style}})
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual('Map tiles by Stamen Design under CC BY 3.0 | Data by OpenStreetMap contributors under ODbL');
- assertLinks(s, [
- 'https://stamen.com/',
- 'https://creativecommons.org/licenses/by/3.0',
- 'https://openstreetmap.org/',
- 'https://www.openstreetmap.org/copyright'
- ]);
- })
- .then(done, done.fail);
- });
- });
-
- it('@noCI @gl should be displayed for style "stamen-watercolor"', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], {mapbox: {style: 'stamen-watercolor'}})
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual('Map tiles by Stamen Design under CC BY 3.0 | Data by OpenStreetMap contributors under CC BY SA');
- assertLinks(s, [
- 'https://stamen.com/',
- 'https://creativecommons.org/licenses/by/3.0',
- 'https://openstreetmap.org/',
- 'https://creativecommons.org/licenses/by-sa/3.0'
- ]);
- })
- .then(done, done.fail);
- });
-
- it('@gl should be displayed for style "open-street-map"', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], {mapbox: {style: 'open-street-map'}})
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual('© OpenStreetMap contributors');
- assertLinks(s, [
- 'https://www.openstreetmap.org/copyright'
- ]);
- })
- .then(done, done.fail);
- });
-
- it('@gl should be displayed for style from Mapbox', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], {mapbox: {style: 'basic'}})
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual('© Mapbox © OpenStreetMap Improve this map');
- assertLinks(s, [
- 'https://www.mapbox.com/about/maps/',
- 'https://www.openstreetmap.org/about/',
- 'https://apps.mapbox.com/feedback/?owner=mapbox&id=basic-v9&access_token=' + MAPBOX_ACCESS_TOKEN // Improve this map
- ]);
- })
- .then(done, done.fail);
- });
-
- function mockLayoutCustomStyle() {
- return {
- mapbox: {
- style: {
- id: 'osm',
- version: 8,
- sources: {
- 'simple-tiles': {
- type: 'raster',
- tiles: [
- 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
- 'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png'
- ],
- tileSize: 256
- }
- },
- layers: [
- {
- id: 'simple-tiles',
- type: 'raster',
- source: 'simple-tiles',
- minzoom: 0,
- maxzoom: 22
- }
- ]
- }
- }
- };
- }
-
- it('@gl should not be displayed for custom style without attribution', function(done) {
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], mockLayoutCustomStyle())
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual('');
- })
- .then(done, done.fail);
- });
-
- it('@gl should be displayed for custom style with attribution', function(done) {
- var attr = 'custom attribution';
- var layout = mockLayoutCustomStyle();
- layout.mapbox.style.sources['simple-tiles'].attribution = attr;
- Plotly.newPlot(gd, [{type: 'scattermapbox'}], layout)
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual(attr);
- })
- .then(done, done.fail);
- });
-
- it('@noCI @gl should be displayed for attributions defined in layers\' sourceattribution', function(done) {
- var mock = require('../../image/mocks/mapbox_layers.json');
- var customMock = Lib.extendDeep(mock);
-
- var attr = 'custom attribution';
- var XSS = '
';
- customMock.data.pop();
- customMock.layout.mapbox.layers[0].sourceattribution = XSS + attr;
-
- Plotly.newPlot(gd, customMock)
- .then(function() {
- var s = d3SelectAll('.mapboxgl-ctrl-attrib');
- expect(s.size()).toBe(1);
- expect(s.text()).toEqual([XSS + attr, '© Mapbox © OpenStreetMap Improve this map'].join(' | '));
- expect(s.html().indexOf('
')).toBe(-1);
- expect(s.html().indexOf('<img src=x onerror="alert(XSS);">')).not.toBe(-1);
- })
- .then(done, done.fail);
- });
- });
-
- function countVisibleTraces(gd, modes) {
- var mapInfo = getMapInfo(gd);
- var cnts = [];
-
- // 'modes' are the ScatterMapbox layers names
- // e.g. 'fill', 'line', 'circle', 'symbol'
-
- modes.forEach(function(mode) {
- var cntPerMode = 0;
-
- mapInfo.traceLayers.forEach(function(l) {
- var info = mapInfo.layers[l];
-
- if(l.indexOf(mode) === -1) return;
- if(info.visibility === 'visible') cntPerMode++;
- });
-
- cnts.push(cntPerMode);
- });
-
- var cnt = cnts.reduce(function(a, b) {
- return (a === b) ? a : null;
- });
-
- // returns null if not all counter per mode are the same,
- // returns the counter if all are the same.
-
- return cnt;
- }
-
- function getStyle(gd, mode, prop) {
- var mapInfo = getMapInfo(gd);
- var values = [];
-
- mapInfo.traceLayers.forEach(function(l) {
- var info = mapInfo.layers[l];
-
- if(l.indexOf(mode) === -1) return;
-
- values.push(info.paint._values[prop].value.value);
- });
-
- return values;
- }
-
- function getGeoJsonData(gd, mode) {
- var mapInfo = getMapInfo(gd);
- var out = [];
-
- mapInfo.traceSources.forEach(function(s) {
- var info = mapInfo.sources[s];
-
- if(s.indexOf(mode) === -1) return;
-
- out.push(info._data);
- });
-
- return out;
- }
-
- function _mouseEvent(type, pos, cb) {
- return new Promise(function(resolve) {
- mouseEvent(type, pos[0], pos[1], {
- buttons: 1 // left button
- });
-
- setTimeout(function() {
- cb();
- resolve();
- }, MOUSE_DELAY);
- });
- }
-
- function _doubleClick(pos) {
- return _mouseEvent('dblclick', pos, noop);
- }
-
- function _drag(p0, p1, cb) {
- var promise = _mouseEvent('mousemove', p0, noop).then(function() {
- return _mouseEvent('mousedown', p0, noop);
- }).then(function() {
- return _mouseEvent('mousemove', p1, noop);
- }).then(function() {
- // repeat mousemove to simulate long dragging motion
- return _mouseEvent('mousemove', p1, noop);
- }).then(function() {
- return _mouseEvent('mouseup', p1, noop);
- }).then(function() {
- return _mouseEvent('mouseup', p1, noop);
- }).then(cb);
-
- return promise;
- }
-});
-
-describe('mapbox react', function() {
- var gd;
-
- beforeEach(function() {
- gd = createGraphDiv();
- });
-
- afterEach(function() {
- Plotly.purge(gd);
- destroyGraphDiv();
- });
-
- it('@gl should be able to react to new tiles', function(done) {
- function assertTile(link) {
- var mapInfo = getMapInfo(gd);
- expect(mapInfo.style.sources.REF.tiles[0]).toEqual(link);
- }
-
- var firstLink = 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png';
- var secondLink = 'https://a.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg';
-
- var fig = {
- data: [
- {
- type: 'scattermapbox',
- lon: [10, 20],
- lat: [20, 10]
- }
- ],
- layout: {
- mapbox: {
- style: {
- version: 8,
- sources: {
- REF: {
- type: 'raster',
- tileSize: 256,
- tiles: [firstLink]
- }
- },
- layers: [{
- id: 'REF',
- source: 'REF',
- type: 'raster'
- }],
- }
- }
- }
- };
-
- Plotly.newPlot(gd, fig)
- .then(function() {
- assertTile(firstLink);
-
- // copy figure
- var newFig = JSON.parse(JSON.stringify(fig));
-
- // new figure
- newFig.layout.mapbox.style.sources = {
- REF: {
- type: 'raster',
- tileSize: 256,
- tiles: [secondLink]
- }
- };
-
- // update
- Plotly.react(gd, newFig);
- })
- .then(function() {
- assertTile(secondLink);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-});
-
-describe('test mapbox trace/layout *below* interactions', function() {
- var gd;
-
- beforeEach(function() {
- gd = createGraphDiv();
- });
-
- afterEach(function(done) {
- Plotly.purge(gd);
- destroyGraphDiv();
- setTimeout(done, 200);
- });
-
- function getLayerIds() {
- var subplot = gd._fullLayout.mapbox._subplot;
- var layers = subplot.map.getStyle().layers;
- var layerIds = layers.map(function(l) { return l.id; });
- return layerIds;
- }
-
- it('@gl should be able to update *below* - scattermapbox + layout layer case', function(done) {
- function _assert(msg, exp) {
- var layersIds = getLayerIds();
- var tracePrefix = 'plotly-trace-layer-' + gd._fullData[0].uid;
-
- expect(layersIds.indexOf(tracePrefix + '-fill')).toBe(exp.trace[0], msg + '| fill');
- expect(layersIds.indexOf(tracePrefix + '-line')).toBe(exp.trace[1], msg + '| line');
- expect(layersIds.indexOf(tracePrefix + '-circle')).toBe(exp.trace[2], msg + '| circle');
- expect(layersIds.indexOf(tracePrefix + '-symbol')).toBe(exp.trace[3], msg + '| symbol');
-
- var layoutLayerId = ['plotly-layout-layer', gd._fullLayout._uid, 'mapbox-0'].join('-');
- expect(layersIds.indexOf(layoutLayerId)).toBe(exp.layout, msg + '| layout layer');
- }
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- uid: 'a'
- }], {
- mapbox: {
- style: 'basic',
- layers: [{
- sourcetype: 'vector',
- source: 'mapbox://mapbox.mapbox-terrain-v2',
- sourcelayer: 'contour',
- type: 'line'
- }]
- }
- })
- .then(function() {
- _assert('default *below*', {
- trace: [20, 21, 22, 23],
- layout: 24
- });
- })
- .then(function() { return Plotly.relayout(gd, 'mapbox.layers[0].below', 'traces'); })
- .then(function() {
- _assert('with layout layer *below:traces*', {
- trace: [21, 22, 23, 24],
- layout: 20
- });
- })
- .then(function() { return Plotly.relayout(gd, 'mapbox.layers[0].below', null); })
- .then(function() {
- _assert('back to default *below* (1)', {
- trace: [20, 21, 22, 23],
- layout: 24
- });
- })
- .then(function() { return Plotly.restyle(gd, 'below', ''); })
- .then(function() {
- _assert('with trace *below:""*', {
- trace: [21, 22, 23, 24],
- layout: 20
- });
- })
- .then(function() { return Plotly.restyle(gd, 'below', null); })
- .then(function() {
- _assert('back to default *below* (2)', {
- trace: [20, 21, 22, 23],
- layout: 24
- });
- })
- .then(function() { return Plotly.restyle(gd, 'below', 'water'); })
- .then(function() {
- _assert('with trace *below:water*', {
- trace: [4, 5, 6, 7],
- layout: 24
- });
- })
- .then(function() { return Plotly.relayout(gd, 'mapbox.layers[0].below', 'water'); })
- .then(function() {
- _assert('with trace AND layout layer *below:water*', {
- trace: [4, 5, 6, 7],
- layout: 8
- });
- })
- .then(function() { return Plotly.relayout(gd, 'mapbox.layers[0].below', ''); })
- .then(function() {
- _assert('with trace *below:water* and layout layer *below:""*', {
- trace: [4, 5, 6, 7],
- layout: 24
- });
- })
- .then(function() { return Plotly.restyle(gd, 'below', ''); })
- .then(function() {
- _assert('with trace AND layout layer *below:water*', {
- trace: [20, 21, 22, 23],
- layout: 24
- });
- })
- .then(function() { return Plotly.update(gd, {below: null}, {'mapbox.layers[0].below': null}); })
- .then(function() {
- _assert('back to default *below* (3)', {
- trace: [20, 21, 22, 23],
- layout: 24
- });
- })
- .then(done, done.fail);
- }, 8 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
-
- it('@gl should be able to update *below* - scattermapbox + choroplethmapbox + densitymapbox case', function(done) {
- function _assert(msg, exp) {
- var layersIds = getLayerIds();
- var tracePrefix = 'plotly-trace-layer-';
-
- var scatterPrefix = tracePrefix + 'scatter';
- expect(layersIds.indexOf(scatterPrefix + '-fill')).toBe(exp.scatter[0], msg + '| scatter fill');
- expect(layersIds.indexOf(scatterPrefix + '-line')).toBe(exp.scatter[1], msg + '| scatter line');
- expect(layersIds.indexOf(scatterPrefix + '-circle')).toBe(exp.scatter[2], msg + '| scatter circle');
- expect(layersIds.indexOf(scatterPrefix + '-symbol')).toBe(exp.scatter[3], msg + '| scatter symbol');
-
- var densityPrefix = tracePrefix + 'density';
- expect(layersIds.indexOf(densityPrefix + '-heatmap')).toBe(exp.density[0], msg + '| density heatmap');
-
- var choroplethPrefix = tracePrefix + 'choropleth';
- expect(layersIds.indexOf(choroplethPrefix + '-fill')).toBe(exp.choropleth[0], msg + '| choropleth fill');
- expect(layersIds.indexOf(choroplethPrefix + '-line')).toBe(exp.choropleth[1], msg + '| choropleth line');
- }
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- uid: 'scatter'
- }, {
- type: 'densitymapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- z: [1, 20, 5],
- uid: 'density'
- }, {
- type: 'choroplethmapbox',
- geojson: 'https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/us-states.json',
- locations: ['AL'],
- z: [10],
- uid: 'choropleth'
- }], {
- mapbox: {style: 'basic'}
- })
- .then(function() {
- _assert('base', {
- scatter: [23, 24, 25, 26],
- density: [17],
- choropleth: [5, 6]
- });
- })
- .then(function() { return Plotly.restyle(gd, 'below', ''); })
- .then(function() {
- _assert('all traces *below:""', {
- scatter: [23, 24, 25, 26],
- density: [22],
- choropleth: [20, 21]
- });
- })
- .then(function() { return Plotly.restyle(gd, 'below', null); })
- .then(function() {
- _assert('back to base', {
- scatter: [23, 24, 25, 26],
- density: [17],
- choropleth: [5, 6]
- });
- })
- .then(done, done.fail);
- }, 8 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
-
- it('@gl should be warn when *below* value does not correspond to a layer on the map', function(done) {
- spyOn(Lib, 'warn');
-
- var notGonnaWork = 'not-gonna-work';
- var arg = [
- 'Trying to add layer with *below* value',
- notGonnaWork,
- 'referencing a layer that does not exist',
- 'or that does not yet exist.'
- ].join(' ');
-
- function _assertFallback(msg, exp) {
- var allArgs = Lib.warn.calls.allArgs();
-
- if(allArgs.length === exp.warnCnt) {
- for(var i = 0; i < exp.warnCnt; i++) {
- expect(allArgs[i][0]).toBe(arg, 'Lib.warn call #' + i);
- }
- } else {
- fail('Incorrect number of Lib.warn calls');
- }
- Lib.warn.calls.reset();
-
- getLayerIds().slice(20, -1).forEach(function(id) {
- expect(id.indexOf('plotly-')).toBe(0, 'layer ' + id + ' fallback to top of map');
- });
- }
-
- Plotly.newPlot(gd, [{
- type: 'scattermapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35]
- }, {
- type: 'densitymapbox',
- lon: [10, 20, 30],
- lat: [15, 25, 35],
- z: [1, 20, 5]
- }, {
- type: 'choroplethmapbox',
- geojson: 'https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/us-states.json',
- locations: ['AL'],
- z: [10]
- }], {
- mapbox: {
- style: 'basic',
- layers: [{
- sourcetype: 'vector',
- source: 'mapbox://mapbox.mapbox-terrain-v2',
- sourcelayer: 'contour',
- type: 'line'
- }]
- }
- })
- .then(function() {
- expect(Lib.warn).toHaveBeenCalledTimes(0);
- })
- .then(function() { return Plotly.restyle(gd, 'below', notGonnaWork); })
- .then(function() {
- // 7 for 4 scattermapbox + 2 choroplethmapbox + 1 densitymapbox layer
- _assertFallback('not-gonna-work for traces', {warnCnt: 7});
- })
- .then(function() { return Plotly.relayout(gd, 'mapbox.layers[0].below', 'not-gonna-work'); })
- .then(function() {
- // same as last but + layout layer
- _assertFallback('not-gonna-work for traces', {warnCnt: 8});
- })
- .then(function() { return Plotly.update(gd, {below: null}, {'mapbox.layers[0].below': null}); })
- .then(function() {
- expect(Lib.warn).toHaveBeenCalledTimes(0);
- })
- .then(done, done.fail);
- }, 8 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
-});
-
-describe('Test mapbox GeoJSON fetching:', function() {
- var gd;
-
- beforeEach(function() {
- gd = createGraphDiv();
- });
-
- afterEach(function(done) {
- Plotly.purge(gd);
- destroyGraphDiv();
- setTimeout(done, 200);
- });
-
- it('@gl should fetch GeoJSON using URLs found in the traces', function(done) {
- var url = 'https://raw.githubusercontent.com/plotly/datasets/master/florida-red-data.json';
- var url2 = 'https://raw.githubusercontent.com/plotly/datasets/master/florida-blue-data.json';
- var cnt = 0;
-
- Plotly.newPlot(gd, [{
- type: 'choroplethmapbox',
- locations: ['a'],
- z: [1],
- geojson: url
- }, {
- type: 'choroplethmapbox',
- locations: ['a'],
- z: [1],
- geojson: url2
- }])
- .catch(function() {
- cnt++;
- })
- .then(function() {
- expect(cnt).toBe(0, 'no failures!');
- expect(Lib.isPlainObject(window.PlotlyGeoAssets[url])).toBe(true, 'is a GeoJSON object');
- expect(Lib.isPlainObject(window.PlotlyGeoAssets[url2])).toBe(true, 'is a GeoJSON object');
- })
- .then(done, done.fail);
- });
-
- it('@gl should fetch GeoJSON using URLs found in the traces', function(done) {
- var actual = '';
-
- Plotly.newPlot(gd, [{
- type: 'choroplethmapbox',
- locations: ['a'],
- z: [1],
- geojson: 'invalidUrl'
- }, {
- type: 'choroplethmapbox',
- locations: ['a'],
- z: [1],
- geojson: 'invalidUrl-two'
- }])
- .catch(function(reason) {
- // bails up after first failure
- actual = reason;
- })
- .then(function() {
- expect(actual).toEqual(new Error('GeoJSON at URL "invalidUrl" does not exist.'));
- expect(window.PlotlyGeoAssets.invalidUrl).toBe(undefined);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-});
-
-describe('mapbox toImage', function() {
- // decreased from 1e5 - perhaps chrome got better at encoding these
- // because I get 99330 and the image still looks correct
- var MINIMUM_LENGTH = 7e4;
-
- var gd;
-
- beforeEach(function() {
- gd = createGraphDiv();
- });
-
- afterEach(function() {
- Plotly.purge(gd);
- Plotly.setPlotConfig({ mapboxAccessToken: null });
- destroyGraphDiv();
- });
-
- it('@gl 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);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl 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);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
- it('@gl 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);
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-});
-
-function getMapInfo(gd) {
- var subplot = gd._fullLayout.mapbox._subplot;
- var map = subplot.map;
-
- var sources = map.style.sourceCaches;
- var layers = map.style._layers;
- var uid = subplot.uid;
-
- var traceSources = Object.keys(sources).filter(function(k) {
- return k.indexOf('source-') === 0;
- });
-
- var traceLayers = Object.keys(layers).filter(function(k) {
- return k.indexOf('plotly-trace-layer-') === 0;
- });
-
- var layoutSources = Object.keys(sources).filter(function(k) {
- return k.indexOf(uid) !== -1;
- });
-
- var layoutLayers = Object.keys(layers).filter(function(k) {
- return k.indexOf(uid) !== -1;
- });
-
- return {
- map: map,
- div: subplot.div,
- sources: sources,
- layers: layers,
- traceSources: traceSources,
- traceLayers: traceLayers,
- layoutSources: layoutSources,
- layoutLayers: layoutLayers,
- center: map.getCenter(),
- zoom: map.getZoom(),
- style: map.getStyle()
- };
-}
diff --git a/test/jasmine/tests/plot_api_react_test.js b/test/jasmine/tests/plot_api_react_test.js
index e858a52e8ad..657127d6734 100644
--- a/test/jasmine/tests/plot_api_react_test.js
+++ b/test/jasmine/tests/plot_api_react_test.js
@@ -876,15 +876,6 @@ describe('@noCIdep Plotly.react', function() {
});
});
- mockLists.mapbox.forEach(function(mockSpec) {
- it('@noCI @gl can redraw "' + mockSpec[0] + '" with no changes as a noop (mapbox mocks)', function(done) {
- Plotly.setPlotConfig({
- mapboxAccessToken: MAPBOX_ACCESS_TOKEN
- });
- _runReactMock(mockSpec, done);
- });
- });
-
mockLists.map.forEach(function(mockSpec) {
it('@noCI @gl can redraw "' + mockSpec[0] + '" with no changes as a noop (map mocks)', function(done) {
Plotly.setPlotConfig({});
diff --git a/test/jasmine/tests/scattermapbox_test.js b/test/jasmine/tests/scattermapbox_test.js
deleted file mode 100644
index aa07efcd5c8..00000000000
--- a/test/jasmine/tests/scattermapbox_test.js
+++ /dev/null
@@ -1,1299 +0,0 @@
-var Plotly = require('../../../lib/index');
-var Plots = require('../../../src/plots/plots');
-var Lib = require('../../../src/lib');
-var Axes = require('../../../src/plots/cartesian/axes');
-
-var ScatterMapbox = require('../../../src/traces/scattermapbox');
-var convert = require('../../../src/traces/scattermapbox/convert');
-
-var createGraphDiv = require('../assets/create_graph_div');
-var destroyGraphDiv = require('../assets/destroy_graph_div');
-
-var supplyAllDefaults = require('../assets/supply_defaults');
-
-var assertHoverLabelContent = require('../assets/custom_assertions').assertHoverLabelContent;
-var mouseEvent = require('../assets/mouse_event');
-var click = require('../assets/click');
-var HOVERMINTIME = require('../../../src/components/fx').constants.HOVERMINTIME;
-
-function move(fromX, fromY, toX, toY, delay) {
- return new Promise(function(resolve) {
- mouseEvent('mousemove', fromX, fromY);
-
- setTimeout(function() {
- mouseEvent('mousemove', toX, toY);
- resolve();
- }, delay || HOVERMINTIME + 10);
- });
-}
-
-describe('scattermapbox defaults', function() {
- 'use strict';
-
- function _supply(traceIn) {
- var traceOut = { visible: true };
- var defaultColor = '#444';
- var layout = { _dataLength: 1 };
-
- ScatterMapbox.supplyDefaults(traceIn, traceOut, defaultColor, layout);
-
- return traceOut;
- }
-
- it('should not truncate \'lon\' if longer than \'lat\'', function() {
- // this is handled at the calc step now via _length.
- var fullTrace = _supply({
- lon: [1, 2, 3],
- lat: [2, 3]
- });
-
- expect(fullTrace.lon).toEqual([1, 2, 3]);
- expect(fullTrace.lat).toEqual([2, 3]);
- expect(fullTrace._length).toBe(2);
- });
-
- it('should not truncate \'lat\' if longer than \'lon\'', function() {
- // this is handled at the calc step now via _length.
- var fullTrace = _supply({
- lon: [1, 2, 3],
- lat: [2, 3, 3, 5]
- });
-
- expect(fullTrace.lon).toEqual([1, 2, 3]);
- expect(fullTrace.lat).toEqual([2, 3, 3, 5]);
- expect(fullTrace._length).toBe(3);
- });
-
- it('should set \'visible\' to false if \'lat\' and/or \'lon\' has zero length', function() {
- var fullTrace = _supply({
- lon: [1, 2, 3],
- lat: []
- });
-
- expect(fullTrace.visible).toEqual(false);
-
- fullTrace = _supply({
- lon: null,
- lat: [1, 2, 3]
- });
-
- expect(fullTrace.visible).toEqual(false);
- });
-
- it('should set \'marker.color\' and \'marker.size\' to first item if symbol is set to \'circle\'', function() {
- var base = {
- mode: 'markers',
- lon: [1, 2, 3],
- lat: [2, 3, 3],
- marker: {
- color: ['red', 'green', 'blue'],
- size: [10, 20, 30]
- }
- };
-
- var fullTrace = _supply(Lib.extendDeep({}, base, {
- marker: { symbol: 'monument' }
- }));
-
- expect(fullTrace.marker.color).toEqual('red');
- expect(fullTrace.marker.size).toEqual(10);
-
- fullTrace = _supply(Lib.extendDeep({}, base, {
- marker: { symbol: ['monument', 'music', 'harbor'] }
- }));
-
- expect(fullTrace.marker.color).toEqual('red');
- expect(fullTrace.marker.size).toEqual(10);
-
- fullTrace = _supply(Lib.extendDeep({}, base, {
- marker: { symbol: 'circle' }
- }));
-
- expect(fullTrace.marker.color).toEqual(['red', 'green', 'blue']);
- expect(fullTrace.marker.size).toEqual([10, 20, 30]);
- });
-
- it('should not fill *marker.line* in fullData while is not available', function() {
- var fullTrace = _supply({
- mode: 'markers',
- lon: [10, 20, 30],
- lat: [10, 20, 30]
- });
-
- expect(fullTrace.marker).toBeDefined();
- expect(fullTrace.marker.line).toBeUndefined();
- });
-});
-
-describe('scattermapbox convert', function() {
- var base = {
- type: 'scattermapbox',
- lon: [10, '20', 30, 20, null, 20, 10],
- lat: [20, 20, '10', null, 10, 10, 20]
- };
-
- function _convert(trace) {
- var gd = { data: [trace] };
- supplyAllDefaults(gd);
-
- var fullTrace = gd._fullData[0];
- Plots.doCalcdata(gd, fullTrace);
-
- var calcTrace = gd.calcdata[0];
-
- var mockAxis = {type: 'linear'};
- Axes.setConvert(mockAxis, gd._fullLayout);
-
- gd._fullLayout.mapbox._subplot = {
- mockAxis: mockAxis
- };
-
- return convert(gd, calcTrace);
- }
-
- function assertVisibility(opts, expectations) {
- var actual = ['fill', 'line', 'circle', 'symbol'].map(function(l) {
- return opts[l].layout.visibility;
- });
-
- expect(actual).toEqual(expectations, 'layer visibility');
- }
-
- it('should generate correct output for markers + circle bubbles traces', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'markers',
- marker: {
- symbol: 'circle',
- size: [10, 20, null, 10, '10'],
- color: [10, null, '30', 20, 10]
- }
- }));
-
- assertVisibility(opts, ['none', 'none', 'visible', 'none']);
-
- expect(opts.circle.paint['circle-color']).toEqual({
- property: 'mcc',
- type: 'identity'
- }, 'circle-color paint');
-
- expect(opts.circle.paint['circle-radius']).toEqual({
- property: 'mrc',
- type: 'identity'
- }, 'circle-radius paint');
-
- expect(opts.circle.paint['circle-opacity']).toBe(0.7, 'circle-opacity');
-
- var circleProps = opts.circle.geojson.features.map(function(f) {
- return f.properties;
- });
-
- // N.B repeated values have same geojson props
- expect(circleProps).toEqual([
- { mcc: 'rgb(220, 220, 220)', mrc: 5 },
- { mcc: '#444', mrc: 10 },
- { mcc: 'rgb(178, 10, 28)', mrc: 0 },
- { mcc: '#444', mrc: 0 },
- { mcc: '#444', mrc: 0 }
- ], 'geojson feature properties');
- });
-
- it('should fill circle-opacity correctly', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'markers',
- marker: {
- symbol: 'circle',
- size: 10,
- color: 'red',
- opacity: [1, null, 0.5, '0.5', '1', 0, 0.8]
- },
- opacity: 0.5
- }));
-
- assertVisibility(opts, ['none', 'none', 'visible', 'none']);
- expect(opts.circle.paint['circle-color']).toBe('red', 'circle-color');
- expect(opts.circle.paint['circle-radius']).toBe(5, 'circle-radius');
-
- expect(opts.circle.paint['circle-opacity']).toEqual({
- property: 'mo',
- type: 'identity'
- }, 'circle-opacity paint');
-
- var circleProps = opts.circle.geojson.features.map(function(f) {
- return f.properties;
- });
-
- expect(circleProps).toEqual([
- { mo: 0.5 },
- { mo: 0 },
- { mo: 0.25 },
- // lat === null
- // lon === null
- { mo: 0 },
- { mo: 0.4 },
- ], 'geojson feature properties');
- });
-
- it('should fill circle props correctly during selections', function() {
- var _base = {
- type: 'scattermapbox',
- mode: 'markers',
- lon: [-10, 30, 20],
- lat: [45, 90, 180],
- marker: {symbol: 'circle'}
- };
-
- var specs = [{
- msg: 'base case',
- patch: {
- selectedpoints: [1, 2]
- },
- expected: {
- opacity: [0.2, 1, 1]
- }
- }, {
- msg: 'with set trace opacity',
- patch: {
- opacity: 0.5,
- selectedpoints: [1, 2]
- },
- expected: {
- opacity: [0.1, 0.5, 0.5]
- }
- }, {
- msg: 'with set scalar marker.opacity',
- patch: {
- marker: {opacity: 0.6},
- selectedpoints: [1, 2]
- },
- expected: {
- opacity: [0.12, 0.6, 0.6]
- }
- }, {
- msg: 'width set array marker.opacity',
- patch: {
- marker: {
- opacity: [0.5, 1, 0.6],
- },
- selectedpoints: [0, 2]
- },
- expected: {
- opacity: [0.5, 0.2, 0.6]
- }
- }, {
- msg: 'with set array marker.opacity including invalid items',
- patch: {
- marker: {opacity: [2, null, -0.6]},
- selectedpoints: [0, 1, 2]
- },
- expected: {
- opacity: [1, 0, 0]
- }
- }, {
- msg: 'with set selected & unselected styles',
- patch: {
- selected: {
- marker: {
- opacity: 1,
- color: 'green',
- size: 20
- }
- },
- unselected: {
- marker: {
- opacity: 0,
- color: 'red',
- size: 5
- }
- },
- selectedpoints: [0, 2]
- },
- expected: {
- opacity: [1, 0, 1],
- color: ['green', 'red', 'green'],
- size: [10, 2.5, 10]
- }
- }, {
- msg: 'with set selected styles only',
- patch: {
- selected: {
- marker: {
- opacity: 1,
- color: 'green',
- size: 20
- }
- },
- selectedpoints: [0, 2]
- },
- expected: {
- opacity: [1, 0.2, 1],
- color: ['green', '#1f77b4', 'green'],
- size: [10, 3, 10]
- }
- }, {
- msg: 'with set selected styles only + array items',
- patch: {
- marker: {
- opacity: [0.5, 0.6, 0.7],
- color: ['blue', 'yellow', 'cyan'],
- size: [50, 60, 70]
- },
- selected: {
- marker: {
- opacity: 1,
- color: 'green',
- size: 20
- }
- },
- selectedpoints: [0, 2]
- },
- expected: {
- opacity: [1, 0.12, 1],
- color: ['green', 'yellow', 'green'],
- size: [10, 30, 10]
- }
- }, {
- msg: 'with set unselected styles only',
- patch: {
- unselected: {
- marker: {
- opacity: 0,
- color: 'red',
- size: 5
- }
- },
- selectedpoints: [0, 2]
- },
- expected: {
- opacity: [1, 0, 1],
- color: ['#1f77b4', 'red', '#1f77b4'],
- size: [3, 2.5, 3]
-
- }
- }, {
- msg: 'with set unselected styles only + array items',
- patch: {
- marker: {
- opacity: [0.5, 0.6, 0.7],
- color: ['blue', 'yellow', 'cyan'],
- size: [50, 60, 70]
- },
- unselected: {
- marker: {
- opacity: 0,
- color: 'red',
- size: 5
- }
- },
- selectedpoints: [0, 2]
- },
- expected: {
- opacity: [0.5, 0, 0.7],
- color: ['blue', 'red', 'cyan'],
- size: [25, 2.5, 35]
- }
- }];
-
- specs.forEach(function(s, i) {
- var msg0 = s.msg + ' - case ' + i + '- ';
- var opts = _convert(Lib.extendDeep({}, _base, s.patch));
- var features = opts.circle.geojson.features;
-
- function _assert(kProp, kExp) {
- var actual = features.map(function(f) { return f.properties[kProp]; });
- var expected = s.expected[kExp];
- var msg = msg0 + ' marker.' + kExp;
-
- if(Array.isArray(expected)) {
- expect(actual).toEqual(expected, msg);
- } else {
- actual.forEach(function(a) {
- expect(a).toBe(undefined, msg);
- });
- }
- }
-
- _assert('mo', 'opacity');
- _assert('mcc', 'color');
- // N.B. sizes in props should be half of the input values
- _assert('mrc', 'size');
- });
- });
-
- it('should generate correct output for fill + markers + lines traces', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'markers+lines',
- marker: { symbol: 'circle' },
- fill: 'toself'
- }));
-
- assertVisibility(opts, ['visible', 'visible', 'visible', 'none']);
-
- var segment1 = [[10, 20], [20, 20], [30, 10]];
- var segment2 = [[20, 10], [10, 20]];
-
- var lineCoords = [segment1, segment2];
- var fillCoords = [[segment1], [segment2]];
-
- expect(opts.line.geojson.coordinates).toEqual(lineCoords, 'line coords');
- expect(opts.fill.geojson.coordinates).toEqual(fillCoords, 'fill coords');
-
- var circleCoords = opts.circle.geojson.features.map(function(f) {
- return f.geometry.coordinates;
- });
-
- expect(circleCoords).toEqual([
- [10, 20], [20, 20], [30, 10], [20, 10], [10, 20]
- ], 'circle coords');
- });
-
- it('should generate correct output for markers + non-circle traces', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'markers',
- marker: { symbol: 'monument' }
- }));
-
- assertVisibility(opts, ['none', 'none', 'none', 'visible']);
-
- var symbolProps = opts.symbol.geojson.features.map(function(f) {
- return [f.properties.symbol, f.properties.text];
- });
-
- var expected = opts.symbol.geojson.features.map(function() {
- return ['monument', ''];
- });
-
- expect(symbolProps).toEqual(expected, 'geojson properties');
- });
-
-
- it('should allow symbols to be rotated and overlapped', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'markers',
- marker: {
- symbol: ['monument', 'music', 'harbor'],
- angle: [0, 90, 45],
- allowoverlap: true
- },
- }));
-
- var symbolAngle = opts.symbol.geojson.features.map(function(f) {
- return f.properties.angle;
- });
-
- var expected = [0, 90, 45, 0, 0];
- expect(symbolAngle).toEqual(expected, 'geojson properties');
-
-
- expect(opts.symbol.layout['icon-rotate'].property).toEqual('angle', 'symbol.layout.icon-rotate');
- expect(opts.symbol.layout['icon-allow-overlap']).toEqual(true, 'symbol.layout.icon-allow-overlap');
- });
-
-
- it('should generate correct output for text + lines traces', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'lines+text',
- connectgaps: true,
- text: ['A', 'B', 'C', 'D', 'E', 'F']
- }));
-
- assertVisibility(opts, ['none', 'visible', 'none', 'visible']);
-
- var lineCoords = [
- [10, 20], [20, 20], [30, 10], [20, 10], [10, 20]
- ];
-
- expect(opts.line.geojson.coordinates).toEqual(lineCoords, 'line coords');
-
- var actualText = opts.symbol.geojson.features.map(function(f) {
- return f.properties.text;
- });
-
- expect(actualText).toEqual(['A', 'B', 'C', 'F', undefined]);
- });
-
- it('should generate correct output for texttemplate without text', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'lines+text',
- connectgaps: true,
- textposition: 'outside',
- texttemplate: ['A', 'B', 'C', 'D', 'E', 'F']
- }));
-
- var actualText = opts.symbol.geojson.features.map(function(f) {
- return f.properties.text;
- });
-
- expect(actualText).toEqual(['A', 'B', 'C', 'F', '']);
- });
-
- it('should convert \\n to \'\' and
to \\n', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'text',
- text: ['one\nline', 'two
lines', 'three
lines
yep']
- }));
-
- var actualText = opts.symbol.geojson.features.map(function(f) {
- return f.properties.text;
- });
-
- expect(actualText).toEqual(['oneline', 'two\nlines', 'three\nlines\nyep', undefined, undefined]);
- });
-
- it('should convert \\n to \'\' and
to \\n - texttemplate case', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'text',
- texttemplate: ['%{lon}\none\nline', '%{lat}
two
lines', '%{lon}\n%{lat}
more
lines']
- }));
-
- var actualText = opts.symbol.geojson.features.map(function(f) {
- return f.properties.text;
- });
-
- expect(actualText).toEqual(['10oneline', '20\ntwo\nlines', '3010\nmore\nlines', '', '']);
- });
-
- it('should generate correct output for texttemplate', function() {
- var mock = {
- type: 'scattermapbox',
- mode: 'markers+text',
- lon: [-73.57, -79.24, -123.06],
- lat: [45.5, 43.4, 49.13],
- text: ['Montreal', 'Toronto', 'Vancouver'],
- texttemplate: '%{text} (%{lon}, %{lat}): %{customdata:.2s}',
- textposition: 'top center',
- customdata: [1780000, 2930000, 675218]
- };
- var opts = _convert(mock);
- var actualText = opts.symbol.geojson.features.map(function(f) {
- return f.properties.text;
- });
-
- expect(actualText).toEqual([
- 'Montreal (−73.57, 45.5): 1.8M',
- 'Toronto (−79.24, 43.4): 2.9M',
- 'Vancouver (−123.06, 49.13): 680k'
- ]);
- });
-
- it('should generate correct output for lines traces with trailing gaps', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'lines',
- lon: [10, '20', 30, 20, null, 20, 10, null, null],
- lat: [20, 20, '10', null, 10, 10, 20, null]
- }));
-
- assertVisibility(opts, ['none', 'visible', 'none', 'none']);
-
- var lineCoords = [
- [[10, 20], [20, 20], [30, 10]],
- [[20, 10], [10, 20]]
- ];
-
- expect(opts.line.geojson.coordinates).toEqual(lineCoords, 'have correct line coords');
- });
-
- it('should correctly convert \'textposition\' to \'text-anchor\' and \'text-offset\'', function() {
- var specs = {
- 'top left': ['top-right', [-0.65, -1.65]],
- 'top center': ['top', [0, -1.65]],
- 'top right': ['top-left', [0.65, -1.65]],
- 'middle left': ['right', [-0.65, 0]],
- 'middle center': ['center', [0, 0]],
- 'middle right': ['left', [0.65, 0]],
- 'bottom left': ['bottom-right', [-0.65, 1.65]],
- 'bottom center': ['bottom', [0, 1.65]],
- 'bottom right': ['bottom-left', [0.65, 1.65]]
- };
-
- Object.keys(specs).forEach(function(k) {
- var spec = specs[k];
-
- var opts = _convert(Lib.extendFlat({}, base, {
- textposition: k,
- mode: 'text+markers',
- marker: { size: 15 },
- text: ['A', 'B', 'C']
- }));
-
- expect([
- opts.symbol.layout['text-anchor'],
- opts.symbol.layout['text-offset']
- ]).toEqual(spec, '(case ' + k + ')');
- });
- });
-
- it('should generate correct output for markers + circle bubbles traces with repeated values', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- lon: ['-96.796988', '-81.379236', '-85.311819', ''],
- lat: ['32.776664', '28.538335', '35.047157', '' ],
- marker: { size: ['5', '49', '5', ''] }
- }));
-
- expect(opts.circle.paint['circle-radius']).toEqual({
- property: 'mrc',
- type: 'identity'
- }, 'circle-radius paint');
-
- var radii = opts.circle.geojson.features.map(function(f) {
- return f.properties.mrc;
- });
-
- expect(radii).toBeCloseToArray([2.5, 24.5, 2.5], 'circle radii');
- });
-
- it('should generate correct output for traces with only blank points', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- mode: 'lines',
- lon: ['', null],
- lat: [null, ''],
- fill: 'toself'
- }));
-
- // not optimal, but doesn't break anything as mapbox-gl accepts empty
- // coordinate arrays
- assertVisibility(opts, ['visible', 'visible', 'none', 'none']);
-
- expect(opts.line.geojson.coordinates).toEqual([], 'line coords');
- expect(opts.fill.geojson.coordinates).toEqual([], 'fill coords');
- });
-
- it('cluster options', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- cluster: {
- enabled: true
- }
- }));
-
- // Ensure that cluster and clusterCount options is added to options
- expect(opts.cluster).toBeInstanceOf(Object);
- expect(opts.clusterCount).toBeInstanceOf(Object);
-
- // Ensure correct type of layers
- expect(opts.cluster.type).toEqual('circle');
- expect(opts.clusterCount.type).toEqual('symbol');
- });
-
- it('cluster colors, sizes, opacities - array', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- cluster: {
- enabled: true,
- color: 'red',
- size: 20,
- opacity: 0.25
- }
- }));
-
- expect(opts.cluster.paint['circle-color']).toEqual('red');
- expect(opts.cluster.paint['circle-radius']).toEqual(20);
- expect(opts.cluster.paint['circle-opacity']).toEqual(0.25);
- });
-
- it('cluster colors, sizes, opacities - array', function() {
- var opts = _convert(Lib.extendFlat({}, base, {
- cluster: {
- enabled: true,
- step: [10],
- color: ['red', 'green'],
- size: [20, 40],
- opacity: [0.25, 0.75]
- }
- }));
-
- expect(opts.cluster.paint['circle-color']).toEqual(['step', ['get', 'point_count'], 'red', 10, 'green']);
- expect(opts.cluster.paint['circle-radius']).toEqual(['step', ['get', 'point_count'], 20, 10, 40]);
- expect(opts.cluster.paint['circle-opacity']).toEqual(['step', ['get', 'point_count'], 0.25, 10, 0.75]);
- });
-});
-
-describe('scattermapbox hover', function() {
- var hoverPoints = ScatterMapbox.hoverPoints;
- var gd;
-
- beforeAll(function(done) {
- Plotly.setPlotConfig({
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- });
-
- gd = createGraphDiv();
-
- var data = [{
- type: 'scattermapbox',
- lon: [10, 20, 30, 300],
- lat: [10, 20, 30, 10],
- text: ['A', 'B', 'C', 'D']
- }];
-
- Plotly.newPlot(gd, data, { autosize: true }).then(done);
- });
-
- afterAll(function() {
- Plotly.purge(gd);
- destroyGraphDiv();
- });
-
- function getPointData(gd) {
- var cd = gd.calcdata;
- var subplot = gd._fullLayout.mapbox._subplot;
-
- return {
- index: false,
- distance: 20,
- cd: cd[0],
- trace: cd[0][0].trace,
- subplot: subplot,
- xa: subplot.xaxis,
- ya: subplot.yaxis
- };
- }
-
- function checkHoverLabel(pos, content) {
- mouseEvent('mousemove', pos[0], pos[1]);
-
- assertHoverLabelContent({
- nums: content[0],
- name: content[1]
- });
- }
-
- it('@gl should generate hover label info (base case)', function() {
- var xval = 11;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.index).toEqual(0);
- expect([out.x0, out.x1, out.y0, out.y1]).toBeCloseToArray([
- 297.444, 299.444, 105.410, 107.410
- ]);
- expect(out.extraText).toEqual('(10°, 10°)
A');
- expect(out.color).toEqual('#1f77b4');
- });
-
- it('@gl should generate hover label info (lon > 180 case)', function() {
- var xval = 301;
- var yval = 11;
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.index).toEqual(3);
- expect([out.x0, out.x1, out.y0, out.y1]).toBeCloseToArray([
- 1122.33, 1124.33, 105.41, 107.41
- ]);
- expect(out.extraText).toEqual('(10°, 300°)
D');
- expect(out.color).toEqual('#1f77b4');
- });
-
- it('@gl should skip over blank and non-string text items', function(done) {
- var xval = 11;
- var yval = 11;
- var out;
-
- Plotly.restyle(gd, 'text', [['', 'B', 'C']]).then(function() {
- out = hoverPoints(getPointData(gd), xval, yval)[0];
- expect(out.extraText).toEqual('(10°, 10°)');
-
- return Plotly.restyle(gd, 'text', [[null, 'B', 'C']]);
- })
- .then(function() {
- out = hoverPoints(getPointData(gd), xval, yval)[0];
- expect(out.extraText).toEqual('(10°, 10°)');
-
- return Plotly.restyle(gd, 'text', [[false, 'B', 'C']]);
- })
- .then(function() {
- out = hoverPoints(getPointData(gd), xval, yval)[0];
- expect(out.extraText).toEqual('(10°, 10°)');
-
- return Plotly.restyle(gd, 'text', [['A', 'B', 'C']]);
- })
- .then(function() {
- out = hoverPoints(getPointData(gd), xval, yval)[0];
- expect(out.extraText).toEqual('(10°, 10°)
A');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label info (positive winding case)', function() {
- var xval = 11 + 720;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.index).toEqual(0);
- expect([out.x0, out.x1, out.y0, out.y1]).toBeCloseToArray([
- 2345.444, 2347.444, 105.410, 107.410
- ]);
- expect(out.extraText).toEqual('(10°, 10°)
A');
- expect(out.color).toEqual('#1f77b4');
- });
-
- it('@gl should generate hover label info (negative winding case)', function() {
- var xval = 11 - 1080;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.index).toEqual(0);
- expect([out.x0, out.x1, out.y0, out.y1]).toBeCloseToArray([
- -2774.555, -2772.555, 105.410, 107.410
- ]);
- expect(out.extraText).toEqual('(10°, 10°)
A');
- expect(out.color).toEqual('#1f77b4');
- });
-
- it('@gl should generate hover label info (hoverinfo: \'lon\' case)', function(done) {
- Plotly.restyle(gd, 'hoverinfo', 'lon').then(function() {
- var xval = 11;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.extraText).toEqual('lon: 10°');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label info (hoverinfo: \'lat\' case)', function(done) {
- Plotly.restyle(gd, 'hoverinfo', 'lat').then(function() {
- var xval = 11;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.extraText).toEqual('lat: 10°');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label info (hoverinfo: \'text\' + \'text\' array case)', function(done) {
- Plotly.restyle(gd, 'hoverinfo', 'text').then(function() {
- var xval = 11;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.extraText).toEqual('A');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label info (hoverinfo: \'text\' + \'hovertext\' array case)', function(done) {
- Plotly.restyle(gd, 'hovertext', ['Apple', 'Banana', 'Orange']).then(function() {
- var xval = 11;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.extraText).toEqual('Apple');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label (\'marker.color\' array case)', function(done) {
- Plotly.restyle(gd, 'marker.color', [['red', 'blue', 'green']]).then(function() {
- var out = hoverPoints(getPointData(gd), 11, 11)[0];
-
- expect(out.color).toEqual('red');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label (\'marker.color\' w/ colorscale case)', function(done) {
- Plotly.restyle(gd, 'marker.color', [[10, 5, 30]]).then(function() {
- var out = hoverPoints(getPointData(gd), 11, 11)[0];
-
- expect(out.color).toEqual('rgb(245, 195, 157)');
- })
- .then(done, done.fail);
- });
-
- it('@gl should generate hover label (\'hoverinfo\' array case)', function(done) {
- function check(expected) {
- var out = hoverPoints(getPointData(gd), 11, 11)[0];
- expect(out.extraText).toEqual(expected);
- }
-
- Plotly.restyle(gd, 'hoverinfo', [['lon', 'lat', 'lon+lat+name']]).then(function() {
- check('lon: 10°');
- return Plotly.restyle(gd, 'hoverinfo', [['lat', 'lon', 'name']]);
- })
- .then(function() {
- check('lat: 10°');
- return Plotly.restyle(gd, 'hoverinfo', [['text', 'lon', 'name']]);
- })
- .then(function() {
- check('Apple');
- return Plotly.restyle(gd, 'hoverinfo', [[null, 'lon', 'name']]);
- })
- .then(function() {
- check('(10°, 10°)
Apple');
- })
- .then(done, done.fail);
- });
-
- it('@gl should pass along hovertemplate', function(done) {
- Plotly.restyle(gd, 'hovertemplate', 'tpl').then(function() {
- var xval = 11;
- var yval = 11;
-
- var out = hoverPoints(getPointData(gd), xval, yval)[0];
-
- expect(out.hovertemplate).toEqual('tpl');
- })
- .then(done, done.fail);
- });
-
- it('@gl should always display hoverlabel when hovertemplate is defined', function(done) {
- Plotly.restyle(gd, {
- name: '',
- hovertemplate: 'tpl2'
- })
- .then(function() {
- checkHoverLabel([190, 215], ['tpl2', '']);
- })
- .then(done, done.fail);
- });
-});
-
-describe('Test plotly events on a scattermapbox plot:', function() {
- var mock = require('../../image/mocks/mapbox_0.json');
- var pointPos = [440, 290];
- var nearPos = [460, 290];
- var blankPos = [10, 10];
- var mockCopy;
- var gd;
-
- beforeAll(function() {
- Plotly.setPlotConfig({
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- });
- });
-
- beforeEach(function(done) {
- gd = createGraphDiv();
- mockCopy = Lib.extendDeep({}, mock);
- mockCopy.layout.width = 800;
- mockCopy.layout.height = 500;
- Plotly.newPlot(gd, mockCopy).then(done);
- });
-
- afterEach(destroyGraphDiv);
-
- describe('click events', function() {
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_click', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should not be trigged when not on data points', function() {
- click(blankPos[0], blankPos[1]);
- expect(futureData).toBe(null);
- });
-
- it('@gl should contain the correct fields', function() {
- click(pointPos[0], pointPos[1]);
-
- var pt = futureData.points[0];
-
- expect(Object.keys(pt).sort()).toEqual([
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- ].sort());
-
- expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- expect(pt.lat).toEqual(10, 'points[0].lat');
- expect(pt.lon).toEqual(10, 'points[0].lon');
- expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
- });
- });
-
- describe('modified click events', function() {
- var clickOpts = {
- altKey: true,
- ctrlKey: true,
- metaKey: true,
- shiftKey: true
- };
-
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_click', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should not be trigged when not on data points', function() {
- click(blankPos[0], blankPos[1], clickOpts);
- expect(futureData).toBe(null);
- });
-
- it('@gl does not register right-clicks', function() {
- click(pointPos[0], pointPos[1], clickOpts);
- expect(futureData).toBe(null);
-
- // TODO: 'should contain the correct fields'
- // This test passed previously, but only because assets/click
- // incorrectly generated a click event for right click. It never
- // worked in reality.
- // var pt = futureData.points[0],
- // evt = futureData.event;
-
- // expect(Object.keys(pt).sort()).toEqual([
- // 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- // ].sort());
-
- // expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- // expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- // expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- // expect(pt.lat).toEqual(10, 'points[0].lat');
- // expect(pt.lon).toEqual(10, 'points[0].lon');
- // expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
-
- // Object.getOwnPropertyNames(clickOpts).forEach(function(opt) {
- // expect(evt[opt]).toEqual(clickOpts[opt], 'event.' + opt);
- // });
- });
- });
-
- describe('hover events', function() {
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_hover', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should contain the correct fields', function() {
- mouseEvent('mousemove', blankPos[0], blankPos[1]);
- mouseEvent('mousemove', pointPos[0], pointPos[1]);
-
- var pt = futureData.points[0];
-
- expect(Object.keys(pt).sort()).toEqual([
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- ].sort());
-
- expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- expect(pt.lat).toEqual(10, 'points[0].lat');
- expect(pt.lon).toEqual(10, 'points[0].lon');
- expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
- });
- });
-
- describe('unhover events', function() {
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_unhover', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should contain the correct fields', function(done) {
- move(pointPos[0], pointPos[1], nearPos[0], nearPos[1], HOVERMINTIME + 10).then(function() {
- var pt = futureData.points[0];
-
- expect(Object.keys(pt).sort()).toEqual([
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- ].sort());
-
- expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- expect(pt.lat).toEqual(10, 'points[0].lat');
- expect(pt.lon).toEqual(10, 'points[0].lon');
- expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
- })
- .then(done, done.fail);
- });
- });
-});
-
-describe('Test plotly events on a scattermapbox plot when css transform is present:', function() {
- var mock = require('../../image/mocks/mapbox_0.json');
- var pointPos = [440 / 2, 290 / 2];
- var nearPos = [460 / 2, 290 / 2];
- var blankPos = [10 / 2, 10 / 2];
- var mockCopy;
- var gd;
-
- function transformPlot(gd, transformString) {
- gd.style.webkitTransform = transformString;
- gd.style.MozTransform = transformString;
- gd.style.msTransform = transformString;
- gd.style.OTransform = transformString;
- gd.style.transform = transformString;
- }
-
- beforeAll(function() {
- Plotly.setPlotConfig({
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- });
- });
-
- beforeEach(function(done) {
- gd = createGraphDiv();
- mockCopy = Lib.extendDeep({}, mock);
- mockCopy.layout.width = 800;
- mockCopy.layout.height = 500;
-
- Plotly.newPlot(gd, mockCopy)
- .then(function() { transformPlot(gd, 'translate(-25%, -25%) scale(0.5)'); })
- .then(done);
- });
-
- afterEach(destroyGraphDiv);
-
- describe('click events', function() {
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_click', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should not be trigged when not on data points', function() {
- click(blankPos[0], blankPos[1]);
- expect(futureData).toBe(null);
- });
-
- it('@gl should contain the correct fields', function() {
- click(pointPos[0], pointPos[1]);
-
- var pt = futureData.points[0];
-
- expect(Object.keys(pt).sort()).toEqual([
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- ].sort());
-
- expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- expect(pt.lat).toEqual(10, 'points[0].lat');
- expect(pt.lon).toEqual(10, 'points[0].lon');
- expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
- });
- });
-
- describe('hover events', function() {
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_hover', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should contain the correct fields', function() {
- mouseEvent('mousemove', blankPos[0], blankPos[1]);
- mouseEvent('mousemove', pointPos[0], pointPos[1]);
-
- var pt = futureData.points[0];
-
- expect(Object.keys(pt).sort()).toEqual([
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- ].sort());
-
- expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- expect(pt.lat).toEqual(10, 'points[0].lat');
- expect(pt.lon).toEqual(10, 'points[0].lon');
- expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
- });
- });
-
- describe('unhover events', function() {
- var futureData;
-
- beforeEach(function() {
- futureData = null;
-
- gd.on('plotly_unhover', function(data) {
- futureData = data;
- });
- });
-
- it('@gl should contain the correct fields', function(done) {
- move(pointPos[0], pointPos[1], nearPos[0], nearPos[1], HOVERMINTIME + 10).then(function() {
- var pt = futureData.points[0];
-
- expect(Object.keys(pt).sort()).toEqual([
- 'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'lon', 'lat', 'bbox'
- ].sort());
-
- expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
- expect(typeof pt.data).toEqual(typeof {}, 'points[0].data');
- expect(typeof pt.fullData).toEqual(typeof {}, 'points[0].fullData');
- expect(pt.lat).toEqual(10, 'points[0].lat');
- expect(pt.lon).toEqual(10, 'points[0].lon');
- expect(pt.pointNumber).toEqual(0, 'points[0].pointNumber');
- })
- .then(done, done.fail);
- });
- });
-});
-
-describe('scattermapbox restyle', function() {
- var gd;
-
- beforeAll(function() {
- Plotly.setPlotConfig({
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- });
-
- gd = createGraphDiv();
- });
-
- afterAll(function() {
- Plotly.purge(gd);
- destroyGraphDiv();
- });
-
- it('@gl should be able to update legendonly to visible', function(done) {
- Plotly.newPlot(gd, {
- data: [{
- lat: [0, 2], lon: [0, 2],
- type: 'scattermapbox',
- mode: 'lines',
- visible: 'legendonly'
- },
- {
- lat: [0, 2], lon: [2, 0],
- type: 'scattermapbox',
- mode: 'lines',
- visible: true
- }
- ], layout: {
- mapbox: {
- style: 'open-street-map',
- zoom: 6,
- center: { lat: 1, lon: 1 }
- },
- showlegend: true
- }
- }).then(function() {
- return Plotly.restyle(gd, 'visible', true);
- }).then(done, done.fail);
- });
-});
diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js
index 3d345c63a3a..251737d9165 100644
--- a/test/jasmine/tests/select_test.js
+++ b/test/jasmine/tests/select_test.js
@@ -691,10 +691,8 @@ describe('Click-to-select', function() {
});
[
- testCase('scattermapbox', require('../../image/mocks/mapbox_0.json'), 650, 195, [[2], []], {},
- { mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN }),
- testCase('choroplethmapbox', require('../../image/mocks/mapbox_choropleth0.json'), 270, 220, [[0]], {},
- { mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN })
+ testCase('scattermap', require('../../image/mocks/map_0.json'), 650, 195, [[2], []], {}, {}),
+ testCase('choroplethmap', require('../../image/mocks/map_choropleth0.json'), 270, 220, [[0]], {}, {})
]
.forEach(function(testCase) {
it('@gl trace type ' + testCase.label, function(done) {
@@ -788,10 +786,8 @@ describe('Click-to-select', function() {
});
[
- testCase('mapbox', require('../../image/mocks/mapbox_0.json'), 650, 195, [[2], []], {},
- { mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN }),
- testCase('mapbox', require('../../image/mocks/mapbox_choropleth0.json'), 270, 220, [[0], []], {},
- { mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN })
+ testCase('scattermap', require('../../image/mocks/map_0.json'), 650, 195, [[2], []], {}, {}),
+ testCase('choroplethmap', require('../../image/mocks/map_choropleth0.json'), 270, 220, [[0], []], {}, {})
].forEach(function(testCase) {
it('@gl for base plot ' + testCase.label, function(done) {
_run(testCase, done);
@@ -2158,70 +2154,6 @@ describe('Test select box and lasso per trace:', function() {
});
});
- [false, true].forEach(function(hasCssTransform) {
- it('@gl should work on scattermapbox traces, hasCssTransform: ' + hasCssTransform, function(done) {
- var assertPoints = makeAssertPoints(['lon', 'lat']);
- var assertRanges = makeAssertRanges('mapbox');
- var assertLassoPoints = makeAssertLassoPoints('mapbox');
- var assertSelectedPoints = makeAssertSelectedPoints();
-
- var fig = Lib.extendDeep({}, require('../../image/mocks/mapbox_bubbles-text'));
-
- fig.data[0].lon.push(null);
- fig.data[0].lat.push(null);
-
- fig.layout.dragmode = 'select';
-
- delete fig.layout.mapbox.bounds;
-
- fig.config = {
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- };
- addInvisible(fig);
-
- _newPlot(gd, fig)
- .then(function() {
- if(hasCssTransform) transformPlot(gd, cssTransform);
-
- return _run(hasCssTransform,
- [[370, 120], [500, 200]],
- function() {
- assertPoints([[30, 30]]);
- assertRanges([[21.99, 34.55], [38.14, 25.98]]);
- assertSelectedPoints({0: [2]});
- },
- null, BOXEVENTS, 'scattermapbox select'
- );
- })
- .then(function() {
- return Plotly.relayout(gd, 'dragmode', 'lasso');
- })
- .then(function() {
- return _run(hasCssTransform,
- [[300, 200], [300, 300], [400, 300], [400, 200], [300, 200]],
- function() {
- assertPoints([[20, 20]]);
- assertSelectedPoints({0: [1]});
- assertLassoPoints([
- [13.28, 25.97], [13.28, 14.33], [25.71, 14.33], [25.71, 25.97], [13.28, 25.97]
- ]);
- },
- null, LASSOEVENTS, 'scattermapbox lasso'
- );
- })
- .then(function() {
- // make selection handlers don't get called in 'pan' dragmode
- return Plotly.relayout(gd, 'dragmode', 'pan');
- })
- .then(function() {
- return _run(hasCssTransform,
- [[370, 120], [500, 200]], null, null, NOEVENTS, 'scattermapbox pan'
- );
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
- });
-
[false, true].forEach(function(hasCssTransform) {
it('@gl should work on scattermap traces, hasCssTransform: ' + hasCssTransform, function(done) {
var assertPoints = makeAssertPoints(['lon', 'lat']);
@@ -2346,58 +2278,6 @@ describe('Test select box and lasso per trace:', function() {
}, LONG_TIMEOUT_INTERVAL);
});
- [false, true].forEach(function(hasCssTransform) {
- it('@gl should work on choroplethmapbox traces, hasCssTransform: ' + hasCssTransform, function(done) {
- var assertPoints = makeAssertPoints(['location', 'z']);
- var assertRanges = makeAssertRanges('mapbox');
- var assertLassoPoints = makeAssertLassoPoints('mapbox');
- var assertSelectedPoints = makeAssertSelectedPoints();
-
- var fig = Lib.extendDeep({}, require('../../image/mocks/mapbox_choropleth0.json'));
-
- fig.data[0].locations.push(null);
-
- fig.layout.dragmode = 'select';
- fig.config = {
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- };
- addInvisible(fig);
-
- _newPlot(gd, fig)
- .then(function() {
- if(hasCssTransform) transformPlot(gd, cssTransform);
-
- return _run(hasCssTransform,
- [[150, 150], [300, 300]],
- function() {
- assertPoints([['NY', 10]]);
- assertRanges([[-83.38, 46.13], [-74.06, 39.29]]);
- assertSelectedPoints({0: [0]});
- },
- null, BOXEVENTS, 'choroplethmapbox select'
- );
- })
- .then(function() {
- return Plotly.relayout(gd, 'dragmode', 'lasso');
- })
- .then(function() {
- return _run(hasCssTransform,
- [[300, 200], [300, 300], [400, 300], [400, 200], [300, 200]],
- function() {
- assertPoints([['MA', 20]]);
- assertSelectedPoints({0: [1]});
- assertLassoPoints([
- [-74.06, 43.936], [-74.06, 39.293], [-67.84, 39.293],
- [-67.84, 43.936], [-74.06, 43.936]
- ]);
- },
- null, LASSOEVENTS, 'choroplethmapbox lasso'
- );
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
- });
-
[false, true].forEach(function(hasCssTransform) {
it('@gl should work on choroplethmap traces, hasCssTransform: ' + hasCssTransform, function(done) {
var assertPoints = makeAssertPoints(['location', 'z']);
@@ -3468,67 +3348,6 @@ describe('Test select box and lasso per trace:', function() {
});
});
- it('@gl should work on choroplethmapbox traces after adding a new trace on top:', function(done) {
- var assertPoints = makeAssertPoints(['location', 'z']);
- var assertRanges = makeAssertRanges('mapbox');
- var assertLassoPoints = makeAssertLassoPoints('mapbox');
- var assertSelectedPoints = makeAssertSelectedPoints();
-
- var fig = Lib.extendDeep({}, require('../../image/mocks/mapbox_choropleth0.json'));
-
- fig.data[0].locations.push(null);
-
- fig.layout.dragmode = 'select';
- fig.config = {
- mapboxAccessToken: require('../../../build/credentials.json').MAPBOX_ACCESS_TOKEN
- };
- addInvisible(fig);
-
- var hasCssTransform = false;
-
- _newPlot(gd, fig)
- .then(function() {
- // add a scatter points on top
- fig.data[3] = {
- type: 'scattermapbox',
- marker: { size: 40 },
- lon: [-70],
- lat: [40]
- };
-
- return Plotly.react(gd, fig);
- })
- .then(function() {
- return _run(hasCssTransform,
- [[150, 150], [300, 300]],
- function() {
- assertPoints([['NY', 10]]);
- assertRanges([[-83.38, 46.13], [-74.06, 39.29]]);
- assertSelectedPoints({0: [0], 3: []});
- },
- null, BOXEVENTS, 'choroplethmapbox select'
- );
- })
- .then(function() {
- return Plotly.relayout(gd, 'dragmode', 'lasso');
- })
- .then(function() {
- return _run(hasCssTransform,
- [[300, 200], [300, 300], [400, 300], [400, 200], [300, 200]],
- function() {
- assertPoints([['MA', 20], []]);
- assertSelectedPoints({0: [1], 3: [0]});
- assertLassoPoints([
- [-74.06, 43.936], [-74.06, 39.293], [-67.84, 39.293],
- [-67.84, 43.936], [-74.06, 43.936]
- ]);
- },
- null, LASSOEVENTS, 'choroplethmapbox lasso'
- );
- })
- .then(done, done.fail);
- }, LONG_TIMEOUT_INTERVAL);
-
it('@gl should work on choroplethmap traces after adding a new trace on top:', function(done) {
var assertPoints = makeAssertPoints(['location', 'z']);
var assertRanges = makeAssertRanges('map');