diff --git a/.circleci/test.sh b/.circleci/test.sh index cb309a89850..3c59591179f 100755 --- a/.circleci/test.sh +++ b/.circleci/test.sh @@ -6,7 +6,7 @@ set +o pipefail ROOT=$(dirname $0)/.. EXIT_STATE=0 -MAX_AUTO_RETRY=5 +MAX_AUTO_RETRY=0 log () { echo -e "\n$1" @@ -55,6 +55,7 @@ case $1 in SHARDS=($(node $ROOT/tasks/shard_jasmine_tests.js --limit=5 --tag=gl | circleci tests split)) for s in ${SHARDS[@]}; do + MAX_AUTO_RETRY=1 retry npm run test-jasmine -- "$s" --tags=gl --skip-tags=noCI --doNotFailOnEmptyTestSuite done @@ -67,6 +68,7 @@ case $1 in SHARDS=($(node $ROOT/tasks/shard_jasmine_tests.js --limit=1 --tag=flaky | circleci tests split)) for s in ${SHARDS[@]}; do + MAX_AUTO_RETRY=5 retry npm run test-jasmine -- "$s" --tags=flaky --skip-tags=noCI done @@ -80,6 +82,7 @@ case $1 in ;; image2) + MAX_AUTO_RETRY=5 retry npm run test-image -- --just-flaky npm run test-export || EXIT_STATE=$? exit $EXIT_STATE diff --git a/test/jasmine/tests/animate_test.js b/test/jasmine/tests/animate_test.js index 2ddc139e011..f569dee0b23 100644 --- a/test/jasmine/tests/animate_test.js +++ b/test/jasmine/tests/animate_test.js @@ -719,7 +719,7 @@ describe('Animating multiple axes', function() { destroyGraphDiv(); }); - it('@flaky updates ranges of secondary axes', function(done) { + it('updates ranges of secondary axes', function(done) { Plotly.plot(gd, [ {y: [1, 2, 3]}, {y: [1, 2, 3], yaxis: 'y2'} @@ -750,7 +750,7 @@ describe('Animating multiple axes', function() { .then(done); }); - it('@flaky updates ranges of secondary axes (date + category case)', function(done) { + it('updates ranges of secondary axes (date + category case)', function(done) { Plotly.plot(gd, [ {x: ['2018-01-01', '2019-01-01', '2020-01-01'], y: [1, 2, 3]}, {x: ['a', 'b', 'c'], y: [1, 2, 3], xaxis: 'x2', yaxis: 'y2'} diff --git a/test/jasmine/tests/annotations_test.js b/test/jasmine/tests/annotations_test.js index e49d2afc70a..eed4798a6fe 100644 --- a/test/jasmine/tests/annotations_test.js +++ b/test/jasmine/tests/annotations_test.js @@ -187,11 +187,13 @@ describe('annotations relayout', function() { expect(typeof MathJax).toBe('undefined'); mockLayout.annotations[14].text = '$x+y+z$'; - Plotly.plot(gd, mockData, mockLayout).then(done); - - spyOn(Loggers, 'warn'); + Plotly.plot(gd, mockData, mockLayout) + .then(function() { + spyOn(Loggers, 'warn'); - Plotly.setPlotConfig({queueLength: 3}); + return Plotly.setPlotConfig({queueLength: 3}); + }) + .then(done); }); afterEach(function() { @@ -327,7 +329,8 @@ describe('annotations relayout', function() { assertText(0, 'left top'); - Plotly.relayout(gd, 'annotations[0].text', 'hello').then(function() { + Plotly.relayout(gd, 'annotations[0].text', 'hello') + .then(function() { assertText(0, 'hello'); return Plotly.relayout(gd, 'annotations[0].text', null); @@ -427,11 +430,15 @@ describe('annotations relayout', function() { {'annotations[0]': 'not an object'}, {'annotations[100]': {text: 'bad index'}} ].forEach(function(update) { - it('warns on ambiguous combinations and invalid values: ' + JSON.stringify(update), function() { - Plotly.relayout(gd, update); - expect(Loggers.warn).toHaveBeenCalled(); - // we could test the results here, but they're ambiguous and/or undefined so why bother? - // the important thing is the developer is warned that something went wrong. + it('warns on ambiguous combinations and invalid values: ' + JSON.stringify(update), function(done) { + Plotly.relayout(gd, update) + .then(function() { + expect(Loggers.warn).toHaveBeenCalled(); + // we could test the results here, but they're ambiguous and/or undefined so why bother? + // the important thing is the developer is warned that something went wrong. + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 37b8f8adf34..0fc627284ab 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1915,118 +1915,174 @@ describe('Test axes', function() { afterEach(destroyGraphDiv); describe('setting, or not setting categoryorder if it is not explicitly declared', function() { - it('should set categoryorder to default if categoryorder and categoryarray are not supplied', function() { - Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], {xaxis: {type: 'category'}}); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + it('should set categoryorder to default if categoryorder and categoryarray are not supplied', function(done) { + Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], {xaxis: {type: 'category'}}) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); - it('should set categoryorder to default even if type is not set to category explicitly', function() { - Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}]); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + it('should set categoryorder to default even if type is not set to category explicitly', function(done) { + Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}]) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); - it('should NOT set categoryorder to default if type is not category', function() { - Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}]); - expect(gd._fullLayout.yaxis.categoryorder).toBe(undefined); - expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + it('should NOT set categoryorder to default if type is not category', function(done) { + Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}]) + .then(function() { + expect(gd._fullLayout.yaxis.categoryorder).toBe(undefined); + expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); - it('should set categoryorder to default if type is overridden to be category', function() { - Plotly.plot(gd, [{x: [1, 2, 3, 4, 5], y: [15, 11, 12, 13, 14]}], {yaxis: {type: 'category'}}); - expect(gd._fullLayout.xaxis.categoryorder).toBe(undefined); - expect(gd._fullLayout.yaxis.categorarray).toBe(undefined); - expect(gd._fullLayout.yaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.yaxis.categorarray).toBe(undefined); + it('should set categoryorder to default if type is overridden to be category', function(done) { + Plotly.plot(gd, [{x: [1, 2, 3, 4, 5], y: [15, 11, 12, 13, 14]}], {yaxis: {type: 'category'}}) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe(undefined); + expect(gd._fullLayout.yaxis.categorarray).toBe(undefined); + expect(gd._fullLayout.yaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.yaxis.categorarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); }); describe('setting categoryorder to "array"', function() { - it('should leave categoryorder on "array" if it is supplied', function() { + it('should leave categoryorder on "array" if it is supplied', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'array', categoryarray: ['b', 'a', 'd', 'e', 'c']} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); - expect(gd._fullLayout.xaxis.categoryarray).toEqual(['b', 'a', 'd', 'e', 'c']); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); + expect(gd._fullLayout.xaxis.categoryarray).toEqual(['b', 'a', 'd', 'e', 'c']); + }) + .catch(failTest) + .then(done); }); - it('should switch categoryorder on "array" if it is not supplied but categoryarray is supplied', function() { + it('should switch categoryorder on "array" if it is not supplied but categoryarray is supplied', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryarray: ['b', 'a', 'd', 'e', 'c']} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); - expect(gd._fullLayout.xaxis.categoryarray).toEqual(['b', 'a', 'd', 'e', 'c']); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); + expect(gd._fullLayout.xaxis.categoryarray).toEqual(['b', 'a', 'd', 'e', 'c']); + }) + .catch(failTest) + .then(done); }); - it('should revert categoryorder to "trace" if "array" is supplied but there is no list', function() { + it('should revert categoryorder to "trace" if "array" is supplied but there is no list', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'array'} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categorarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); }); describe('do not set categoryorder to "array" if list exists but empty', function() { - it('should switch categoryorder to default if list is not supplied', function() { + it('should switch categoryorder to default if list is not supplied', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'array', categoryarray: []} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categoryarray).toEqual([]); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryarray).toEqual([]); + }) + .catch(failTest) + .then(done); }); - it('should not switch categoryorder on "array" if categoryarray is supplied but empty', function() { + it('should not switch categoryorder on "array" if categoryarray is supplied but empty', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryarray: []} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categoryarray).toEqual(undefined); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryarray).toEqual(undefined); + }) + .catch(failTest) + .then(done); }); }); describe('do NOT set categoryorder to "array" if it has some other proper value', function() { - it('should use specified categoryorder if it is supplied even if categoryarray exists', function() { + it('should use specified categoryorder if it is supplied even if categoryarray exists', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'trace', categoryarray: ['b', 'a', 'd', 'e', 'c']} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); - it('should use specified categoryorder if it is supplied even if categoryarray exists', function() { + it('should use specified categoryorder if it is supplied even if categoryarray exists', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'category ascending', categoryarray: ['b', 'a', 'd', 'e', 'c']} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('category ascending'); - expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('category ascending'); + expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); - it('should use specified categoryorder if it is supplied even if categoryarray exists', function() { + it('should use specified categoryorder if it is supplied even if categoryarray exists', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'category descending', categoryarray: ['b', 'a', 'd', 'e', 'c']} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('category descending'); - expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('category descending'); + expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); }); describe('setting categoryorder to the default if the value is unexpected', function() { - it('should switch categoryorder to "trace" if mode is supplied but invalid', function() { + it('should switch categoryorder to "trace" if mode is supplied but invalid', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'invalid value'} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); - expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryarray).toBe(undefined); + }) + .catch(failTest) + .then(done); }); - it('should switch categoryorder to "array" if mode is supplied but invalid and list is supplied', function() { + it('should switch categoryorder to "array" if mode is supplied but invalid and list is supplied', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: {type: 'category', categoryorder: 'invalid value', categoryarray: ['b', 'a', 'd', 'e', 'c']} - }); - expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); - expect(gd._fullLayout.xaxis.categoryarray).toEqual(['b', 'a', 'd', 'e', 'c']); + }) + .then(function() { + expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); + expect(gd._fullLayout.xaxis.categoryarray).toEqual(['b', 'a', 'd', 'e', 'c']); + }) + .catch(failTest) + .then(done); }); }); }); @@ -2041,11 +2097,15 @@ describe('Test axes', function() { afterEach(destroyGraphDiv); describe('a category has the same value of one of the auto range computed extreme', function() { - it('should compute the right range for X axis', function() { + it('should compute the right range for X axis', function(done) { Plotly.plot(gd, [{x: ['0', '-0.5', '3.5', 'Not Known'], y: [ '1.0', '1.0', '2.0', '1.0'], type: 'bar'}], { xaxis: {type: 'category', autorange: true} - }); - expect(gd._fullLayout.xaxis._rl).toEqual([-0.5, 3.5]); + }) + .then(function() { + expect(gd._fullLayout.xaxis._rl).toEqual([-0.5, 3.5]); + }) + .catch(failTest) + .then(done); }); }); }); @@ -2060,7 +2120,7 @@ describe('Test axes', function() { afterEach(destroyGraphDiv); - it('should set defaults on bad inputs', function() { + it('should set defaults on bad inputs', function(done) { var layout = { yaxis: { ticklen: 'invalid', @@ -2072,19 +2132,22 @@ describe('Test axes', function() { } }; - Plotly.plot(gd, data, layout); - - var yaxis = gd._fullLayout.yaxis; - expect(yaxis.ticklen).toBe(5); - expect(yaxis.tickwidth).toBe(1); - expect(yaxis.tickcolor).toBe('#444'); - expect(yaxis.ticks).toBe('outside'); - expect(yaxis.showticklabels).toBe(true); - expect(yaxis.tickfont).toEqual({ family: '"Open Sans", verdana, arial, sans-serif', size: 12, color: '#444' }); - expect(yaxis.tickangle).toBe('auto'); + Plotly.plot(gd, data, layout) + .then(function() { + var yaxis = gd._fullLayout.yaxis; + expect(yaxis.ticklen).toBe(5); + expect(yaxis.tickwidth).toBe(1); + expect(yaxis.tickcolor).toBe('#444'); + expect(yaxis.ticks).toBe('outside'); + expect(yaxis.showticklabels).toBe(true); + expect(yaxis.tickfont).toEqual({ family: '"Open Sans", verdana, arial, sans-serif', size: 12, color: '#444' }); + expect(yaxis.tickangle).toBe('auto'); + }) + .catch(failTest) + .then(done); }); - it('should use valid inputs', function() { + it('should use valid inputs', function(done) { var layout = { yaxis: { ticklen: 10, @@ -2096,19 +2159,22 @@ describe('Test axes', function() { } }; - Plotly.plot(gd, data, layout); - - var yaxis = gd._fullLayout.yaxis; - expect(yaxis.ticklen).toBe(10); - expect(yaxis.tickwidth).toBe(5); - expect(yaxis.tickcolor).toBe('#F00'); - expect(yaxis.ticks).toBe('outside'); - expect(yaxis.showticklabels).toBe(true); - expect(yaxis.tickfont).toEqual({ family: 'Garamond', size: 72, color: '#0FF' }); - expect(yaxis.tickangle).toBe(-20); + Plotly.plot(gd, data, layout) + .then(function() { + var yaxis = gd._fullLayout.yaxis; + expect(yaxis.ticklen).toBe(10); + expect(yaxis.tickwidth).toBe(5); + expect(yaxis.tickcolor).toBe('#F00'); + expect(yaxis.ticks).toBe('outside'); + expect(yaxis.showticklabels).toBe(true); + expect(yaxis.tickfont).toEqual({ family: 'Garamond', size: 72, color: '#0FF' }); + expect(yaxis.tickangle).toBe(-20); + }) + .catch(failTest) + .then(done); }); - it('should conditionally coerce based on showticklabels', function() { + it('should conditionally coerce based on showticklabels', function(done) { var layout = { yaxis: { showticklabels: false, @@ -2116,10 +2182,13 @@ describe('Test axes', function() { } }; - Plotly.plot(gd, data, layout); - - var yaxis = gd._fullLayout.yaxis; - expect(yaxis.tickangle).toBeUndefined(); + Plotly.plot(gd, data, layout) + .then(function() { + var yaxis = gd._fullLayout.yaxis; + expect(yaxis.tickangle).toBeUndefined(); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index 2cc797770b5..6573b0028fe 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -4,7 +4,6 @@ var BADNUM = require('@src/constants/numerical').BADNUM; var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var failTest = require('../assets/fail_test'); -var delay = require('../assets/delay'); var Lib = require('@src/lib'); describe('calculated data and points', function() { @@ -17,36 +16,45 @@ describe('calculated data and points', function() { afterEach(destroyGraphDiv); describe('connectGaps', function() { - it('should exclude null and undefined points when false', function() { - Plotly.plot(gd, [{ x: [1, 2, 3, undefined, 5], y: [1, null, 3, 4, 5]}], {}); - - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + it('should exclude null and undefined points when false', function(done) { + Plotly.plot(gd, [{ x: [1, 2, 3, undefined, 5], y: [1, null, 3, 4, 5]}], {}) + .then(function() { + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + }) + .catch(failTest) + .then(done); }); - it('should exclude null and undefined points as categories when false', function() { - Plotly.plot(gd, [{ x: [1, 2, 3, undefined, 5], y: [1, null, 3, 4, 5] }], { xaxis: { type: 'category' }}); - - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + it('should exclude null and undefined points as categories when false', function(done) { + Plotly.plot(gd, [{ x: [1, 2, 3, undefined, 5], y: [1, null, 3, 4, 5] }], { xaxis: { type: 'category' }}) + .then(function() { + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + }) + .catch(failTest) + .then(done); }); }); describe('category ordering', function() { describe('default category ordering reified', function() { - it('should output categories in the given order by default', function() { + it('should output categories in the given order by default', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category' - }}); - - expect(gd.calcdata[0][0].y).toEqual(15); - expect(gd.calcdata[0][1].y).toEqual(11); - expect(gd.calcdata[0][2].y).toEqual(12); - expect(gd.calcdata[0][3].y).toEqual(13); - expect(gd.calcdata[0][4].y).toEqual(14); + }}) + .then(function() { + expect(gd.calcdata[0][0].y).toEqual(15); + expect(gd.calcdata[0][1].y).toEqual(11); + expect(gd.calcdata[0][2].y).toEqual(12); + expect(gd.calcdata[0][3].y).toEqual(13); + expect(gd.calcdata[0][4].y).toEqual(14); + }) + .catch(failTest) + .then(done); }); - it('should output categories in the given order if `trace` order is explicitly specified', function() { + it('should output categories in the given order if `trace` order is explicitly specified', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'trace' @@ -54,95 +62,115 @@ describe('calculated data and points', function() { // Trace order as in, if a line or curve is drawn through points, what's the trace sequence. // These are two orthogonal concepts. Currently, the trace order is implied // by the order the {x,y} arrays are specified. - }}); - - expect(gd.calcdata[0][0].y).toEqual(15); - expect(gd.calcdata[0][1].y).toEqual(11); - expect(gd.calcdata[0][2].y).toEqual(12); - expect(gd.calcdata[0][3].y).toEqual(13); - expect(gd.calcdata[0][4].y).toEqual(14); + }}) + .then(function() { + expect(gd.calcdata[0][0].y).toEqual(15); + expect(gd.calcdata[0][1].y).toEqual(11); + expect(gd.calcdata[0][2].y).toEqual(12); + expect(gd.calcdata[0][3].y).toEqual(13); + expect(gd.calcdata[0][4].y).toEqual(14); + }) + .catch(failTest) + .then(done); }); }); describe('domain alphanumerical category ordering', function() { - it('should output categories in ascending domain alphanumerical order', function() { + it('should output categories in ascending domain alphanumerical order', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'category ascending' - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in descending domain alphanumerical order', function() { + it('should output categories in descending domain alphanumerical order', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'category descending' - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 4, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 0, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 3, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 1, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 4, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 0, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 3, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 1, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in ascending domain alphanumerical order even if categories are all numbers', function() { + it('should output categories in ascending domain alphanumerical order even if categories are all numbers', function(done) { Plotly.plot(gd, [{x: [3, 1, 5, 2, 4], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'category ascending' - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in categoryorder order even if category array is defined', function() { + it('should output categories in categoryorder order even if category array is defined', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'category ascending', categoryarray: ['b', 'a', 'd', 'e', 'c'] // These must be ignored. Alternative: error? - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in ascending domain alphanumerical order, excluding undefined', function() { + it('should output categories in ascending domain alphanumerical order, excluding undefined', function(done) { Plotly.plot(gd, [{x: ['c', undefined, 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'category ascending' - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 15})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 15})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should combine duplicate categories', function() { + it('should combine duplicate categories', function(done) { Plotly.plot(gd, [{x: [ '1', '1'], y: [10, 20]}], { xaxis: { type: 'category', categoryorder: 'category ascending' - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - - expect(gd._fullLayout.xaxis._categories).toEqual(['1']); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd._fullLayout.xaxis._categories).toEqual(['1']); + }) + .catch(failTest) + .then(done); }); - it('should skip over visible-false traces', function() { + it('should skip over visible-false traces', function(done) { Plotly.plot(gd, [{ x: [1, 2, 3], y: [7, 6, 5], @@ -155,95 +183,113 @@ describe('calculated data and points', function() { yaxis2: { categoryorder: 'category descending' } - }); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 10, y: 2})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 9, y: 1})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 8, y: 0})); - expect(gd._fullLayout.yaxis2._categories).toEqual(['C', 'B', 'A']); + }) + .then(function() { + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 10, y: 2})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 9, y: 1})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 8, y: 0})); + expect(gd._fullLayout.yaxis2._categories).toEqual(['C', 'B', 'A']); + }) + .catch(failTest) + .then(done); }); }); describe('explicit category ordering', function() { - it('should output categories in explicitly supplied order, independent of trace order', function() { + it('should output categories in explicitly supplied order, independent of trace order', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: ['b', 'a', 'd', 'e', 'c'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order even if category values are all numbers', function() { + it('should output categories in explicitly supplied order even if category values are all numbers', function(done) { Plotly.plot(gd, [{x: [3, 1, 5, 2, 4], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: [2, 1, 4, 5, 3] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order, independent of trace order, pruned', function() { + it('should output categories in explicitly supplied order, independent of trace order, pruned', function(done) { Plotly.plot(gd, [{x: ['c', undefined, 'e', 'b', 'd'], y: [15, 11, 12, null, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: ['b', 'a', 'd', 'e', 'c'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order even if not all categories are present', function() { + it('should output categories in explicitly supplied order even if not all categories are present', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: ['b', 'x', 'a', 'd', 'z', 'e', 'c'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 2, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 5, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 2, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 5, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categoryarray', function() { + it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categoryarray', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: ['y', 'b', 'x', 'a', 'd', 'z', 'e', 'c', 'q', 'k'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 7, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 3, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 4, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 7, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 3, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 4, y: 14})); - // The auto-range feature currently eliminates unused category ticks on the left/right axis tails. - // The below test case reifies this current behavior, and checks proper order of categories kept. + // The auto-range feature currently eliminates unused category ticks on the left/right axis tails. + // The below test case reifies this current behavior, and checks proper order of categories kept. - var domTickTexts = Array.prototype.slice.call(document.querySelectorAll('g.xtick')) - .map(function(e) {return e.__data__.text;}); + var domTickTexts = Array.prototype.slice.call(document.querySelectorAll('g.xtick')) + .map(function(e) {return e.__data__.text;}); - expect(domTickTexts).toEqual(['b', 'x', 'a', 'd', 'z', 'e', 'c']); // y, q and k has no data points + expect(domTickTexts).toEqual(['b', 'x', 'a', 'd', 'z', 'e', 'c']); // y, q and k has no data points + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categoryarray', function() { + it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categoryarray', function(done) { // The auto-range feature currently eliminates unutilized category ticks on the left/right edge // BUT keeps it if a data point with null is added; test is almost identical to the one above // except that it explicitly adds an axis tick for y @@ -252,56 +298,65 @@ describe('calculated data and points', function() { type: 'category', categoryorder: 'array', categoryarray: ['y', 'b', 'x', 'a', 'd', 'z', 'e', 'c', 'q', 'k'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 7, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 3, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 4, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 7, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 3, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 1, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 4, y: 14})); - var domTickTexts = Array.prototype.slice.call(document.querySelectorAll('g.xtick')) - .map(function(e) {return e.__data__.text;}); + var domTickTexts = Array.prototype.slice.call(document.querySelectorAll('g.xtick')) + .map(function(e) {return e.__data__.text;}); - expect(domTickTexts).toEqual(['y', 'b', 'x', 'a', 'd', 'z', 'e', 'c']); // q, k has no data; y is null + expect(domTickTexts).toEqual(['y', 'b', 'x', 'a', 'd', 'z', 'e', 'c']); // q, k has no data; y is null + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order even if not all categories are present, and should interact with a null value orthogonally', function() { + it('should output categories in explicitly supplied order even if not all categories are present, and should interact with a null value orthogonally', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, null, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: ['b', 'x', 'a', 'd', 'z', 'e', 'c'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: BADNUM, y: BADNUM})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 5, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 5, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); + }) + .catch(failTest) + .then(done); }); - it('should output categories in explicitly supplied order first, if not all categories are covered', function() { + it('should output categories in explicitly supplied order first, if not all categories are covered', function(done) { Plotly.plot(gd, [{x: ['c', 'a', 'e', 'b', 'd'], y: [15, 11, 12, 13, 14]}], { xaxis: { type: 'category', categoryorder: 'array', categoryarray: ['b', 'a', 'x', 'c'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 3, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); - expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 5, y: 14})); - - // The order of the rest is unspecified, no need to check. Alternative: make _both_ categoryorder and - // categories effective; categories would take precedence and the remaining items would be sorted - // based on the categoryorder. This of course means that the mere presence of categories triggers this - // behavior, rather than an explicit 'explicit' categoryorder. + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 3, y: 15})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 5, y: 14})); + + // The order of the rest is unspecified, no need to check. Alternative: make _both_ categoryorder and + // categories effective; categories would take precedence and the remaining items would be sorted + // based on the categoryorder. This of course means that the mere presence of categories triggers this + // behavior, rather than an explicit 'explicit' categoryorder. + }) + .catch(failTest) + .then(done); }); }); describe('ordering tests in the presence of multiple traces - mutually exclusive', function() { - it('baseline testing for the unordered, disjunct case', function() { + it('baseline testing for the unordered, disjunct case', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Seals']; @@ -310,24 +365,27 @@ describe('calculated data and points', function() { {x: x1, y: x1.map(function(d, i) {return i + 10;})}, {x: x2, y: x2.map(function(d, i) {return i + 20;})}, {x: x3, y: x3.map(function(d, i) {return i + 30;})} - ]); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); + ]) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order follows the trace order (even if categoryarray is specified)', function() { + it('category order follows the trace order (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Seals']; @@ -340,24 +398,27 @@ describe('calculated data and points', function() { // type: 'category', // commented out to rely on autotyping for added realism categoryorder: 'trace', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order is category ascending (even if categoryarray is specified)', function() { + it('category order is category ascending (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Seals']; @@ -371,24 +432,27 @@ describe('calculated data and points', function() { categoryorder: 'category ascending', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] // this is the expected sorted outcome: ['Bearing','Bulb','Cord','Fuse','Gear','Leak','Motor','Plug','Pump','Seals','Switch'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 10, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 7, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 3, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 1, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 9, y: 32})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 10, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 7, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 3, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 1, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 9, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order is category descending (even if categoryarray is specified)', function() { + it('category order is category descending (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Seals']; @@ -402,24 +466,27 @@ describe('calculated data and points', function() { categoryorder: 'category descending', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] // this is the expected sorted outcome: ["Switch", "Seals", "Pump", "Plug", "Motor", "Leak", "Gear", "Fuse", "Cord", "Bulb", "Bearing"] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 10, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 3, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 8, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 7, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 9, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 10, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 3, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 8, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 7, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 9, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order follows categoryarray', function() { + it('category order follows categoryarray', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Seals']; @@ -432,26 +499,29 @@ describe('calculated data and points', function() { // type: 'category', // commented out to rely on autotyping for added realism categoryorder: 'array', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 6, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 8, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 4, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 10, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 3, y: 32})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 6, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 8, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 4, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 10, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 3, y: 32})); + }) + .catch(failTest) + .then(done); }); }); describe('ordering tests in the presence of multiple traces - partially overlapping', function() { - it('baseline testing for the unordered, partially overlapping case', function() { + it('baseline testing for the unordered, partially overlapping case', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; @@ -460,25 +530,28 @@ describe('calculated data and points', function() { {x: x1, y: x1.map(function(d, i) {return i + 10;})}, {x: x2, y: x2.map(function(d, i) {return i + 20;})}, {x: x3, y: x3.map(function(d, i) {return i + 30;})} - ]); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); - expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 10, y: 33})); + ]) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 10, y: 33})); + }) + .catch(failTest) + .then(done); }); - it('category order follows the trace order (even if categoryarray is specified)', function() { + it('category order follows the trace order (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; @@ -491,25 +564,28 @@ describe('calculated data and points', function() { // type: 'category', // commented out to rely on autotyping for added realism categoryorder: 'trace', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); - expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 10, y: 33})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 3, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 4, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 6, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 10, y: 33})); + }) + .catch(failTest) + .then(done); }); - it('category order is category ascending (even if categoryarray is specified)', function() { + it('category order is category ascending (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; @@ -523,25 +599,28 @@ describe('calculated data and points', function() { categoryorder: 'category ascending', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] // this is the expected sorted outcome: ['Bearing','Bulb','Cord','Fuse','Gear','Leak','Motor','Plug','Pump','Seals','Switch'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 10, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 7, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 3, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 1, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); - expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 9, y: 33})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 6, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 10, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 7, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 3, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 1, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 8, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); + expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 9, y: 33})); + }) + .catch(failTest) + .then(done); }); - it('category order is category descending (even if categoryarray is specified)', function() { + it('category order is category descending (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; @@ -555,25 +634,28 @@ describe('calculated data and points', function() { categoryorder: 'category descending', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] // this is the expected sorted outcome: ["Switch", "Seals", "Pump", "Plug", "Motor", "Leak", "Gear", "Fuse", "Cord", "Bulb", "Bearing"] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 10, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 3, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 8, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 7, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 9, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); - expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 1, y: 33})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 10, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 4, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 3, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 8, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 7, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 9, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 5, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); + expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 1, y: 33})); + }) + .catch(failTest) + .then(done); }); - it('category order follows categoryarray', function() { + it('category order follows categoryarray', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; @@ -586,27 +668,30 @@ describe('calculated data and points', function() { // type: 'category', // commented out to rely on autotyping for added realism categoryorder: 'array', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 6, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 8, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 4, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 10, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); - expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 3, y: 33})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 6, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 8, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 4, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 10, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 3, y: 33})); + }) + .catch(failTest) + .then(done); }); }); describe('ordering tests in the presence of multiple traces - fully overlapping', function() { - it('baseline testing for the unordered, fully overlapping case', function() { + it('baseline testing for the unordered, fully overlapping case', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -615,22 +700,25 @@ describe('calculated data and points', function() { {x: x1, y: x1.map(function(d, i) {return i + 10;})}, {x: x2, y: x2.map(function(d, i) {return i + 20;})}, {x: x3, y: x3.map(function(d, i) {return i + 30;})} - ]); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + ]) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 1, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 0, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 1, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 0, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 0, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 0, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order follows the trace order (even if categoryarray is specified)', function() { + it('category order follows the trace order (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -643,22 +731,25 @@ describe('calculated data and points', function() { // type: 'category', // commented out to rely on autotyping for added realism categoryorder: 'trace', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 0, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 1, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 0, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 1, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 0, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 0, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 0, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order is category ascending (even if categoryarray is specified)', function() { + it('category order is category ascending (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -672,22 +763,25 @@ describe('calculated data and points', function() { categoryorder: 'category ascending', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] // this is the expected sorted outcome: ['Bearing','Bulb','Cord','Fuse','Gear','Leak','Motor','Plug','Pump','Seals','Switch'] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 1, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 1, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 1, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 1, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order is category descending (even if categoryarray is specified)', function() { + it('category order is category descending (even if categoryarray is specified)', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -701,22 +795,25 @@ describe('calculated data and points', function() { categoryorder: 'category descending', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] // this is the expected sorted outcome: ["Switch", "Seals", "Pump", "Plug", "Motor", "Leak", "Gear", "Fuse", "Cord", "Bulb", "Bearing"] - }}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 2, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 0, y: 12})); + }}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 2, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 0, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 2, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 1, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 0, y: 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 2, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 1, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 0, y: 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 0, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 1, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 2, y: 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 0, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 1, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 2, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order follows categoryarray', function() { + it('category order follows categoryarray', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -731,22 +828,25 @@ describe('calculated data and points', function() { categoryorder: 'array', categoryarray: ['Bearing', 'Motor', 'Gear'] } - }); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 1, y: 12})); + }) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 1, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 2, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 1, y: 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 2, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 1, y: 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 1, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 2, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 1, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 2, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); + }) + .catch(failTest) + .then(done); }); - it('category order follows categoryarray even if data is sparse', function() { + it('category order follows categoryarray even if data is sparse', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -761,24 +861,27 @@ describe('calculated data and points', function() { categoryorder: 'array', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] } - }); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + }) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 1, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 9, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 1, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 9, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 2, y: 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 2, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 9, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); + }) + .catch(failTest) + .then(done); }); }); describe('ordering and stacking combined', function() { - it('partially overlapping category order follows categoryarray and stacking produces expected results', function() { + it('partially overlapping category order follows categoryarray and stacking produces expected results', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; @@ -794,25 +897,28 @@ describe('calculated data and points', function() { categoryorder: 'array', categoryarray: ['Switch', 'Bearing', 'Motor', 'Seals', 'Pump', 'Cord', 'Plug', 'Bulb', 'Fuse', 'Gear', 'Leak'] } - }); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); - - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 6, y: 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); - expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 8, y: 23})); - expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); - - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 4, y: 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 10, y: 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 11 + 32})); - expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 3, y: 33})); + }) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 9, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 1, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 2, y: 12})); + + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 6, y: 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 5, y: 22})); + expect(gd.calcdata[1][3]).toEqual(jasmine.objectContaining({x: 8, y: 23})); + expect(gd.calcdata[1][4]).toEqual(jasmine.objectContaining({x: 7, y: 24})); + + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 4, y: 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 10, y: 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 11 + 32})); + expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 3, y: 33})); + }) + .catch(failTest) + .then(done); }); - it('fully overlapping - category order follows categoryarray and stacking produces expected results', function() { + it('fully overlapping - category order follows categoryarray and stacking produces expected results', function(done) { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; var x3 = ['Motor', 'Gear', 'Bearing']; @@ -828,49 +934,58 @@ describe('calculated data and points', function() { categoryorder: 'array', categoryarray: ['Bearing', 'Motor', 'Gear'] } - }); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 10})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 1, y: 12})); + }) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 10})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: 0, y: 11})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 1, y: 12})); - expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 11 + 20})); - expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 2, y: 10 + 21})); - expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 1, y: 12 + 22})); + expect(gd.calcdata[1][0]).toEqual(jasmine.objectContaining({x: 0, y: 11 + 20})); + expect(gd.calcdata[1][1]).toEqual(jasmine.objectContaining({x: 2, y: 10 + 21})); + expect(gd.calcdata[1][2]).toEqual(jasmine.objectContaining({x: 1, y: 12 + 22})); - expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 1, y: 12 + 22 + 30})); - expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 2, y: 10 + 21 + 31})); - expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 11 + 20 + 32})); + expect(gd.calcdata[2][0]).toEqual(jasmine.objectContaining({x: 1, y: 12 + 22 + 30})); + expect(gd.calcdata[2][1]).toEqual(jasmine.objectContaining({x: 2, y: 10 + 21 + 31})); + expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 11 + 20 + 32})); + }) + .catch(failTest) + .then(done); }); }); - it('should order categories per axis', function() { + it('should order categories per axis', function(done) { Plotly.plot(gd, [ {x: ['a', 'c', 'g', 'e']}, {x: ['b', 'h', 'f', 'd'], xaxis: 'x2'} ], { xaxis: {categoryorder: 'category ascending', domain: [0, 0.4]}, xaxis2: {categoryorder: 'category descending', domain: [0.6, 1]} - }); - - expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'c', 'e', 'g']); - expect(gd._fullLayout.xaxis2._categories).toEqual(['h', 'f', 'd', 'b']); + }) + .then(function() { + expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'c', 'e', 'g']); + expect(gd._fullLayout.xaxis2._categories).toEqual(['h', 'f', 'd', 'b']); + }) + .catch(failTest) + .then(done); }); - it('should consider number categories and their string representation to be the same', function() { + it('should consider number categories and their string representation to be the same', function(done) { Plotly.plot(gd, [{ x: ['a', 'b', 1, '1'], y: [1, 2, 3, 4] }], { xaxis: {type: 'category'} - }); - - expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'b', '1']); - expect(gd._fullLayout.xaxis._categoriesMap).toEqual({ - '1': 2, - 'a': 0, - 'b': 1 - }); + }) + .then(function() { + expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'b', '1']); + expect(gd._fullLayout.xaxis._categoriesMap).toEqual({ + '1': 2, + 'a': 0, + 'b': 1 + }); + }) + .catch(failTest) + .then(done); }); describe('by value', function() { @@ -984,7 +1099,6 @@ describe('calculated data and points', function() { expect(gd._fullLayout[trace.type === 'splom' ? 'xaxis' : axName]._categories).toEqual(finalOrder, 'wrong order'); } }) - .then(delay(100)) .catch(failTest) .then(done); } @@ -1121,16 +1235,19 @@ describe('calculated data and points', function() { }); describe('customdata', function() { - it('should pass customdata to the calcdata points', function() { + it('should pass customdata to the calcdata points', function(done) { Plotly.plot(gd, [{ x: [0, 1, 3], y: [4, 5, 7], customdata: ['a', 'b', {foo: 'bar'}] - }], {}); - - expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({data: 'a'})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({data: 'b'})); - expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({data: {foo: 'bar'}})); + }], {}) + .then(function() { + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({data: 'a'})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({data: 'b'})); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({data: {foo: 'bar'}})); + }) + .catch(failTest) + .then(done); }); }); }); diff --git a/test/jasmine/tests/carpet_test.js b/test/jasmine/tests/carpet_test.js index 5cac607b711..7ae4e770ab5 100644 --- a/test/jasmine/tests/carpet_test.js +++ b/test/jasmine/tests/carpet_test.js @@ -724,6 +724,7 @@ describe('scattercarpet hover labels', function() { [200, 200], fig, [['a: 0.200', 'b: 3.500', 'y: 2.900'], 'a = 0.2'] ) + .catch(failTest) .then(done); }); @@ -736,6 +737,7 @@ describe('scattercarpet hover labels', function() { [200, 200], fig, [['a: 0.200', 'b: 3.500', 'y: 2.900', 'D'], 'a = 0.2'] ) + .catch(failTest) .then(done); }); @@ -747,6 +749,7 @@ describe('scattercarpet hover labels', function() { [200, 200], fig, [['a: 0.200', 'y: 2.900'], null] ) + .catch(failTest) .then(done); }); @@ -758,6 +761,7 @@ describe('scattercarpet hover labels', function() { [200, 200], fig, [['b: 3.500', 'y: 2.900'], null] ) + .catch(failTest) .then(done); }); @@ -769,6 +773,7 @@ describe('scattercarpet hover labels', function() { [200, 200], fig, [['f(0.2, 3.5) = 2.900'], 'scattercarpet #5'] ) + .catch(failTest) .then(done); }); @@ -780,6 +785,7 @@ describe('scattercarpet hover labels', function() { [200, 200], fig, [['f(0.2, 3.5) = 3.0'], 'pt #3'] ) + .catch(failTest) .then(done); }); }); diff --git a/test/jasmine/tests/cartesian_interact_test.js b/test/jasmine/tests/cartesian_interact_test.js index 0c75de8b436..6ba153b3dea 100644 --- a/test/jasmine/tests/cartesian_interact_test.js +++ b/test/jasmine/tests/cartesian_interact_test.js @@ -32,7 +32,6 @@ describe('zoom box element', function() { mockCopy.layout.dragmode = 'zoom'; Plotly.plot(gd, mockCopy.data, mockCopy.layout) - .catch(failTest) .then(done); }); @@ -974,7 +973,7 @@ describe('axis zoom/pan and main plot zoom', function() { var yr0 = [-0.211, 3.211]; var specs = [{ - desc: 'zoombox on xy', + desc: '@flaky zoombox on xy', drag: ['xy', 'nsew', 30, 30], exp: [ [['xaxis', 'xaxis2', 'xaxis3'], [1.457, 2.328]], @@ -2338,7 +2337,7 @@ describe('Event data:', function() { expect('marker.colorbar.tickvals' in pt).toBe(false, 'marker.colorbar.tickvals'); expect('marker.colorbar.ticktext' in pt).toBe(false, 'marker.colorbar.ticktext'); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -2366,7 +2365,7 @@ describe('Event data:', function() { expect('marker.colorbar.tickvals' in pt).toBe(false, 'marker.colorbar.tickvals'); expect('marker.colorbar.ticktext' in pt).toBe(false, 'marker.colorbar.ticktext'); }) - .catch(fail) + .catch(failTest) .then(done); }); }); diff --git a/test/jasmine/tests/choropleth_test.js b/test/jasmine/tests/choropleth_test.js index 12ebf2130c1..96fa664aca0 100644 --- a/test/jasmine/tests/choropleth_test.js +++ b/test/jasmine/tests/choropleth_test.js @@ -205,6 +205,7 @@ describe('Test choropleth hover:', function() { fig, ['RUS\n10', 'trace 1'] ) + .catch(failTest) .then(done); }); }); @@ -220,6 +221,7 @@ describe('Test choropleth hover:', function() { fig, ['tpl 10', 'x'] ) + .catch(failTest) .then(done); }); }); @@ -236,6 +238,7 @@ describe('Test choropleth hover:', function() { fig, ['tExT', null] ) + .catch(failTest) .then(done); }); }); @@ -252,6 +255,7 @@ describe('Test choropleth hover:', function() { fig, ['-text-', null] ) + .catch(failTest) .then(done); }); }); @@ -269,6 +273,7 @@ describe('Test choropleth hover:', function() { fig, ['-text-', null] ) + .catch(failTest) .then(done); }); }); @@ -295,6 +300,7 @@ describe('Test choropleth hover:', function() { fontFamily: 'Roboto' } ) + .catch(failTest) .then(done); }); }); @@ -310,6 +316,7 @@ describe('Test choropleth hover:', function() { fig, ['RUS', 'trace 1'] ) + .catch(failTest) .then(done); }); }); @@ -330,7 +337,9 @@ describe('Test choropleth hover:', function() { [false, true].forEach(function(hasCssTransform) { it('- base case (truncate z decimals), hasCssTransform: ' + hasCssTransform, function(done) { - run(hasCssTransform, pos, base(), exp).then(done); + run(hasCssTransform, pos, base(), exp) + .catch(failTest) + .then(done); }); }); @@ -338,7 +347,9 @@ describe('Test choropleth hover:', function() { it('- hovertemplate case (same z truncation), hasCssTransform: ' + hasCssTransform, function(done) { var fig = base(); fig.hovertemplate = '%{z}%{location}'; - run(hasCssTransform, pos, fig, exp).then(done); + run(hasCssTransform, pos, fig, exp) + .catch(failTest) + .then(done); }); }); }); @@ -350,7 +361,9 @@ describe('Test choropleth hover:', function() { fig.data[0].hovertemplate = '%{properties.name}%{ct[0]:.1f} | %{ct[1]:.1f}'; fig.layout.geo.projection = {scale: 20}; - run(hasCssTransform, [300, 200], fig, ['New York', '-75.1 | 42.6']).then(done); + run(hasCssTransform, [300, 200], fig, ['New York', '-75.1 | 42.6']) + .catch(failTest) + .then(done); }); }); }); diff --git a/test/jasmine/tests/choroplethmapbox_test.js b/test/jasmine/tests/choroplethmapbox_test.js index e01641bd5f1..33195943581 100644 --- a/test/jasmine/tests/choroplethmapbox_test.js +++ b/test/jasmine/tests/choroplethmapbox_test.js @@ -516,7 +516,7 @@ describe('Test choroplethmapbox convert:', function() { }); }); -describe('@noCI Test choroplethmapbox hover:', function() { +describe('Test choroplethmapbox hover:', function() { var gd; afterEach(function(done) { @@ -653,7 +653,7 @@ describe('@noCI Test choroplethmapbox hover:', function() { }); }); -describe('@noCI Test choroplethmapbox interactions:', function() { +describe('Test choroplethmapbox interactions:', function() { var gd; var geojson = { diff --git a/test/jasmine/tests/click_test.js b/test/jasmine/tests/click_test.js index 5f15f61292a..9031148b699 100644 --- a/test/jasmine/tests/click_test.js +++ b/test/jasmine/tests/click_test.js @@ -57,22 +57,24 @@ describe('Test click interactions:', function() { var futureData, clickPassthroughs, contextPassthroughs; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); - - futureData = undefined; - clickPassthroughs = 0; - contextPassthroughs = 0; + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; + clickPassthroughs = 0; + contextPassthroughs = 0; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); - gd.addEventListener('click', function() { - clickPassthroughs++; - }); - gd.addEventListener('contextmenu', function() { - contextPassthroughs++; - }); + gd.addEventListener('click', function() { + clickPassthroughs++; + }); + gd.addEventListener('contextmenu', function() { + contextPassthroughs++; + }); + }) + .then(done); }); // Later we want to emit plotly events for clicking in the graph but not on data @@ -80,7 +82,7 @@ describe('Test click interactions:', function() { // pass through to event handlers attached to gd. it('should not be triggered when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); // this is a weird one - in the real case the original click never // happens, it gets canceled by preventDefault in mouseup, but we // add our own synthetic click. @@ -100,7 +102,7 @@ describe('Test click interactions:', function() { // Any reason we should handle these? it('should not be triggered when in the margin', function() { click(marginPos[0], marginPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); expect(clickPassthroughs).toBe(1); expect(contextPassthroughs).toBe(0); }); @@ -136,7 +138,8 @@ describe('Test click interactions:', function() { }); it('works with fixedrange axes', function(done) { - Plotly.relayout(gd, {'xaxis.fixedrange': true, 'yaxis.fixedrange': true}).then(function() { + Plotly.relayout(gd, {'xaxis.fixedrange': true, 'yaxis.fixedrange': true}) + .then(function() { click(pointPos[0], pointPos[1]); expect(futureData.points.length).toEqual(1); expect(clickPassthroughs).toBe(2); @@ -156,7 +159,7 @@ describe('Test click interactions:', function() { expect(evt.clientX).toEqual(pointPos[0]); expect(evt.clientY).toEqual(pointPos[1]); }) - .catch(fail) + .catch(failTest) .then(done); }); @@ -180,21 +183,21 @@ describe('Test click interactions:', function() { [modClickOpts, rightClickOpts].forEach(function(clickOpts, i) { it('should not be triggered when not on data points', function() { click(blankPos[0], blankPos[1], clickOpts); - expect(futureData === undefined).toBe(true, i); + expect(futureData).toBe(null, i); expect(clickPassthroughs).toBe(0, i); expect(contextPassthroughs).toBe(0, i); }); it('should not be triggered when in the margin', function() { click(marginPos[0], marginPos[1], clickOpts); - expect(futureData === undefined).toBe(true, i); + expect(futureData).toBe(null, i); expect(clickPassthroughs).toBe(0, i); expect(contextPassthroughs).toBe(0, i); }); it('should not be triggered if you dont cancel contextmenu', function() { click(pointPos[0], pointPos[1], Lib.extendFlat({}, clickOpts, {cancelContext: false})); - expect(futureData === undefined).toBe(true, i); + expect(futureData).toBe(null, i); expect(clickPassthroughs).toBe(0, i); expect(contextPassthroughs).toBe(1, i); }); @@ -237,42 +240,48 @@ describe('Test click interactions:', function() { }); describe('click event with hoverinfo set to skip - plotly_click', function() { - var futureData = null; + var futureData; beforeEach(function(done) { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); modifiedMockCopy.data[0].hoverinfo = 'skip'; Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not register the click', function() { click(pointPos[0], pointPos[1]); - expect(futureData).toEqual(null); + expect(futureData).toBe(null); }); }); describe('click events with hoverinfo set to skip - plotly_hover', function() { - var futureData = null; + var futureData; beforeEach(function(done) { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); modifiedMockCopy.data[0].hoverinfo = 'skip'; Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); + .then(function() { + futureData = null; - gd.on('plotly_hover', function(data) { - futureData = data; - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not register the hover', function() { click(pointPos[0], pointPos[1]); - expect(futureData).toEqual(null); + expect(futureData).toBe(null); }); }); @@ -283,11 +292,14 @@ describe('Test click interactions:', function() { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); modifiedMockCopy.data[0].hoverinfo = 'none'; Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields despite hoverinfo: "none"', function() { @@ -313,11 +325,14 @@ describe('Test click interactions:', function() { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); modifiedMockCopy.data[0].hoverinfo = 'none'; Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); + .then(function() { + futureData = null; - gd.on('plotly_hover', function(data) { - futureData = data; - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields despite hoverinfo: "none"', function() { @@ -347,11 +362,14 @@ describe('Test click interactions:', function() { var modifiedMockCopy = Lib.extendDeep({}, mockCopy); modifiedMockCopy.data[0].hoverinfo = 'none'; Plotly.plot(gd, modifiedMockCopy.data, modifiedMockCopy.layout) - .then(done); + .then(function() { + futureData = null; - gd.on('plotly_unhover', function(data) { - futureData = data; - }); + gd.on('plotly_unhover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields despite hoverinfo: "none"', function(done) { @@ -371,7 +389,9 @@ describe('Test click interactions:', function() { var evt = futureData.event; expect(evt.clientX).toEqual(blankPos[0]); expect(evt.clientY).toEqual(blankPos[1]); - }).then(done); + }) + .catch(failTest) + .then(done); }); }); @@ -379,18 +399,24 @@ describe('Test click interactions:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_doubleclick', function(data) { - futureData = data; - }); + gd.on('plotly_doubleclick', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should return null', function(done) { - doubleClick(pointPos[0], pointPos[1]).then(function() { + doubleClick(pointPos[0], pointPos[1]) + .then(function() { expect(futureData).toBe(null); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -676,7 +702,8 @@ describe('Test click interactions:', function() { } it('when set to \'reset+autorange\' (the default) should work when \'autorange\' is on', function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); @@ -689,9 +716,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'reset+autorange\' (the default) should reset to set range on double click', function(done) { @@ -710,9 +737,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'reset+autorange\' (the default) should autosize on 1st double click and reset on 2nd', function(done) { @@ -791,9 +818,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(newAutoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(newAutoRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'reset\' should work when \'autorange\' is on', function(done) { @@ -810,9 +837,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'reset\' should reset to set range on double click', function(done) { @@ -831,9 +858,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'reset\' should reset on all double clicks', function(done) { @@ -847,9 +874,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(setRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(setRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'autosize\' should work when \'autorange\' is on', function(done) { @@ -866,9 +893,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'autosize\' should set to autorange on double click', function(done) { @@ -887,9 +914,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('when set to \'autosize\' should reset on all double clicks', function(done) { @@ -903,9 +930,9 @@ describe('Test click interactions:', function() { }).then(function() { expect(gd.layout.xaxis.range).toBeCloseToArray(autoRangeX); expect(gd.layout.yaxis.range).toBeCloseToArray(autoRangeY); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should not try to autorange fixedrange:true axes when rangeInitial is not set', function(done) { diff --git a/test/jasmine/tests/command_test.js b/test/jasmine/tests/command_test.js index c21bfadb4c5..31211c62c94 100644 --- a/test/jasmine/tests/command_test.js +++ b/test/jasmine/tests/command_test.js @@ -536,7 +536,8 @@ describe('component bindings', function() { }); // Doesn't trigger the callback: - Plotly.relayout(gd, 'width', 400).then(function() { + Plotly.relayout(gd, 'width', 400) + .then(function() { // Triggers the callback: return Plotly.restyle(gd, 'marker.color', 'green'); }).then(function() { diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index 53277b6be93..28819423c52 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -231,24 +231,30 @@ describe('config argument', function() { afterEach(destroyGraphDiv); - it('should not display the edit link by default', function() { - Plotly.plot(gd, [], {}); - - var link = document.getElementsByClassName('js-plot-link-container')[0]; + it('should not display the edit link by default', function(done) { + Plotly.plot(gd, [], {}) + .then(function() { + var link = document.getElementsByClassName('js-plot-link-container')[0]; - expect(link).toBeUndefined(); + expect(link).toBeUndefined(); + }) + .catch(failTest) + .then(done); }); - it('should display a link when true', function() { - Plotly.plot(gd, [], {}, { showLink: true }); - - var link = document.getElementsByClassName('js-plot-link-container')[0]; + it('should display a link when true', function(done) { + Plotly.plot(gd, [], {}, { showLink: true }) + .then(function() { + var link = document.getElementsByClassName('js-plot-link-container')[0]; - expect(link.textContent).toBe('Edit chart »'); + expect(link.textContent).toBe('Edit chart »'); - var bBox = link.getBoundingClientRect(); - expect(bBox.width).toBeGreaterThan(0); - expect(bBox.height).toBeGreaterThan(0); + var bBox = link.getBoundingClientRect(); + expect(bBox.width).toBeGreaterThan(0); + expect(bBox.height).toBeGreaterThan(0); + }) + .catch(failTest) + .then(done); }); }); @@ -442,10 +448,9 @@ describe('config argument', function() { var gd; var mockCopy; - beforeEach(function(done) { + beforeEach(function() { gd = createGraphDiv(); mockCopy = Lib.extendDeep({}, mock); - done(); }); afterEach(destroyGraphDiv); @@ -459,16 +464,22 @@ describe('config argument', function() { }); } - it('should have drag rectangles cursors by default', function() { - Plotly.plot(gd, mockCopy.data, {}); - - testDraggers(1); + it('should have drag rectangles cursors by default', function(done) { + Plotly.plot(gd, mockCopy.data, {}) + .then(function() { + testDraggers(1); + }) + .catch(failTest) + .then(done); }); - it('should not have drag rectangles when disabled', function() { - Plotly.plot(gd, mockCopy.data, {}, { showAxisDragHandles: false }); - - testDraggers(0); + it('should not have drag rectangles when disabled', function(done) { + Plotly.plot(gd, mockCopy.data, {}, { showAxisDragHandles: false }) + .then(function() { + testDraggers(0); + }) + .catch(failTest) + .then(done); }); }); @@ -477,41 +488,46 @@ describe('config argument', function() { var gd, mockCopy; - beforeEach(function(done) { + beforeEach(function() { gd = createGraphDiv(); mockCopy = Lib.extendDeep({}, mock); - done(); }); afterEach(destroyGraphDiv); - it('allows axis range entry by default', function() { - Plotly.plot(gd, mockCopy.data, {}); - - var corner = document.getElementsByClassName('edrag')[0]; - var cornerBox = corner.getBoundingClientRect(); - var cornerX = cornerBox.left + cornerBox.width / 2; - var cornerY = cornerBox.top + cornerBox.height / 2; + it('allows axis range entry by default', function(done) { + Plotly.plot(gd, mockCopy.data, {}) + .then(function() { + var corner = document.getElementsByClassName('edrag')[0]; + var cornerBox = corner.getBoundingClientRect(); + var cornerX = cornerBox.left + cornerBox.width / 2; + var cornerY = cornerBox.top + cornerBox.height / 2; - click(cornerX, cornerY); + click(cornerX, cornerY); - var editBox = document.getElementsByClassName('plugin-editable editable')[0]; - expect(editBox).toBeDefined(); - expect(editBox.getAttribute('contenteditable')).toBe('true'); + var editBox = document.getElementsByClassName('plugin-editable editable')[0]; + expect(editBox).toBeDefined(); + expect(editBox.getAttribute('contenteditable')).toBe('true'); + }) + .catch(failTest) + .then(done); }); - it('disallows axis range entry when disabled', function() { - Plotly.plot(gd, mockCopy.data, {}, { showAxisRangeEntryBoxes: false }); - - var corner = document.getElementsByClassName('edrag')[0]; - var cornerBox = corner.getBoundingClientRect(); - var cornerX = cornerBox.left + cornerBox.width / 2; - var cornerY = cornerBox.top + cornerBox.height / 2; + it('disallows axis range entry when disabled', function(done) { + Plotly.plot(gd, mockCopy.data, {}, { showAxisRangeEntryBoxes: false }) + .then(function() { + var corner = document.getElementsByClassName('edrag')[0]; + var cornerBox = corner.getBoundingClientRect(); + var cornerX = cornerBox.left + cornerBox.width / 2; + var cornerY = cornerBox.top + cornerBox.height / 2; - click(cornerX, cornerY); + click(cornerX, cornerY); - var editBox = document.getElementsByClassName('plugin-editable editable')[0]; - expect(editBox).toBeUndefined(); + var editBox = document.getElementsByClassName('plugin-editable editable')[0]; + expect(editBox).toBeUndefined(); + }) + .catch(failTest) + .then(done); }); }); @@ -665,30 +681,33 @@ describe('config argument', function() { gd = parent.childNodes[0]; } - it('@flaky should resize when the viewport width/height changes', function(done) { + it('should resize when the viewport width/height changes', function(done) { fillParent(1, 1); Plotly.plot(gd, data, {}, {responsive: true}) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should still be responsive if the plot is edited', function(done) { + it('should still be responsive if the plot is edited', function(done) { fillParent(1, 1); Plotly.plot(gd, data, {}, {responsive: true}) .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should still be responsive if the plot is purged and replotted', function(done) { + it('should still be responsive if the plot is purged and replotted', function(done) { fillParent(1, 1); Plotly.plot(gd, data, {}, {responsive: true}) .then(function() {return Plotly.newPlot(gd, data, {}, {responsive: true});}) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should only have one resize handler when plotted more than once', function(done) { + it('should only have one resize handler when plotted more than once', function(done) { fillParent(1, 1); var cntWindowResize = 0; window.addEventListener('resize', function() {cntWindowResize++;}); @@ -707,15 +726,16 @@ describe('config argument', function() { .then(done); }); - it('@flaky should become responsive if configured as such via Plotly.react', function(done) { + it('should become responsive if configured as such via Plotly.react', function(done) { fillParent(1, 1); Plotly.plot(gd, data, {}, {responsive: false}) .then(function() {return Plotly.react(gd, data, {}, {responsive: true});}) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should stop being responsive if configured as such via Plotly.react', function(done) { + it('should stop being responsive if configured as such via Plotly.react', function(done) { fillParent(1, 1); Plotly.plot(gd, data, {}, {responsive: true}) // Check initial size @@ -733,7 +753,7 @@ describe('config argument', function() { }); // Testing fancier CSS layouts - it('@flaky should resize horizontally in a flexbox when responsive: true', function(done) { + it('should resize horizontally in a flexbox when responsive: true', function(done) { parent.style.display = 'flex'; parent.style.flexDirection = 'row'; fillParent(1, 2, function() { @@ -742,10 +762,11 @@ describe('config argument', function() { Plotly.plot(gd, data, {}, { responsive: true }) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should resize vertically in a flexbox when responsive: true', function(done) { + it('should resize vertically in a flexbox when responsive: true', function(done) { parent.style.display = 'flex'; parent.style.flexDirection = 'column'; fillParent(2, 1, function() { @@ -754,10 +775,11 @@ describe('config argument', function() { Plotly.plot(gd, data, {}, { responsive: true }) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should resize in both direction in a grid when responsive: true', function(done) { + it('should resize in both direction in a grid when responsive: true', function(done) { var numCols = 2; var numRows = 2; parent.style.display = 'grid'; @@ -767,10 +789,11 @@ describe('config argument', function() { Plotly.plot(gd, data, {}, { responsive: true }) .then(testResponsive) + .catch(failTest) .then(done); }); - it('@flaky should provide a fixed non-zero width/height when autosize/responsive: true and container\' size is zero', function(done) { + it('should provide a fixed non-zero width/height when autosize/responsive: true and container\' size is zero', function(done) { fillParent(1, 1, function() { this.style.display = 'inline-block'; this.style.width = null; @@ -798,7 +821,7 @@ describe('config argument', function() { // The following test is to guarantee we're not breaking the existing (although maybe not ideal) behaviour. // In a future version, one may prefer responsive/autosize:true winning over an explicit width/height when embedded in a webpage. - it('@flaky should use the explicitly provided width/height even if autosize/responsive:true', function(done) { + it('should use the explicitly provided width/height even if autosize/responsive:true', function(done) { fillParent(1, 1, function() { this.style.width = '1000px'; this.style.height = '500px'; diff --git a/test/jasmine/tests/contourgl_test.js b/test/jasmine/tests/contourgl_test.js index e1d50f60452..4979a0029ee 100644 --- a/test/jasmine/tests/contourgl_test.js +++ b/test/jasmine/tests/contourgl_test.js @@ -250,9 +250,9 @@ describe('contourgl plots', function() { return Plotly.relayout(gd, 'xaxis.autorange', true); }).then(function() { expect(scene2d.xaxis.range).toEqual([1, -1]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/densitymapbox_test.js b/test/jasmine/tests/densitymapbox_test.js index 3fb5f67e61f..3e0ef8576ae 100644 --- a/test/jasmine/tests/densitymapbox_test.js +++ b/test/jasmine/tests/densitymapbox_test.js @@ -270,7 +270,7 @@ describe('Test densitymapbox convert:', function() { }); }); -describe('@noCI Test densitymapbox hover:', function() { +describe('Test densitymapbox hover:', function() { var gd; afterEach(function(done) { @@ -375,7 +375,7 @@ describe('@noCI Test densitymapbox hover:', function() { }); }); -describe('@noCI Test densitymapbox interactions:', function() { +describe('Test densitymapbox interactions:', function() { var gd; beforeEach(function() { diff --git a/test/jasmine/tests/draw_newshape_test.js b/test/jasmine/tests/draw_newshape_test.js index e81b969f6b0..669dadef237 100644 --- a/test/jasmine/tests/draw_newshape_test.js +++ b/test/jasmine/tests/draw_newshape_test.js @@ -1089,7 +1089,7 @@ describe('Activate and edit editable shapes', function() { afterEach(destroyGraphDiv); ['mouse'].forEach(function(device) { - it('@flaky reactangle using ' + device, function(done) { + it('reactangle using ' + device, function(done) { var i = 0; // shape index Plotly.newPlot(gd, { @@ -1224,7 +1224,7 @@ describe('Activate and edit editable shapes', function() { .then(done); }); - it('@flaky circle using ' + device, function(done) { + it('circle using ' + device, function(done) { var i = 1; // shape index Plotly.newPlot(gd, { @@ -1281,7 +1281,7 @@ describe('Activate and edit editable shapes', function() { .then(done); }); - it('@flaky closed-path using ' + device, function(done) { + it('closed-path using ' + device, function(done) { var i = 2; // shape index Plotly.newPlot(gd, { @@ -1326,7 +1326,7 @@ describe('Activate and edit editable shapes', function() { .then(done); }); - it('@flaky bezier curves using ' + device, function(done) { + it('bezier curves using ' + device, function(done) { var i = 5; // shape index Plotly.newPlot(gd, { @@ -1371,7 +1371,7 @@ describe('Activate and edit editable shapes', function() { .then(done); }); - it('@flaky multi-cell path using ' + device, function(done) { + it('multi-cell path using ' + device, function(done) { var i = 6; // shape index Plotly.newPlot(gd, { diff --git a/test/jasmine/tests/errorbars_test.js b/test/jasmine/tests/errorbars_test.js index b138705e2e7..9ef256b9727 100644 --- a/test/jasmine/tests/errorbars_test.js +++ b/test/jasmine/tests/errorbars_test.js @@ -79,7 +79,7 @@ describe('errorbar plotting', function() { {xs: 10, xh: 13} ]); - Plotly.restyle(gd, {'error_x.array': [[1]], 'error_y.arrayminus': [[5, 6]]}); + return Plotly.restyle(gd, {'error_x.array': [[1]], 'error_y.arrayminus': [[5, 6]]}); }) .then(function() { countBars(1, 2); @@ -88,7 +88,7 @@ describe('errorbar plotting', function() { {ys: 34, yh: 40} ]); - Plotly.restyle(gd, {'error_x.array': [[7, 8]], 'error_y.arrayminus': [[9]]}); + return Plotly.restyle(gd, {'error_x.array': [[7, 8]], 'error_y.arrayminus': [[9]]}); }) .then(function() { countBars(2, 1); diff --git a/test/jasmine/tests/funnelarea_test.js b/test/jasmine/tests/funnelarea_test.js index 50a6403fa02..99863d4ac81 100644 --- a/test/jasmine/tests/funnelarea_test.js +++ b/test/jasmine/tests/funnelarea_test.js @@ -960,6 +960,7 @@ describe('funnelarea hovering', function() { .then(function() { assertLabel('0\n12|345|678@91\n99@9%'); }) + .catch(failTest) .then(done); }); @@ -981,6 +982,7 @@ describe('funnelarea hovering', function() { .then(function() { assertLabel('D\n0\n4\n14.3%'); }) + .catch(failTest) .then(done); }); @@ -1128,16 +1130,20 @@ describe('Test event data of interactions on a funnelarea plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('should contain the correct fields', function() { @@ -1147,21 +1153,24 @@ describe('Test event data of interactions on a funnelarea plot:', function() { checkEventData(futureData); }); - it('should not contain pointNumber if aggregating', function() { + it('should not contain pointNumber if aggregating', function(done) { var values = gd.data[0].values; var labels = []; for(var i = 0; i < values.length; i++) labels.push(i); Plotly.restyle(gd, { labels: [labels.concat(labels)], values: [values.concat(values)] - }); - - click(pointPos[0], pointPos[1]); - expect(futureData.points.length).toEqual(1); + }) + .then(function() { + click(pointPos[0], pointPos[1]); + expect(futureData.points.length).toEqual(1); - expect(futureData.points[0].pointNumber).toBeUndefined(); - expect(futureData.points[0].i).toBeUndefined(); - expect(futureData.points[0].pointNumbers).toEqual([0, 5]); + expect(futureData.points[0].pointNumber).toBeUndefined(); + expect(futureData.points[0].i).toBeUndefined(); + expect(futureData.points[0].pointNumbers).toEqual([0, 5]); + }) + .catch(failTest) + .then(done); }); }); @@ -1175,21 +1184,25 @@ describe('Test event data of interactions on a funnelarea plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('does not respond to right-click', function() { click(pointPos[0], pointPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); // TODO: 'should contain the correct fields' // This test passed previously, but only because assets/click @@ -1210,12 +1223,15 @@ describe('Test event data of interactions on a funnelarea plot:', function() { var futureData; beforeEach(function(done) { - futureData = undefined; - Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.newPlot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_hover', function(data) { - futureData = data; - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { @@ -1227,13 +1243,17 @@ describe('Test event data of interactions on a funnelarea plot:', function() { it('should not emit a hover if you\'re dragging', function() { gd._dragging = true; mouseEvent('mouseover', pointPos[0], pointPos[1]); - expect(futureData).toBeUndefined(); + expect(futureData).toBe(null); }); - it('should not emit a hover if hover is disabled', function() { - Plotly.relayout(gd, 'hovermode', false); - mouseEvent('mouseover', pointPos[0], pointPos[1]); - expect(futureData).toBeUndefined(); + it('should not emit a hover if hover is disabled', function(done) { + Plotly.relayout(gd, 'hovermode', false) + .then(function() { + mouseEvent('mouseover', pointPos[0], pointPos[1]); + expect(futureData).toBe(null); + }) + .catch(failTest) + .then(done); }); }); @@ -1241,12 +1261,15 @@ describe('Test event data of interactions on a funnelarea plot:', function() { var futureData; beforeEach(function(done) { - futureData = undefined; - Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.newPlot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_unhover', function(data) { - futureData = data; - }); + gd.on('plotly_unhover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { @@ -1258,7 +1281,7 @@ describe('Test event data of interactions on a funnelarea plot:', function() { it('should not emit an unhover if you didn\'t first hover', function() { mouseEvent('mouseout', pointPos[0], pointPos[1]); - expect(futureData).toBeUndefined(); + expect(futureData).toBe(null); }); }); }); @@ -1300,6 +1323,7 @@ describe('funnelarea relayout', function() { var slices = d3.selectAll(SLICES_SELECTOR); slices.each(checkRelayoutColor); }) + .catch(failTest) .then(done); }); }); diff --git a/test/jasmine/tests/fx_test.js b/test/jasmine/tests/fx_test.js index 0b2910342fc..c7b3d4d09d1 100644 --- a/test/jasmine/tests/fx_test.js +++ b/test/jasmine/tests/fx_test.js @@ -4,6 +4,7 @@ var d3 = require('@plotly/d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var supplyAllDefaults = require('../assets/supply_defaults'); +var failTest = require('../assets/fail_test'); describe('Fx defaults', function() { 'use strict'; @@ -268,6 +269,6 @@ describe('relayout', function() { return Plotly.relayout(gd, 'xaxis.fixedrange', false); }).then(function() { assertMainDrag('ew-resize', true); - }).then(done); + }).catch(failTest).then(done); }); }); diff --git a/test/jasmine/tests/geo_test.js b/test/jasmine/tests/geo_test.js index 91432a3ea2a..2a0fdcc8dcb 100644 --- a/test/jasmine/tests/geo_test.js +++ b/test/jasmine/tests/geo_test.js @@ -874,7 +874,8 @@ describe('Test geo interactions', function() { 'geo.projection.rotation': { lon: 82, lat: -19 } }; - Plotly.relayout(gd, update).then(function() { + Plotly.relayout(gd, update) + .then(function() { setTimeout(function() { mouseEvent('mousemove', 288, 170); @@ -1063,9 +1064,9 @@ describe('Test geo interactions', function() { }).then(function() { expect(countTraces('scattergeo')).toBe(1); expect(countTraces('choropleth')).toBe(1); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should toggle choropleth elements', function(done) { @@ -1080,9 +1081,9 @@ describe('Test geo interactions', function() { }).then(function() { expect(countTraces('scattergeo')).toBe(1); expect(countTraces('choropleth')).toBe(1); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -1112,9 +1113,9 @@ describe('Test geo interactions', function() { expect(countTraces('choropleth')).toBe(0); expect(countGeos()).toBe(0); expect(countColorBars()).toBe(0); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -1306,9 +1307,9 @@ describe('Test geo interactions', function() { checkScatterGeoOrder(); expect(countChoroplethPaths()).toBe(N_LOCATIONS_AT_START - 1); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should be able to update line/marker/text nodes and choropleth paths', function(done) { @@ -1333,9 +1334,9 @@ describe('Test geo interactions', function() { checkScatterGeoOrder(); expect(countChoroplethPaths()).toBe(locationsQueue.length); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); }); @@ -1809,17 +1810,20 @@ describe('Test event property of interactions on a geo plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - futureData = undefined; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('should contain the correct fields', function() { @@ -1859,22 +1863,25 @@ describe('Test event property of interactions on a geo plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - futureData = undefined; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('does not support right-click', function() { click(pointPos[0], pointPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); // TODO: 'should contain the correct fields' // This test passed previously, but only because assets/click @@ -1911,11 +1918,15 @@ describe('Test event property of interactions on a geo plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_hover', function(data) { - futureData = data; - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { @@ -1950,11 +1961,15 @@ describe('Test event property of interactions on a geo plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_unhover', function(data) { - futureData = data; - }); + gd.on('plotly_unhover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function(done) { diff --git a/test/jasmine/tests/gl3d_hover_click_test.js b/test/jasmine/tests/gl3d_hover_click_test.js index 9b77e2d6151..2747ff630ec 100644 --- a/test/jasmine/tests/gl3d_hover_click_test.js +++ b/test/jasmine/tests/gl3d_hover_click_test.js @@ -327,6 +327,7 @@ describe('Test gl3d trace click/hover:', function() { fontColor: 'rgb(255, 255, 255)' }, 'initial'); }) + .catch(failTest) .then(done); }); @@ -446,6 +447,7 @@ describe('Test gl3d trace click/hover:', function() { .then(function() { assertHoverText(null, null, null, '!!! 43 !!!'); }) + .catch(failTest) .then(done); }); @@ -471,6 +473,7 @@ describe('Test gl3d trace click/hover:', function() { .then(function() { assertEventData(140.72, -96.97, -96.97, 0, 2); }) + .catch(failTest) .then(done); }); @@ -547,7 +550,7 @@ describe('Test gl3d trace click/hover:', function() { .then(done); }); - it('@gl should display correct face colors', function(done) { + it('@noCI @gl should display correct face colors', function(done) { var fig = mesh3dcoloringMock; Plotly.newPlot(gd, fig) @@ -600,7 +603,7 @@ describe('Test gl3d trace click/hover:', function() { .then(done); }); - it('@gl should display correct face intensities (uniform grid)', function(done) { + it('@noCI @gl should display correct face intensities (uniform grid)', function(done) { var fig = mesh3dcellIntensityMock; Plotly.newPlot(gd, fig) @@ -631,7 +634,7 @@ describe('Test gl3d trace click/hover:', function() { .then(done); }); - it('@gl should display correct face intensities (non-uniform grid)', function(done) { + it('@noCI @gl should display correct face intensities (non-uniform grid)', function(done) { var fig = mesh3dbunnyMock; Plotly.newPlot(gd, fig) @@ -662,7 +665,7 @@ describe('Test gl3d trace click/hover:', function() { .then(done); }); - it('@gl should display correct face intensities *alpha-hull* case', function(done) { + it('@noCI @gl should display correct face intensities *alpha-hull* case', function(done) { var fig = { data: [{ type: 'mesh3d', @@ -706,7 +709,7 @@ describe('Test gl3d trace click/hover:', function() { .then(done); }); - it('@gl should display correct face intensities *delaunay* case', function(done) { + it('@noCI @gl should display correct face intensities *delaunay* case', function(done) { var fig = { data: [{ type: 'mesh3d', diff --git a/test/jasmine/tests/gl3d_plot_interact_test.js b/test/jasmine/tests/gl3d_plot_interact_test.js index 210dc862871..2adb6ccfbb9 100644 --- a/test/jasmine/tests/gl3d_plot_interact_test.js +++ b/test/jasmine/tests/gl3d_plot_interact_test.js @@ -78,7 +78,7 @@ describe('Test gl3d before/after plot', function() { gd = createGraphDiv(); return Plotly.plot(gd, _mock); }) - .then(delay(20)) + .then(delay(100)) .then(function() { var cameraIn = gd._fullLayout.scene.camera; expect(cameraIn.up.x).toEqual(0, 'cameraIn.up.x'); @@ -91,7 +91,7 @@ describe('Test gl3d before/after plot', function() { expect(cameraIn.eye.y).toEqual(1.2, 'cameraIn.eye.y'); expect(cameraIn.eye.z).toEqual(1.2, 'cameraIn.eye.z'); }) - .then(delay(20)) + .then(delay(100)) .then(function() { var cameraBefore = gd._fullLayout.scene._scene.camera; expect(cameraBefore.up[0]).toBeCloseTo(0, 2, 'cameraBefore.up[0]'); @@ -106,7 +106,7 @@ describe('Test gl3d before/after plot', function() { expect(cameraBefore.mouseListener.enabled === true); }) .then(_clickThere) - .then(delay(20)) + .then(delay(100)) .then(function() { var cameraAfter = gd._fullLayout.scene._scene.camera; expect(cameraAfter.up[0]).toBeCloseTo(0, 2, 'cameraAfter.up[0]'); @@ -121,7 +121,7 @@ describe('Test gl3d before/after plot', function() { expect(cameraAfter.mouseListener.enabled === true); }) .then(_clickOtherplace) - .then(delay(20)) + .then(delay(100)) .then(function() { var cameraFinal = gd._fullLayout.scene._scene.camera; expect(cameraFinal.up[0]).toBeCloseTo(0, 2, 'cameraFinal.up[0]'); @@ -135,6 +135,7 @@ describe('Test gl3d before/after plot', function() { expect(cameraFinal.eye[2]).not.toBeCloseTo(1.2, 2, 'cameraFinal.eye[2]'); expect(cameraFinal.mouseListener.enabled === true); }) + .catch(failTest) .then(done); }); }); @@ -172,10 +173,11 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.dragmode === 'orbit').toBe(true); }) + .catch(failTest) .then(done); }); @@ -199,10 +201,11 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.dragmode === 'turntable').toBe(true); }) + .catch(failTest) .then(done); }); @@ -221,10 +224,11 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.dragmode === 'turntable').toBe(true); }) + .catch(failTest) .then(done); }); @@ -248,10 +252,11 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.dragmode === 'turntable').toBe(true); }) + .catch(failTest) .then(done); }); @@ -275,10 +280,11 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.dragmode === 'turntable').not.toBe(true); }) + .catch(failTest) .then(done); }); @@ -297,11 +303,12 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.camera.projection.type === 'perspective').toBe(true); expect(gd._fullLayout.scene._scene.camera._ortho === false).toBe(true); }) + .catch(failTest) .then(done); }); @@ -323,11 +330,12 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { expect(gd._fullLayout.scene.camera.projection.type === 'orthographic').toBe(true); expect(gd._fullLayout.scene._scene.camera._ortho === true).toBe(true); }) + .catch(failTest) .then(done); }); @@ -349,7 +357,7 @@ describe('Test gl3d plots', function() { } } }) - .then(delay(20)) + .then(function() { return Plotly.relayout(gd, 'scene.camera.projection.type', 'orthographic'); }) @@ -378,6 +386,7 @@ describe('Test gl3d plots', function() { expect(gd._fullLayout.scene.camera.projection.type === 'perspective').toBe(true); expect(gd._fullLayout.scene._scene.camera._ortho === false).toBe(true); }) + .catch(failTest) .then(done); }); @@ -459,7 +468,7 @@ describe('Test gl3d modebar handlers - perspective case', function() { }; Plotly.plot(gd, mock) - .then(delay(20)) + .then(function() { modeBar = gd._fullLayout._modeBar; }) @@ -561,18 +570,22 @@ describe('Test gl3d modebar handlers - perspective case', function() { expect(gd._fullLayout.scene._scene.viewInitial.eye).toEqual({ x: 0.1, y: 0.1, z: 1 }); expect(gd._fullLayout.scene2._scene.viewInitial.eye).toEqual({ x: 2.5, y: 2.5, z: 2.5 }); - gd.once('plotly_relayout', function() { - assertScenes(gd._fullLayout, 'camera.eye.x', 1.25); - assertScenes(gd._fullLayout, 'camera.eye.y', 1.25); - assertScenes(gd._fullLayout, 'camera.eye.z', 1.25); + return new Promise(function(resolve) { + gd.once('plotly_relayout', function() { + assertScenes(gd._fullLayout, 'camera.eye.x', 1.25); + assertScenes(gd._fullLayout, 'camera.eye.y', 1.25); + assertScenes(gd._fullLayout, 'camera.eye.z', 1.25); - expect(gd._fullLayout.scene._scene.getCamera().eye.z).toBeCloseTo(1.25); - expect(gd._fullLayout.scene2._scene.getCamera().eye.z).toBeCloseTo(1.25); + expect(gd._fullLayout.scene._scene.getCamera().eye.z).toBeCloseTo(1.25); + expect(gd._fullLayout.scene2._scene.getCamera().eye.z).toBeCloseTo(1.25); - done(); - }); + resolve(); + }); - buttonDefault.click(); + buttonDefault.click(); + }) + .catch(failTest) + .then(done); }); it('@gl button resetCameraDefault3d should reset to initial aspectmode & aspectratios', function(done) { @@ -584,21 +597,25 @@ describe('Test gl3d modebar handlers - perspective case', function() { expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 }); expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 }); - gd.once('plotly_relayout', function() { - expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('auto'); - expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual'); - - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); - - done(); - }); + return new Promise(function(resolve) { + gd.once('plotly_relayout', function() { + expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('auto'); + expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual'); + + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); + + resolve(); + }); - buttonDefault.click(); + buttonDefault.click(); + }) + .catch(failTest) + .then(done); }); it('@gl button resetCameraLastSave3d should reset to initial aspectmode & aspectratios', function(done) { @@ -610,18 +627,22 @@ describe('Test gl3d modebar handlers - perspective case', function() { expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 }); expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 }); - gd.once('plotly_relayout', function() { - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); - - done(); - }); + return new Promise(function(resolve) { + gd.once('plotly_relayout', function() { + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); + + resolve(); + }); - buttonDefault.click(); + buttonDefault.click(); + }) + .catch(failTest) + .then(done); }); it('@gl button resetCameraLastSave3d should reset camera to default', function(done) { @@ -694,6 +715,7 @@ describe('Test gl3d modebar handlers - perspective case', function() { assertCameraEye(gd._fullLayout.scene, 0.1, 0.1, 4); assertCameraEye(gd._fullLayout.scene2, 2.5, 2.5, 5); }) + .catch(failTest) .then(done); }); }); @@ -748,7 +770,7 @@ describe('Test gl3d modebar handlers - orthographic case', function() { }; Plotly.plot(gd, mock) - .then(delay(20)) + .then(function() { modeBar = gd._fullLayout._modeBar; }) @@ -766,18 +788,22 @@ describe('Test gl3d modebar handlers - orthographic case', function() { expect(gd._fullLayout.scene._scene.viewInitial.eye).toEqual({ x: 0.1, y: 0.1, z: 1 }); expect(gd._fullLayout.scene2._scene.viewInitial.eye).toEqual({ x: 2.5, y: 2.5, z: 2.5 }); - gd.once('plotly_relayout', function() { - assertScenes(gd._fullLayout, 'camera.eye.x', 1.25); - assertScenes(gd._fullLayout, 'camera.eye.y', 1.25); - assertScenes(gd._fullLayout, 'camera.eye.z', 1.25); + return new Promise(function(resolve) { + gd.once('plotly_relayout', function() { + assertScenes(gd._fullLayout, 'camera.eye.x', 1.25); + assertScenes(gd._fullLayout, 'camera.eye.y', 1.25); + assertScenes(gd._fullLayout, 'camera.eye.z', 1.25); - expect(gd._fullLayout.scene._scene.getCamera().eye.z).toBeCloseTo(1.25); - expect(gd._fullLayout.scene2._scene.getCamera().eye.z).toBeCloseTo(1.25); + expect(gd._fullLayout.scene._scene.getCamera().eye.z).toBeCloseTo(1.25); + expect(gd._fullLayout.scene2._scene.getCamera().eye.z).toBeCloseTo(1.25); - done(); - }); + resolve(); + }); - buttonDefault.click(); + buttonDefault.click(); + }) + .catch(failTest) + .then(done); }); it('@gl button resetCameraDefault3d should reset to initial aspectmode & aspectratios', function(done) { @@ -789,21 +815,25 @@ describe('Test gl3d modebar handlers - orthographic case', function() { expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 }); expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 }); - gd.once('plotly_relayout', function() { - expect(gd._fullLayout.scene._scene.aspectmode).toEqual(undefined); - expect(gd._fullLayout.scene2._scene.aspectmode).toEqual(undefined); - - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); - - done(); - }); + return new Promise(function(resolve) { + gd.once('plotly_relayout', function() { + expect(gd._fullLayout.scene._scene.aspectmode).toEqual(undefined); + expect(gd._fullLayout.scene2._scene.aspectmode).toEqual(undefined); + + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); + + resolve(); + }); - buttonDefault.click(); + buttonDefault.click(); + }) + .catch(failTest) + .then(done); }); it('@gl button resetCameraLastSave3d should reset to initial aspectmode & aspectratios', function(done) { @@ -815,21 +845,25 @@ describe('Test gl3d modebar handlers - orthographic case', function() { expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 }); expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 }); - gd.once('plotly_relayout', function() { - expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('auto'); - expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual'); - - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); - expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); - expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); - - done(); - }); + return new Promise(function(resolve) { + gd.once('plotly_relayout', function() { + expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('auto'); + expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual'); + + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1); + expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2); + expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1); + + resolve(); + }); - buttonDefault.click(); + buttonDefault.click(); + }) + .catch(failTest) + .then(done); }); it('@gl button resetCameraLastSave3d should reset camera to default', function(done) { @@ -902,6 +936,7 @@ describe('Test gl3d modebar handlers - orthographic case', function() { assertCameraEye(gd._fullLayout.scene, 0.1, 0.1, 4); assertCameraEye(gd._fullLayout.scene2, 2.5, 2.5, 5); }) + .catch(failTest) .then(done); }); }); @@ -1216,7 +1251,7 @@ describe('Test gl3d drag and wheel interactions', function() { var modeBar; Plotly.plot(gd, mock) - .then(delay(20)) + .then(function() { modeBar = gd._fullLayout._modeBar; }) @@ -1620,23 +1655,16 @@ describe('Test gl3d relayout calls', function() { }) .then(function() { expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective'); - }) - .then(function() { + return Plotly.relayout(gd, 'scene.camera.projection.type', 'orthographic'); }) .then(function() { expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic'); - }) - .then(function() { - return selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click(); - }) - .then(function() { + + selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click(); expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic'); - }) - .then(function() { - return selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click(); - }) - .then(function() { + + selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click(); expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic'); }) .catch(failTest) @@ -1670,23 +1698,16 @@ describe('Test gl3d relayout calls', function() { }) .then(function() { expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic'); - }) - .then(function() { + return Plotly.relayout(gd, 'scene.camera.projection.type', 'perspective'); }) .then(function() { expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective'); - }) - .then(function() { - return selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click(); - }) - .then(function() { + + selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click(); expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective'); - }) - .then(function() { - return selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click(); - }) - .then(function() { + + selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click(); expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective'); }) .catch(failTest) @@ -2094,6 +2115,7 @@ describe('Test removal of gl contexts', function() { Plots.cleanPlot([], {}, gd._fullData, gd._fullLayout); expect(gd._fullLayout.scene._scene.glplot).toBe(null); }) + .catch(failTest) .then(done); }); @@ -2138,6 +2160,7 @@ describe('Test removal of gl contexts', function() { firstCanvas !== secondCanvas && firstGlContext.isContextLost() ); }) + .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/histogram2d_test.js b/test/jasmine/tests/histogram2d_test.js index cab4e2523e7..a03523ee710 100644 --- a/test/jasmine/tests/histogram2d_test.js +++ b/test/jasmine/tests/histogram2d_test.js @@ -263,57 +263,71 @@ describe('Test histogram2d', function() { expect(gd.data[0].autobiny).toBeUndefined(); } - it('handles autobin correctly on restyles', function() { + it('handles autobin correctly on restyles', function(done) { var x1 = [ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]; var y1 = [ 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]; - Plotly.newPlot(gd, [{type: 'histogram2d', x: x1, y: y1}]); - _assert( - {start: 0.5, end: 4.5, size: 1}, - {start: 0.5, end: 4.5, size: 1}, - undefined, undefined); - - // same range but fewer samples increases sizes - Plotly.restyle(gd, {x: [[1, 3, 4]], y: [[1, 2, 4]]}); - _assert( - {start: -0.5, end: 5.5, size: 2}, - {start: -0.5, end: 5.5, size: 2}, - undefined, undefined); - - // larger range - Plotly.restyle(gd, {x: [[10, 30, 40]], y: [[10, 20, 40]]}); - _assert( - {start: -0.5, end: 59.5, size: 20}, - {start: -0.5, end: 59.5, size: 20}, - undefined, undefined); - - // explicit changes to bin settings - Plotly.restyle(gd, 'xbins.start', 12); - _assert( - {start: 12, end: 59.5, size: 20}, - {start: -0.5, end: 59.5, size: 20}, - {start: 12}, undefined); - - Plotly.restyle(gd, {'ybins.end': 12, 'ybins.size': 3}); - _assert( - {start: 12, end: 59.5, size: 20}, - // with the new autobin algo, start responds to autobin - {start: 8.5, end: 12, size: 3}, - {start: 12}, - {end: 12, size: 3}); - - // restart autobin - Plotly.restyle(gd, {autobinx: true, autobiny: true}); - _assert( - {start: -0.5, end: 59.5, size: 20}, - {start: -0.5, end: 59.5, size: 20}, - undefined, undefined); + Plotly.newPlot(gd, [{type: 'histogram2d', x: x1, y: y1}]) + .then(function() { + _assert( + {start: 0.5, end: 4.5, size: 1}, + {start: 0.5, end: 4.5, size: 1}, + undefined, undefined); + + // same range but fewer samples increases sizes + return Plotly.restyle(gd, {x: [[1, 3, 4]], y: [[1, 2, 4]]}); + }) + .then(function() { + _assert( + {start: -0.5, end: 5.5, size: 2}, + {start: -0.5, end: 5.5, size: 2}, + undefined, undefined); + + // larger range + return Plotly.restyle(gd, {x: [[10, 30, 40]], y: [[10, 20, 40]]}); + }) + .then(function() { + _assert( + {start: -0.5, end: 59.5, size: 20}, + {start: -0.5, end: 59.5, size: 20}, + undefined, undefined); + + // explicit changes to bin settings + return Plotly.restyle(gd, 'xbins.start', 12); + }) + .then(function() { + _assert( + {start: 12, end: 59.5, size: 20}, + {start: -0.5, end: 59.5, size: 20}, + {start: 12}, undefined); + + return Plotly.restyle(gd, {'ybins.end': 12, 'ybins.size': 3}); + }) + .then(function() { + _assert( + {start: 12, end: 59.5, size: 20}, + // with the new autobin algo, start responds to autobin + {start: 8.5, end: 12, size: 3}, + {start: 12}, + {end: 12, size: 3}); + + // restart autobin + return Plotly.restyle(gd, {autobinx: true, autobiny: true}); + }) + .then(function() { + _assert( + {start: -0.5, end: 59.5, size: 20}, + {start: -0.5, end: 59.5, size: 20}, + undefined, undefined); + }) + .catch(failTest) + .then(done); }); - it('respects explicit autobin: false as a one-time autobin', function() { + it('respects explicit autobin: false as a one-time autobin', function(done) { // patched in for backward compat, but there aren't really // autobinx/autobiny attributes anymore var x1 = [ @@ -323,12 +337,18 @@ describe('Test histogram2d', function() { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]; var binSpec = {start: 0.5, end: 4.5, size: 1}; - Plotly.newPlot(gd, [{type: 'histogram2d', x: x1, y: y1, autobinx: false, autobiny: false}]); - _assert(binSpec, binSpec, binSpec, binSpec); + Plotly.newPlot(gd, [{type: 'histogram2d', x: x1, y: y1, autobinx: false, autobiny: false}]) + .then(function() { + _assert(binSpec, binSpec, binSpec, binSpec); - // with autobin false this will no longer update the bins. - Plotly.restyle(gd, {x: [[1, 3, 4]], y: [[1, 2, 4]]}); - _assert(binSpec, binSpec, binSpec, binSpec); + // with autobin false this will no longer update the bins. + return Plotly.restyle(gd, {x: [[1, 3, 4]], y: [[1, 2, 4]]}); + }) + .then(function() { + _assert(binSpec, binSpec, binSpec, binSpec); + }) + .catch(failTest) + .then(done); }); }); }); diff --git a/test/jasmine/tests/histogram_test.js b/test/jasmine/tests/histogram_test.js index 064cac6678a..88b600ed583 100644 --- a/test/jasmine/tests/histogram_test.js +++ b/test/jasmine/tests/histogram_test.js @@ -1109,78 +1109,108 @@ describe('Test histogram', function() { afterEach(destroyGraphDiv); - it('should update autobins correctly when restyling', function() { + it('should update autobins correctly when restyling', function(done) { // note: I'm *not* testing what this does to gd.data, as that's // really a matter of convenience and will perhaps change later (v2?) var data1 = [1.5, 2, 2, 3, 3, 3, 4, 4, 5]; - Plotly.plot(gd, [{x: data1, type: 'histogram' }]); - expect(gd._fullData[0].xbins).toEqual({start: 1, end: 6, size: 1}); - expect(gd._fullData[0].nbinsx).toBe(0); - - // same range but fewer samples changes autobin size - var data2 = [1.5, 5]; - Plotly.restyle(gd, 'x', [data2]); - expect(gd._fullData[0].xbins).toEqual({start: -2.5, end: 7.5, size: 5}); - expect(gd._fullData[0].nbinsx).toBe(0); - - // different range - var data3 = [10, 20.2, 20, 30, 30, 30, 40, 40, 50]; - Plotly.restyle(gd, 'x', [data3]); - expect(gd._fullData[0].xbins).toEqual({start: 5, end: 55, size: 10}); - expect(gd._fullData[0].nbinsx).toBe(0); - - // explicit change to start does not update anything else - Plotly.restyle(gd, 'xbins.start', 3); - expect(gd._fullData[0].xbins).toEqual({start: 3, end: 55, size: 10}); - expect(gd._fullData[0].nbinsx).toBe(0); - - // restart autobin - Plotly.restyle(gd, 'autobinx', true); - expect(gd._fullData[0].xbins).toEqual({start: 5, end: 55, size: 10}); - expect(gd._fullData[0].nbinsx).toBe(0); - - // explicit end does not update anything else - Plotly.restyle(gd, 'xbins.end', 43); - expect(gd._fullData[0].xbins).toEqual({start: 5, end: 43, size: 10}); - expect(gd._fullData[0].nbinsx).toBe(0); - - // nbins would update all three, but explicit end is honored - Plotly.restyle(gd, 'nbinsx', 3); - expect(gd._fullData[0].xbins).toEqual({start: 0, end: 43, size: 20}); - expect(gd._fullData[0].nbinsx).toBe(3); - - // explicit size updates auto start *and* end, and moots nbins - Plotly.restyle(gd, {'xbins.end': null, 'xbins.size': 2}); - expect(gd._fullData[0].xbins).toEqual({start: 9, end: 51, size: 2}); - expect(gd._fullData[0].nbinsx).toBeUndefined(); + Plotly.plot(gd, [{x: data1, type: 'histogram' }]) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 1, end: 6, size: 1}); + expect(gd._fullData[0].nbinsx).toBe(0); + + // same range but fewer samples changes autobin size + var data2 = [1.5, 5]; + return Plotly.restyle(gd, 'x', [data2]); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: -2.5, end: 7.5, size: 5}); + expect(gd._fullData[0].nbinsx).toBe(0); + + // different range + var data3 = [10, 20.2, 20, 30, 30, 30, 40, 40, 50]; + return Plotly.restyle(gd, 'x', [data3]); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 5, end: 55, size: 10}); + expect(gd._fullData[0].nbinsx).toBe(0); + + // explicit change to start does not update anything else + return Plotly.restyle(gd, 'xbins.start', 3); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 3, end: 55, size: 10}); + expect(gd._fullData[0].nbinsx).toBe(0); + + // restart autobin + return Plotly.restyle(gd, 'autobinx', true); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 5, end: 55, size: 10}); + expect(gd._fullData[0].nbinsx).toBe(0); + + // explicit end does not update anything else + return Plotly.restyle(gd, 'xbins.end', 43); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 5, end: 43, size: 10}); + expect(gd._fullData[0].nbinsx).toBe(0); + + // nbins would update all three, but explicit end is honored + return Plotly.restyle(gd, 'nbinsx', 3); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 0, end: 43, size: 20}); + expect(gd._fullData[0].nbinsx).toBe(3); + + // explicit size updates auto start *and* end, and moots nbins + return Plotly.restyle(gd, {'xbins.end': null, 'xbins.size': 2}); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 9, end: 51, size: 2}); + expect(gd._fullData[0].nbinsx).toBeUndefined(); + }) + .catch(failTest) + .then(done); }); - it('respects explicit autobin: false as a one-time autobin', function() { + it('respects explicit autobin: false as a one-time autobin', function(done) { var data1 = [1.5, 2, 2, 3, 3, 3, 4, 4, 5]; - Plotly.plot(gd, [{x: data1, type: 'histogram', autobinx: false }]); - // we have no bins, so even though autobin is false we have to autobin once - // but for backward compat. calc pushes these bins back into gd.data - // even though there's no `autobinx` attribute anymore. - expect(gd._fullData[0].xbins).toEqual({start: 1, end: 6, size: 1}); - expect(gd.data[0].xbins).toEqual({start: 1, end: 6, size: 1}); - - // since autobin is false, this will not change the bins - var data2 = [1.5, 5]; - Plotly.restyle(gd, 'x', [data2]); - expect(gd._fullData[0].xbins).toEqual({start: 1, end: 6, size: 1}); + Plotly.plot(gd, [{x: data1, type: 'histogram', autobinx: false }]) + .then(function() { + // we have no bins, so even though autobin is false we have to autobin once + // but for backward compat. calc pushes these bins back into gd.data + // even though there's no `autobinx` attribute anymore. + expect(gd._fullData[0].xbins).toEqual({start: 1, end: 6, size: 1}); + expect(gd.data[0].xbins).toEqual({start: 1, end: 6, size: 1}); + + // since autobin is false, this will not change the bins + var data2 = [1.5, 5]; + return Plotly.restyle(gd, 'x', [data2]); + }) + .then(function() { + expect(gd._fullData[0].xbins).toEqual({start: 1, end: 6, size: 1}); + }) + .catch(failTest) + .then(done); }); - it('allows changing axis type with new x data', function() { + it('allows changing axis type with new x data', function(done) { var x1 = [1, 1, 1, 1, 2, 2, 2, 3, 3, 4]; var x2 = ['2017-01-01', '2017-01-01', '2017-01-01', '2017-01-02', '2017-01-02', '2017-01-03']; - Plotly.newPlot(gd, [{x: x1, type: 'histogram'}]); - expect(gd._fullLayout.xaxis.type).toBe('linear'); - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.5, 4.5], 3); + Plotly.newPlot(gd, [{x: x1, type: 'histogram'}]) + .then(function() { + expect(gd._fullLayout.xaxis.type).toBe('linear'); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.5, 4.5], 3); - Plotly.restyle(gd, {x: [x2]}); - expect(gd._fullLayout.xaxis.type).toBe('date'); - expect(gd._fullLayout.xaxis.range).toEqual(['2016-12-31 12:00', '2017-01-03 12:00']); + return Plotly.restyle(gd, {x: [x2]}); + }) + .then(function() { + expect(gd._fullLayout.xaxis.type).toBe('date'); + expect(gd._fullLayout.xaxis.range).toEqual(['2016-12-31 12:00', '2017-01-03 12:00']); + }) + .catch(failTest) + .then(done); }); it('can resize a plot with several histograms', function(done) { diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index 8899802f7c2..48f98c7059f 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -553,6 +553,7 @@ describe('hover info', function() { nums: 'PV learning ...' }); }) + .catch(failTest) .then(done); }); }); @@ -1391,25 +1392,33 @@ describe('hover info', function() { this.gd = createGraphDiv(); }); - it('should display the correct format when ticklabels true', function() { - Plotly.plot(this.gd, data, layout); - mouseEvent('mousemove', 303, 213); + it('should display the correct format when ticklabels true', function(done) { + Plotly.plot(this.gd, data, layout) + .then(function() { + mouseEvent('mousemove', 303, 213); - assertHoverLabelContent({ - nums: '0.23', - axis: '2' - }); + assertHoverLabelContent({ + nums: '0.23', + axis: '2' + }); + }) + .catch(failTest) + .then(done); }); - it('should display the correct format when ticklabels false', function() { + it('should display the correct format when ticklabels false', function(done) { layout.yaxis.showticklabels = false; - Plotly.plot(this.gd, data, layout); - mouseEvent('mousemove', 303, 213); + Plotly.plot(this.gd, data, layout) + .then(function() { + mouseEvent('mousemove', 303, 213); - assertHoverLabelContent({ - nums: '0.23', - axis: '2' - }); + assertHoverLabelContent({ + nums: '0.23', + axis: '2' + }); + }) + .catch(failTest) + .then(done); }); }); @@ -1923,7 +1932,7 @@ describe('hover info', function() { } }) .then(function() { - Plotly.restyle(gd, 'hovertemplate', '%{y:$010,.2f}trace 0'); + return Plotly.restyle(gd, 'hovertemplate', '%{y:$010,.2f}trace 0'); }) .then(function() { Fx.hover('graph', evt, 'xy'); @@ -2408,6 +2417,7 @@ describe('hover info on overlaid subplots', function() { axis: '1' }); }) + .catch(failTest) .then(done); }); }); @@ -2473,6 +2483,7 @@ describe('hover after resizing', function() { .then(function() { return check(pos1, [null, null, null], 'back to initial, not showing blank spot'); }) + .catch(failTest) .then(done); }); }); @@ -2505,7 +2516,9 @@ describe('hover on fill', function() { assertLabelsCorrect([242, 142], [252, 133.8], 'trace 2'); assertLabelsCorrect([242, 292], [233, 210], 'trace 1'); assertLabelsCorrect([147, 252], [158.925, 248.1], 'trace 0'); - }).then(done); + }) + .catch(failTest) + .then(done); }); it('should always show one label in the right place (symmetric fill edge case)', function(done) { @@ -4047,45 +4060,51 @@ describe('hover distance', function() { }); }); - it('responds to hoverdistance change', function() { + it('responds to hoverdistance change', function(done) { var gd = document.getElementById('graph'); var evt = { xpx: 475, ypx: 180 }; - Plotly.relayout(gd, 'hoverdistance', 30); - - Fx.hover('graph', evt, 'xy'); + Plotly.relayout(gd, 'hoverdistance', 30) + .then(function() { + Fx.hover('graph', evt, 'xy'); - var hoverTrace = gd._hoverdata[0]; + var hoverTrace = gd._hoverdata[0]; - expect(hoverTrace.curveNumber).toEqual(0); - expect(hoverTrace.pointNumber).toEqual(1); - expect(hoverTrace.x).toEqual(2); - expect(hoverTrace.y).toEqual(3); + expect(hoverTrace.curveNumber).toEqual(0); + expect(hoverTrace.pointNumber).toEqual(1); + expect(hoverTrace.x).toEqual(2); + expect(hoverTrace.y).toEqual(3); - assertHoverLabelContent({ - nums: '(2, 3)', - name: 'trace 0' - }); + assertHoverLabelContent({ + nums: '(2, 3)', + name: 'trace 0' + }); + }) + .catch(failTest) + .then(done); }); it('correctly responds to setting the hoverdistance to -1 by increasing ' + - 'the range of search for points to hover to Infinity', function() { + 'the range of search for points to hover to Infinity', function(done) { var gd = document.getElementById('graph'); var evt = { xpx: 475, ypx: 180 }; - Plotly.relayout(gd, 'hoverdistance', -1); - - Fx.hover('graph', evt, 'xy'); + Plotly.relayout(gd, 'hoverdistance', -1) + .then(function() { + Fx.hover('graph', evt, 'xy'); - var hoverTrace = gd._hoverdata[0]; + var hoverTrace = gd._hoverdata[0]; - expect(hoverTrace.curveNumber).toEqual(0); - expect(hoverTrace.pointNumber).toEqual(1); - expect(hoverTrace.x).toEqual(2); - expect(hoverTrace.y).toEqual(3); + expect(hoverTrace.curveNumber).toEqual(0); + expect(hoverTrace.pointNumber).toEqual(1); + expect(hoverTrace.x).toEqual(2); + expect(hoverTrace.y).toEqual(3); - assertHoverLabelContent({ - nums: '(2, 3)', - name: 'trace 0' - }); + assertHoverLabelContent({ + nums: '(2, 3)', + name: 'trace 0' + }); + }) + .catch(failTest) + .then(done); }); }); @@ -4124,35 +4143,41 @@ describe('hover distance', function() { }); }); - it('responds to hoverdistance change from 10 to 30 (part 1)', function() { + it('responds to hoverdistance change from 10 to 30 (part 1)', function(done) { var gd = document.getElementById('graph'); var evt = { xpx: 450, ypx: 155 }; - Plotly.relayout(gd, 'hoverdistance', 10); - - Fx.hover('graph', evt, 'xy'); + Plotly.relayout(gd, 'hoverdistance', 10) + .then(function() { + Fx.hover('graph', evt, 'xy'); - expect(gd._hoverdata).toEqual(undefined); + expect(gd._hoverdata).toEqual(undefined); + }) + .catch(failTest) + .then(done); }); - it('responds to hoverdistance change from 10 to 30 (part 2)', function() { + it('responds to hoverdistance change from 10 to 30 (part 2)', function(done) { var gd = document.getElementById('graph'); var evt = { xpx: 450, ypx: 155 }; - Plotly.relayout(gd, 'hoverdistance', 30); - - Fx.hover('graph', evt, 'xy'); + Plotly.relayout(gd, 'hoverdistance', 30) + .then(function() { + Fx.hover('graph', evt, 'xy'); - var hoverTrace = gd._hoverdata[0]; + var hoverTrace = gd._hoverdata[0]; - expect(hoverTrace.curveNumber).toEqual(0); - expect(hoverTrace.pointNumber).toEqual(1); - expect(hoverTrace.x).toEqual(2); - expect(hoverTrace.y).toEqual(3); + expect(hoverTrace.curveNumber).toEqual(0); + expect(hoverTrace.pointNumber).toEqual(1); + expect(hoverTrace.x).toEqual(2); + expect(hoverTrace.y).toEqual(3); - assertHoverLabelContent({ - nums: '3', - axis: '2', - name: 'trace 0' - }); + assertHoverLabelContent({ + nums: '3', + axis: '2', + name: 'trace 0' + }); + }) + .catch(failTest) + .then(done); }); it('responds to hoverdistance change from default to 0 (part 1)', function() { @@ -4174,14 +4199,17 @@ describe('hover distance', function() { }); }); - it('responds to hoverdistance change from default to 0 (part 2)', function() { + it('responds to hoverdistance change from default to 0 (part 2)', function(done) { var gd = document.getElementById('graph'); var evt = { xpx: 475, ypx: 155 }; - Plotly.relayout(gd, 'hoverdistance', 0); - - Fx.hover('graph', evt, 'xy'); + Plotly.relayout(gd, 'hoverdistance', 0) + .then(function() { + Fx.hover('graph', evt, 'xy'); - expect(gd._hoverdata).toEqual(undefined); + expect(gd._hoverdata).toEqual(undefined); + }) + .catch(failTest) + .then(done); }); it('responds to setting the hoverdistance to -1 by increasing ' + @@ -4194,24 +4222,27 @@ describe('hover distance', function() { }); it('responds to setting the hoverdistance to -1 by increasing ' + - 'the range of search for points to hover to Infinity (part 2)', function() { + 'the range of search for points to hover to Infinity (part 2)', function(done) { var gd = document.getElementById('graph'); var evt = { xpx: 450, ypx: 155 }; - Plotly.relayout(gd, 'hoverdistance', -1); - - Fx.hover('graph', evt, 'xy'); + Plotly.relayout(gd, 'hoverdistance', -1) + .then(function() { + Fx.hover('graph', evt, 'xy'); - var hoverTrace = gd._hoverdata[0]; + var hoverTrace = gd._hoverdata[0]; - expect(hoverTrace.curveNumber).toEqual(0); - expect(hoverTrace.pointNumber).toEqual(1); - expect(hoverTrace.x).toEqual(2); - expect(hoverTrace.y).toEqual(3); + expect(hoverTrace.curveNumber).toEqual(0); + expect(hoverTrace.pointNumber).toEqual(1); + expect(hoverTrace.x).toEqual(2); + expect(hoverTrace.y).toEqual(3); - assertHoverLabelContent({ - nums: '(2, 3)', - name: 'trace 0' - }); + assertHoverLabelContent({ + nums: '(2, 3)', + name: 'trace 0' + }); + }) + .catch(failTest) + .then(done); }); }); @@ -4337,7 +4368,8 @@ describe('hover label rotation:', function() { }); it('should not rotate labels under *hovermode:closest*', function(done) { - Plotly.relayout(gd, 'hovermode', 'closest').then(function() { + Plotly.relayout(gd, 'hovermode', 'closest') + .then(function() { _hover(gd, { xval: 1.9, yval: 1 }); assertHoverLabelContent({ nums: '(2, 1)', @@ -4385,7 +4417,8 @@ describe('hover label rotation:', function() { }); it('should not rotate labels under *hovermode:closest*', function(done) { - Plotly.relayout(gd, 'hovermode', 'closest').then(function() { + Plotly.relayout(gd, 'hovermode', 'closest') + .then(function() { _hover(gd, { xval: 1.9, yval: 1 }); assertHoverLabelContent({ nums: '(2, 1)', diff --git a/test/jasmine/tests/layout_images_test.js b/test/jasmine/tests/layout_images_test.js index 8638c99a632..4f2de029009 100644 --- a/test/jasmine/tests/layout_images_test.js +++ b/test/jasmine/tests/layout_images_test.js @@ -107,36 +107,39 @@ describe('Layout images', function() { expect(subplotLayer.selectAll('image').size()).toBe(subplot); } - it('should draw images on the right layers', function() { - Plotly.plot(gd, data, { images: [{ + it('should draw images on the right layers', function(done) { + Plotly.newPlot(gd, data, { images: [{ source: jsLogo, layer: 'above' - }]}); - - checkLayers(1, 0, 0); - - destroyGraphDiv(); - gd = createGraphDiv(); - Plotly.plot(gd, data, { images: [{ - source: jsLogo, - layer: 'below' - }]}); - - checkLayers(0, 1, 0); - - destroyGraphDiv(); - gd = createGraphDiv(); - Plotly.plot(gd, data, { images: [{ - source: jsLogo, - layer: 'below', - xref: 'x', - yref: 'y' - }]}); - - checkLayers(0, 0, 1); + }]}) + .then(function() { + checkLayers(1, 0, 0); + }) + .then(function() { + return Plotly.newPlot(gd, data, { images: [{ + source: jsLogo, + layer: 'below' + }]}); + }) + .then(function() { + checkLayers(0, 1, 0); + }) + .then(function() { + return Plotly.newPlot(gd, data, { images: [{ + source: jsLogo, + layer: 'below', + xref: 'x', + yref: 'y' + }]}); + }) + .then(function() { + checkLayers(0, 0, 1); + }) + .catch(failTest) + .then(done); }); - it('should fall back on imageLowerLayer for below missing subplots', function() { + it('should fall back on imageLowerLayer for below missing subplots', function(done) { Plotly.newPlot(gd, [ {x: [1, 3], y: [1, 3]}, {x: [1, 3], y: [1, 3], xaxis: 'x2', yaxis: 'y2'} @@ -156,44 +159,87 @@ describe('Layout images', function() { xref: 'x2', yref: 'y' }] - }); - - checkLayers(0, 2, 0); + }) + .then(function() { + checkLayers(0, 2, 0); + }) + .catch(failTest) + .then(done); }); describe('with anchors and sizing', function() { - function testAspectRatio(xAnchor, yAnchor, sizing, expected) { - Plotly.plot(gd, data, { images: [{ - source: jsLogo, - xanchor: xAnchor, - yanchor: yAnchor, - sizing: sizing - }]}); - + function testAspectRatio(expected) { var image = Plotly.d3.select('image'); var parValue = image.attr('preserveAspectRatio'); expect(parValue).toBe(expected); } - it('should work for center middle', function() { - testAspectRatio('center', 'middle', undefined, 'xMidYMid'); + it('should work for center middle', function(done) { + Plotly.plot(gd, data, { images: [{ + source: jsLogo, + xanchor: 'center', + yanchor: 'middle' + }]}) + .then(function() { + expect(Plotly.d3.select('image').attr('preserveAspectRatio')).toBe('xMidYMid'); + }) + .catch(failTest) + .then(done); }); - it('should work for left top', function() { - testAspectRatio('left', 'top', undefined, 'xMinYMin'); + it('should work for left top', function(done) { + Plotly.plot(gd, data, { images: [{ + source: jsLogo, + xanchor: 'left', + yanchor: 'top' + }]}) + .then(function() { + testAspectRatio('xMinYMin'); + }) + .catch(failTest) + .then(done); }); - it('should work for right bottom', function() { - testAspectRatio('right', 'bottom', undefined, 'xMaxYMax'); + it('should work for right bottom', function(done) { + Plotly.plot(gd, data, { images: [{ + source: jsLogo, + xanchor: 'right', + yanchor: 'bottom' + }]}) + .then(function() { + testAspectRatio('xMaxYMax'); + }) + .catch(failTest) + .then(done); }); - it('should work for stretch sizing', function() { - testAspectRatio('middle', 'center', 'stretch', 'none'); + it('should work for stretch sizing', function(done) { + Plotly.plot(gd, data, { images: [{ + source: jsLogo, + xanchor: 'middle', + yanchor: 'center', + sizing: 'stretch' + }]}) + .then(function() { + testAspectRatio('none'); + }) + .catch(failTest) + .then(done); }); - it('should work for fill sizing', function() { - testAspectRatio('invalid', 'invalid', 'fill', 'xMinYMin slice'); + it('should work for fill sizing', function(done) { + Plotly.plot(gd, data, { images: [{ + source: jsLogo, + xanchor: 'invalid', + yanchor: 'invalid', + sizing: 'fill' + }]}) + .then(function() { + testAspectRatio('xMinYMin slice'); + }) + .catch(failTest) + .then(done); }); }); }); @@ -237,7 +283,9 @@ describe('Layout images', function() { expect(newPos.top).toBe(oldPos.top); mouseEvent('mouseup', 300, 250); - }).then(done); + }) + .catch(failTest) + .then(done); }); it('should move when referencing axes', function(done) { @@ -269,7 +317,9 @@ describe('Layout images', function() { expect(newPos.top).toBe(oldPos.top + 50); mouseEvent('mouseup', 300, 250); - }).then(done); + }) + .catch(failTest) + .then(done); }); }); @@ -309,8 +359,9 @@ describe('Layout images', function() { Plotly.relayout(gd, 'images[0].source', dataUriImage) .then(function() { expect(newCanvasElement).toBeUndefined(); + + return Plotly.relayout(gd, 'images[0].source', jsLogo); }) - .then(function() { return Plotly.relayout(gd, 'images[0].source', jsLogo); }) .then(function() { expect(newCanvasElement).toBeDefined(); expect(newCanvasElement.toDataURL).toHaveBeenCalledTimes(1); @@ -323,11 +374,14 @@ describe('Layout images', function() { var img = Plotly.d3.select('image'); var url = img.attr('xlink:href'); - Plotly.relayout(gd, 'images[0].source', pythonLogo).then(function() { + Plotly.relayout(gd, 'images[0].source', pythonLogo) + .then(function() { var newImg = Plotly.d3.select('image'); var newUrl = newImg.attr('xlink:href'); expect(url).not.toBe(newUrl); - }).then(done); + }) + .catch(failTest) + .then(done); }); it('should update the image position if changed', function(done) { @@ -340,20 +394,26 @@ describe('Layout images', function() { expect([+img.attr('x'), +img.attr('y')]).toEqual([760, -120]); - Plotly.relayout(gd, update).then(function() { + Plotly.relayout(gd, update) + .then(function() { var newImg = Plotly.d3.select('image'); expect([+newImg.attr('x'), +newImg.attr('y')]).toEqual([80, 100]); - }).then(done); + }) + .catch(failTest) + .then(done); }); it('should remove the image tag if an invalid source', function(done) { var selection = Plotly.d3.select('image'); expect(selection.size()).toBe(1); - Plotly.relayout(gd, 'images[0].source', 'invalidUrl').then(function() { + Plotly.relayout(gd, 'images[0].source', 'invalidUrl') + .then(function() { var newSelection = Plotly.d3.select('image'); expect(newSelection.size()).toBe(0); - }).then(done); + }) + .catch(failTest) + .then(done); }); }); @@ -430,9 +490,9 @@ describe('Layout images', function() { .then(function() { assertImages(0); expect(gd.layout.images).toBeUndefined(); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); }); diff --git a/test/jasmine/tests/legend_scroll_test.js b/test/jasmine/tests/legend_scroll_test.js index 7233d66674c..19b1ddbaeac 100644 --- a/test/jasmine/tests/legend_scroll_test.js +++ b/test/jasmine/tests/legend_scroll_test.js @@ -70,9 +70,8 @@ describe('The legend', function() { var mockCopy = Lib.extendDeep({}, mock); - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { - done(); - }); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(done); }); afterEach(destroyGraph); @@ -326,7 +325,6 @@ describe('The legend', function() { Plotly.relayout(gd, 'showlegend', false); Plotly.relayout(gd, 'showlegend', true); - legend = getLegend(); scrollBox = getScrollBox(); scrollBar = getScrollBar(); @@ -384,18 +382,20 @@ describe('The legend', function() { expect(countLegendGroups(gd)).toBe(1); expect(countLegendClipPaths(gd)).toBe(1); - Plotly.relayout(gd, 'showlegend', false).then(function() { + Plotly.relayout(gd, 'showlegend', false) + .then(function() { expect(countLegendGroups(gd)).toBe(0); expect(countLegendClipPaths(gd)).toBe(0); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should resize when relayout\'ed with new height', function(done) { var origLegendHeight = getLegendHeight(gd); - Plotly.relayout(gd, 'height', gd._fullLayout.height / 2).then(function() { + Plotly.relayout(gd, 'height', gd._fullLayout.height / 2) + .then(function() { var legendHeight = getLegendHeight(gd); // legend still exists and not duplicated @@ -405,9 +405,9 @@ describe('The legend', function() { // clippath resized to new height less than new plot height expect(+legendHeight).toBe(getPlotHeight(gd)); expect(+legendHeight).toBeLessThan(+origLegendHeight); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -436,12 +436,13 @@ describe('The legend', function() { expect(countLegendGroups(gd)).toBe(1); expect(countLegendClipPaths(gd)).toBe(1); - Plotly.relayout(gd, 'showlegend', false).then(function() { + Plotly.relayout(gd, 'showlegend', false) + .then(function() { expect(countLegendGroups(gd)).toBe(0); expect(countLegendClipPaths(gd)).toBe(0); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should resize when traces added', function(done) { @@ -451,9 +452,9 @@ describe('The legend', function() { var legendHeight = getLegendHeight(gd); expect(+legendHeight).toBeCloseTo(+origLegendHeight + 19, 0); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); }); diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index 7d2126f031c..ad82a2d7eb0 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -841,7 +841,7 @@ describe('legend relayout update', function() { expect(d3.selectAll('.legendtitletext')[0].length).toBe(1); }) .then(function() { - Plotly.react(gd, { + return Plotly.react(gd, { data: data, layout: { showlegend: true @@ -874,8 +874,9 @@ describe('legend orientation change:', function() { return Plotly.relayout(gd, 'legend.bgcolor', initialLegendBGColor); }).then(function() { expect(gd._fullLayout.legend.bgcolor).toBe(initialLegendBGColor); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -925,9 +926,9 @@ describe('legend restyle update', function() { }).then(function() { expect(countLegendItems()).toEqual(1); assertTraceToggleRect(); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/lib_test.js b/test/jasmine/tests/lib_test.js index 08f34799996..cc8620dbcb6 100644 --- a/test/jasmine/tests/lib_test.js +++ b/test/jasmine/tests/lib_test.js @@ -2752,9 +2752,9 @@ describe('Queue', function() { }).then(function() { expect(gd.undoQueue.index).toEqual(0); expect(gd.undoQueue.queue).toEqual([]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should fill in undoQueue up to value found in *queueLength* config', function(done) { diff --git a/test/jasmine/tests/mapbox_test.js b/test/jasmine/tests/mapbox_test.js index b9fe58eec70..d2467b85ab7 100644 --- a/test/jasmine/tests/mapbox_test.js +++ b/test/jasmine/tests/mapbox_test.js @@ -486,7 +486,7 @@ describe('mapbox credentials', function() { }, LONG_TIMEOUT_INTERVAL); }); -describe('@noCI, mapbox plots', function() { +describe('mapbox plots', function() { var mock = require('@mocks/mapbox_0.json'); var gd; @@ -608,7 +608,7 @@ describe('@noCI, mapbox plots', 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); + }).catch(failTest).then(done); }, LONG_TIMEOUT_INTERVAL); it('@gl should not update zoom while scroll wheeling', function(done) { @@ -628,7 +628,7 @@ describe('@noCI, mapbox plots', function() { // call since a scroll wheel zoom is underway expect(map.setZoom).toHaveBeenCalledTimes(1); }); - }).then(done); + }).catch(failTest).then(done); }, LONG_TIMEOUT_INTERVAL); it('@gl should be able to restyle', function(done) { @@ -718,7 +718,8 @@ describe('@noCI, mapbox plots', function() { assertLayout([-4.710, 19.475], 1.234, [80, 100, 908, 270]); - Plotly.relayout(gd, 'mapbox.center', { lon: 0, lat: 0 }).then(function() { + Plotly.relayout(gd, 'mapbox.center', { lon: 0, lat: 0 }) + .then(function() { expect(restyleCnt).toEqual(0); expect(relayoutCnt).toEqual(1); @@ -765,7 +766,8 @@ describe('@noCI, mapbox plots', function() { assertLayout('Mapbox Dark'); - Plotly.relayout(gd, 'mapbox.style', 'light').then(function() { + Plotly.relayout(gd, 'mapbox.style', 'light') + .then(function() { assertLayout('Mapbox Light'); return Plotly.relayout(gd, 'mapbox.style', 'dark'); @@ -841,7 +843,8 @@ describe('@noCI, mapbox plots', function() { expect(countVisibleLayers(gd)).toEqual(0); - Plotly.relayout(gd, 'mapbox.layers[0]', layer0).then(function() { + Plotly.relayout(gd, 'mapbox.layers[0]', layer0) + .then(function() { expect(getLayerLength(gd)).toEqual(1); expect(countVisibleLayers(gd)).toEqual(1); @@ -1138,13 +1141,15 @@ describe('@noCI, mapbox plots', function() { }, 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) { + 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() { + }) + .then(function() { expect(gd._fullLayout.mapbox.accesstoken).toEqual(MAPBOX_ACCESS_TOKEN); expect(gd._promises.length).toEqual(0); }) @@ -1669,7 +1674,7 @@ describe('@noCI, mapbox plots', function() { } }); -describe('@noCI, mapbox react', function() { +describe('mapbox react', function() { var gd; beforeEach(function() { @@ -1746,7 +1751,7 @@ describe('@noCI, mapbox react', function() { }, LONG_TIMEOUT_INTERVAL); }); -describe('@noCI test mapbox trace/layout *below* interactions', function() { +describe('test mapbox trace/layout *below* interactions', function() { var gd; beforeEach(function() { @@ -2010,7 +2015,7 @@ describe('@noCI test mapbox trace/layout *below* interactions', function() { }, 8 * jasmine.DEFAULT_TIMEOUT_INTERVAL); }); -describe('@noCI Test mapbox GeoJSON fetching:', function() { +describe('Test mapbox GeoJSON fetching:', function() { var gd; beforeEach(function() { @@ -2047,6 +2052,7 @@ describe('@noCI Test mapbox GeoJSON fetching:', function() { expect(Lib.isPlainObject(window.PlotlyGeoAssets[url])).toBe(true, 'is a GeoJSON object'); expect(Lib.isPlainObject(window.PlotlyGeoAssets[url2])).toBe(true, 'is a GeoJSON object'); }) + .catch(failTest) .then(done); }); @@ -2072,11 +2078,12 @@ describe('@noCI Test mapbox GeoJSON fetching:', function() { expect(actual).toEqual(new Error('GeoJSON at URL "invalidUrl" does not exist.')); expect(window.PlotlyGeoAssets.invalidUrl).toBe(undefined); }) + .catch(failTest) .then(done); }, LONG_TIMEOUT_INTERVAL); }); -describe('@noCI, mapbox toImage', function() { +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; diff --git a/test/jasmine/tests/modebar_test.js b/test/jasmine/tests/modebar_test.js index 0c67f65e4a7..f5db01e588b 100644 --- a/test/jasmine/tests/modebar_test.js +++ b/test/jasmine/tests/modebar_test.js @@ -1353,7 +1353,7 @@ describe('ModeBar', function() { }); }); - describe('@noCI mapbox handlers', function() { + describe('mapbox handlers', function() { it('@gl button *resetViewMapbox* should reset the mapbox view attribute to their default', function(done) { var gd = createGraphDiv(); @@ -1395,6 +1395,7 @@ describe('ModeBar', function() { _assert(10, 10, 8); button.isActive(false); }) + .catch(failTest) .then(done); }); }); @@ -1495,6 +1496,7 @@ describe('ModeBar', function() { style = document.querySelector(styleSelector); expect(style).toBeNull(); }) + .catch(failTest) .then(done); }); @@ -1576,6 +1578,7 @@ describe('ModeBar', function() { size = modeBarEl.getBoundingClientRect(); expect(size.width > size.height).toBeTruthy(); }) + .catch(failTest) .then(done); }); }); diff --git a/test/jasmine/tests/parcoords_test.js b/test/jasmine/tests/parcoords_test.js index eaeaa4bd5b3..ff3afecb1b9 100644 --- a/test/jasmine/tests/parcoords_test.js +++ b/test/jasmine/tests/parcoords_test.js @@ -916,44 +916,52 @@ describe('parcoords basic use', function() { var mockCopy; var gd; - beforeEach(function(done) { + beforeEach(function() { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + mockCopy = Lib.extendDeep({}, mock); mockCopy.data[0].domain = { x: [0.1, 0.9], y: [0.05, 0.85] }; - var hasGD = !!gd; - if(!hasGD) gd = createGraphDiv(); - Plotly.react(gd, mockCopy) - .catch(failTest) - .then(done); + gd = createGraphDiv(); }); - afterAll(purgeGraphDiv); + afterEach(purgeGraphDiv); - it('@gl should create three WebGL contexts per graph', function() { - var cnt = 0; - d3.select(gd).selectAll('canvas').each(function(d) { - if(d.regl) cnt++; - }); - expect(cnt).toBe(3); + it('@gl should create three WebGL contexts per graph', function(done) { + Plotly.react(gd, mockCopy) + .then(function() { + var cnt = 0; + d3.select(gd).selectAll('canvas').each(function(d) { + if(d.regl) cnt++; + }); + expect(cnt).toBe(3); + }) + .catch(failTest) + .then(done); }); - it('@gl `Plotly.plot` should have proper fields on `gd.data` on initial rendering', function() { - expect(gd.data.length).toEqual(1); - expect(gd.data[0].dimensions.length).toEqual(11); - expect(document.querySelectorAll('.axis').length).toEqual(10); // one dimension is `visible: false` - expect(gd.data[0].line.cmin).toEqual(-4000); - expect(gd.data[0].dimensions[0].visible).not.toBeDefined(); - expect(gd.data[0].dimensions[4].visible).toEqual(true); - expect(gd.data[0].dimensions[5].visible).toEqual(false); - expect(gd.data[0].dimensions[0].range).not.toBeDefined(); - expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); - expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); - expect(gd.data[0].dimensions[1].range).toBeDefined(); - expect(gd.data[0].dimensions[1].range).toEqual([0, 700000]); - expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + it('@gl `Plotly.plot` should have proper fields on `gd.data` on initial rendering', function(done) { + Plotly.react(gd, mockCopy) + .then(function() { + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(document.querySelectorAll('.axis').length).toEqual(10); // one dimension is `visible: false` + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].visible).not.toBeDefined(); + expect(gd.data[0].dimensions[4].visible).toEqual(true); + expect(gd.data[0].dimensions[5].visible).toEqual(false); + expect(gd.data[0].dimensions[0].range).not.toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].range).toBeDefined(); + expect(gd.data[0].dimensions[1].range).toEqual([0, 700000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + }) + .catch(failTest) + .then(done); }); it('@gl Calling `Plotly.plot` again should add the new parcoords', function(done) { @@ -962,7 +970,11 @@ describe('parcoords basic use', function() { reversedMockCopy.data[0].dimensions.forEach(function(d) {d.id = 'R_' + d.id;}); reversedMockCopy.data[0].dimensions.forEach(function(d) {d.label = 'R_' + d.label;}); - Plotly.plot(gd, reversedMockCopy).then(function() { + Plotly.react(gd, mockCopy) + .then(function() { + return Plotly.plot(gd, reversedMockCopy); + }) + .then(function() { expect(gd.data.length).toEqual(2); expect(gd.data[0].dimensions.length).toEqual(11); @@ -984,17 +996,20 @@ describe('parcoords basic use', function() { }); it('@gl Calling `Plotly.restyle` with a string path to colorscale should amend the preexisting parcoords', function(done) { - expect(gd.data.length).toEqual(1); - - Plotly.restyle(gd, 'line.colorscale', 'Viridis').then(function() { + Plotly.react(gd, mockCopy) + .then(function() { expect(gd.data.length).toEqual(1); - expect(gd.data[0].line.colorscale).toEqual('Viridis'); - expect(gd.data[0].dimensions.length).toEqual(11); - expect(gd.data[0].line.cmin).toEqual(-4000); - expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); - expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); - expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + return Plotly.restyle(gd, 'line.colorscale', 'Viridis').then(function() { + expect(gd.data.length).toEqual(1); + + expect(gd.data[0].line.colorscale).toEqual('Viridis'); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + }); }) .catch(failTest) .then(done); @@ -1012,7 +1027,8 @@ describe('parcoords basic use', function() { }; } - restyleDimension('label', 'new label')() + Plotly.react(gd, mockCopy) + .then(restyleDimension('label', 'new label')) .then(restyleDimension('tickvals', [[0, 0.1, 0.4, 1, 2]])) .then(restyleDimension('ticktext', [['alpha', 'gamma', 'beta', 'omega', 'epsilon']])) .then(restyleDimension('tickformat', '4s')) @@ -1025,11 +1041,15 @@ describe('parcoords basic use', function() { }); it('@gl Calling `Plotly.restyle` with an object should amend the preexisting parcoords', function(done) { - var newStyle = Lib.extendDeep({}, mockCopy.data[0].line); - newStyle.colorscale = 'Viridis'; - newStyle.reversescale = false; + Plotly.react(gd, mockCopy) + .then(function() { + var newStyle = Lib.extendDeep({}, mockCopy.data[0].line); + newStyle.colorscale = 'Viridis'; + newStyle.reversescale = false; - Plotly.restyle(gd, {line: newStyle}).then(function() { + return Plotly.restyle(gd, {line: newStyle}); + }) + .then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].line.colorscale).toEqual('Viridis'); @@ -1054,12 +1074,15 @@ describe('parcoords basic use', function() { }; })(); - gd.on('plotly_restyle', function() { - tester.set(true); - }); + Plotly.react(gd, mockCopy) + .then(function() { + gd.on('plotly_restyle', function() { + tester.set(true); + }); - expect(tester.get()).toBe(false); - Plotly.restyle(gd, 'line.colorscale', 'Viridis') + expect(tester.get()).toBe(false); + return Plotly.restyle(gd, 'line.colorscale', 'Viridis'); + }) .then(function() { expect(tester.get()).toBe(true); }) @@ -1071,16 +1094,19 @@ describe('parcoords basic use', function() { var hoverCalls = 0; var unhoverCalls = 0; - gd.on('plotly_hover', function() { hoverCalls++; }); - gd.on('plotly_unhover', function() { unhoverCalls++; }); + Plotly.react(gd, mockCopy) + .then(function() { + gd.on('plotly_hover', function() { hoverCalls++; }); + gd.on('plotly_unhover', function() { unhoverCalls++; }); - expect(hoverCalls).toBe(0); - expect(unhoverCalls).toBe(0); + expect(hoverCalls).toBe(0); + expect(unhoverCalls).toBe(0); - mouseTo(324, 216); - mouseTo(315, 218); + mouseTo(324, 216); + mouseTo(315, 218); - delay(20)() + return delay(20)(); + }) .then(function() { expect(hoverCalls).toBe(1); expect(unhoverCalls).toBe(0); @@ -1096,9 +1122,13 @@ describe('parcoords basic use', function() { }); it('@gl Calling `Plotly.relayout` with string should amend the preexisting parcoords', function(done) { - expect(gd.layout.width).toEqual(1184); + Plotly.react(gd, mockCopy) + .then(function() { + expect(gd.layout.width).toEqual(1184); - Plotly.relayout(gd, 'width', 500).then(function() { + return Plotly.relayout(gd, 'width', 500); + }) + .then(function() { expect(gd.data.length).toEqual(1); expect(gd.layout.width).toEqual(500); @@ -1114,9 +1144,13 @@ describe('parcoords basic use', function() { }); it('@gl Calling `Plotly.relayout`with object should amend the preexisting parcoords', function(done) { - expect(gd.layout.width).toEqual(1184); + Plotly.react(gd, mockCopy) + .then(function() { + expect(gd.layout.width).toEqual(1184); - Plotly.relayout(gd, {width: 500}).then(function() { + return Plotly.relayout(gd, {width: 500}); + }) + .then(function() { expect(gd.data.length).toEqual(1); expect(gd.layout.width).toEqual(500); @@ -1170,13 +1204,9 @@ describe('parcoords basic use', function() { .then(done); }); - it('@gl should fire *plotly_webglcontextlost* when on webgl context lost', function() { + it('@gl should fire *plotly_webglcontextlost* when on webgl context lost', function(done) { var eventData; var cnt = 0; - gd.on('plotly_webglcontextlost', function(d) { - eventData = d; - cnt++; - }); function trigger(name) { var ev = new window.WebGLContextEvent('webglcontextlost'); @@ -1190,52 +1220,61 @@ describe('parcoords basic use', function() { expect(cnt).toBe(c); } - trigger('context'); - _assert('contextLayer', 1); + Plotly.react(gd, mockCopy) + .then(function() { + gd.on('plotly_webglcontextlost', function(d) { + eventData = d; + cnt++; + }); - trigger('focus'); - _assert('focusLayer', 2); + trigger('context'); + _assert('contextLayer', 1); - trigger('pick'); - _assert('pickLayer', 3); + trigger('focus'); + _assert('focusLayer', 2); + + trigger('pick'); + _assert('pickLayer', 3); + }) + .catch(failTest) + .then(done); }); }); describe('parcoords react more attributes', function() { var gd; - beforeEach(function(done) { - var hasGD = !!gd; - if(!hasGD) gd = createGraphDiv(); - - Plotly.react(gd, mock3) - .catch(failTest) - .then(done); + beforeEach(function() { + gd = createGraphDiv(); }); - afterAll(purgeGraphDiv); + afterEach(purgeGraphDiv); it('@gl should change various axis parameters', function(done) { - var mockCopy = Lib.extendDeep({}, mock3); - var m0 = mockCopy.data[0]; - m0.labelangle = '-90'; - m0.labelfont = { size: '24', family: 'Times', color: 'orange' }; - m0.rangefont = { size: '20', family: 'Times', color: 'brown' }; - m0.tickfont = { size: '16', family: 'Times', color: 'yellow' }; - m0.dimensions[0].label = 'Changed!'; - m0.dimensions[1].range = ['-2', '2']; - m0.dimensions[2].constraintrange = []; - m0.dimensions[1].multiselect = false; - m0.dimensions[1].constraintrange = [ - [-1.5, -0.5], - [0, 1.5] // won't be selected because multiselect is tuned off. - ]; - m0.dimensions[0].constraintrange = [[2, 4], [7, 10], [11, 12]]; - m0.dimensions[0].tickvals = ['1', '2', '3', '5', '8', '13']; - m0.dimensions[0].ticktext = ['1/1', '2/1', '3/2', '5/3', '8/5', '13/8']; - m0.domain = { x: [0, 0.5], y: [0, 0.5] }; + Plotly.react(gd, mock3) + .then(function() { + var mockCopy = Lib.extendDeep({}, mock3); + var m0 = mockCopy.data[0]; + m0.labelangle = '-90'; + m0.labelfont = { size: '24', family: 'Times', color: 'orange' }; + m0.rangefont = { size: '20', family: 'Times', color: 'brown' }; + m0.tickfont = { size: '16', family: 'Times', color: 'yellow' }; + m0.dimensions[0].label = 'Changed!'; + m0.dimensions[1].range = ['-2', '2']; + m0.dimensions[2].constraintrange = []; + m0.dimensions[1].multiselect = false; + m0.dimensions[1].constraintrange = [ + [-1.5, -0.5], + [0, 1.5] // won't be selected because multiselect is tuned off. + ]; + m0.dimensions[0].constraintrange = [[2, 4], [7, 10], [11, 12]]; + m0.dimensions[0].tickvals = ['1', '2', '3', '5', '8', '13']; + m0.dimensions[0].ticktext = ['1/1', '2/1', '3/2', '5/3', '8/5', '13/8']; + m0.domain = { x: [0, 0.5], y: [0, 0.5] }; - Plotly.react(gd, mockCopy.data).then(function() { + return Plotly.react(gd, mockCopy.data); + }) + .then(function() { var allParcoords = d3.selectAll('.' + PC.cn.parcoords); var allLabels = allParcoords.selectAll('.' + PC.cn.axisTitle); @@ -1311,7 +1350,7 @@ describe('parcoords react more attributes', function() { m0.dimensions[1].visible = true; }) .then(function() { - Plotly.react(gd, mockCopy.data).then(function() { + return Plotly.react(gd, mockCopy.data).then(function() { var allParcoords = d3.selectAll('.' + PC.cn.parcoords); var allLabels = allParcoords.selectAll('.' + PC.cn.axisTitle); @@ -1353,6 +1392,8 @@ describe('parcoords constraint interactions - without defined axis ranges', func var snapDelay = 100; var noSnapDelay = 20; beforeAll(function() { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + initialSnapDuration = PC.bar.snapDuration; PC.bar.snapDuration = shortenedSnapDuration; }); @@ -1362,26 +1403,12 @@ describe('parcoords constraint interactions - without defined axis ranges', func PC.bar.snapDuration = initialSnapDuration; }); - beforeEach(function(done) { - var hasGD = !!gd; - if(!hasGD) gd = createGraphDiv(); - - Plotly.react(gd, initialFigure()) - .then(function() { - if(hasGD) { - expect(getDashArray(0)).toBeCloseToArray(initialDashArray0); - expect(getDashArray(1)).toBeCloseToArray(initialDashArray1); - } else { - initialDashArray0 = getDashArray(0); - initialDashArray1 = getDashArray(1); - checkDashCount(initialDashArray0, 1); - checkDashCount(initialDashArray1, 1); - } - }) - .catch(failTest) - .then(done); + beforeEach(function() { + gd = createGraphDiv(); }); + afterEach(purgeGraphDiv); + function getDashArray(index) { var highlight = document.querySelectorAll('.highlight')[index]; return highlight.attributes['stroke-dasharray'].value.split(',').map(Number); @@ -1400,15 +1427,26 @@ describe('parcoords constraint interactions - without defined axis ranges', func expect(dashArray.length).toBe(segmentCount, dashArray); } - it('@noCI @gl snaps ordinal constraints', function(done) { - // first: drag almost to 2 but not quite - constraint will snap back to [2.75, 4] - mostOfDrag(105, 165, 105, 190); - var newDashArray = getDashArray(0); - expect(newDashArray).not.toBeCloseToArray(initialDashArray0); - checkDashCount(newDashArray, 1); + it('@gl snaps ordinal constraints', function(done) { + var newDashArray; + + Plotly.react(gd, initialFigure()) + .then(function() { + initialDashArray0 = getDashArray(0); + initialDashArray1 = getDashArray(1); + checkDashCount(initialDashArray0, 1); + checkDashCount(initialDashArray1, 1); - mouseEvent('mouseup', 105, 190); - delay(snapDelay)().then(function() { + // first: drag almost to 2 but not quite - constraint will snap back to [2.75, 4] + mostOfDrag(105, 165, 105, 190); + newDashArray = getDashArray(0); + expect(newDashArray).not.toBeCloseToArray(initialDashArray0); + checkDashCount(newDashArray, 1); + + mouseEvent('mouseup', 105, 190); + return delay(snapDelay)(); + }) + .then(function() { expect(getDashArray(0)).toBeCloseToArray(initialDashArray0); expect(gd.data[0].dimensions[0].constraintrange).toBeCloseToArray([2.75, 4]); @@ -1478,15 +1516,26 @@ describe('parcoords constraint interactions - without defined axis ranges', func .then(done); }); - it('@noCI @gl updates continuous constraints with no snap', function(done) { - // first: extend 7 to 5 - mostOfDrag(295, 160, 295, 200); - var newDashArray = getDashArray(1); - expect(newDashArray).not.toBeCloseToArray(initialDashArray1); - checkDashCount(newDashArray, 1); + it('@gl updates continuous constraints with no snap', function(done) { + var newDashArray; + + Plotly.react(gd, initialFigure()) + .then(function() { + initialDashArray0 = getDashArray(0); + initialDashArray1 = getDashArray(1); + checkDashCount(initialDashArray0, 1); + checkDashCount(initialDashArray1, 1); + + // first: extend 7 to 5 + mostOfDrag(295, 160, 295, 200); + newDashArray = getDashArray(1); + expect(newDashArray).not.toBeCloseToArray(initialDashArray1); + checkDashCount(newDashArray, 1); - mouseEvent('mouseup', 295, 190); - delay(noSnapDelay)().then(function() { + mouseEvent('mouseup', 295, 190); + return delay(noSnapDelay)(); + }) + .then(function() { expect(getDashArray(1)).toBeCloseToArray(newDashArray); expect(gd.data[0].dimensions[1].constraintrange).toBeCloseToArray([4.8959, 9]); @@ -1519,10 +1568,13 @@ describe('parcoords constraint interactions - without defined axis ranges', func .then(done); }); - it('@noCI @gl will only select one region when multiselect is disabled', function(done) { + it('@gl will only select one region when multiselect is disabled', function(done) { var newDashArray; - Plotly.restyle(gd, {'dimensions[1].multiselect': false}) + Plotly.react(gd, initialFigure()) + .then(function() { + return Plotly.restyle(gd, {'dimensions[1].multiselect': false}); + }) .then(function() { expect(getDashArray(1)).toBeCloseToArray(initialDashArray1); @@ -1556,10 +1608,10 @@ describe('parcoords constraint interactions - without defined axis ranges', func .then(done); }); - it('@noCI @gl should keep single point dimension selected', function(done) { + it('@gl should keep single point dimension selected', function(done) { var testLayer = '.gl-canvas-focus'; - Plotly.newPlot(gd, { + Plotly.react(gd, { data: [ { type: 'parcoords', @@ -1630,6 +1682,8 @@ describe('parcoords constraint interactions - with defined axis ranges', functio var shortenedSnapDuration = 20; var noSnapDelay = 20; beforeAll(function() { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + initialSnapDuration = PC.bar.snapDuration; PC.bar.snapDuration = shortenedSnapDuration; }); @@ -1639,24 +1693,24 @@ describe('parcoords constraint interactions - with defined axis ranges', functio PC.bar.snapDuration = initialSnapDuration; }); - beforeEach(function(done) { - var hasGD = !!gd; - if(!hasGD) gd = createGraphDiv(); - - Plotly.react(gd, initialFigure()) - .catch(failTest) - .then(done); + beforeEach(function() { + gd = createGraphDiv(); }); - it('@noCI @gl updates constraints above and below axis ranges', function(done) { - expect(gd.data[0].dimensions[1].constraintrange).toBeCloseToArray([4, 6]); + afterEach(purgeGraphDiv); + it('@gl updates constraints above and below axis ranges', function(done) { var x = 295; - // first: move above range - mostOfDrag(x, 200, x, 100); - mouseEvent('mouseup', x, 100); - delay(noSnapDelay)() + Plotly.react(gd, initialFigure()) + .then(function() { + expect(gd.data[0].dimensions[1].constraintrange).toBeCloseToArray([4, 6]); + + // first: move above range + mostOfDrag(x, 200, x, 100); + mouseEvent('mouseup', x, 100); + return delay(noSnapDelay)(); + }) .then(function() { expect(gd.data[0].dimensions[1].constraintrange).toBeCloseToArray([5.75, 8.25]); // move back @@ -1722,21 +1776,21 @@ describe('parcoords constraint click interactions - with pre-defined constraint PC.bar.snapDuration = initialSnapDuration; }); - beforeEach(function(done) { - var hasGD = !!gd; - if(!hasGD) gd = createGraphDiv(); - - Plotly.react(gd, initialFigure()) - .catch(failTest) - .then(done); + beforeEach(function() { + gd = createGraphDiv(); }); - it('@noCI @gl should not drop constraintrange on click', function(done) { - expect(gd._fullData[0].dimensions[1].constraintrange).toBeCloseToArray([0.75, 2.25]); + afterEach(purgeGraphDiv); - // click to add a new item to the selection - mouseClick(295, 200); - delay(snapDelay)() + it('@gl should not drop constraintrange on click', function(done) { + Plotly.react(gd, initialFigure()) + .then(function() { + expect(gd._fullData[0].dimensions[1].constraintrange).toBeCloseToArray([0.75, 2.25]); + + // click to add a new item to the selection + mouseClick(295, 200); + delay(snapDelay)(); + }) .then(function() { expect(gd._fullData[0].dimensions[1].constraintrange).toBeCloseToArray([[0.75, 2.25], [2.75, 3.25]]); diff --git a/test/jasmine/tests/pie_test.js b/test/jasmine/tests/pie_test.js index 5e18f96583c..98d730f570c 100644 --- a/test/jasmine/tests/pie_test.js +++ b/test/jasmine/tests/pie_test.js @@ -1310,6 +1310,7 @@ describe('pie hovering', function() { .then(function() { assertLabel('0\n12|345|678@91\n99@9%'); }) + .catch(failTest) .then(done); }); @@ -1331,6 +1332,7 @@ describe('pie hovering', function() { .then(function() { assertLabel('D\n0\n4\n14.3%'); }) + .catch(failTest) .then(done); }); @@ -1583,16 +1585,20 @@ describe('Test event data of interactions on a pie plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('should contain the correct fields', function() { @@ -1602,21 +1608,24 @@ describe('Test event data of interactions on a pie plot:', function() { checkEventData(futureData); }); - it('should not contain pointNumber if aggregating', function() { + it('should not contain pointNumber if aggregating', function(done) { var values = gd.data[0].values; var labels = []; for(var i = 0; i < values.length; i++) labels.push(i); Plotly.restyle(gd, { labels: [labels.concat(labels)], values: [values.concat(values)] - }); - - click(pointPos[0], pointPos[1]); - expect(futureData.points.length).toEqual(1); + }) + .then(function() { + click(pointPos[0], pointPos[1]); + expect(futureData.points.length).toEqual(1); - expect(futureData.points[0].pointNumber).toBeUndefined(); - expect(futureData.points[0].i).toBeUndefined(); - expect(futureData.points[0].pointNumbers).toEqual([4, 9]); + expect(futureData.points[0].pointNumber).toBeUndefined(); + expect(futureData.points[0].i).toBeUndefined(); + expect(futureData.points[0].pointNumbers).toEqual([4, 9]); + }) + .catch(failTest) + .then(done); }); }); @@ -1630,21 +1639,25 @@ describe('Test event data of interactions on a pie plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('does not respond to right-click', function() { click(pointPos[0], pointPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); // TODO: 'should contain the correct fields' // This test passed previously, but only because assets/click @@ -1665,12 +1678,15 @@ describe('Test event data of interactions on a pie plot:', function() { var futureData; beforeEach(function(done) { - futureData = undefined; - Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.newPlot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_hover', function(data) { - futureData = data; - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { @@ -1682,13 +1698,17 @@ describe('Test event data of interactions on a pie plot:', function() { it('should not emit a hover if you\'re dragging', function() { gd._dragging = true; mouseEvent('mouseover', pointPos[0], pointPos[1]); - expect(futureData).toBeUndefined(); + expect(futureData).toBe(null); }); - it('should not emit a hover if hover is disabled', function() { - Plotly.relayout(gd, 'hovermode', false); - mouseEvent('mouseover', pointPos[0], pointPos[1]); - expect(futureData).toBeUndefined(); + it('should not emit a hover if hover is disabled', function(done) { + Plotly.relayout(gd, 'hovermode', false) + .then(function() { + mouseEvent('mouseover', pointPos[0], pointPos[1]); + expect(futureData).toBe(null); + }) + .catch(failTest) + .then(done); }); }); @@ -1696,12 +1716,15 @@ describe('Test event data of interactions on a pie plot:', function() { var futureData; beforeEach(function(done) { - futureData = undefined; - Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.newPlot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_unhover', function(data) { - futureData = data; - }); + gd.on('plotly_unhover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { @@ -1713,7 +1736,7 @@ describe('Test event data of interactions on a pie plot:', function() { it('should not emit an unhover if you didn\'t first hover', function() { mouseEvent('mouseout', pointPos[0], pointPos[1]); - expect(futureData).toBeUndefined(); + expect(futureData).toBe(null); }); }); }); @@ -1755,6 +1778,7 @@ describe('pie relayout', function() { var slices = d3.selectAll(SLICES_SELECTOR); slices.each(checkRelayoutColor); }) + .catch(failTest) .then(done); }); }); diff --git a/test/jasmine/tests/plot_api_react_test.js b/test/jasmine/tests/plot_api_react_test.js index 7f2a0903660..5eec393530e 100644 --- a/test/jasmine/tests/plot_api_react_test.js +++ b/test/jasmine/tests/plot_api_react_test.js @@ -962,16 +962,16 @@ describe('clear bglayer react', function() { }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('green'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter3d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'red' } }); }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe(undefined); expect(hasBgRect()).toBe(false); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter', x: x, y: y, z: z }], layout: { plot_bgcolor: 'green' } }); @@ -990,16 +990,16 @@ describe('clear bglayer react', function() { }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('green'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter3d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'red' } }); }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe(undefined); expect(hasBgRect()).toBe(false); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter2d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'green' } }); @@ -1018,16 +1018,16 @@ describe('clear bglayer react', function() { }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe(undefined); expect(hasBgRect()).toBe(false); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter2d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'green' } }); }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('green'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter3d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'red' } }); @@ -1046,16 +1046,16 @@ describe('clear bglayer react', function() { }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe(undefined); expect(hasBgRect()).toBe(false); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter', x: x, y: y, z: z }], layout: { plot_bgcolor: 'green' } }); }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('green'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter3d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'red' } }); @@ -1074,16 +1074,16 @@ describe('clear bglayer react', function() { }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('yellow'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter2d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'green' } }); }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('green'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter', x: x, y: y, z: z }], layout: { plot_bgcolor: 'yellow' } }); @@ -1102,16 +1102,16 @@ describe('clear bglayer react', function() { }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('yellow'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter', x: x, y: y, z: z }], layout: { plot_bgcolor: 'green' } }); }).then(function() { expect(gd._fullLayout.plot_bgcolor).toBe('green'); expect(hasBgRect()).toBe(true); - }).then(function() { - Plotly.react(gd, { + + return Plotly.react(gd, { data: [{ type: 'scatter2d', x: x, y: y, z: z }], layout: { plot_bgcolor: 'yellow' } }); @@ -1550,7 +1550,7 @@ describe('Plotly.react and uirevision attributes', function() { var checkAllVisible = checkVisible([true, true, true], true); var checkSomeHidden = checkVisible([false, true, false], false); - _run(fig, hideSome, checkAllVisible, checkSomeHidden).then(done); + _run(fig, hideSome, checkAllVisible, checkSomeHidden).catch(failTest).then(done); }); it('@gl preserves modebar interactions using modebar.uirevision', function(done) { @@ -1601,7 +1601,7 @@ describe('Plotly.react and uirevision attributes', function() { var checkOriginalModes = checkState([], attrs(true)); var checkEditedModes = checkState([], attrs()); - _run(fig, editModes, checkOriginalModes, checkEditedModes).then(done); + _run(fig, editModes, checkOriginalModes, checkEditedModes).catch(failTest).then(done); }); it('preserves geo viewport changes using geo.uirevision', function(done) { @@ -1633,7 +1633,7 @@ describe('Plotly.react and uirevision attributes', function() { var checkOriginalView = checkState([], attrs(true)); var checkEditedView = checkState([], attrs()); - _run(fig, editView, checkOriginalView, checkEditedView).then(done); + _run(fig, editView, checkOriginalView, checkEditedView).catch(failTest).then(done); }); it('preserves geo viewport changes using geo.uirevision (fitbounds case)', function(done) { @@ -1666,7 +1666,7 @@ describe('Plotly.react and uirevision attributes', function() { var checkOriginalView = checkState([], attrs(true)); var checkEditedView = checkState([], attrs()); - _run(fig, editView, checkOriginalView, checkEditedView).then(done); + _run(fig, editView, checkOriginalView, checkEditedView).catch(failTest).then(done); }); it('@gl preserves 3d camera changes using scene.uirevision', function(done) { @@ -1706,7 +1706,7 @@ describe('Plotly.react and uirevision attributes', function() { var checkOriginalCamera = _checkCamera(true); var checkEditedCamera = _checkCamera(false); - _run(fig, editCamera, checkOriginalCamera, checkEditedCamera).then(done); + _run(fig, editCamera, checkOriginalCamera, checkEditedCamera).catch(failTest).then(done); }); it('preserves selectedpoints using selectionrevision', function(done) { @@ -1739,7 +1739,7 @@ describe('Plotly.react and uirevision attributes', function() { {selectedpoints: [[2]]} ]); - _run(fig, editSelection, checkNoSelection, checkSelection).then(done); + _run(fig, editSelection, checkNoSelection, checkSelection).catch(failTest).then(done); }); it('preserves selectedpoints using selectedrevision (groupby case)', function(done) { @@ -1779,7 +1779,7 @@ describe('Plotly.react and uirevision attributes', function() { // point 4 is last, in group 3 var checkSelection = checkState([{selectedpoints: [[5, 7, 8, 4]]}]); - _run(fig, editSelection, checkNoSelection, checkSelection).then(done); + _run(fig, editSelection, checkNoSelection, checkSelection).catch(failTest).then(done); }); it('preserves polar view changes using polar.uirevision', function(done) { @@ -1827,6 +1827,7 @@ describe('Plotly.react and uirevision attributes', function() { .then(function() { return _run(fig2, editPolar, checkInitial, checkEdited); }) + .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 97a8e1e8b1f..29669c95d1b 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -547,26 +547,29 @@ describe('Test plot api', function() { it('passes update data back to plotly_relayout unmodified ' + 'even if deprecated attributes have been used', function(done) { - Plotly.newPlot(gd, [{y: [1, 3, 2]}]); + Plotly.newPlot(gd, [{y: [1, 3, 2]}]) + .then(function() { + gd.on('plotly_relayout', function(eventData) { + expect(eventData).toEqual({ + 'title': 'Plotly chart', + 'xaxis.title': 'X', + 'xaxis.titlefont': {color: 'green'}, + 'yaxis.title': 'Y', + 'polar.radialaxis.title': 'Radial' + }); + done(); + }); - gd.on('plotly_relayout', function(eventData) { - expect(eventData).toEqual({ + return Plotly.relayout(gd, { 'title': 'Plotly chart', 'xaxis.title': 'X', 'xaxis.titlefont': {color: 'green'}, 'yaxis.title': 'Y', 'polar.radialaxis.title': 'Radial' }); - done(); - }); - - Plotly.relayout(gd, { - 'title': 'Plotly chart', - 'xaxis.title': 'X', - 'xaxis.titlefont': {color: 'green'}, - 'yaxis.title': 'Y', - 'polar.radialaxis.title': 'Radial' - }); + }) + .catch(failTest) + .then(done); }); }); @@ -619,7 +622,7 @@ describe('Test plot api', function() { expect(subroutines.layoutReplot.calls.count()).toBeGreaterThan(0, msg); } - it('should trigger replot (but not recalc) when switching into select or lasso dragmode for scattergl traces', function() { + it('should trigger replot (but not recalc) when switching into select or lasso dragmode for scattergl traces', function(done) { gd = mock({ data: [{ type: 'scattergl', @@ -631,23 +634,37 @@ describe('Test plot api', function() { } }); - Plotly.relayout(gd, 'dragmode', 'pan'); - expectModeBarOnly('pan'); + Plotly.relayout(gd, 'dragmode', 'pan') + .then(function() { + expectModeBarOnly('pan'); - Plotly.relayout(mock(gd), 'dragmode', 'lasso'); - expectReplot('lasso 1'); + return Plotly.relayout(mock(gd), 'dragmode', 'lasso'); + }) + .then(function() { + expectReplot('lasso 1'); - Plotly.relayout(mock(gd), 'dragmode', 'select'); - expectModeBarOnly('select 1'); + return Plotly.relayout(mock(gd), 'dragmode', 'select'); + }) + .then(function() { + expectModeBarOnly('select 1'); - Plotly.relayout(mock(gd), 'dragmode', 'lasso'); - expectModeBarOnly('lasso 2'); + return Plotly.relayout(mock(gd), 'dragmode', 'lasso'); + }) + .then(function() { + expectModeBarOnly('lasso 2'); - Plotly.relayout(mock(gd), 'dragmode', 'zoom'); - expectModeBarOnly('zoom'); + return Plotly.relayout(mock(gd), 'dragmode', 'zoom'); + }) + .then(function() { + expectModeBarOnly('zoom'); - Plotly.relayout(mock(gd), 'dragmode', 'select'); - expectReplot('select 2'); + return Plotly.relayout(mock(gd), 'dragmode', 'select'); + }) + .then(function() { + expectReplot('select 2'); + }) + .catch(failTest) + .then(done); }); it('should trigger replot (but not recalc) when changing attributes that affect axis length/range', function() { @@ -682,7 +699,9 @@ describe('Test plot api', function() { 'grid.subplots[1][1]': 'xy' }; - for(var attr in axLayoutEdits) { + var attr; + var checkAttr = expectReplot(attr); + for(attr in axLayoutEdits) { gd = mock({ data: [{y: [1, 2]}, {y: [4, 3], xaxis: 'x2', yaxis: 'y2'}], layout: { @@ -691,8 +710,8 @@ describe('Test plot api', function() { } }); - Plotly.relayout(gd, attr, axLayoutEdits[attr]); - expectReplot(attr); + Plotly.relayout(gd, attr, axLayoutEdits[attr]) + .then(checkAttr); } }); @@ -740,7 +759,7 @@ describe('Test plot api', function() { }); }); - it('should trigger calc on axis range updates when constraints are present', function() { + it('should trigger calc on axis range updates when constraints are present', function(done) { gd = mock({ data: [{ y: [1, 2, 1] @@ -751,8 +770,12 @@ describe('Test plot api', function() { } }); - Plotly.relayout(gd, 'xaxis.range[0]', 0); - expect(gd.calcdata).toBeUndefined(); + Plotly.relayout(gd, 'xaxis.range[0]', 0) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + }) + .catch(failTest) + .then(done); }); }); @@ -774,96 +797,124 @@ describe('Test plot api', function() { gd.emit = function() {}; } - it('calls Scatter.arraysToCalcdata and Plots.style on scatter styling', function() { + it('calls Scatter.arraysToCalcdata and Plots.style on scatter styling', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3]}], layout: {} }; mockDefaultsAndCalc(gd); - Plotly.restyle(gd, {'marker.color': 'red'}); - expect(Scatter.arraysToCalcdata).toHaveBeenCalled(); - expect(Bar.arraysToCalcdata).not.toHaveBeenCalled(); - expect(Plots.style).toHaveBeenCalled(); - expect(plotApi.plot).not.toHaveBeenCalled(); - // "docalc" deletes gd.calcdata - make sure this didn't happen - expect(gd.calcdata).toBeDefined(); + Plotly.restyle(gd, {'marker.color': 'red'}) + .then(function() { + expect(Scatter.arraysToCalcdata).toHaveBeenCalled(); + expect(Bar.arraysToCalcdata).not.toHaveBeenCalled(); + expect(Plots.style).toHaveBeenCalled(); + expect(plotApi.plot).not.toHaveBeenCalled(); + // "docalc" deletes gd.calcdata - make sure this didn't happen + expect(gd.calcdata).toBeDefined(); + }) + .catch(failTest) + .then(done); }); - it('calls Bar.arraysToCalcdata and Plots.style on bar styling', function() { + it('calls Bar.arraysToCalcdata and Plots.style on bar styling', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3], type: 'bar'}], layout: {} }; mockDefaultsAndCalc(gd); - Plotly.restyle(gd, {'marker.color': 'red'}); - expect(Scatter.arraysToCalcdata).not.toHaveBeenCalled(); - expect(Bar.arraysToCalcdata).toHaveBeenCalled(); - expect(Plots.style).toHaveBeenCalled(); - expect(plotApi.plot).not.toHaveBeenCalled(); - expect(gd.calcdata).toBeDefined(); + Plotly.restyle(gd, {'marker.color': 'red'}) + .then(function() { + expect(Scatter.arraysToCalcdata).not.toHaveBeenCalled(); + expect(Bar.arraysToCalcdata).toHaveBeenCalled(); + expect(Plots.style).toHaveBeenCalled(); + expect(plotApi.plot).not.toHaveBeenCalled(); + expect(gd.calcdata).toBeDefined(); + }) + .catch(failTest) + .then(done); }); - it('should do full replot when arrayOk attributes are updated', function() { + it('should do full replot when arrayOk attributes are updated', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3]}], layout: {} }; mockDefaultsAndCalc(gd); - Plotly.restyle(gd, 'marker.color', [['red', 'green', 'blue']]); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + Plotly.restyle(gd, 'marker.color', [['red', 'green', 'blue']]) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'marker.color', 'yellow'); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'marker.color', 'yellow'); + }) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'marker.color', 'blue'); - expect(gd.calcdata).toBeDefined(); - expect(plotApi.plot).not.toHaveBeenCalled(); + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'marker.color', 'blue'); + }) + .then(function() { + expect(gd.calcdata).toBeDefined(); + expect(plotApi.plot).not.toHaveBeenCalled(); - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'marker.color', [['red', 'blue', 'green']]); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'marker.color', [['red', 'blue', 'green']]); + }) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); + }) + .catch(failTest) + .then(done); }); - it('should do full replot when arrayOk base attributes are updated', function() { + it('should do full replot when arrayOk base attributes are updated', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3]}], layout: {} }; mockDefaultsAndCalc(gd); - Plotly.restyle(gd, 'hoverlabel.bgcolor', [['red', 'green', 'blue']]); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + Plotly.restyle(gd, 'hoverlabel.bgcolor', [['red', 'green', 'blue']]) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'hoverlabel.bgcolor', 'yellow'); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'hoverlabel.bgcolor', 'yellow'); + }) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'hoverlabel.bgcolor', 'blue'); - expect(gd.calcdata).toBeDefined(); - expect(plotApi.plot).not.toHaveBeenCalled(); + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'hoverlabel.bgcolor', 'blue'); + }) + .then(function() { + expect(gd.calcdata).toBeDefined(); + expect(plotApi.plot).not.toHaveBeenCalled(); - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'hoverlabel.bgcolor', [['red', 'blue', 'green']]); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'hoverlabel.bgcolor', [['red', 'blue', 'green']]); + }) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); + }) + .catch(failTest) + .then(done); }); - it('should do full replot when attribute container are updated', function() { + it('should do full replot when attribute container are updated', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3]}], layout: { @@ -877,92 +928,112 @@ describe('Test plot api', function() { marker: { color: ['red', 'blue', 'green'] } - }); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + }) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); + }) + .catch(failTest) + .then(done); }); - it('calls plot on xgap and ygap styling', function() { + it('calls plot on xgap and ygap styling', function(done) { var gd = { data: [{z: [[1, 2, 3], [4, 5, 6], [7, 8, 9]], showscale: false, type: 'heatmap'}], layout: {} }; mockDefaultsAndCalc(gd); - Plotly.restyle(gd, {'xgap': 2}); - expect(plotApi.plot).toHaveBeenCalled(); + Plotly.restyle(gd, {'xgap': 2}) + .then(function() { + expect(plotApi.plot).toHaveBeenCalled(); - Plotly.restyle(gd, {'ygap': 2}); - expect(plotApi.plot.calls.count()).toEqual(2); + return Plotly.restyle(gd, {'ygap': 2}); + }) + .then(function() { + expect(plotApi.plot.calls.count()).toEqual(2); + }) + .catch(failTest) + .then(done); }); - it('should clear calcdata when restyling \'zmin\' and \'zmax\' on contour traces', function() { - var contour = { + [ + { data: [{ type: 'contour', z: [[1, 2, 3], [1, 2, 1]] }] - }; - - var histogram2dcontour = { + }, + { data: [{ type: 'histogram2dcontour', x: [1, 1, 2, 2, 2, 3], y: [0, 0, 0, 0, 1, 3] }] - }; - - var mocks = [contour, histogram2dcontour]; - - mocks.forEach(function(gd) { - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'zmin', 0); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); - + } + ].forEach(function(gd) { + it('should clear calcdata when restyling \'zmin\' and \'zmax\' on ' + gd.data.type + ' traces', function(done) { mockDefaultsAndCalc(gd); plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'zmax', 10); - expect(gd.calcdata).toBeUndefined(); - expect(plotApi.plot).toHaveBeenCalled(); + Plotly.restyle(gd, 'zmin', 0) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); + + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'zmax', 10); + }) + .then(function() { + expect(gd.calcdata).toBeUndefined(); + expect(plotApi.plot).toHaveBeenCalled(); + }) + .catch(failTest) + .then(done); }); }); - it('should not clear calcdata when restyling \'zmin\' and \'zmax\' on heatmap traces', function() { - var heatmap = { + [ + { data: [{ type: 'heatmap', z: [[1, 2, 3], [1, 2, 1]] }] - }; - - var histogram2d = { + }, + { data: [{ type: 'histogram2d', x: [1, 1, 2, 2, 2, 3], y: [0, 0, 0, 0, 1, 3] }] - }; - - var mocks = [heatmap, histogram2d]; - - mocks.forEach(function(gd) { - mockDefaultsAndCalc(gd); - plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'zmin', 0); - expect(gd.calcdata).toBeDefined(); - expect(plotApi.plot).toHaveBeenCalled(); - + } + ].forEach(function(gd) { + it('should not clear calcdata when restyling \'zmin\' and \'zmax\' on ' + gd.data.type + ' traces', function(done) { mockDefaultsAndCalc(gd); plotApi.plot.calls.reset(); - Plotly.restyle(gd, 'zmax', 10); - expect(gd.calcdata).toBeDefined(); - expect(plotApi.plot).toHaveBeenCalled(); + Plotly.restyle(gd, 'zmin', 0) + .then(function() { + expect(gd.calcdata).toBeDefined(); + expect(plotApi.plot).toHaveBeenCalled(); + + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'zmax', 10); + }) + .then(function() { + expect(gd.calcdata).toBeDefined(); + expect(plotApi.plot).toHaveBeenCalled(); + + mockDefaultsAndCalc(gd); + plotApi.plot.calls.reset(); + return Plotly.restyle(gd, 'zmin', 0); + }) + .catch(failTest) + .then(done); }); }); - it('ignores undefined values', function() { + it('ignores undefined values', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3], type: 'scatter'}], layout: {} @@ -971,15 +1042,21 @@ describe('Test plot api', function() { mockDefaultsAndCalc(gd); // Check to see that the color is updated: - Plotly.restyle(gd, {'marker.color': 'blue'}); - expect(gd._fullData[0].marker.color).toBe('blue'); + Plotly.restyle(gd, {'marker.color': 'blue'}) + .then(function() { + expect(gd._fullData[0].marker.color).toBe('blue'); - // Check to see that the color is unaffected: - Plotly.restyle(gd, {'marker.color': undefined}); - expect(gd._fullData[0].marker.color).toBe('blue'); + // Check to see that the color is unaffected: + return Plotly.restyle(gd, {'marker.color': undefined}); + }) + .then(function() { + expect(gd._fullData[0].marker.color).toBe('blue'); + }) + .catch(failTest) + .then(done); }); - it('ignores invalid trace indices', function() { + it('ignores invalid trace indices', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3], type: 'scatter'}], layout: {} @@ -988,10 +1065,12 @@ describe('Test plot api', function() { mockDefaultsAndCalc(gd); // Call restyle on an invalid trace indice - Plotly.restyle(gd, {'type': 'scatter', 'marker.color': 'red'}, [1]); + Plotly.restyle(gd, {'type': 'scatter', 'marker.color': 'red'}, [1]) + .catch(failTest) + .then(done); }); - it('restores null values to defaults', function() { + it('restores null values to defaults', function(done) { var gd = { data: [{x: [1, 2, 3], y: [1, 2, 3], type: 'scatter'}], layout: {} @@ -1001,15 +1080,21 @@ describe('Test plot api', function() { var colorDflt = gd._fullData[0].marker.color; // Check to see that the color is updated: - Plotly.restyle(gd, {'marker.color': 'blue'}); - expect(gd._fullData[0].marker.color).toBe('blue'); + Plotly.restyle(gd, {'marker.color': 'blue'}) + .then(function() { + expect(gd._fullData[0].marker.color).toBe('blue'); - // Check to see that the color is restored to the original default: - Plotly.restyle(gd, {'marker.color': null}); - expect(gd._fullData[0].marker.color).toBe(colorDflt); + // Check to see that the color is restored to the original default: + return Plotly.restyle(gd, {'marker.color': null}); + }) + .then(function() { + expect(gd._fullData[0].marker.color).toBe(colorDflt); + }) + .catch(failTest) + .then(done); }); - it('can target specific traces by leaving properties undefined', function() { + it('can target specific traces by leaving properties undefined', function(done) { var gd = { data: [ {x: [1, 2, 3], y: [1, 2, 3], type: 'scatter'}, @@ -1022,14 +1107,20 @@ describe('Test plot api', function() { var colorDflt = [gd._fullData[0].marker.color, gd._fullData[1].marker.color]; // Check only second trace's color has been changed: - Plotly.restyle(gd, {'marker.color': [undefined, 'green']}); - expect(gd._fullData[0].marker.color).toBe(colorDflt[0]); - expect(gd._fullData[1].marker.color).toBe('green'); + Plotly.restyle(gd, {'marker.color': [undefined, 'green']}) + .then(function() { + expect(gd._fullData[0].marker.color).toBe(colorDflt[0]); + expect(gd._fullData[1].marker.color).toBe('green'); - // Check both colors restored to the original default: - Plotly.restyle(gd, {'marker.color': [null, null]}); - expect(gd._fullData[0].marker.color).toBe(colorDflt[0]); - expect(gd._fullData[1].marker.color).toBe(colorDflt[1]); + // Check both colors restored to the original default: + return Plotly.restyle(gd, {'marker.color': [null, null]}); + }) + .then(function() { + expect(gd._fullData[0].marker.color).toBe(colorDflt[0]); + expect(gd._fullData[1].marker.color).toBe(colorDflt[1]); + }) + .catch(failTest) + .then(done); }); }); @@ -2251,28 +2342,29 @@ describe('Test plot api', function() { var initialData = []; var layout = { title: 'Redraw' }; - Plotly.newPlot(gd, initialData, layout); - - var trace1 = { - x: [1, 2, 3, 4], - y: [4, 1, 5, 3], - name: 'First Trace' - }; - var trace2 = { - x: [1, 2, 3, 4], - y: [14, 11, 15, 13], - name: 'Second Trace' - }; - var trace3 = { - x: [1, 2, 3, 4], - y: [5, 3, 7, 1], - name: 'Third Trace' - }; + Plotly.newPlot(gd, initialData, layout) + .then(function() { + var trace1 = { + x: [1, 2, 3, 4], + y: [4, 1, 5, 3], + name: 'First Trace' + }; + var trace2 = { + x: [1, 2, 3, 4], + y: [14, 11, 15, 13], + name: 'Second Trace' + }; + var trace3 = { + x: [1, 2, 3, 4], + y: [5, 3, 7, 1], + name: 'Third Trace' + }; - var newData = [trace1, trace2, trace3]; - gd.data = newData; + var newData = [trace1, trace2, trace3]; + gd.data = newData; - Plotly.redraw(gd) + return Plotly.redraw(gd); + }) .then(function() { expect(d3.selectAll('g.trace.scatter').size()).toEqual(3); }) @@ -2697,7 +2789,6 @@ describe('Test plot api', function() { layout = gd.layout; calcdata = gd.calcdata; }) - .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/plot_interact_test.js b/test/jasmine/tests/plot_interact_test.js index 4ab482e870c..0ce89a264f8 100644 --- a/test/jasmine/tests/plot_interact_test.js +++ b/test/jasmine/tests/plot_interact_test.js @@ -124,7 +124,8 @@ describe('Test plot structure', function() { expect(countScatterTraces()).toEqual(mock.data.length); expect(countSubplots()).toEqual(1); - Plotly.relayout(gd, {xaxis: null, yaxis: null}).then(function() { + Plotly.relayout(gd, {xaxis: null, yaxis: null}) + .then(function() { expect(countScatterTraces()).toEqual(1); expect(countSubplots()).toEqual(1); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); @@ -227,19 +228,22 @@ describe('Test plot structure', function() { var mockCopy = extendMock(); var gd = createGraphDiv(); - Plotly.plot(gd, mockCopy.data, mockCopy.layout); - - Plotly.restyle(gd, { - type: 'scatter', - x: [[1, 2, 3]], - y: [[2, 1, 2]], - z: null - }, 0); - - Plotly.restyle(gd, 'type', 'contour', 1); - - Plotly.restyle(gd, 'type', 'heatmap', 2) - .then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + return Plotly.restyle(gd, { + type: 'scatter', + x: [[1, 2, 3]], + y: [[2, 1, 2]], + z: null + }, 0); + }) + .then(function() { + return Plotly.restyle(gd, 'type', 'contour', 1); + }) + .then(function() { + return Plotly.restyle(gd, 'type', 'heatmap', 2); + }) + .then(done); }); it('has four *subplot* nodes', function() { diff --git a/test/jasmine/tests/plots_test.js b/test/jasmine/tests/plots_test.js index a5dc0aaacc4..8c9e313b836 100644 --- a/test/jasmine/tests/plots_test.js +++ b/test/jasmine/tests/plots_test.js @@ -787,8 +787,9 @@ describe('Test Plots', function() { expect(d3.selectAll('g.trace.scattergeo').size()).toEqual(1); destroyGraphDiv(); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should handle cases when module plot is not set (ternary case)', function(done) { @@ -806,8 +807,9 @@ describe('Test Plots', function() { expect(d3.selectAll('g.trace.scatter').size()).toEqual(1); destroyGraphDiv(); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/polar_test.js b/test/jasmine/tests/polar_test.js index c5836307b60..c15e02a4b4c 100644 --- a/test/jasmine/tests/polar_test.js +++ b/test/jasmine/tests/polar_test.js @@ -908,7 +908,7 @@ describe('Test polar interactions:', function() { .then(done); }); - it('@flaky should respond to drag interactions on plot area', function(done) { + it('should respond to drag interactions on plot area', function(done) { var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json')); // to avoid dragging on hover labels diff --git a/test/jasmine/tests/range_selector_test.js b/test/jasmine/tests/range_selector_test.js index fbea9d73170..d135b2ce710 100644 --- a/test/jasmine/tests/range_selector_test.js +++ b/test/jasmine/tests/range_selector_test.js @@ -467,7 +467,6 @@ describe('range selector interactions:', function() { mockCopy = Lib.extendDeep({}, mock); Plotly.plot(gd, mockCopy.data, mockCopy.layout) - .catch(failTest) .then(done); }); @@ -514,7 +513,8 @@ describe('range selector interactions:', function() { }); it('should be able to be removed by `relayout`', function(done) { - Plotly.relayout(gd, 'xaxis.rangeselector.visible', false).then(function() { + Plotly.relayout(gd, 'xaxis.rangeselector.visible', false) + .then(function() { assertNodeCount('.rangeselector', 0); assertNodeCount('.button', 0); }) @@ -527,7 +527,8 @@ describe('range selector interactions:', function() { assertNodeCount('.button', len); - Plotly.relayout(gd, 'xaxis.rangeselector.buttons[0]', null).then(function() { + Plotly.relayout(gd, 'xaxis.rangeselector.buttons[0]', null) + .then(function() { assertNodeCount('.button', len - 1); return Plotly.relayout(gd, 'xaxis.rangeselector.buttons[1]', 'remove'); @@ -543,7 +544,8 @@ describe('range selector interactions:', function() { checkButtonColor('rgb(238, 238, 238)', 'rgb(212, 212, 212)'); - Plotly.relayout(gd, prefix + 'bgcolor', 'red').then(function() { + Plotly.relayout(gd, prefix + 'bgcolor', 'red') + .then(function() { checkButtonColor('rgb(255, 0, 0)', 'rgb(255, 128, 128)'); return Plotly.relayout(gd, prefix + 'activecolor', 'blue'); @@ -601,12 +603,14 @@ describe('range selector interactions:', function() { 'xaxis.range[1]': '2015-11-30' }; - Plotly.relayout(gd, update).then(function() { + Plotly.relayout(gd, update) + .then(function() { // '1m' should be active after the relayout checkActiveButton(0, '1m'); return Plotly.relayout(gd, 'xaxis.autorange', true); - }).then(function() { + }) + .then(function() { // 'all' should be after an autoscale checkActiveButton(buttons.size() - 1, 'back to all'); }) @@ -631,7 +635,6 @@ describe('range selector automargin', function() { }}); Plotly.plot(gd, mockCopy.data, mockCopy.layout) - .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/sankey_test.js b/test/jasmine/tests/sankey_test.js index c5f038e071b..bacd53f85b5 100644 --- a/test/jasmine/tests/sankey_test.js +++ b/test/jasmine/tests/sankey_test.js @@ -378,8 +378,9 @@ describe('sankey tests', function() { .then(function() { expect(gd.data.length).toEqual(0); expect(d3.selectAll('.sankey').size()).toEqual(0); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.deleteTraces removes draggers', function(done) { @@ -413,8 +414,9 @@ describe('sankey tests', function() { .then(function() { expect(gd.data.length).toEqual(1); expect(d3.selectAll('.sankey').size()).toEqual(1); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('\'node\' remains visible even if \'value\' is very low', function(done) { @@ -434,8 +436,9 @@ describe('sankey tests', function() { expect(d3.selectAll('.sankey .node-rect')[0].reduce(function(prevMin, rect) { return Math.min(prevMin, d3.select(rect).attr('height')); }, Infinity)).toEqual(0.5); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('switch from normal to circular Sankey on react', function(done) { @@ -449,8 +452,9 @@ describe('sankey tests', function() { }) .then(function() { expect(gd.calcdata[0][0].circular).toBe(true); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('switch from circular to normal Sankey on react', function(done) { @@ -473,8 +477,9 @@ describe('sankey tests', function() { }) .then(function() { expect(gd.calcdata[0][0].circular).toBe(false); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('can create groups, restyle groups and properly update DOM', function(done) { @@ -533,8 +538,9 @@ describe('sankey tests', function() { }) .then(function() { expect(gd.calcdata[0][0].circular).toBe(false); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('prevents nodes from overlapping in snap arrangement', function(done) { @@ -1343,7 +1349,7 @@ describe('sankey tests', function() { .then(done); }); - it('@noCI should persist the position of every nodes after drag in attributes nodes.(x|y)', function(done) { + it('should persist the position of every nodes after drag in attributes nodes.(x|y)', function(done) { mockCopy.data[0].arrangement = arrangement; var move = [50, -50]; var nodes; diff --git a/test/jasmine/tests/scatter3d_test.js b/test/jasmine/tests/scatter3d_test.js index 4d6c8826047..0d2a999e335 100644 --- a/test/jasmine/tests/scatter3d_test.js +++ b/test/jasmine/tests/scatter3d_test.js @@ -158,6 +158,7 @@ describe('Test scatter3d interactions:', function() { expect(gd._fullLayout._has('gl3d')).toBe(true); expect(gd._fullLayout.scene._scene).toBeDefined(); }) + .catch(failTest) .then(done); }); @@ -174,6 +175,7 @@ describe('Test scatter3d interactions:', function() { expect(gd._fullLayout._has('gl3d')).toBe(false); expect(gd._fullLayout.scene === undefined).toBe(true); }) + .catch(failTest) .then(done); }); @@ -238,6 +240,7 @@ describe('Test scatter3d interactions:', function() { .then(function() { assertObjects(order0); }) + .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/scattergeo_test.js b/test/jasmine/tests/scattergeo_test.js index e01d67fb8af..3f673be7fd4 100644 --- a/test/jasmine/tests/scattergeo_test.js +++ b/test/jasmine/tests/scattergeo_test.js @@ -314,7 +314,6 @@ describe('Test scattergeo hover', function() { lat: [10, 20, 30], text: ['A', 'B', 'C'] }]) - .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/scattergl_test.js b/test/jasmine/tests/scattergl_test.js index 4e1c60d10d9..d409d89e753 100644 --- a/test/jasmine/tests/scattergl_test.js +++ b/test/jasmine/tests/scattergl_test.js @@ -219,16 +219,19 @@ describe('end-to-end scattergl tests', function() { }); it('@gl should change plot type with incomplete data', function(done) { - Plotly.plot(gd, [{}]); - expect(function() { - Plotly.restyle(gd, {type: 'scattergl', x: [[1]]}, 0); - }).not.toThrow(); - - expect(function() { - Plotly.restyle(gd, {y: [[1]]}, 0); - }).not.toThrow(); - - done(); + Plotly.plot(gd, [{}]) + .then(function() { + expect(function() { + return Plotly.restyle(gd, {type: 'scattergl', x: [[1]]}, 0); + }).not.toThrow(); + }) + .then(function() { + expect(function() { + return Plotly.restyle(gd, {y: [[1]]}, 0); + }).not.toThrow(); + }) + .catch(failTest) + .then(done); }); it('@gl should restyle opacity', function(done) { diff --git a/test/jasmine/tests/scattermapbox_test.js b/test/jasmine/tests/scattermapbox_test.js index e788b341e2f..39018139d7e 100644 --- a/test/jasmine/tests/scattermapbox_test.js +++ b/test/jasmine/tests/scattermapbox_test.js @@ -658,7 +658,7 @@ describe('scattermapbox convert', function() { }); }); -describe('@noCI scattermapbox hover', function() { +describe('scattermapbox hover', function() { var hoverPoints = ScatterMapbox.hoverPoints; var gd; @@ -762,6 +762,7 @@ describe('@noCI scattermapbox hover', function() { out = hoverPoints(getPointData(gd), xval, yval)[0]; expect(out.extraText).toEqual('(10°, 10°)
A'); }) + .catch(failTest) .then(done); }); @@ -801,8 +802,9 @@ describe('@noCI scattermapbox hover', function() { var out = hoverPoints(getPointData(gd), xval, yval)[0]; expect(out.extraText).toEqual('lon: 10°'); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('@gl should generate hover label info (hoverinfo: \'lat\' case)', function(done) { @@ -813,8 +815,9 @@ describe('@noCI scattermapbox hover', function() { var out = hoverPoints(getPointData(gd), xval, yval)[0]; expect(out.extraText).toEqual('lat: 10°'); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('@gl should generate hover label info (hoverinfo: \'text\' + \'text\' array case)', function(done) { @@ -825,8 +828,9 @@ describe('@noCI scattermapbox hover', function() { var out = hoverPoints(getPointData(gd), xval, yval)[0]; expect(out.extraText).toEqual('A'); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('@gl should generate hover label info (hoverinfo: \'text\' + \'hovertext\' array case)', function(done) { @@ -837,8 +841,9 @@ describe('@noCI scattermapbox hover', function() { var out = hoverPoints(getPointData(gd), xval, yval)[0]; expect(out.extraText).toEqual('Apple'); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('@gl should generate hover label (\'marker.color\' array case)', function(done) { @@ -847,6 +852,7 @@ describe('@noCI scattermapbox hover', function() { expect(out.color).toEqual('red'); }) + .catch(failTest) .then(done); }); @@ -856,6 +862,7 @@ describe('@noCI scattermapbox hover', function() { expect(out.color).toEqual('rgb(245, 195, 157)'); }) + .catch(failTest) .then(done); }); @@ -892,8 +899,9 @@ describe('@noCI scattermapbox hover', function() { var out = hoverPoints(getPointData(gd), xval, yval)[0]; expect(out.hovertemplate).toEqual('tpl'); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('@gl should always display hoverlabel when hovertemplate is defined', function(done) { @@ -903,12 +911,13 @@ describe('@noCI scattermapbox hover', function() { }) .then(function() { checkHoverLabel([190, 215], ['tpl2', '']); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); -describe('@noCI Test plotly events on a scattermapbox plot:', function() { +describe('Test plotly events on a scattermapbox plot:', function() { var mock = require('@mocks/mapbox_0.json'); var pointPos = [440, 290]; var nearPos = [460, 290]; @@ -936,7 +945,8 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { var futureData; beforeEach(function() { - futureData = undefined; + futureData = null; + gd.on('plotly_click', function(data) { futureData = data; }); @@ -944,7 +954,7 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { it('@gl should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('@gl should contain the correct fields', function() { @@ -976,7 +986,8 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { var futureData; beforeEach(function() { - futureData = undefined; + futureData = null; + gd.on('plotly_click', function(data) { futureData = data; }); @@ -984,12 +995,12 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { it('@gl should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('@gl does not register right-clicks', function() { click(pointPos[0], pointPos[1], clickOpts); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); // TODO: 'should contain the correct fields' // This test passed previously, but only because assets/click @@ -1019,6 +1030,8 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { var futureData; beforeEach(function() { + futureData = null; + gd.on('plotly_hover', function(data) { futureData = data; }); @@ -1047,6 +1060,8 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { var futureData; beforeEach(function() { + futureData = null; + gd.on('plotly_unhover', function(data) { futureData = data; }); @@ -1066,12 +1081,14 @@ describe('@noCI Test plotly events on a scattermapbox plot:', function() { 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); + }) + .catch(failTest) + .then(done); }); }); }); -describe('@noCI Test plotly events on a scattermapbox plot when css transform is present:', function() { +describe('Test plotly events on a scattermapbox plot when css transform is present:', function() { var mock = require('@mocks/mapbox_0.json'); var pointPos = [440 / 2, 290 / 2]; var nearPos = [460 / 2, 290 / 2]; @@ -1110,7 +1127,8 @@ describe('@noCI Test plotly events on a scattermapbox plot when css transform is var futureData; beforeEach(function() { - futureData = undefined; + futureData = null; + gd.on('plotly_click', function(data) { futureData = data; }); @@ -1118,7 +1136,7 @@ describe('@noCI Test plotly events on a scattermapbox plot when css transform is it('@gl should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('@gl should contain the correct fields', function() { @@ -1143,6 +1161,8 @@ describe('@noCI Test plotly events on a scattermapbox plot when css transform is var futureData; beforeEach(function() { + futureData = null; + gd.on('plotly_hover', function(data) { futureData = data; }); @@ -1171,6 +1191,8 @@ describe('@noCI Test plotly events on a scattermapbox plot when css transform is var futureData; beforeEach(function() { + futureData = null; + gd.on('plotly_unhover', function(data) { futureData = data; }); @@ -1190,7 +1212,9 @@ describe('@noCI Test plotly events on a scattermapbox plot when css transform is 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); + }) + .catch(failTest) + .then(done); }); }); }); diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index bdb7d01a2c5..e5f484cfa48 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -257,7 +257,7 @@ describe('Click-to-select', function() { desc: 'is clicked while add/subtract modifier keys are active', clickOpts: { shiftKey: true } }].forEach(function(testData) { - it('@flaky ' + testData.desc, function(done) { + it('' + testData.desc, function(done) { plotMock14() .then(function() { return _immediateClickPt(mock14Pts[7]); }) .then(function() { @@ -278,7 +278,7 @@ describe('Click-to-select', function() { }); }); - it('@flaky cleanly clears and starts selections although add/subtract mode on', function(done) { + it('cleanly clears and starts selections although add/subtract mode on', function(done) { plotMock14() .then(function() { return _immediateClickPt(mock14Pts[7]); @@ -299,7 +299,7 @@ describe('Click-to-select', function() { .then(done); }); - it('@flaky supports adding to an existing selection', function(done) { + it('supports adding to an existing selection', function(done) { plotMock14() .then(function() { return _immediateClickPt(mock14Pts[7]); }) .then(function() { @@ -311,7 +311,7 @@ describe('Click-to-select', function() { .then(done); }); - it('@flaky supports subtracting from an existing selection', function(done) { + it('supports subtracting from an existing selection', function(done) { plotMock14() .then(function() { return _immediateClickPt(mock14Pts[7]); }) .then(function() { @@ -327,7 +327,7 @@ describe('Click-to-select', function() { .then(done); }); - it('@flaky can be used interchangeably with lasso/box select', function(done) { + it('can be used interchangeably with lasso/box select', function(done) { plotMock14() .then(function() { return _immediateClickPt(mock14Pts[35]); @@ -424,7 +424,7 @@ describe('Click-to-select', function() { .then(done); }); - it('@flaky is supported in pan/zoom mode', function(done) { + it('is supported in pan/zoom mode', function(done) { plotMock14({ dragmode: 'zoom' }) .then(function() { return _immediateClickPt(mock14Pts[35]); @@ -459,7 +459,7 @@ describe('Click-to-select', function() { .then(done); }); - it('@flaky retains selected points when switching between pan and zoom mode', function(done) { + it('retains selected points when switching between pan and zoom mode', function(done) { plotMock14({ dragmode: 'zoom' }) .then(function() { return _immediateClickPt(mock14Pts[35]); @@ -513,7 +513,7 @@ describe('Click-to-select', function() { .then(done); }); - it('@flaky deals correctly with histogram\'s binning in the persistent selection case', function(done) { + it('deals correctly with histogram\'s binning in the persistent selection case', function(done) { var mock = require('@mocks/histogram_colorscale.json'); var firstBinPts = [0]; var secondBinPts = [1, 2]; @@ -553,7 +553,7 @@ describe('Click-to-select', function() { function shiftClickThirdBin() { return _click(351, 347, { shiftKey: true }); } }); - it('@flaky ignores clicks on boxes in a box trace type', function(done) { + it('ignores clicks on boxes in a box trace type', function(done) { var mock = Lib.extendDeep({}, require('@mocks/box_grouped_horz.json')); mock.layout.clickmode = 'event+select'; @@ -588,7 +588,7 @@ describe('Click-to-select', function() { describe('is disabled when clickmode does not include \'select\'', function() { ['select', 'lasso'] .forEach(function(dragmode) { - it('@flaky and dragmode is ' + dragmode, function(done) { + it('and dragmode is ' + dragmode, function(done) { plotMock14({ clickmode: 'event', dragmode: dragmode }) .then(function() { // Still, the plotly_selected event should be thrown, @@ -607,7 +607,7 @@ describe('Click-to-select', function() { describe('is disabled when clickmode does not include \'select\'', function() { ['pan', 'zoom'] .forEach(function(dragmode) { - it('@flaky and dragmode is ' + dragmode, function(done) { + it('and dragmode is ' + dragmode, function(done) { plotMock14({ clickmode: 'event', dragmode: dragmode }) .then(function() { _immediateClickPt(mock14Pts[1]); @@ -629,7 +629,7 @@ describe('Click-to-select', function() { // - Some mocks don't specify a width and height, so this needs // to be set explicitly to ensure click coordinates fit. - // The non-gl traces: use @flaky CI annotation + // The non-gl traces: use CI annotation [ testCase('histrogram', require('@mocks/histogram_colorscale.json'), 355, 301, [3, 4, 5]), testCase('box', require('@mocks/box_grouped_horz.json'), 610, 342, [[2], [], []], @@ -653,7 +653,7 @@ describe('Click-to-select', function() { [[], [], [], [19], [], []], { dragmode: 'zoom' }), ] .forEach(function(testCase) { - it('@flaky trace type ' + testCase.label, function(done) { + it('trace type ' + testCase.label, function(done) { _run(testCase, done); }); }); @@ -676,7 +676,7 @@ describe('Click-to-select', function() { { mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN }) ] .forEach(function(testCase) { - it('@noCI @gl trace type ' + testCase.label, function(done) { + it('@gl trace type ' + testCase.label, function(done) { _run(testCase, done); }); }); @@ -753,19 +753,18 @@ describe('Click-to-select', function() { testCase('polar', require('@mocks/polar_scatter.json'), 130, 290, [[], [], [], [19], [], []], { dragmode: 'zoom' }) ].forEach(function(testCase) { - it('@flaky for base plot ' + testCase.label, function(done) { + it('for base plot ' + testCase.label, function(done) { _run(testCase, done); }); }); - // The mapbox traces: use @noCI annotation cause they are usually too resource-intensive [ testCase('mapbox', require('@mocks/mapbox_0.json'), 650, 195, [[2], []], {}, { mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN }), testCase('mapbox', require('@mocks/mapbox_choropleth0.json'), 270, 220, [[0], []], {}, { mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN }) ].forEach(function(testCase) { - it('@noCI @gl for base plot ' + testCase.label, function(done) { + it('@gl for base plot ' + testCase.label, function(done) { _run(testCase, done); }); }); @@ -875,7 +874,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should trigger selecting/selected/deselect events', function(done) { + it('should trigger selecting/selected/deselect events', function(done) { resetEvents(gd); drag(selectPath); @@ -914,7 +913,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should handle add/sub selection', function(done) { + it('should handle add/sub selection', function(done) { resetEvents(gd); drag(selectPath); @@ -1021,7 +1020,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should trigger selecting/selected/deselect events', function(done) { + it('should trigger selecting/selected/deselect events', function(done) { resetEvents(gd); drag(lassoPath); @@ -1060,7 +1059,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should set selected points in graph data', function(done) { + it('should set selected points in graph data', function(done) { resetEvents(gd); drag(lassoPath); @@ -1079,7 +1078,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should set selected points in full data', function(done) { + it('should set selected points in full data', function(done) { resetEvents(gd); drag(lassoPath); @@ -1098,7 +1097,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should trigger selecting/selected/deselect events for touches', function(done) { + it('should trigger selecting/selected/deselect events for touches', function(done) { resetEvents(gd); drag(lassoPath, {type: 'touch'}); @@ -1133,7 +1132,7 @@ describe('Test select box and lasso in general:', function() { }); }); - it('@flaky should skip over non-visible traces', function(done) { + it('should skip over non-visible traces', function(done) { // note: this tests a mock with one or several invisible traces // the invisible traces in the other tests test for multiple // traces, with some visible and some not. @@ -1212,7 +1211,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should skip over BADNUM items', function(done) { + it('should skip over BADNUM items', function(done) { var data = [{ mode: 'markers', x: [null, undefined, NaN, 0, 'NA'], @@ -1251,7 +1250,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky scroll zoom should clear selection regions', function(done) { + it('scroll zoom should clear selection regions', function(done) { var gd = createGraphDiv(); var mockCopy = Lib.extendDeep({}, mock); mockCopy.layout.dragmode = 'select'; @@ -1303,7 +1302,7 @@ describe('Test select box and lasso in general:', function() { }]; specs.forEach(function(s) { - it('- @flaky on ' + s.axType + ' axes', function(done) { + it('- on ' + s.axType + ' axes', function(done) { var gd = createGraphDiv(); Plotly.plot(gd, [], { @@ -1345,7 +1344,7 @@ describe('Test select box and lasso in general:', function() { }]; specs.forEach(function(s) { - it('- @flaky on ' + s.axType + ' axes', function(done) { + it('- on ' + s.axType + ' axes', function(done) { var gd = createGraphDiv(); Plotly.plot(gd, [], { @@ -1368,7 +1367,7 @@ describe('Test select box and lasso in general:', function() { }); }); - it('@flaky should have their selection outlines cleared during *axrange* relayout calls', function(done) { + it('should have their selection outlines cleared during *axrange* relayout calls', function(done) { var gd = createGraphDiv(); var fig = Lib.extendDeep({}, mock); fig.layout.dragmode = 'select'; @@ -1390,7 +1389,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should select the right data with the corresponding select direction', function(done) { + it('should select the right data with the corresponding select direction', function(done) { var gd = createGraphDiv(); // drag around just the center point, but if we have a selectdirection we may @@ -1450,7 +1449,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should cleanly clear and restart selections on double click when add/subtract mode on', function(done) { + it('should cleanly clear and restart selections on double click when add/subtract mode on', function(done) { var gd = createGraphDiv(); var fig = Lib.extendDeep({}, require('@mocks/0.json')); @@ -1487,7 +1486,7 @@ describe('Test select box and lasso in general:', function() { } }); - it('@flaky should clear selected points on double click only on pan/lasso modes', function(done) { + it('should clear selected points on double click only on pan/lasso modes', function(done) { var gd = createGraphDiv(); var fig = Lib.extendDeep({}, require('@mocks/0.json')); fig.data = [fig.data[0]]; @@ -1596,7 +1595,7 @@ describe('Test select box and lasso in general:', function() { .then(done); }); - it('@flaky should remember selection polygons from previous select/lasso mode', function(done) { + it('should remember selection polygons from previous select/lasso mode', function(done) { var gd = createGraphDiv(); var path1 = [[150, 150], [170, 170]]; var path2 = [[193, 193], [213, 193]]; @@ -1885,7 +1884,7 @@ describe('Test select box and lasso per trace:', function() { } [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on scatterternary traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on scatterternary traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['a', 'b', 'c']); var assertSelectedPoints = makeAssertSelectedPoints(); @@ -1943,7 +1942,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on scattercarpet traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on scattercarpet traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['a', 'b']); var assertSelectedPoints = makeAssertSelectedPoints(); @@ -1984,7 +1983,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@noCI @gl should work on scattermapbox traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('@gl should work on scattermapbox traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['lon', 'lat']); var assertRanges = makeAssertRanges('mapbox'); var assertLassoPoints = makeAssertLassoPoints('mapbox'); @@ -2099,7 +2098,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on scattergeo traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on scattergeo traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['lon', 'lat']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges('geo'); @@ -2202,7 +2201,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on scatterpolar traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on scatterpolar traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['r', 'theta']); var assertSelectedPoints = makeAssertSelectedPoints(); @@ -2245,7 +2244,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on barpolar traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on barpolar traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['r', 'theta']); var assertSelectedPoints = makeAssertSelectedPoints(); @@ -2306,7 +2305,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on choropleth traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on choropleth traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['location', 'z']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges('geo', -0.5); @@ -2373,7 +2372,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for waterfall traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for waterfall traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2435,7 +2434,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for funnel traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for funnel traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2499,7 +2498,7 @@ describe('Test select box and lasso per trace:', function() { }); [false].forEach(function(hasCssTransform) { - it('@flaky should work for bar traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for bar traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2591,7 +2590,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for date/category traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for date/category traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y']); var assertSelectedPoints = makeAssertSelectedPoints(); @@ -2655,7 +2654,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for histogram traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for histogram traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y', 'pointIndices']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2708,7 +2707,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for box traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for box traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'y', 'x']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2777,7 +2776,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for box traces (q1/median/q3 case), hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for box traces (q1/median/q3 case), hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'y', 'x']); var assertSelectedPoints = makeAssertSelectedPoints(); @@ -2830,7 +2829,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work for violin traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for violin traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'y', 'x']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2898,7 +2897,7 @@ describe('Test select box and lasso per trace:', function() { [false].forEach(function(hasCssTransform) { ['ohlc', 'candlestick'].forEach(function(type) { - it('@flaky should work for ' + type + ' traces, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work for ' + type + ' traces, hasCssTransform: ' + hasCssTransform, function(done) { var assertPoints = makeAssertPoints(['curveNumber', 'x', 'open', 'high', 'low', 'close']); var assertSelectedPoints = makeAssertSelectedPoints(); var assertRanges = makeAssertRanges(); @@ -2978,7 +2977,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on traces with enabled transforms, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on traces with enabled transforms, hasCssTransform: ' + hasCssTransform, function(done) { var assertSelectedPoints = makeAssertSelectedPoints(); Plotly.plot(gd, [{ @@ -3025,7 +3024,7 @@ describe('Test select box and lasso per trace:', function() { }); [false, true].forEach(function(hasCssTransform) { - it('@flaky should work on scatter/bar traces with text nodes, hasCssTransform: ' + hasCssTransform, function(done) { + it('should work on scatter/bar traces with text nodes, hasCssTransform: ' + hasCssTransform, function(done) { var assertSelectedPoints = makeAssertSelectedPoints(); function assertFillOpacity(exp, msg) { @@ -3082,7 +3081,7 @@ describe('Test select box and lasso per trace:', function() { var waitingTime = sankeyConstants.duration * 2; [false].forEach(function(hasCssTransform) { - it('@flaky select, hasCssTransform: ' + hasCssTransform, function(done) { + it('select, hasCssTransform: ' + hasCssTransform, function(done) { var fig = Lib.extendDeep({}, require('@mocks/sankey_circular.json')); fig.layout.dragmode = 'select'; var dblClickPos = [250, 400]; @@ -3118,7 +3117,7 @@ describe('Test select box and lasso per trace:', function() { }); }); - it('@flaky should not work when dragmode is undefined', function(done) { + it('should not work when dragmode is undefined', function(done) { var fig = Lib.extendDeep({}, require('@mocks/sankey_circular.json')); fig.layout.dragmode = undefined; @@ -3230,7 +3229,7 @@ describe('Test that selections persist:', function() { }); // trigger a recalc - Plotly.restyle(gd, 'x0', 1); + return Plotly.restyle(gd, 'x0', 1); }) .then(function() { _assert({ @@ -3272,9 +3271,8 @@ describe('Test that selections persist:', function() { }); // trigger a recalc - Plotly.restyle(gd, 'histfunc', 'sum'); + return Plotly.restyle(gd, 'histfunc', 'sum'); }) - .then(done) .then(function() { _assert({ selected: [undefined, 1, undefined, undefined, undefined], diff --git a/test/jasmine/tests/shapes_test.js b/test/jasmine/tests/shapes_test.js index 116ccfa988e..7c80fbe07be 100644 --- a/test/jasmine/tests/shapes_test.js +++ b/test/jasmine/tests/shapes_test.js @@ -240,7 +240,8 @@ describe('Test shapes:', function() { }); it('should be able to get relayout', function(done) { - Plotly.relayout(gd, {height: 200, width: 400}).then(function() { + Plotly.relayout(gd, {height: 200, width: 400}) + .then(function() { expect(countShapeLowerLayerNodes()).toEqual(1); expect(countShapePathsInLowerLayer()) .toEqual(countShapesInLowerLayer(gd)); @@ -261,7 +262,8 @@ describe('Test shapes:', function() { }); it('should be able to get relayout', function(done) { - Plotly.relayout(gd, {height: 200, width: 400}).then(function() { + Plotly.relayout(gd, {height: 200, width: 400}) + .then(function() { expect(countShapeUpperLayerNodes()).toEqual(1); expect(countShapePathsInUpperLayer()) .toEqual(countShapesInUpperLayer(gd)); @@ -283,7 +285,8 @@ describe('Test shapes:', function() { }); it('should be able to get relayout', function(done) { - Plotly.relayout(gd, {height: 200, width: 400}).then(function() { + Plotly.relayout(gd, {height: 200, width: 400}) + .then(function() { expect(countShapeLayerNodesInSubplots()) .toEqual(countSubplots(gd)); expect(countShapePathsInSubplots()) @@ -323,7 +326,8 @@ describe('Test shapes:', function() { var index = countShapes(gd); var shape = getRandomShape(); - Plotly.relayout(gd, 'shapes[' + index + ']', shape).then(function() { + Plotly.relayout(gd, 'shapes[' + index + ']', shape) + .then(function() { expect(countShapePathsInUpperLayer()).toEqual(pathCount + 1); expect(getLastShape(gd)).toEqual(shape); expect(countShapes(gd)).toEqual(index + 1); @@ -345,7 +349,8 @@ describe('Test shapes:', function() { var index = countShapes(gd); var shape = getRandomShape(); - Plotly.relayout(gd, 'shapes[' + index + ']', shape).then(function() { + Plotly.relayout(gd, 'shapes[' + index + ']', shape) + .then(function() { expect(countShapePathsInUpperLayer()).toEqual(pathCount + 1); expect(getLastShape(gd)).toEqual(shape); expect(countShapes(gd)).toEqual(index + 1); @@ -373,7 +378,8 @@ describe('Test shapes:', function() { }); it('should be able to remove all shapes', function(done) { - Plotly.relayout(gd, { shapes: null }).then(function() { + Plotly.relayout(gd, { shapes: null }) + .then(function() { expect(countShapePathsInUpperLayer()).toEqual(0); expect(countShapePathsInLowerLayer()).toEqual(0); expect(countShapePathsInSubplots()).toEqual(0); @@ -405,7 +411,8 @@ describe('Test shapes:', function() { Plotly.relayout(gd, { shapes: [ getRandomShape(), getRandomShape() - ]}).then(function() { + ]}) + .then(function() { expect(countShapePathsInUpperLayer()).toEqual(2); expect(countShapePathsInLowerLayer()).toEqual(0); expect(countShapePathsInSubplots()).toEqual(0); @@ -433,20 +440,24 @@ describe('Test shapes:', function() { .toEqual(shapesInUpperLayer + 1); expect(getLastShape(gd)).toEqual(shape); expect(countShapes(gd)).toEqual(index + 1); - }).then(function() { + }) + .then(function() { shape.layer = 'below'; - Plotly.relayout(gd, astr + '.layer', shape.layer); - }).then(function() { + return Plotly.relayout(gd, astr + '.layer', shape.layer); + }) + .then(function() { expect(countShapePathsInLowerLayer()) .toEqual(shapesInLowerLayer + 1); expect(countShapePathsInUpperLayer()) .toEqual(shapesInUpperLayer); expect(getLastShape(gd)).toEqual(shape); expect(countShapes(gd)).toEqual(index + 1); - }).then(function() { + }) + .then(function() { shape.layer = 'above'; - Plotly.relayout(gd, astr + '.layer', shape.layer); - }).then(function() { + return Plotly.relayout(gd, astr + '.layer', shape.layer); + }) + .then(function() { expect(countShapePathsInLowerLayer()) .toEqual(shapesInLowerLayer); expect(countShapePathsInUpperLayer()) @@ -857,7 +868,8 @@ describe('A fixed size path shape', function() { assertShapeSize(getFirstShapeNode(), 30, 20); - Plotly.relayout(gd, {height: 200, width: 600}).then(function() { + Plotly.relayout(gd, {height: 200, width: 600}) + .then(function() { assertShapeSize(getFirstShapeNode(), 30, 20); }) .catch(failTest) @@ -869,8 +881,9 @@ describe('A fixed size path shape', function() { .then(function() { drag({node: getFirstShapeNode(), dpos: [50, 50]}).then(function() { assertShapeSize(getFirstShapeNode(), 30, 20); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -891,8 +904,9 @@ describe('A fixed size path shape', function() { expect(bbox.height).toBe(20); expect(bbox.width).toBeLessThan(widthBeforeDrag); assertShapeFullyVisible(shapeNodeAfterDrag); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -913,8 +927,9 @@ describe('A fixed size path shape', function() { expect(bbox.width).toBe(30); expect(bbox.height).toBeLessThan(heightBeforeDrag); assertShapeFullyVisible(shapeNodeAfterDrag); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); }); @@ -1028,7 +1043,8 @@ describe('A fixed size shape', function() { var shapeNode = getFirstShapeNode(); assertShapeSize(shapeNode, 25, 25); - Plotly.relayout(gd, {height: 200, width: 600}).then(function() { + Plotly.relayout(gd, {height: 200, width: 600}) + .then(function() { var reRenderedShapeNode = getFirstShapeNode(); assertShapeSize(reRenderedShapeNode, 25, 25); }) @@ -1041,8 +1057,9 @@ describe('A fixed size shape', function() { .then(function() { drag({node: getFirstShapeNode(), dpos: [50, 50]}).then(function() { assertShapeSize(getFirstShapeNode(), 25, 25); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -1064,12 +1081,13 @@ describe('A fixed size shape', function() { expect(bbox.height).toBe(25); expect(bbox.width).toBeLessThan(widthBeforeDrag); assertShapeFullyVisible(shapeNodeAfterDrag); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); - it('@flaky being sized relative to data vertically is getting lower ' + + it('being sized relative to data vertically is getting lower ' + 'when being dragged to expand the y-axis', function(done) { layout.shapes[0].ysizemode = 'data'; @@ -1087,8 +1105,9 @@ describe('A fixed size shape', function() { expect(bbox.width).toBe(25); expect(bbox.height).toBeLessThan(heightBeforeDrag); assertShapeFullyVisible(shapeNodeAfterDrag); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -1109,7 +1128,7 @@ describe('A fixed size shape', function() { shapeAndResizeTypes.forEach(function(testCase) { describe('of type ' + testCase.type + ' can be ' + testCase.resizeDisplayName, function() { resizeDirections.forEach(function(direction) { - it('@flaky over direction ' + direction, function(done) { + it('over direction ' + direction, function(done) { layout.shapes[0].type = testCase.type; Plotly.plot(gd, data, layout, {editable: true}) @@ -1129,8 +1148,9 @@ describe('A fixed size shape', function() { expect(bBoxAfterDrag.height).toBe(bBoxBeforeDrag.height + resizeFactor * Math.abs(dy)); expect(bBoxAfterDrag.width).toBe(bBoxBeforeDrag.width + resizeFactor * Math.abs(dx)); assertShapeFullyVisible(shapeNodeAfterDrag); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); }); @@ -1143,7 +1163,7 @@ describe('A fixed size shape', function() { layout.shapes[0].yanchor = 3; }); - it('@flaky can be moved by dragging the middle', function(done) { + it('can be moved by dragging the middle', function(done) { Plotly.plot(gd, data, layout, {editable: true}) .then(function() { var shapeNodeBeforeDrag = getFirstShapeNode(); @@ -1158,13 +1178,13 @@ describe('A fixed size shape', function() { assertShapeSize(shapeNodeAfterDrag, 25, 25); expect(bBoxAfterDrag.left).toBe(bBoxBeforeDrag.left + 10); expect(bBoxAfterDrag.top).toBe(bBoxBeforeDrag.top - 10); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); - it('@flaky can be resized by dragging the start point', function(done) { + it('can be resized by dragging the start point', function(done) { Plotly.plot(gd, data, layout, {editable: true}) .then(function() { var shapeNodeBeforeDrag = getFirstShapeNode(); @@ -1181,13 +1201,13 @@ describe('A fixed size shape', function() { expect(bBoxAfterDrag.right).toBe(bBoxBeforeDrag.right + 25, 'right'); expect(bBoxAfterDrag.bottom).toBe(bBoxBeforeDrag.bottom, 'bottom'); expect(bBoxAfterDrag.left).toBe(bBoxBeforeDrag.left + 25, 'left'); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); - it('@flaky can be resized by dragging the end point', function(done) { + it('can be resized by dragging the end point', function(done) { Plotly.plot(gd, data, layout, {editable: true}) .then(function() { var shapeNodeBeforeDrag = getFirstShapeNode(); @@ -1204,9 +1224,9 @@ describe('A fixed size shape', function() { expect(bBoxAfterDrag.right).toBe(bBoxBeforeDrag.right + 50, 'right'); expect(bBoxAfterDrag.bottom).toBe(bBoxBeforeDrag.bottom - 10, 'bottom'); expect(bBoxAfterDrag.left).toBe(bBoxBeforeDrag.left, 'left'); - - done(); - }); + }) + .catch(failTest) + .then(done); }); }); }); @@ -1342,7 +1362,7 @@ describe('Test shapes', function() { ]; testCases.forEach(function(testCase) { - it('@flaky ' + testCase.title + ' should be draggable', function(done) { + it('' + testCase.title + ' should be draggable', function(done) { setupLayout(testCase, [{type: 'line'}, {type: 'rect'}, {type: 'circle'}, {type: 'path'}]); testDragEachShape(done); }); @@ -1353,7 +1373,7 @@ describe('Test shapes', function() { var testTitle = testCase.title + ' should be resizeable over direction ' + direction; - it('@flaky ' + testTitle, function(done) { + it('' + testTitle, function(done) { // Exclude line because it has a different resize behavior setupLayout(testCase, [{type: 'rect'}, {type: 'circle'}, {type: 'path'}]); testResizeEachShape(direction, done); @@ -1365,7 +1385,7 @@ describe('Test shapes', function() { ['start', 'end'].forEach(function(linePoint) { var testTitle = 'Line shape ' + testCase.title + ' should be resizable by dragging the ' + linePoint + ' point'; - it('@flaky ' + testTitle, function(done) { + it('' + testTitle, function(done) { setupLayout(testCase, [{type: 'line'}]); testLineResize(linePoint, done); }); diff --git a/test/jasmine/tests/sliders_test.js b/test/jasmine/tests/sliders_test.js index 6d82d668ea6..858d787b314 100644 --- a/test/jasmine/tests/sliders_test.js +++ b/test/jasmine/tests/sliders_test.js @@ -282,7 +282,8 @@ describe('ugly internal manipulation of steps', function() { expect(gd._fullLayout.sliders[0].active).toEqual(0); // Set the active index higher than it can go: - Plotly.relayout(gd, {'sliders[0].active': 2}).then(function() { + Plotly.relayout(gd, {'sliders[0].active': 2}) + .then(function() { // Confirm nothing changed expect(gd._fullLayout.sliders[0].active).toEqual(0); @@ -365,7 +366,8 @@ describe('sliders interactions', function() { expect(gd._fullLayout._pushmargin['slider-1']).toBeDefined(); assertPlotSize({heightLessThan: 270}, 'initial'); - Plotly.relayout(gd, 'sliders[0].visible', false).then(function() { + Plotly.relayout(gd, 'sliders[0].visible', false) + .then(function() { assertNodeCount('.' + constants.groupClassName, 1); expect(gd._fullLayout._pushmargin['slider-0']).toBeUndefined(); expect(gd._fullLayout._pushmargin['slider-1']).toBeDefined(); @@ -385,7 +387,8 @@ describe('sliders interactions', function() { 'sliders[0].visible': true, 'sliders[1].visible': true }); - }).then(function() { + }) + .then(function() { assertNodeCount('.' + constants.groupClassName, 1); expect(gd._fullLayout._pushmargin['slider-0']).toBeDefined(); expect(gd._fullLayout._pushmargin['slider-1']).toBeUndefined(); diff --git a/test/jasmine/tests/snapshot_test.js b/test/jasmine/tests/snapshot_test.js index c88d177f7d1..de1bb67a091 100644 --- a/test/jasmine/tests/snapshot_test.js +++ b/test/jasmine/tests/snapshot_test.js @@ -209,7 +209,7 @@ describe('Plotly.Snapshot', function() { var svgElements = svgDOM.getElementsByTagName('svg'); expect(svgElements.length).toBe(1); - }).then(done); + }).catch(failTest).then(done); }); it('should not return any nested svg tags of annotations', function(done) { @@ -220,7 +220,7 @@ describe('Plotly.Snapshot', function() { var svgElements = svgDOM.getElementsByTagName('svg'); expect(svgElements.length).toBe(1); - }).then(done); + }).catch(failTest).then(done); }); it('should force *visibility: visible* for text elements with *visibility: inherit*', function(done) { @@ -244,9 +244,9 @@ describe('Plotly.Snapshot', function() { expect(textElements[i].style.visibility).toEqual(''); expect(textElements[i].style.display).toEqual(''); } - - done(); - }); + }) + .catch(failTest) + .then(done); }); describe('should handle quoted style properties', function() { diff --git a/test/jasmine/tests/sunburst_test.js b/test/jasmine/tests/sunburst_test.js index 2d98c55af76..c2558caceb8 100644 --- a/test/jasmine/tests/sunburst_test.js +++ b/test/jasmine/tests/sunburst_test.js @@ -1647,6 +1647,7 @@ describe('Test sunburst interactions edge cases', function() { .then(function() { assertHoverLabelContent({ nums: 'D\n4\n0' }); }) + .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/table_test.js b/test/jasmine/tests/table_test.js index 2f3859a1dc0..c8c338bd4d2 100644 --- a/test/jasmine/tests/table_test.js +++ b/test/jasmine/tests/table_test.js @@ -152,8 +152,9 @@ describe('table', function() { expect(gd.data[0].header.values.length).toEqual(2); expect(gd.data[0].cells.values.length).toEqual(2); expect(document.querySelectorAll('.' + cn.yColumn).length).toEqual(2); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Works with one column', function(done) { @@ -164,8 +165,9 @@ describe('table', function() { expect(gd.data[0].header.values.length).toEqual(1); expect(gd.data[0].cells.values.length).toEqual(1); expect(document.querySelectorAll('.' + cn.yColumn).length).toEqual(1); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Does not error with zero columns', function(done) { @@ -177,8 +179,9 @@ describe('table', function() { expect(gd.data[0].header.values.length).toEqual(0); expect(gd.data[0].cells.values.length).toEqual(0); expect(document.querySelectorAll('.' + cn.yColumn).length).toEqual(0); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Does not raise an error with zero lines', function(done) { @@ -194,8 +197,9 @@ describe('table', function() { expect(gd.data[0].header.values.length).toEqual(2); expect(gd.data[0].cells.values.length).toEqual(2); expect(document.querySelectorAll('.' + cn.yColumn).length).toEqual(2); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should remove scroll glyph and capture zone when *staticPlot:true*', function(done) { @@ -243,8 +247,9 @@ describe('table', function() { expect(gd.data[0].header.values.length).toEqual(7); expect(document.querySelectorAll('.' + cn.yColumn).length).toEqual(7); expect(document.querySelectorAll('.' + cn.columnCell).length).toEqual(7 * 2); // both column rows to render - done(); - }); + }) + .catch(failTest) + .then(done); }); it('`Plotly.plot` should render all columns even if no header contents were supplied yet', function(done) { @@ -259,8 +264,9 @@ describe('table', function() { expect(document.querySelectorAll('#header').length).toEqual(7); expect(document.querySelectorAll('#header .' + cn.columnCell).length).toEqual(7); expect(document.querySelector('#header .' + cn.columnCell + ' text').textContent).toEqual(''); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('`Plotly.plot` should render all the column headers even if not all header values were supplied', function(done) { @@ -274,8 +280,9 @@ describe('table', function() { expect(document.querySelectorAll('#header').length).toEqual(7); expect(document.querySelectorAll('#header .' + cn.columnCell).length).toEqual(7); expect(document.querySelector('#header .' + cn.columnCell + ' text').textContent).toEqual('A'); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); @@ -309,8 +316,9 @@ describe('table', function() { Plotly.plot(gd, reversedMockCopy.data, reversedMockCopy.layout).then(function() { expect(gd.data.length).toEqual(2); expect(document.querySelectorAll('.' + cn.yColumn).length).toEqual(7 * 2); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Calling `Plotly.restyle` with a string path should amend the preexisting table', function(done) { @@ -324,9 +332,9 @@ describe('table', function() { expect(gd.data[0].cells.values.length).toEqual(7); expect(gd.data[0].header.line.color).toEqual(['dimgray', 'grey']); // no change relative to original mock value expect(gd.data[0].cells.line.color).toEqual(['grey']); // no change relative to original mock value - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Calling `Plotly.restyle` for a `header.values` change should amend the preexisting one', function(done) { @@ -345,25 +353,30 @@ describe('table', function() { restyleValues('cells', 0, [['new cell content 1', 'new cell content 2']])() .then(restyleValues('cells', 2, [[0, 0.1]])) .then(restyleValues('header', 1, [['Species top', 'Species bottom']])) + .catch(failTest) .then(done); }); it('Calling `Plotly.relayout` with string should amend the preexisting table', function(done) { expect(gd.layout.width).toEqual(1000); - Plotly.relayout(gd, 'width', 500).then(function() { + Plotly.relayout(gd, 'width', 500) + .then(function() { expect(gd.data.length).toEqual(1); expect(gd.layout.width).toEqual(500); - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Calling `Plotly.relayout` with object should amend the preexisting table', function(done) { expect(gd.layout.width).toEqual(1000); - Plotly.relayout(gd, {width: 500}).then(function() { + Plotly.relayout(gd, {width: 500}) + .then(function() { expect(gd.data.length).toEqual(1); expect(gd.layout.width).toEqual(500); - done(); - }); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/template_test.js b/test/jasmine/tests/template_test.js index b6668464dbf..66008699a0f 100644 --- a/test/jasmine/tests/template_test.js +++ b/test/jasmine/tests/template_test.js @@ -216,7 +216,6 @@ describe('template interactions', function() { var mock = Lib.extendDeep({}, templateMock); gd = createGraphDiv(); Plotly.newPlot(gd, mock) - .catch(failTest) .then(done); }); afterEach(destroyGraphDiv); @@ -398,7 +397,7 @@ describe('validateTemplate', function() { path: 'layout.annotations[4]', templateitemname: 'nope', msg: 'There are no templates for item layout.annotations[4] with name nope' - }]).then(done); + }]).catch(failTest).then(done); }); it('catches missing template.data', function(done) { @@ -411,7 +410,7 @@ describe('validateTemplate', function() { }], // check only the first error - we don't care about the specifics // uncovered after we already know there's no template.data - 1).then(done); + 1).catch(failTest).then(done); }); it('catches missing template.layout', function(done) { @@ -421,6 +420,6 @@ describe('validateTemplate', function() { checkValidate(noLayoutMock, [{ code: 'layout', msg: 'The template has no key layout.' - }], 1).then(done); + }], 1).catch(failTest).then(done); }); }); diff --git a/test/jasmine/tests/ternary_test.js b/test/jasmine/tests/ternary_test.js index ad5470195a2..abb45214ee5 100644 --- a/test/jasmine/tests/ternary_test.js +++ b/test/jasmine/tests/ternary_test.js @@ -55,9 +55,9 @@ describe('ternary plots', function() { return Plotly.restyle(gd, 'visible', true); }).then(function() { expect(countTraces('scatter')).toEqual(1); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should be able to delete and add traces', function(done) { @@ -97,9 +97,9 @@ describe('ternary plots', function() { expect(countTernarySubplot()).toEqual(1); expect(countTraces('scatter')).toEqual(1); checkTitles(1); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('should be able to restyle', function(done) { @@ -115,7 +115,9 @@ describe('ternary plots', function() { 'translate(118.53,170.59)', 'translate(248.76,117.69)' ]); - }).then(done); + }) + .catch(failTest) + .then(done); }); it('should display to hover labels', function(done) { @@ -832,18 +834,20 @@ describe('Test event property of interactions on a ternary plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); - - futureData = undefined; + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should not be trigged when not on data points', function() { click(blankPos[0], blankPos[1]); - expect(futureData).toBe(undefined); + expect(futureData).toBe(null); }); it('should contain the correct fields', function() { @@ -876,13 +880,15 @@ describe('Test event property of interactions on a ternary plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); - - futureData = undefined; + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_click', function(data) { - futureData = data; - }); + gd.on('plotly_click', function(data) { + futureData = data; + }); + }) + .then(done); }); var modClickOpts = { @@ -905,12 +911,12 @@ describe('Test event property of interactions on a ternary plot:', function() { [modClickOpts, rightClickOpts].forEach(function(clickOpts, i) { it('should not be triggered when not on data points', function() { click(blankPos[0], blankPos[1], clickOpts); - expect(futureData === undefined).toBe(true, i); + expect(futureData).toBe(null, i); }); it('should not be triggered when not canceling context', function() { click(pointPos[0], pointPos[1], Lib.extendFlat({}, clickOpts, {cancelContext: false})); - expect(futureData === undefined).toBe(true, i); + expect(futureData).toBe(null, i); }); it('should contain the correct fields', function() { @@ -949,11 +955,15 @@ describe('Test event property of interactions on a ternary plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_hover', function(data) { - futureData = data; - }); + gd.on('plotly_hover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { @@ -996,11 +1006,15 @@ describe('Test event property of interactions on a ternary plot:', function() { var futureData; beforeEach(function(done) { - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + Plotly.plot(gd, mockCopy.data, mockCopy.layout) + .then(function() { + futureData = null; - gd.on('plotly_unhover', function(data) { - futureData = data; - }); + gd.on('plotly_unhover', function(data) { + futureData = data; + }); + }) + .then(done); }); it('should contain the correct fields', function() { diff --git a/test/jasmine/tests/titles_test.js b/test/jasmine/tests/titles_test.js index 5c9b74f714e..1d889f756c7 100644 --- a/test/jasmine/tests/titles_test.js +++ b/test/jasmine/tests/titles_test.js @@ -9,6 +9,7 @@ var rgb = require('@src/components/color').rgb; var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var mouseEvent = require('../assets/mouse_event'); +var failTest = require('../assets/fail_test'); describe('Plot title', function() { 'use strict'; @@ -42,17 +43,23 @@ describe('Plot title', function() { ref: 'paper' }; - it('is centered horizontally and vertically above the plot by default', function() { - Plotly.plot(gd, data, {title: {text: 'Plotly line chart'}}); - - expectDefaultCenteredPosition(gd); + it('is centered horizontally and vertically above the plot by default', function(done) { + Plotly.plot(gd, data, {title: {text: 'Plotly line chart'}}) + .then(function() { + expectDefaultCenteredPosition(gd); + }) + .catch(failTest) + .then(done); }); - it('can still be defined as `layout.title` to ensure backwards-compatibility', function() { - Plotly.plot(gd, data, {title: 'Plotly line chart'}); - - expectTitle('Plotly line chart'); - expectDefaultCenteredPosition(gd); + it('can still be defined as `layout.title` to ensure backwards-compatibility', function(done) { + Plotly.plot(gd, data, {title: 'Plotly line chart'}) + .then(function() { + expectTitle('Plotly line chart'); + expectDefaultCenteredPosition(gd); + }) + .catch(failTest) + .then(done); }); it('can be updated via `relayout`', function(done) { @@ -62,7 +69,7 @@ describe('Plot title', function() { return Plotly.relayout(gd, {title: {text: 'Some other title'}}); }) .then(expectTitleFn('Some other title')) - .catch(fail) + .catch(failTest) .then(done); }); @@ -77,34 +84,43 @@ describe('Plot title', function() { xref: 'paper' } ].forEach(function(testCase) { - it('can be placed at the left edge of the ' + testCase.selector.desc, function() { + it('can be placed at the left edge of the ' + testCase.selector.desc, function(done) { Plotly.plot(gd, data, extendLayout({ xref: testCase.xref, x: 0, xanchor: 'left' - })); - - expectLeftEdgeAlignedTo(testCase.selector); + })) + .then(function() { + expectLeftEdgeAlignedTo(testCase.selector); + }) + .catch(failTest) + .then(done); }); - it('can be placed at the right edge of the ' + testCase.selector.desc, function() { + it('can be placed at the right edge of the ' + testCase.selector.desc, function(done) { Plotly.plot(gd, data, extendLayout({ xref: testCase.xref, x: 1, xanchor: 'right' - })); - - expectRightEdgeAlignedTo(testCase.selector); + })) + .then(function() { + expectRightEdgeAlignedTo(testCase.selector); + }) + .catch(failTest) + .then(done); }); - it('can be placed at the center of the ' + testCase.selector.desc, function() { + it('can be placed at the center of the ' + testCase.selector.desc, function(done) { Plotly.plot(gd, data, extendLayout({ xref: testCase.xref, x: 0.5, xanchor: 'center' - })); - - expectCenteredWithin(testCase.selector); + })) + .then(function() { + expectCenteredWithin(testCase.selector); + }) + .catch(failTest) + .then(done); }); }); @@ -119,52 +135,65 @@ describe('Plot title', function() { yref: 'paper' } ].forEach(function(testCase) { - it('can be placed at the top edge of the ' + testCase.selector.desc, function() { + it('can be placed at the top edge of the ' + testCase.selector.desc, function(done) { Plotly.plot(gd, data, extendLayout({ yref: testCase.yref, y: 1, yanchor: 'top' - })); - - expectCapLineAlignsWithTopEdgeOf(testCase.selector); + })) + .then(function() { + expectCapLineAlignsWithTopEdgeOf(testCase.selector); + }) + .catch(failTest) + .then(done); }); - it('can be placed at the bottom edge of the ' + testCase.selector.desc, function() { + it('can be placed at the bottom edge of the ' + testCase.selector.desc, function(done) { Plotly.plot(gd, data, extendLayout({ yref: testCase.yref, y: 0, yanchor: 'bottom' - })); - - expectBaselineAlignsWithBottomEdgeOf(testCase.selector); + })) + .then(function() { + expectBaselineAlignsWithBottomEdgeOf(testCase.selector); + }) + .catch(failTest) + .then(done); }); - it('can be placed in the vertical center of the ' + testCase.selector.desc, function() { + it('can be placed in the vertical center of the ' + testCase.selector.desc, function(done) { Plotly.plot(gd, data, extendLayout({ yref: testCase.yref, y: 0.5, yanchor: 'middle' - })); - - expectCenteredVerticallyWithin(testCase.selector); + })) + .then(function() { + expectCenteredVerticallyWithin(testCase.selector); + }) + .catch(failTest) + .then(done); }); }); // y 'auto' value it('provides a y \'auto\' value putting title baseline in middle ' + - 'of top margin irrespective of `yref`', function() { + 'of top margin irrespective of `yref`', function(done) { // yref: 'container' Plotly.plot(gd, data, extendLayout({ yref: 'container', y: 'auto' - })); - - expectBaselineInMiddleOfTopMargin(gd); - - // yref: 'paper' - Plotly.relayout(gd, {'title.yref': 'paper'}); + })) + .then(function() { + expectBaselineInMiddleOfTopMargin(gd); - expectBaselineInMiddleOfTopMargin(gd); + // yref: 'paper' + return Plotly.relayout(gd, {'title.yref': 'paper'}); + }) + .then(function() { + expectBaselineInMiddleOfTopMargin(gd); + }) + .catch(failTest) + .then(done); }); // xanchor 'auto' test @@ -184,15 +213,18 @@ describe('Plot title', function() { function runXAnchorAutoTest(testCase, xref) { var testDesc = 'with {xanchor: \'auto\', x: ' + testCase.x + ', xref: \'' + xref + '\'} expected to be aligned ' + testCase.expAlignment; - it(testDesc, function() { + it(testDesc, function(done) { Plotly.plot(gd, data, extendLayout({ xref: xref, x: testCase.x, xanchor: 'auto' - })); - - var textAnchor = titleSel().attr('text-anchor'); - expect(textAnchor).toBe(testCase.expAlignment, testDesc); + })) + .then(function() { + var textAnchor = titleSel().attr('text-anchor'); + expect(textAnchor).toBe(testCase.expAlignment, testDesc); + }) + .catch(failTest) + .then(done); }); } @@ -215,76 +247,94 @@ describe('Plot title', function() { function runYAnchorAutoTest(testCase, yref, elemSelector) { var testDesc = 'with {yanchor: \'auto\', y: ' + testCase.y + ', yref: \'' + yref + '\'} expected to be aligned ' + testCase.expAlignment; - it(testDesc, function() { + it(testDesc, function(done) { Plotly.plot(gd, data, extendLayout({ yref: yref, y: testCase.y, yanchor: 'auto' - })); - - testCase.expFn(elemSelector); + })) + .then(function() { + testCase.expFn(elemSelector); + }) + .catch(failTest) + .then(done); }); } it('{y: \'auto\'} overrules {yanchor: \'auto\'} to support behavior ' + - 'before chart title alignment was introduced', function() { + 'before chart title alignment was introduced', function(done) { Plotly.plot(gd, data, extendLayout({ y: 'auto', yanchor: 'auto' - })); - - expectDefaultCenteredPosition(gd); + })) + .then(function() { + expectDefaultCenteredPosition(gd); + }) + .catch(failTest) + .then(done); }); // Horizontal padding [containerElemSelector, paperElemSelector].forEach(function(refSelector) { - it('can be placed x pixels away from left ' + refSelector.desc + ' edge', function() { + it('can be placed x pixels away from left ' + refSelector.desc + ' edge', function(done) { Plotly.plot(gd, data, extendLayout({ xref: refSelector.ref, xanchor: 'left', x: 0, pad: titlePad - })); - - expect(titleSel().attr('text-anchor')).toBe('start'); - expect(titleX() - 10).toBe(leftOf(refSelector)); + })) + .then(function() { + expect(titleSel().attr('text-anchor')).toBe('start'); + expect(titleX() - 10).toBe(leftOf(refSelector)); + }) + .catch(failTest) + .then(done); }); }); [containerElemSelector, paperElemSelector].forEach(function(refSelector) { - it('can be placed x pixels away from right ' + refSelector.desc + ' edge', function() { + it('can be placed x pixels away from right ' + refSelector.desc + ' edge', function(done) { Plotly.plot(gd, data, extendLayout({ xref: refSelector.ref, xanchor: 'right', x: 1, pad: titlePad - })); - - expect(titleSel().attr('text-anchor')).toBe('end'); - expect(titleX() + 10).toBe(rightOf(refSelector)); + })) + .then(function() { + expect(titleSel().attr('text-anchor')).toBe('end'); + expect(titleX() + 10).toBe(rightOf(refSelector)); + }) + .catch(failTest) + .then(done); }); }); [containerElemSelector, paperElemSelector].forEach(function(refSelector) { it('figures out for itself which horizontal padding applies when {xanchor: \'auto\'}' + - refSelector.desc + ' edge', function() { + refSelector.desc + ' edge', function(done) { Plotly.plot(gd, data, extendLayout({ xref: refSelector.ref, xanchor: 'auto', x: 1, pad: titlePad - })); - - expect(titleSel().attr('text-anchor')).toBe('end'); - expect(titleX() + 10).toBe(rightOf(refSelector)); - - Plotly.relayout(gd, 'title.x', 0); - - expect(titleSel().attr('text-anchor')).toBe('start'); - expect(titleX() - 10).toBe(leftOf(refSelector)); - - Plotly.relayout(gd, 'title.x', 0.5); - expectCenteredWithin(refSelector); + })) + .then(function() { + expect(titleSel().attr('text-anchor')).toBe('end'); + expect(titleX() + 10).toBe(rightOf(refSelector)); + + return Plotly.relayout(gd, 'title.x', 0); + }) + .then(function() { + expect(titleSel().attr('text-anchor')).toBe('start'); + expect(titleX() - 10).toBe(leftOf(refSelector)); + + return Plotly.relayout(gd, 'title.x', 0.5); + }) + .then(function() { + expectCenteredWithin(refSelector); + }) + .catch(failTest) + .then(done); }); }); @@ -294,19 +344,22 @@ describe('Plot title', function() { {pad: {l: 20}, dir: 'left'}, {pad: {r: 20}, dir: 'right'} ].forEach(function(testCase) { - it('mutes ' + testCase.dir + ' padding for {xanchor: \'center\'}', function() { + it('mutes ' + testCase.dir + ' padding for {xanchor: \'center\'}', function(done) { Plotly.plot(gd, data, extendLayout({ xref: 'paper', xanchor: 'middle', x: 0.5, pad: testCase.pad - })); - - expectCenteredWithin(paperElemSelector); + })) + .then(function() { + expectCenteredWithin(paperElemSelector); + }) + .catch(failTest) + .then(done); }); }); - it('mutes left padding when xanchor is right', function() { + it('mutes left padding when xanchor is right', function(done) { Plotly.plot(gd, data, extendLayout({ xref: 'paper', x: 1, @@ -314,12 +367,15 @@ describe('Plot title', function() { pad: { l: 1000 } - })); - - expectRightEdgeAlignedTo(paperElemSelector); + })) + .then(function() { + expectRightEdgeAlignedTo(paperElemSelector); + }) + .catch(failTest) + .then(done); }); - it('mutes right padding when xanchor is left', function() { + it('mutes right padding when xanchor is left', function(done) { Plotly.plot(gd, data, extendLayout({ xref: 'paper', x: 0, @@ -327,60 +383,75 @@ describe('Plot title', function() { pad: { r: 1000 } - })); - - expectLeftEdgeAlignedTo(paperElemSelector); + })) + .then(function() { + expectLeftEdgeAlignedTo(paperElemSelector); + }) + .catch(failTest) + .then(done); }); // Vertical padding [containerElemSelector, paperElemSelector].forEach(function(refSelector) { - it('can be placed x pixels below top ' + refSelector.desc + ' edge', function() { + it('can be placed x pixels below top ' + refSelector.desc + ' edge', function(done) { Plotly.plot(gd, data, extendLayout({ yref: refSelector.ref, yanchor: 'top', y: 1, pad: titlePad - })); - - var capLineY = calcTextCapLineY(titleSel()); - expect(capLineY).toBe(topOf(refSelector) + 10); + })) + .then(function() { + var capLineY = calcTextCapLineY(titleSel()); + expect(capLineY).toBe(topOf(refSelector) + 10); + }) + .catch(failTest) + .then(done); }); }); [containerElemSelector, paperElemSelector].forEach(function(refSelector) { - it('can be placed x pixels above bottom ' + refSelector.desc + ' edge', function() { + it('can be placed x pixels above bottom ' + refSelector.desc + ' edge', function(done) { Plotly.plot(gd, data, extendLayout({ yref: refSelector.ref, yanchor: 'bottom', y: 0, pad: titlePad - })); - - var baselineY = calcTextBaselineY(titleSel()); - expect(baselineY).toBe(bottomOf(refSelector) - 10); + })) + .then(function() { + var baselineY = calcTextBaselineY(titleSel()); + expect(baselineY).toBe(bottomOf(refSelector) - 10); + }) + .catch(failTest) + .then(done); }); }); [containerElemSelector, paperElemSelector].forEach(function(refSelector) { it('figures out for itself which vertical padding applies when {yanchor: \'auto\'}' + - refSelector.desc + ' edge', function() { + refSelector.desc + ' edge', function(done) { Plotly.plot(gd, data, extendLayout({ yref: refSelector.ref, yanchor: 'auto', y: 1, pad: titlePad - })); - - var capLineY = calcTextCapLineY(titleSel()); - expect(capLineY).toBe(topOf(refSelector) + 10); - - Plotly.relayout(gd, 'title.y', 0); - - var baselineY = calcTextBaselineY(titleSel()); - expect(baselineY).toBe(bottomOf(refSelector) - 10); - - Plotly.relayout(gd, 'title.y', 0.5); - expectCenteredVerticallyWithin(refSelector); + })) + .then(function() { + var capLineY = calcTextCapLineY(titleSel()); + expect(capLineY).toBe(topOf(refSelector) + 10); + + return Plotly.relayout(gd, 'title.y', 0); + }) + .then(function() { + var baselineY = calcTextBaselineY(titleSel()); + expect(baselineY).toBe(bottomOf(refSelector) - 10); + + return Plotly.relayout(gd, 'title.y', 0.5); + }) + .then(function() { + expectCenteredVerticallyWithin(refSelector); + }) + .catch(failTest) + .then(done); }); }); @@ -390,19 +461,22 @@ describe('Plot title', function() { {pad: {t: 20}, dir: 'top'}, {pad: {b: 20}, dir: 'bottom'} ].forEach(function(testCase) { - it('mutes ' + testCase.dir + ' padding for {yanchor: \'middle\'}', function() { + it('mutes ' + testCase.dir + ' padding for {yanchor: \'middle\'}', function(done) { Plotly.plot(gd, data, extendLayout({ yref: 'paper', yanchor: 'middle', y: 0.5, pad: testCase.pad - })); - - expectCenteredVerticallyWithin(paperElemSelector); + })) + .then(function() { + expectCenteredVerticallyWithin(paperElemSelector); + }) + .catch(failTest) + .then(done); }); }); - it('mutes top padding when yanchor is bottom', function() { + it('mutes top padding when yanchor is bottom', function(done) { Plotly.plot(gd, data, extendLayout({ yref: 'paper', y: 0, @@ -410,12 +484,15 @@ describe('Plot title', function() { pad: { t: 1000 } - })); - - expectBaselineAlignsWithBottomEdgeOf(paperElemSelector); + })) + .then(function() { + expectBaselineAlignsWithBottomEdgeOf(paperElemSelector); + }) + .catch(failTest) + .then(done); }); - it('mutes bottom padding when yanchor is top', function() { + it('mutes bottom padding when yanchor is top', function(done) { Plotly.plot(gd, data, extendLayout({ yref: 'paper', y: 1, @@ -423,9 +500,12 @@ describe('Plot title', function() { pad: { b: 1000 } - })); - - expectCapLineAlignsWithTopEdgeOf(paperElemSelector); + })) + .then(function() { + expectCapLineAlignsWithTopEdgeOf(paperElemSelector); + }) + .catch(failTest) + .then(done); }); function extendLayout(titleAttrs) { @@ -591,16 +671,22 @@ describe('Titles can be updated', function() { } } ].forEach(function(testCase) { - it('via `Plotly.relayout` ' + testCase.desc, function() { - Plotly.relayout(gd, testCase.update); - - expectChangedTitles(); + it('via `Plotly.relayout` ' + testCase.desc, function(done) { + Plotly.relayout(gd, testCase.update) + .then(function() { + expectChangedTitles(); + }) + .catch(failTest) + .then(done); }); - it('via `Plotly.update` ' + testCase.desc, function() { - Plotly.update(gd, {}, testCase.update); - - expectChangedTitles(); + it('via `Plotly.update` ' + testCase.desc, function(done) { + Plotly.update(gd, {}, testCase.update) + .then(function() { + expectChangedTitles(); + }) + .catch(failTest) + .then(done); }); }); @@ -648,7 +734,7 @@ describe('Titles and labels', function() { } } }).then(function() { - Plotly.react(gd, { + return Plotly.react(gd, { data: [ { type: 'bar', @@ -673,7 +759,7 @@ describe('Titles and labels', function() { expect(xTitleSel().text()).toBe('x-new'); expect(d3.select('.xtick').text()).toBe('b'); }) - .catch(fail) + .catch(failTest) .then(done); }); }); @@ -690,7 +776,7 @@ describe('Titles support setting custom font properties', function() { afterEach(destroyGraphDiv); - it('through defining a `font` property in the respective title attribute', function() { + it('through defining a `font` property in the respective title attribute', function(done) { var layout = { title: { text: 'Plotly line chart', @@ -721,14 +807,18 @@ describe('Titles support setting custom font properties', function() { } } }; - Plotly.plot(gd, data, layout); - expectTitleFont('blue', 'serif', 24); - expectXAxisTitleFont('#333', 'sans-serif', 20); - expectYAxisTitleFont('#666', 'Arial', 16); + Plotly.plot(gd, data, layout) + .then(function() { + expectTitleFont('blue', 'serif', 24); + expectXAxisTitleFont('#333', 'sans-serif', 20); + expectYAxisTitleFont('#666', 'Arial', 16); + }) + .catch(failTest) + .then(done); }); - it('through using the deprecated `titlefont` properties (backwards-compatibility)', function() { + it('through using the deprecated `titlefont` properties (backwards-compatibility)', function(done) { var layout = { title: { text: 'Plotly line chart', @@ -759,11 +849,15 @@ describe('Titles support setting custom font properties', function() { } } }; - Plotly.plot(gd, data, layout); - expectTitleFont('blue', 'serif', 24); - expectXAxisTitleFont('#333', 'sans-serif', 20); - expectYAxisTitleFont('#666', 'Arial', 16); + Plotly.plot(gd, data, layout) + .then(function() { + expectTitleFont('blue', 'serif', 24); + expectXAxisTitleFont('#333', 'sans-serif', 20); + expectYAxisTitleFont('#666', 'Arial', 16); + }) + .catch(failTest) + .then(done); }); }); @@ -779,7 +873,7 @@ describe('Title fonts can be updated', function() { var NEW_YTITLE_FONT = {color: '#999', family: 'serif', size: 12}; var gd; - beforeEach(function() { + beforeEach(function(done) { var layout = { title: { text: 'Plotly line chart', @@ -799,11 +893,13 @@ describe('Title fonts can be updated', function() { } }; gd = createGraphDiv(); - Plotly.plot(gd, data, Lib.extendDeep({}, layout)); - - expectTitleFont('black', 'sans-serif', 24); - expectXAxisTitleFont('red', 'serif', 20); - expectYAxisTitleFont('green', 'monospace', 16); + Plotly.plot(gd, data, Lib.extendDeep({}, layout)) + .then(function() { + expectTitleFont('black', 'sans-serif', 24); + expectXAxisTitleFont('red', 'serif', 20); + expectYAxisTitleFont('green', 'monospace', 16); + }) + .then(done); }); afterEach(destroyGraphDiv); @@ -883,16 +979,22 @@ describe('Title fonts can be updated', function() { } } ].forEach(function(testCase) { - it('via `Plotly.relayout` ' + testCase.desc, function() { - Plotly.relayout(gd, testCase.update); - - expectChangedTitleFonts(); + it('via `Plotly.relayout` ' + testCase.desc, function(done) { + Plotly.relayout(gd, testCase.update) + .then(function() { + expectChangedTitleFonts(); + }) + .catch(failTest) + .then(done); }); - it('via `Plotly.update` ' + testCase.desc, function() { - Plotly.update(gd, {}, testCase.update); - - expectChangedTitleFonts(); + it('via `Plotly.update` ' + testCase.desc, function(done) { + Plotly.update(gd, {}, testCase.update) + .then(function() { + expectChangedTitleFonts(); + }) + .catch(failTest) + .then(done); }); }); @@ -946,47 +1048,54 @@ describe('Titles for multiple axes', function() { afterEach(destroyGraphDiv); - it('still support deprecated `title` and `titlefont` syntax (backwards-compatibility)', function() { - Plotly.plot(gd, data, multiAxesLayout); - - expect(xTitleSel(1).text()).toBe('X-Axis 1'); - expect(xTitleSel(1).node().style.fontSize).toBe('30px'); + it('still support deprecated `title` and `titlefont` syntax (backwards-compatibility)', function(done) { + Plotly.plot(gd, data, multiAxesLayout) + .then(function() { + expect(xTitleSel(1).text()).toBe('X-Axis 1'); + expect(xTitleSel(1).node().style.fontSize).toBe('30px'); - expect(xTitleSel(2).text()).toBe('X-Axis 2'); - expect(xTitleSel(2).node().style.fontFamily).toBe('serif'); + expect(xTitleSel(2).text()).toBe('X-Axis 2'); + expect(xTitleSel(2).node().style.fontFamily).toBe('serif'); - expect(yTitleSel(1).text()).toBe('Y-Axis 1'); - expect(yTitleSel(1).node().style.fontFamily).toBe('Roboto'); + expect(yTitleSel(1).text()).toBe('Y-Axis 1'); + expect(yTitleSel(1).node().style.fontFamily).toBe('Roboto'); - expect(yTitleSel(2).text()).toBe('Y-Axis 2'); - expect(yTitleSel(2).node().style.fill).toBe(rgb('blue')); + expect(yTitleSel(2).text()).toBe('Y-Axis 2'); + expect(yTitleSel(2).node().style.fill).toBe(rgb('blue')); + }) + .catch(failTest) + .then(done); }); - it('can be updated using deprecated `title` and `titlefont` syntax (backwards-compatibility)', function() { - Plotly.plot(gd, data, multiAxesLayout); - - Plotly.relayout(gd, { - 'xaxis2.title': '2nd X-Axis', - 'xaxis2.titlefont.color': 'pink', - 'xaxis2.titlefont.family': 'sans-serif', - 'xaxis2.titlefont.size': '14', - 'yaxis2.title': '2nd Y-Axis', - 'yaxis2.titlefont.color': 'yellow', - 'yaxis2.titlefont.family': 'monospace', - 'yaxis2.titlefont.size': '5' - }); - - var x2Style = xTitleSel(2).node().style; - expect(xTitleSel(2).text()).toBe('2nd X-Axis'); - expect(x2Style.fill).toBe(rgb('pink')); - expect(x2Style.fontFamily).toBe('sans-serif'); - expect(x2Style.fontSize).toBe('14px'); - - var y2Style = yTitleSel(2).node().style; - expect(yTitleSel(2).text()).toBe('2nd Y-Axis'); - expect(y2Style.fill).toBe(rgb('yellow')); - expect(y2Style.fontFamily).toBe('monospace'); - expect(y2Style.fontSize).toBe('5px'); + it('can be updated using deprecated `title` and `titlefont` syntax (backwards-compatibility)', function(done) { + Plotly.plot(gd, data, multiAxesLayout) + .then(function() { + return Plotly.relayout(gd, { + 'xaxis2.title': '2nd X-Axis', + 'xaxis2.titlefont.color': 'pink', + 'xaxis2.titlefont.family': 'sans-serif', + 'xaxis2.titlefont.size': '14', + 'yaxis2.title': '2nd Y-Axis', + 'yaxis2.titlefont.color': 'yellow', + 'yaxis2.titlefont.family': 'monospace', + 'yaxis2.titlefont.size': '5' + }); + }) + .then(function() { + var x2Style = xTitleSel(2).node().style; + expect(xTitleSel(2).text()).toBe('2nd X-Axis'); + expect(x2Style.fill).toBe(rgb('pink')); + expect(x2Style.fontFamily).toBe('sans-serif'); + expect(x2Style.fontSize).toBe('14px'); + + var y2Style = yTitleSel(2).node().style; + expect(yTitleSel(2).text()).toBe('2nd Y-Axis'); + expect(y2Style.fill).toBe(rgb('yellow')); + expect(y2Style.fontFamily).toBe('monospace'); + expect(y2Style.fontSize).toBe('5px'); + }) + .catch(failTest) + .then(done); }); }); @@ -1179,6 +1288,7 @@ describe('Editable titles', function() { checkTitle('g', 'Click to enter Plot title', 0.2, 0.2) ]); }) + .catch(failTest) .then(done); }); @@ -1195,10 +1305,11 @@ describe('Editable titles', function() { checkTitle('g', 'Click to enter Plot title', 0, 1) ]); }) + .catch(failTest) .then(done); }); - it('@flaky has no hover effects for titles that used to be blank', function(done) { + it('has no hover effects for titles that used to be blank', function(done) { Plotly.plot(gd, data, { xaxis: {title: {text: ''}}, yaxis: {title: {text: ''}}, @@ -1220,6 +1331,7 @@ describe('Editable titles', function() { checkTitle('g', 'TTT', 1, 1) ]); }) + .catch(failTest) .then(done); }); }); diff --git a/test/jasmine/tests/toimage_test.js b/test/jasmine/tests/toimage_test.js index 24190b6f231..fc684e3a7e1 100644 --- a/test/jasmine/tests/toimage_test.js +++ b/test/jasmine/tests/toimage_test.js @@ -57,7 +57,7 @@ describe('Plotly.toImage', function() { expect(isPromise(returnValue)).toBe(true); - returnValue.then(done); + returnValue.catch(failTest).then(done); }); it('should throw error with unsupported file type', function(done) { diff --git a/test/jasmine/tests/transform_aggregate_test.js b/test/jasmine/tests/transform_aggregate_test.js index f95aaab13c9..a5a8c9cfe98 100644 --- a/test/jasmine/tests/transform_aggregate_test.js +++ b/test/jasmine/tests/transform_aggregate_test.js @@ -11,7 +11,7 @@ describe('aggregate', function() { afterEach(destroyGraphDiv); - it('handles all funcs for numeric data', function() { + it('handles all funcs for numeric data', function(done) { // throw in some non-numbers, they should get discarded except first/last Plotly.newPlot(gd, [{ x: [1, 2, 3, 4, 'fail'], @@ -51,25 +51,28 @@ describe('aggregate', function() { }], { // log axis doesn't change how sum (or avg but not tested) works xaxis: {type: 'log'} - }); - - var traceOut = gd._fullData[0]; - - expect(traceOut.x).toEqual([8, 2]); - expect(traceOut.y).toBeCloseToArray([3.3, 2.2], 5); - expect(traceOut.customdata).toEqual([-3, undefined]); - expect(traceOut.marker.size).toEqual([0.1, 0.2]); - expect(traceOut.marker.color).toEqual([10, 4]); - expect(traceOut.marker.opacity).toEqual([0.6, 'boo']); - expect(traceOut.marker.line.color).toEqual(['the end', 3.3]); - expect(traceOut.marker.line.width).toEqual([4, 1]); - - var transform = traceOut.transforms[0]; - var inverseMapping = transform._indexToPoints; - expect(inverseMapping).toEqual({0: [0, 2, 3, 4], 1: [1]}); + }) + .then(function() { + var traceOut = gd._fullData[0]; + + expect(traceOut.x).toEqual([8, 2]); + expect(traceOut.y).toBeCloseToArray([3.3, 2.2], 5); + expect(traceOut.customdata).toEqual([-3, undefined]); + expect(traceOut.marker.size).toEqual([0.1, 0.2]); + expect(traceOut.marker.color).toEqual([10, 4]); + expect(traceOut.marker.opacity).toEqual([0.6, 'boo']); + expect(traceOut.marker.line.color).toEqual(['the end', 3.3]); + expect(traceOut.marker.line.width).toEqual([4, 1]); + + var transform = traceOut.transforms[0]; + var inverseMapping = transform._indexToPoints; + expect(inverseMapping).toEqual({0: [0, 2, 3, 4], 1: [1]}); + }) + .catch(failTest) + .then(done); }); - it('handles all funcs except sum for date data', function() { + it('handles all funcs except sum for date data', function(done) { // weird cases handled in another test Plotly.newPlot(gd, [{ x: ['2001-01-01', '', '2001-01-03', '2001-01-05', '2001-01-07'], @@ -95,19 +98,22 @@ describe('aggregate', function() { {target: 'x', func: 'min'} ] }] - }]); - - var traceOut = gd._fullData[0]; - - expect(traceOut.x).toEqual(['2001-01-04', undefined]); - expect(traceOut.y).toEqual(['1990-12-23', '2005-03-15']); - expect(traceOut.text).toEqual(['2001-01-01 12:37', '2001-01-01 12:35']); - expect(traceOut.hovertext).toEqual(['a', '2001-01-02']); - expect(traceOut.customdata).toEqual(['2001-05', 'b']); - expect(traceOut.marker.line.width).toEqual([4, 1]); + }]) + .then(function() { + var traceOut = gd._fullData[0]; + + expect(traceOut.x).toEqual(['2001-01-04', undefined]); + expect(traceOut.y).toEqual(['1990-12-23', '2005-03-15']); + expect(traceOut.text).toEqual(['2001-01-01 12:37', '2001-01-01 12:35']); + expect(traceOut.hovertext).toEqual(['a', '2001-01-02']); + expect(traceOut.customdata).toEqual(['2001-05', 'b']); + expect(traceOut.marker.line.width).toEqual([4, 1]); + }) + .catch(failTest) + .then(done); }); - it('handles all funcs except sum and avg for category data', function() { + it('handles all funcs except sum and avg for category data', function(done) { // weird cases handled in another test Plotly.newPlot(gd, [{ x: ['a', 'b', 'c', 'aa', 'd'], @@ -130,20 +136,23 @@ describe('aggregate', function() { }] }], { xaxis: {categoryarray: ['aaa', 'aa', 'a', 'b', 'c']} - }); - - var traceOut = gd._fullData[0]; - - // explicit order (only possible for axis data) - expect(traceOut.x).toEqual(['aa', 'b']); - // implied order from data - expect(traceOut.y).toEqual(['t', 'w']); - expect(traceOut.text).toEqual(['a', 'b']); - expect(traceOut.hovertext).toEqual(['c', 'b']); - expect(traceOut.marker.line.width).toEqual([4, 1]); + }) + .then(function() { + var traceOut = gd._fullData[0]; + + // explicit order (only possible for axis data) + expect(traceOut.x).toEqual(['aa', 'b']); + // implied order from data + expect(traceOut.y).toEqual(['t', 'w']); + expect(traceOut.text).toEqual(['a', 'b']); + expect(traceOut.hovertext).toEqual(['c', 'b']); + expect(traceOut.marker.line.width).toEqual([4, 1]); + }) + .catch(failTest) + .then(done); }); - it('allows date and category sums, and category avg, with weird output', function() { + it('allows date and category sums, and category avg, with weird output', function(done) { // this test is more of an FYI than anything else - it doesn't break but // these results are usually meaningless. @@ -160,24 +169,27 @@ describe('aggregate', function() { {target: 'text', func: 'avg'} ] }] - }]); - - var traceOut = gd._fullData[0]; - - // date sums: 1970-01-01 is "zero", there are shifts due to # of leap years - // without that shift these would be 2032-01-02 and 2032-01-06 - expect(traceOut.x).toEqual(['2032-01-03', '2032-01-07']); - // category sums: can go off the end of the category array -> gives undefined - expect(traceOut.y).toEqual(['b', undefined]); - // category average: can result in fractional categories -> rounds (0.5 rounds to 1) - expect(traceOut.text).toEqual(['b', 'b']); - - var transform = traceOut.transforms[0]; - var inverseMapping = transform._indexToPoints; - expect(inverseMapping).toEqual({0: [0, 1], 1: [2, 3]}); + }]) + .then(function() { + var traceOut = gd._fullData[0]; + + // date sums: 1970-01-01 is "zero", there are shifts due to # of leap years + // without that shift these would be 2032-01-02 and 2032-01-06 + expect(traceOut.x).toEqual(['2032-01-03', '2032-01-07']); + // category sums: can go off the end of the category array -> gives undefined + expect(traceOut.y).toEqual(['b', undefined]); + // category average: can result in fractional categories -> rounds (0.5 rounds to 1) + expect(traceOut.text).toEqual(['b', 'b']); + + var transform = traceOut.transforms[0]; + var inverseMapping = transform._indexToPoints; + expect(inverseMapping).toEqual({0: [0, 1], 1: [2, 3]}); + }) + .catch(failTest) + .then(done); }); - it('can aggregate on an existing data array', function() { + it('can aggregate on an existing data array', function(done) { Plotly.newPlot(gd, [{ x: [1, 2, 3, 4, 5], y: [2, 4, 6, 8, 10], @@ -190,20 +202,23 @@ describe('aggregate', function() { {target: 'y', func: 'avg'} ] }] - }]); - - var traceOut = gd._fullData[0]; + }]) + .then(function() { + var traceOut = gd._fullData[0]; - expect(traceOut.x).toEqual([8, 7]); - expect(traceOut.y).toBeCloseToArray([16 / 3, 7], 5); - expect(traceOut.marker.size).toEqual([10, 20]); + expect(traceOut.x).toEqual([8, 7]); + expect(traceOut.y).toBeCloseToArray([16 / 3, 7], 5); + expect(traceOut.marker.size).toEqual([10, 20]); - var transform = traceOut.transforms[0]; - var inverseMapping = transform._indexToPoints; - expect(inverseMapping).toEqual({0: [0, 1, 4], 1: [2, 3]}); + var transform = traceOut.transforms[0]; + var inverseMapping = transform._indexToPoints; + expect(inverseMapping).toEqual({0: [0, 1, 4], 1: [2, 3]}); + }) + .catch(failTest) + .then(done); }); - it('can handle case where aggregation array is missing', function() { + it('can handle case where aggregation array is missing', function(done) { Plotly.newPlot(gd, [{ x: [1, 2, 3, 4, 5], y: [2, 4, 6, 8, 10], @@ -212,20 +227,23 @@ describe('aggregate', function() { type: 'aggregate', groups: 'marker.size' }] - }]); - - var traceOut = gd._fullData[0]; + }]) + .then(function() { + var traceOut = gd._fullData[0]; - expect(traceOut.x).toEqual([1, 3]); - expect(traceOut.y).toEqual([2, 6]); - expect(traceOut.marker.size).toEqual([10, 20]); + expect(traceOut.x).toEqual([1, 3]); + expect(traceOut.y).toEqual([2, 6]); + expect(traceOut.marker.size).toEqual([10, 20]); - var transform = traceOut.transforms[0]; - var inverseMapping = transform._indexToPoints; - expect(inverseMapping).toEqual({0: [0, 1, 4], 1: [2, 3]}); + var transform = traceOut.transforms[0]; + var inverseMapping = transform._indexToPoints; + expect(inverseMapping).toEqual({0: [0, 1, 4], 1: [2, 3]}); + }) + .catch(failTest) + .then(done); }); - it('handles median, mode, rms, stddev, change & range for numeric data', function() { + it('handles median, mode, rms, stddev, change & range for numeric data', function(done) { // again, nothing is going to barf with non-numeric data, but sometimes it // won't make much sense. @@ -252,22 +270,25 @@ describe('aggregate', function() { {target: 'marker.color', func: 'stddev'} ] }] - }]); - - var traceOut = gd._fullData[0]; - - // 1 and 2 both have count of 2 in the first group, - // but 2 gets to that count first - expect(traceOut.x).toEqual([2, 1]); - expect(traceOut.y).toBeCloseToArray([3.5, 2], 5); - expect(traceOut.customdata).toEqual([-4, 0]); - expect(traceOut.marker.size).toBeCloseToArray([Math.sqrt(51 / 4), 2], 5); - expect(traceOut.marker.opacity).toEqual([0.8, 0]); - expect(traceOut.marker.line.width).toBeCloseToArray([0.5, 0], 5); - expect(traceOut.marker.color).toBeCloseToArray([Math.sqrt(1 / 3), 0], 5); + }]) + .then(function() { + var traceOut = gd._fullData[0]; + + // 1 and 2 both have count of 2 in the first group, + // but 2 gets to that count first + expect(traceOut.x).toEqual([2, 1]); + expect(traceOut.y).toBeCloseToArray([3.5, 2], 5); + expect(traceOut.customdata).toEqual([-4, 0]); + expect(traceOut.marker.size).toBeCloseToArray([Math.sqrt(51 / 4), 2], 5); + expect(traceOut.marker.opacity).toEqual([0.8, 0]); + expect(traceOut.marker.line.width).toBeCloseToArray([0.5, 0], 5); + expect(traceOut.marker.color).toBeCloseToArray([Math.sqrt(1 / 3), 0], 5); + }) + .catch(failTest) + .then(done); }); - it('handles ragged data - extra groups are ignored', function() { + it('handles ragged data - extra groups are ignored', function(done) { Plotly.newPlot(gd, [{ x: [1, 1, 2, 2, 1, 3, 4], y: [1, 2, 3, 4, 5], // shortest array controls all @@ -279,15 +300,18 @@ describe('aggregate', function() { {target: 'y', func: 'median'}, ] }] - }]); - - var traceOut = gd._fullData[0]; + }]) + .then(function() { + var traceOut = gd._fullData[0]; - expect(traceOut.x).toEqual([2, 1]); - expect(traceOut.y).toBeCloseToArray([3.5, 2], 5); + expect(traceOut.x).toEqual([2, 1]); + expect(traceOut.y).toBeCloseToArray([3.5, 2], 5); + }) + .catch(failTest) + .then(done); }); - it('handles ragged data - groups is the shortest, others are ignored', function() { + it('handles ragged data - groups is the shortest, others are ignored', function(done) { Plotly.newPlot(gd, [{ x: [1, 1, 2, 2, 1, 3, 4], y: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], @@ -299,15 +323,18 @@ describe('aggregate', function() { {target: 'y', func: 'median'}, ] }] - }]); - - var traceOut = gd._fullData[0]; + }]) + .then(function() { + var traceOut = gd._fullData[0]; - expect(traceOut.x).toEqual([2, 1]); - expect(traceOut.y).toBeCloseToArray([3.5, 2], 5); + expect(traceOut.x).toEqual([2, 1]); + expect(traceOut.y).toBeCloseToArray([3.5, 2], 5); + }) + .catch(failTest) + .then(done); }); - it('links fullData aggregations to userData via _index', function() { + it('links fullData aggregations to userData via _index', function(done) { Plotly.newPlot(gd, [{ x: [1, 2, 3, 4, 5], y: [2, 4, 6, 8, 10], @@ -324,23 +351,26 @@ describe('aggregate', function() { {target: 'y', func: 'avg'} ] }] - }]); - - var traceOut = gd._fullData[0]; - var fullAggregation = traceOut.transforms[0]; - var fullAggregations = fullAggregation.aggregations; - var enabledAggregations = fullAggregations.filter(function(agg) { - return agg.enabled; - }); + }]) + .then(function() { + var traceOut = gd._fullData[0]; + var fullAggregation = traceOut.transforms[0]; + var fullAggregations = fullAggregation.aggregations; + var enabledAggregations = fullAggregations.filter(function(agg) { + return agg.enabled; + }); - expect(enabledAggregations[0].target).toEqual('x'); - expect(enabledAggregations[0]._index).toEqual(0); + expect(enabledAggregations[0].target).toEqual('x'); + expect(enabledAggregations[0]._index).toEqual(0); - expect(enabledAggregations[1].target).toEqual('y'); - expect(enabledAggregations[1]._index).toEqual(2); + expect(enabledAggregations[1].target).toEqual('y'); + expect(enabledAggregations[1]._index).toEqual(2); - expect(enabledAggregations[2].target).toEqual('marker.color'); - expect(enabledAggregations[2]._index).toEqual(-1); + expect(enabledAggregations[2].target).toEqual('marker.color'); + expect(enabledAggregations[2]._index).toEqual(-1); + }) + .catch(failTest) + .then(done); }); it('does not error out on bad *group* value', function(done) { @@ -361,7 +391,7 @@ describe('aggregate', function() { .then(done); }); - it('use numeric sort function for median', function() { + it('use numeric sort function for median', function(done) { var subject = ['M', 'M', 'M']; var score = [2, 10, 11]; @@ -379,9 +409,12 @@ describe('aggregate', function() { }] }]; - Plotly.newPlot(gd, data); - - var traceOut = gd._fullData[0]; - expect(traceOut.y[0]).toBe(10); + Plotly.newPlot(gd, data) + .then(function() { + var traceOut = gd._fullData[0]; + expect(traceOut.y[0]).toBe(10); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/transform_filter_test.js b/test/jasmine/tests/transform_filter_test.js index 159175d6ea0..a5006e2672c 100644 --- a/test/jasmine/tests/transform_filter_test.js +++ b/test/jasmine/tests/transform_filter_test.js @@ -1377,7 +1377,7 @@ describe('filter resulting in empty coordinate arrays', function() { }); mockList.forEach(function(d) { - it('@noCI @gl' + d[0], function(done) { + it('@gl' + d[0], function(done) { gd = createGraphDiv(); var fig = filter2empty(d[1]); Plotly.newPlot(gd, fig).catch(failTest).then(done); diff --git a/test/jasmine/tests/transform_multi_test.js b/test/jasmine/tests/transform_multi_test.js index 817867f900c..a867ee29ee1 100644 --- a/test/jasmine/tests/transform_multi_test.js +++ b/test/jasmine/tests/transform_multi_test.js @@ -582,9 +582,9 @@ describe('multiple transforms:', function() { expect(gd._fullData[1].x.length).toEqual(3); assertDims([3, 3]); - - done(); - }); + }) + .catch(failTest) + .then(done); }); it('Plotly.deleteTraces should work', function(done) { diff --git a/test/jasmine/tests/transition_test.js b/test/jasmine/tests/transition_test.js index 0bbef67eb53..17278ccc839 100644 --- a/test/jasmine/tests/transition_test.js +++ b/test/jasmine/tests/transition_test.js @@ -76,7 +76,8 @@ function runTests(transitionDuration) { } var p1, p2; - Plotly.relayout(gd, {annotations: [{x: 0, y: 0, text: 'test'}]}).then(function() { + Plotly.relayout(gd, {annotations: [{x: 0, y: 0, text: 'test'}]}) + .then(function() { p1 = annotationPosition(); return Plots.transition(gd, null, { @@ -107,7 +108,8 @@ function runTests(transitionDuration) { } var p1, p2, e1, e2; - Plotly.relayout(gd, {images: [{x: 0, y: 0, source: jsLogo}]}).then(function() { + Plotly.relayout(gd, {images: [{x: 0, y: 0, source: jsLogo}]}) + .then(function() { p1 = imagesrc(); e1 = imageel(); @@ -850,7 +852,7 @@ describe('Plotly.react transitions:', function() { .then(done); }); - it('@flaky should not transition layout when axis auto-ranged value do not changed', function(done) { + it('should not transition layout when axis auto-ranged value do not changed', function(done) { var data = [{y: [1, 2, 1]}]; var layout = {transition: {duration: 10}}; @@ -1189,7 +1191,7 @@ describe('Plotly.react transitions:', function() { .then(done); }); - it('@flaky should update ranges of date and category axes', function(done) { + it('should update ranges of date and category axes', function(done) { Plotly.plot(gd, [ {x: ['2018-01-01', '2019-01-01', '2020-01-01'], y: [1, 2, 3]}, {x: ['a', 'b', 'c'], y: [1, 2, 3], xaxis: 'x2', yaxis: 'y2'} diff --git a/test/jasmine/tests/treemap_test.js b/test/jasmine/tests/treemap_test.js index fa49e0b92ca..08bec0a82a7 100644 --- a/test/jasmine/tests/treemap_test.js +++ b/test/jasmine/tests/treemap_test.js @@ -1569,6 +1569,7 @@ describe('Test treemap interactions edge cases', function() { .then(function() { assertHoverLabelContent({ nums: 'D\n4\n0' }); }) + .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js index 3deaf0fa434..78f375eead4 100644 --- a/test/jasmine/tests/updatemenus_test.js +++ b/test/jasmine/tests/updatemenus_test.js @@ -280,7 +280,6 @@ describe('update menus buttons', function() { dropdownMenus = allMenus.filter(function(opts) { return opts.type !== 'buttons'; }); Plotly.plot(gd, mockCopy.data, mockCopy.layout) - .catch(failTest) .then(done); }); @@ -322,7 +321,6 @@ describe('update menus initialization', function() { ] }] }) - .catch(failTest) .then(done); }); @@ -353,7 +351,6 @@ describe('update menus interactions', function() { mockCopy.layout.updatemenus[1].x = 1; Plotly.plot(gd, mockCopy.data, mockCopy.layout) - .catch(failTest) .then(done); }); @@ -508,7 +505,8 @@ describe('update menus interactions', function() { // the command by setting execute = false first: expect(gd.data[0].line.color).toEqual('blue'); - Plotly.relayout(gd, 'updatemenus[0].buttons[2].execute', false).then(function() { + Plotly.relayout(gd, 'updatemenus[0].buttons[2].execute', false) + .then(function() { return click(selectHeader(0)); }).then(function() { return click(selectButton(2)); @@ -730,7 +728,8 @@ describe('update menus interactions', function() { assertItemColor(selectHeader(0), 'rgb(255, 255, 255)'); assertItemDims(selectHeader(1), 95, 33); - Plotly.relayout(gd, 'updatemenus[0].bgcolor', 'red').then(function() { + Plotly.relayout(gd, 'updatemenus[0].bgcolor', 'red') + .then(function() { assertItemColor(selectHeader(0), 'rgb(255, 0, 0)'); return click(selectHeader(0)); @@ -1090,7 +1089,6 @@ describe('update menus interaction with scrollbox:', function() { menuRight = menus[3]; menuUp = menus[4]; }) - .catch(failTest) .then(done); });