diff --git a/package-lock.json b/package-lock.json index 6f9d31f2650..2105b7f2907 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6438,9 +6438,9 @@ "dev": true }, "jasmine-core": { - "version": "2.99.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", - "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz", + "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==", "dev": true }, "js-base64": { @@ -6735,12 +6735,6 @@ "which": "^1.2.1" } }, - "karma-fail-fast-reporter": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/karma-fail-fast-reporter/-/karma-fail-fast-reporter-1.0.5.tgz", - "integrity": "sha1-9ScyP5jcXx6oEEfwCkuD7etgv3U=", - "dev": true - }, "karma-firefox-launcher": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", @@ -6757,15 +6751,18 @@ } }, "karma-jasmine": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", - "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz", + "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", + "dev": true, + "requires": { + "jasmine-core": "^3.3" + } }, "karma-jasmine-spec-tags": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/karma-jasmine-spec-tags/-/karma-jasmine-spec-tags-1.0.1.tgz", - "integrity": "sha1-Mz7WJZKSMG81Dez3f5uNxcOVQhI=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-spec-tags/-/karma-jasmine-spec-tags-1.1.0.tgz", + "integrity": "sha512-uhGYcGV1jmUSe2QZ6D/pmVehnggQaB8LCaG17EWetYJnGGu6C7LUcPkVNeMXMiewwa5V6g8RxOG8LP8Jh1ZBsQ==", "dev": true }, "karma-spec-reporter": { diff --git a/package.json b/package.json index 4aa75b39b64..045d7583924 100644 --- a/package.json +++ b/package.json @@ -132,16 +132,15 @@ "gzip-size": "^5.1.1", "image-size": "^0.7.4", "into-stream": "^4.0.0", - "jasmine-core": "^2.99.1", + "jasmine-core": "^3.4.0", "jsdom": "^11.12.0", "karma": "^4.1.0", "karma-browserify": "^6.0.0", "karma-chrome-launcher": "^2.0.0", - "karma-fail-fast-reporter": "^1.0.5", "karma-firefox-launcher": "^1.0.1", "karma-ie-launcher": "^1.0.0", - "karma-jasmine": "^1.1.2", - "karma-jasmine-spec-tags": "^1.0.1", + "karma-jasmine": "^2.0.1", + "karma-jasmine-spec-tags": "^1.1.0", "karma-spec-reporter": "0.0.32", "karma-verbose-reporter": "0.0.6", "karma-viewport": "^1.0.4", diff --git a/test/jasmine/assets/custom_assertions.js b/test/jasmine/assets/custom_assertions.js index 30828bf7605..067a1f09b88 100644 --- a/test/jasmine/assets/custom_assertions.js +++ b/test/jasmine/assets/custom_assertions.js @@ -1,6 +1,7 @@ 'use strict'; var d3 = require('d3'); +var negateIf = require('./negate_if'); exports.assertDims = function(dims) { var traces = d3.selectAll('.trace'); @@ -122,8 +123,7 @@ exports.assertHoverLabelContent = function(expectation, msg) { assertLabelContent(nameSel, expectation.name, ptMsg + ' (name)'); if('isRotated' in expectation) { - expect(g.attr('transform').match(reRotate)) - .negateIf(expectation.isRotated) + negateIf(expectation.isRotated, expect(g.attr('transform').match(reRotate))) .toBe(null, ptMsg + ' should be rotated'); } } else if(ptCnt > 1) { @@ -162,8 +162,7 @@ exports.assertHoverLabelContent = function(expectation, msg) { }); if('isRotated' in expectation) { - expect(g.attr('transform').match(reRotate)) - .negateIf(expectation.isRotated) + negateIf(expectation.isRotated, expect(g.attr('transform').match(reRotate))) .toBe(null, ptMsg + ' ' + i + ' should be rotated'); } }); diff --git a/test/jasmine/assets/custom_matchers.js b/test/jasmine/assets/custom_matchers.js index f1d877d8d51..515e77b741d 100644 --- a/test/jasmine/assets/custom_matchers.js +++ b/test/jasmine/assets/custom_matchers.js @@ -1,15 +1,6 @@ /* * custom_matchers - to be included in karma.conf.js, so it can * add these matchers to jasmine globally and all suites have access. - * - * Also adds `.negateIf` which is not a matcher but a conditional `.not`: - * - * expect(x).negateIf(condition).toBe(0); - * - * is equivalent to: - * - * if(condition) expect(x).toBe(0); - * else expect(x).not.toBe(0); */ 'use strict'; @@ -241,9 +232,4 @@ function arrayToStr(array) { beforeAll(function() { jasmine.addMatchers(matchers); - - jasmine.Expectation.prototype.negateIf = function(negate) { - if(negate) return this.not; - return this; - }; }); diff --git a/test/jasmine/assets/negate_if.js b/test/jasmine/assets/negate_if.js new file mode 100644 index 00000000000..dab8aadb898 --- /dev/null +++ b/test/jasmine/assets/negate_if.js @@ -0,0 +1,21 @@ +'use strict'; + +/** + * Helpers that can negate an expectation given a condition + * + * @param {boolean OR function} condition + * @param {jasmine expect return} expectation + * @returns {jasmine expect return} + * + * Example: + * + * negateIf(myCondition, expect(actual)).toBe(expected); + * + */ +function negateIf(condition, expectation) { + return (typeof condition === 'function' ? condition() : condition) ? + expectation.not : + expectation; +} + +module.exports = negateIf; diff --git a/test/jasmine/karma.conf.js b/test/jasmine/karma.conf.js index 1f7da995b80..8a045467271 100644 --- a/test/jasmine/karma.conf.js +++ b/test/jasmine/karma.conf.js @@ -4,10 +4,15 @@ var path = require('path'); var minimist = require('minimist'); var constants = require('../../tasks/util/constants'); -var isCI = !!process.env.CI; +var isCI = Boolean(process.env.CI); + var argv = minimist(process.argv.slice(4), { string: ['bundleTest', 'width', 'height'], - 'boolean': ['info', 'nowatch', 'failFast', 'verbose', 'Chrome', 'Firefox', 'IE11'], + 'boolean': [ + 'info', + 'nowatch', 'failFast', 'verbose', 'randomize', + 'Chrome', 'Firefox', 'IE11' + ], alias: { 'Chrome': 'chrome', 'Firefox': ['firefox', 'FF'], @@ -21,6 +26,7 @@ var argv = minimist(process.argv.slice(4), { nowatch: isCI, failFast: false, verbose: false, + randomize: false, width: '1035', height: '617' } @@ -60,6 +66,7 @@ if(argv.info) { ' - `--failFast` (dflt: `false`): exit karma upon first test failure', ' - `--verbose` (dflt: `false`): show test result using verbose reporter', ' - `--showSkipped` (dflt: `false`): show tests that are skipped', + ' - `--randomize` (dflt: `false`): randomize test ordering (useful to detect bad test teardown)', ' - `--tags`: run only test with given tags (using the `jasmine-spec-tags` framework)', ' - `--width`(dflt: 1035): set width of the browser window', ' - `--height` (dflt: 617): set height of the browser window', @@ -113,7 +120,6 @@ var pathToUnpolyfill = path.join(__dirname, 'assets', 'unpolyfill.js'); var pathToMathJax = path.join(constants.pathToDist, 'extras', 'mathjax'); var reporters = ((isFullSuite && !argv.tags) || argv.showSkipped) ? ['dots', 'spec'] : ['progress']; -if(argv.failFast) reporters.push('fail-fast'); if(argv.verbose) reporters.push('verbose'); function func(config) { @@ -224,27 +230,33 @@ func.defaultConfig = { debug: true }, - // Options for `karma-jasmine-spec-tags` - // see https://www.npmjs.com/package/karma-jasmine-spec-tags - // - // A few tests don't behave well on CI - // add @noCI to the spec description to skip a spec on CI - // - // Although not recommended, some tests "depend" on other - // tests to pass (e.g. the Plotly.react tests check that - // all available traces and transforms are tested). Tag these - // with @noCIdep, so that - // - $ npm run test-jasmine -- tags=noCI,noCIdep - // can pass. - // - // Label tests that require a WebGL-context by @gl so that - // they can be skipped using: - // - $ npm run test-jasmine -- --skip-tags=gl - // or run is isolation easily using: - // - $ npm run test-jasmine -- --tags=gl client: { + // Options for `karma-jasmine-spec-tags` + // see https://www.npmjs.com/package/karma-jasmine-spec-tags + // + // A few tests don't behave well on CI + // add @noCI to the spec description to skip a spec on CI + // + // Although not recommended, some tests "depend" on other + // tests to pass (e.g. the Plotly.react tests check that + // all available traces and transforms are tested). Tag these + // with @noCIdep, so that + // - $ npm run test-jasmine -- tags=noCI,noCIdep + // can pass. + // + // Label tests that require a WebGL-context by @gl so that + // they can be skipped using: + // - $ npm run test-jasmine -- --skip-tags=gl + // or run is isolation easily using: + // - $ npm run test-jasmine -- --tags=gl tagPrefix: '@', - skipTags: isCI ? 'noCI' : null + skipTags: isCI ? 'noCI' : null, + + // See https://jasmine.github.io/api/3.4/Configuration.html + jasmine: { + random: argv.randomize, + failFast: argv.failFast + } }, // use 'karma-spec-reporter' to log info about skipped specs @@ -253,14 +265,8 @@ func.defaultConfig = { suppressFailed: true, suppressPassed: true, suppressSkipped: false, - showSpecTiming: false, - // use 'karma-fail-fast-reporter' to fail fast w/o conflicting - // with other karma plugins - failFast: false - }, - - // e.g. when a test file does not container a given spec tags - failOnEmptyTestSuite: false + showSpecTiming: false + } }; func.defaultConfig.preprocessors[pathToCustomMatchers] = ['browserify']; diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index b81ce4cc08c..9a108e5644a 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -12,6 +12,7 @@ var DBLCLICKDELAY = require('../../../src/constants/interactions').DBLCLICKDELAY var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var failTest = require('../assets/fail_test'); +var negateIf = require('../assets/negate_if'); var checkTicks = require('../assets/custom_assertions').checkTicks; var supplyAllDefaults = require('../assets/supply_defaults'); var color = require('../../../src/components/color'); @@ -1759,7 +1760,7 @@ describe('A bar plot', function() { if(!i) return; var bbox = this.getBoundingClientRect(); ['left', 'right', 'top', 'bottom', 'width', 'height'].forEach(function(dim) { - expect(bbox[dim]).negateIf(dims.indexOf(dim) === -1) + negateIf(dims.indexOf(dim) === -1, expect(bbox[dim])) .toBeWithin(bbox1[dim], 0.1, msg + ' (' + i + '): ' + dim); }); }); diff --git a/test/jasmine/tests/colorbar_test.js b/test/jasmine/tests/colorbar_test.js index 33091d779ee..ac11638f43c 100644 --- a/test/jasmine/tests/colorbar_test.js +++ b/test/jasmine/tests/colorbar_test.js @@ -8,6 +8,7 @@ var subroutines = require('@src/plot_api/subroutines'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var failTest = require('../assets/fail_test'); +var negateIf = require('../assets/negate_if'); var supplyAllDefaults = require('../assets/supply_defaults'); var assertPlotSize = require('../assets/custom_assertions').assertPlotSize; var drag = require('../assets/drag'); @@ -119,7 +120,7 @@ describe('Test colorbar:', function() { var cbbg = colorbars.selectAll('.cbbg'); var cbfills = colorbars.selectAll('.cbfill'); - expect(cbfills.size()).negateIf(multiFill).toBe(1); + negateIf(multiFill, expect(cbfills.size())).toBe(1); if(!cbHeight) cbHeight = 400; var bgHeight = +cbbg.attr('height'); diff --git a/test/jasmine/tests/geo_test.js b/test/jasmine/tests/geo_test.js index 5253c43b6b7..0ecc00250ef 100644 --- a/test/jasmine/tests/geo_test.js +++ b/test/jasmine/tests/geo_test.js @@ -11,6 +11,7 @@ var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var failTest = require('../assets/fail_test'); +var negateIf = require('../assets/negate_if'); var getClientPosition = require('../assets/get_client_position'); var mouseEvent = require('../assets/mouse_event'); var click = require('../assets/click'); @@ -1571,8 +1572,8 @@ describe('Test geo base layers', function() { var cd0 = gd.calcdata[0]; var subplot = gd._fullLayout.geo._subplot; - expect(cd0[0].geojson).negateIf(geojson[0]).toBe(null); - expect(cd0[1].geojson).negateIf(geojson[1]).toBe(null); + negateIf(geojson[0], expect(cd0[0].geojson)).toBe(null); + negateIf(geojson[1], expect(cd0[1].geojson)).toBe(null); expect(Object.keys(subplot.layers).length).toEqual(layers.length, '# of layers'); diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 3df45e4af6c..885fbba5cc2 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -17,6 +17,7 @@ var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var failTest = require('../assets/fail_test'); +var negateIf = require('../assets/negate_if'); var checkTicks = require('../assets/custom_assertions').checkTicks; var supplyAllDefaults = require('../assets/supply_defaults'); @@ -1110,9 +1111,9 @@ describe('Test plot api', function() { var zmax1 = 10; function check(auto, msg) { - expect(gd._fullData[0].zmin).negateIf(auto).toBe(zmin0, msg); + negateIf(auto, expect(gd._fullData[0].zmin)).toBe(zmin0, msg); expect(gd._fullData[0].zauto).toBe(auto, msg); - expect(gd._fullData[1].zmax).negateIf(auto).toBe(zmax1, msg); + negateIf(auto, expect(gd._fullData[1].zmax)).toBe(zmax1, msg); expect(gd._fullData[1].zauto).toBe(auto, msg); } @@ -1153,12 +1154,12 @@ describe('Test plot api', function() { function check(auto, autocolorscale, msg) { expect(gd._fullData[0].marker.cauto).toBe(auto, msg); - expect(gd._fullData[0].marker.cmin).negateIf(auto).toBe(mcmin0); + negateIf(auto, expect(gd._fullData[0].marker.cmin)).toBe(mcmin0); expect(gd._fullData[0].marker.autocolorscale).toBe(autocolorscale, msg); expect(gd._fullData[0].marker.colorscale).toEqual(auto ? autocscale : scales[mcscl0]); expect(gd._fullData[1].marker.line.cauto).toBe(auto, msg); - expect(gd._fullData[1].marker.line.cmax).negateIf(auto).toBe(mlcmax1); + negateIf(auto, expect(gd._fullData[1].marker.line.cmax)).toBe(mlcmax1); expect(gd._fullData[1].marker.line.autocolorscale).toBe(autocolorscale, msg); expect(gd._fullData[1].marker.line.colorscale).toEqual(auto ? autocscale : scales[mlcscl1]); } @@ -1323,8 +1324,8 @@ describe('Test plot api', function() { function check(auto, msg) { expect(gd.data[0].autocontour).toBe(auto, msg); expect(gd.data[1].autocontour).toBe(auto, msg); - expect(gd.data[0].contours.start).negateIf(auto).toBe(start0, msg); - expect(gd.data[1].contours.size).negateIf(auto).toBe(size1, msg); + negateIf(auto, expect(gd.data[0].contours.start)).toBe(start0, msg); + negateIf(auto, expect(gd.data[1].contours.size)).toBe(size1, msg); } Plotly.plot(gd, [ @@ -1411,9 +1412,9 @@ describe('Test plot api', function() { var dtick1 = 0.8; function check(auto, msg) { - expect(gd._fullData[0].colorbar.tick0).negateIf(auto).toBe(tick00, msg); + negateIf(auto, expect(gd._fullData[0].colorbar.tick0)).toBe(tick00, msg); expect(gd._fullData[0].colorbar.tickmode).toBe(auto ? 'auto' : 'linear', msg); - expect(gd._fullData[1].colorbar.dtick).negateIf(auto).toBe(dtick1, msg); + negateIf(auto, expect(gd._fullData[1].colorbar.dtick)).toBe(dtick1, msg); expect(gd._fullData[1].colorbar.tickmode).toBe(auto ? 'auto' : 'linear', msg); } diff --git a/test/jasmine/tests/polar_test.js b/test/jasmine/tests/polar_test.js index e9ada238e78..e087f2495e4 100644 --- a/test/jasmine/tests/polar_test.js +++ b/test/jasmine/tests/polar_test.js @@ -7,6 +7,7 @@ var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var failTest = require('../assets/fail_test'); +var negateIf = require('../assets/negate_if'); var mouseEvent = require('../assets/mouse_event'); var click = require('../assets/click'); var doubleClick = require('../assets/double_click'); @@ -460,7 +461,7 @@ describe('Test relayout on polar subplots:', function() { expect(txt.text()).toBe(content, 'radial axis title'); } - expect(newBBox).negateIf(didBBoxChanged).toEqual(lastBBox, 'did bbox change'); + negateIf(didBBoxChanged, expect(newBBox)).toEqual(lastBBox, 'did bbox change'); lastBBox = newBBox; } diff --git a/test/jasmine/tests/scatter_test.js b/test/jasmine/tests/scatter_test.js index 7643125f063..a20945e303d 100644 --- a/test/jasmine/tests/scatter_test.js +++ b/test/jasmine/tests/scatter_test.js @@ -8,6 +8,7 @@ var Plotly = require('@lib/index'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var customAssertions = require('../assets/custom_assertions'); +var negateIf = require('../assets/negate_if'); var failTest = require('../assets/fail_test'); var transitions = require('../assets/transitions'); @@ -952,7 +953,7 @@ describe('end-to-end scatter tests', function() { function checkFill(visible, msg) { var fillSelection = d3.select(gd).selectAll('.scatterlayer .js-fill'); expect(fillSelection.size()).toBe(1, msg); - expect(fillSelection.attr('d')).negateIf(visible).toBe('M0,0Z', msg); + negateIf(visible, expect(fillSelection.attr('d'))).toBe('M0,0Z', msg); } Plotly.newPlot(gd, [trace0, trace1, trace2], {}, {scrollZoom: true})