From a03d64d0e6d1bb43cee764c956c4c3c95880994e Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 12:06:48 -0400 Subject: [PATCH 1/9] Handle day of week str - add auto dflt for pattern --- src/plots/cartesian/axis_defaults.js | 40 ++++++++++++++++++++++-- src/plots/cartesian/layout_attributes.js | 7 +++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 594ebdbaf49..c16c3f2aa2c 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -21,6 +21,8 @@ var handleCategoryOrderDefaults = require('./category_order_defaults'); var handleLineGridDefaults = require('./line_grid_defaults'); var setConvert = require('./set_convert'); +var DAY_OF_WEEK = require('./constants').WEEKDAY_PATTERN; + /** * options: object containing: * @@ -161,6 +163,27 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { itemOut.bounds = itemOut.bounds.slice(0, 2); } + var dfltPattern = ''; + var i, q; + for(i = 0; i < bnds.length; i++) { + q = indexOfDay(bnds[i]); + if(q !== -1) { + dfltPattern = DAY_OF_WEEK; + break; + } + } + var pattern = coerce('pattern', dfltPattern); + + if(pattern === DAY_OF_WEEK) { + for(i = 0; i < bnds.length; i++) { + q = indexOfDay(bnds[i]); + if(q !== -1) { + // convert to integers i.e 'Monday' --> 1 + itemOut.bounds[i] = bnds[i] = q; + } + } + } + if(containerOut.autorange === false) { var rng = containerOut.range; @@ -175,8 +198,6 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { return; } } - - coerce('pattern'); } else { var values = coerce('values'); @@ -189,3 +210,18 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { } } } + +var weekSTR = [ + 'sun', + 'mon', + 'tue', + 'wed', + 'thu', + 'fri', + 'sat' +]; + +function indexOfDay(v) { + var str = String(v).substr(0, 3).toLowerCase(); + return weekSTR.indexOf(str); +} diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 2d219abd45c..b52635f0f3e 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -280,16 +280,17 @@ module.exports = { pattern: { valType: 'enumerated', values: [DAY_OF_WEEK, HOUR, ''], - dflt: '', role: 'info', editType: 'calc', description: [ 'Determines a pattern on the time line that generates breaks.', - 'If *' + DAY_OF_WEEK + '* - Sunday-based weekday as a decimal number [0, 6].', + 'If *' + DAY_OF_WEEK + '* - days of the week in English e.g. \'Sunday\' or `\sun\`', + 'as well as Sunday-based integers between 0 and 6.', 'If *' + HOUR + '* - hour (24-hour clock) as decimal numbers between 0 and 24.', 'for more info.', 'Examples:', - '- { pattern: \'' + DAY_OF_WEEK + '\', bounds: [6, 0] }', + '- { pattern: \'' + DAY_OF_WEEK + '\', bounds: [6, 1] }', + ' or simply { bounds: [\'sat\', \'mon\'] }', ' breaks from Saturday to Monday (i.e. skips the weekends).', '- { pattern: \'' + HOUR + '\', bounds: [17, 8] }', ' breaks from 5pm to 8am (i.e. skips non-work hours).' From d52a803e751e5645e2c220b3d02a52c453defbb8 Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 12:51:13 -0400 Subject: [PATCH 2/9] add tests to handle weekday strings --- test/jasmine/tests/axes_test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 71e4c26595e..1bac10d248b 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1135,6 +1135,33 @@ describe('Test axes', function() { expect(layoutOut.xaxis2.rangebreaks[0].pattern).toBe('day of week', 'coerced'); expect(layoutOut.xaxis3.rangebreaks[0].pattern).toBe(undefined, 'not coerce, using *values*'); }); + + it('should auto default rangebreaks.pattern to *day of week* when *bounds* include a weekday string and convert bounds to integer days', function() { + layoutIn = { + xaxis: {type: 'date', rangebreaks: [ + {bounds: ['Saturday', 'Monday']} + ]}, + xaxis2: {type: 'date', rangebreaks: [ + {bounds: ['sun', 'thu']}, + {bounds: ['mon', 'fri']}, + {bounds: ['tue', 'sat']}, + {bounds: ['wed', '-1']} + ]} + }; + layoutOut._subplots.xaxis.push('x2'); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + + expect(layoutOut.xaxis.rangebreaks[0].pattern).toBe('day of week', 'complete Capital'); + expect(layoutOut.xaxis2.rangebreaks[0].pattern).toBe('day of week', '3-letter case'); + expect(layoutOut.xaxis2.rangebreaks[0].bounds[0]).toBe(0, 'convert sun'); + expect(layoutOut.xaxis2.rangebreaks[1].bounds[0]).toBe(1, 'convert mon'); + expect(layoutOut.xaxis2.rangebreaks[2].bounds[0]).toBe(2, 'convert tue'); + expect(layoutOut.xaxis2.rangebreaks[3].bounds[0]).toBe(3, 'convert wed'); + expect(layoutOut.xaxis2.rangebreaks[0].bounds[1]).toBe(4, 'convert thu'); + expect(layoutOut.xaxis2.rangebreaks[1].bounds[1]).toBe(5, 'convert fri'); + expect(layoutOut.xaxis2.rangebreaks[2].bounds[1]).toBe(6, 'convert sat'); + expect(layoutOut.xaxis2.rangebreaks[3].bounds[1]).toBe('-1', 'string'); + }); }); describe('constraints relayout', function() { From 05ab23ca6f8d51100f04c9bdc91e053d926f0c24 Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 13:42:27 -0400 Subject: [PATCH 3/9] mention matching logic in description --- src/plots/cartesian/layout_attributes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index b52635f0f3e..194e2ea4ffa 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -285,6 +285,7 @@ module.exports = { description: [ 'Determines a pattern on the time line that generates breaks.', 'If *' + DAY_OF_WEEK + '* - days of the week in English e.g. \'Sunday\' or `\sun\`', + '(matching is case-insensitive and considers only the first three characters),', 'as well as Sunday-based integers between 0 and 6.', 'If *' + HOUR + '* - hour (24-hour clock) as decimal numbers between 0 and 24.', 'for more info.', From db2c3a3af9018477def1a6abb22b88b70c5081ab Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 14:12:59 -0400 Subject: [PATCH 4/9] attempt improve performance (a bit) by using object lookup, early return and non-strict condition checks --- src/plots/cartesian/axis_defaults.js | 33 +++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index c16c3f2aa2c..72d3ed3f216 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -167,7 +167,7 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { var i, q; for(i = 0; i < bnds.length; i++) { q = indexOfDay(bnds[i]); - if(q !== -1) { + if(q) { dfltPattern = DAY_OF_WEEK; break; } @@ -177,9 +177,9 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { if(pattern === DAY_OF_WEEK) { for(i = 0; i < bnds.length; i++) { q = indexOfDay(bnds[i]); - if(q !== -1) { - // convert to integers i.e 'Monday' --> 1 - itemOut.bounds[i] = bnds[i] = q; + if(q) { + // convert to integers i.e 'Sunday' --> 0 + itemOut.bounds[i] = bnds[i] = q - 1; } } } @@ -211,17 +211,20 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { } } -var weekSTR = [ - 'sun', - 'mon', - 'tue', - 'wed', - 'thu', - 'fri', - 'sat' -]; +// these numbers are one more than what bounds would be mapped to +var dayStrToNum = { + sun: 1, + mon: 2, + tue: 3, + wed: 4, + thu: 5, + fri: 6, + sat: 7 +}; function indexOfDay(v) { - var str = String(v).substr(0, 3).toLowerCase(); - return weekSTR.indexOf(str); + if(typeof v !== 'string') return; + return dayStrToNum[ + String(v).substr(0, 3).toLowerCase() + ]; } From c48f551fb2c93fe856f340a55c470f6a8c54ea1b Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi <33888540+archmoj@users.noreply.github.com> Date: Wed, 18 Mar 2020 14:24:51 -0400 Subject: [PATCH 5/9] no need to cast string to string Co-Authored-By: alexcjohnson --- src/plots/cartesian/axis_defaults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 72d3ed3f216..19661d0bb92 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -225,6 +225,6 @@ var dayStrToNum = { function indexOfDay(v) { if(typeof v !== 'string') return; return dayStrToNum[ - String(v).substr(0, 3).toLowerCase() + v.substr(0, 3).toLowerCase() ]; } From 550a3756da650fe3f3481fa13ce42092c39e5000 Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 14:35:01 -0400 Subject: [PATCH 6/9] improve matching - only need to test first two bounds - avoid touching bounds length --- src/plots/cartesian/axis_defaults.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 19661d0bb92..0564eaa5319 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -165,17 +165,19 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { var dfltPattern = ''; var i, q; - for(i = 0; i < bnds.length; i++) { - q = indexOfDay(bnds[i]); - if(q) { - dfltPattern = DAY_OF_WEEK; - break; + if(bnds.length === 2) { + for(i = 0; i < 2; i++) { + q = indexOfDay(bnds[i]); + if(q) { + dfltPattern = DAY_OF_WEEK; + break; + } } } var pattern = coerce('pattern', dfltPattern); - if(pattern === DAY_OF_WEEK) { - for(i = 0; i < bnds.length; i++) { + if(bnds.length === 2 && pattern === DAY_OF_WEEK) { + for(i = 0; i < 2; i++) { q = indexOfDay(bnds[i]); if(q) { // convert to integers i.e 'Sunday' --> 0 From e481a13deba3322d6279dd4f0acddc04f297ebbd Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 16:03:53 -0400 Subject: [PATCH 7/9] validate numberic bounds when using patterns --- src/plots/cartesian/axis_defaults.js | 38 ++++++++++++++++++-- test/jasmine/tests/axes_test.js | 52 ++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 0564eaa5319..2562b0afaf9 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -8,6 +8,8 @@ 'use strict'; +var isNumeric = require('fast-isnumeric'); + var Registry = require('../../registry'); var Lib = require('../../lib'); @@ -22,6 +24,7 @@ var handleLineGridDefaults = require('./line_grid_defaults'); var setConvert = require('./set_convert'); var DAY_OF_WEEK = require('./constants').WEEKDAY_PATTERN; +var HOUR = require('./constants').HOUR_PATTERN; /** * options: object containing: @@ -175,8 +178,11 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { } } var pattern = coerce('pattern', dfltPattern); - - if(bnds.length === 2 && pattern === DAY_OF_WEEK) { + if(pattern && bnds.length !== 2) { + itemOut.enabled = false; + return; + } + if(pattern === DAY_OF_WEEK) { for(i = 0; i < 2; i++) { q = indexOfDay(bnds[i]); if(q) { @@ -185,6 +191,34 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { } } } + if(pattern) { + // ensure types and ranges + for(i = 0; i < 2; i++) { + q = bnds[i]; + switch(pattern) { + case DAY_OF_WEEK : + if(isNumeric(q)) q = Math.floor(q); + + q = Math.floor(+q); + if(!(q >= 0 && q < 7)) { + itemOut.enabled = false; + return; + } + // use int [0, 7) + itemOut.bounds[i] = bnds[i] = q; + break; + + case HOUR : + if(!(q >= 0 && q <= 24)) { // accept 24 + itemOut.enabled = false; + return; + } + // use float [0, 24] + itemOut.bounds[i] = bnds[i] = q; + break; + } + } + } if(containerOut.autorange === false) { var rng = containerOut.range; diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 1bac10d248b..a03d02020a6 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1162,6 +1162,58 @@ describe('Test axes', function() { expect(layoutOut.xaxis2.rangebreaks[2].bounds[1]).toBe(6, 'convert sat'); expect(layoutOut.xaxis2.rangebreaks[3].bounds[1]).toBe('-1', 'string'); }); + + it('should validate inputs in respect to *day of week* pattern', function() { + layoutIn = { + xaxis: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: ['6.999', '0'] }]}, + xaxis2: {type: 'date', rangebreaks: [{bounds: ['Sunday'] }]}, + xaxis3: {type: 'date', rangebreaks: [{bounds: ['sun', 'mon', 'tue'] }]}, + xaxis4: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '-1'] }]}, + xaxis5: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '-.001'] }]}, + xaxis6: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '7'] }]}, + xaxis7: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '6.999'] }]} + }; + layoutOut._subplots.xaxis.push('x2', 'x3', 'x4', 'x5', 'x6', 'x7'); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + + expect(layoutOut.xaxis.rangebreaks[0].enabled).toBe(true, 'valid'); + expect(layoutOut.xaxis.rangebreaks[0].bounds[0]).toBe(6, 'cast float to int'); + expect(layoutOut.xaxis.rangebreaks[0].bounds[1]).toBe(0, 'cast string to int'); + expect(layoutOut.xaxis2.rangebreaks[0].enabled).toBe(false, 'reject bounds.length < 2'); + expect(layoutOut.xaxis3.rangebreaks[0].enabled).toBe(true, 'do not reject bounds.length > 2'); + expect(layoutOut.xaxis3.rangebreaks[0].bounds.length).toBe(2, 'pick first two'); + expect(layoutOut.xaxis4.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); + expect(layoutOut.xaxis5.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); + expect(layoutOut.xaxis6.rangebreaks[0].enabled).toBe(false, 'reject bound >= 7'); + expect(layoutOut.xaxis7.rangebreaks[0].enabled).toBe(true, 'do not reject bound < 7'); + }); + + it('should validate inputs in respect to *hour* pattern', function() { + layoutIn = { + xaxis: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: ['23.999', '0'] }]}, + xaxis2: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1] }]}, + xaxis3: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, 2, 3] }]}, + xaxis4: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '-1'] }]}, + xaxis5: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '-.001'] }]}, + xaxis6: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '24.001'] }]}, + xaxis7: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '23.999'] }]}, + xaxis8: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '24'] }]} + }; + layoutOut._subplots.xaxis.push('x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8'); + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + + expect(layoutOut.xaxis.rangebreaks[0].enabled).toBe(true, 'valid'); + expect(layoutOut.xaxis.rangebreaks[0].bounds[0]).toBe('23.999', 'do not cast float to int'); + expect(layoutOut.xaxis.rangebreaks[0].bounds[1]).toBe('0', 'do not cast string to int'); + expect(layoutOut.xaxis2.rangebreaks[0].enabled).toBe(false, 'reject bounds.length < 2'); + expect(layoutOut.xaxis3.rangebreaks[0].enabled).toBe(true, 'do not reject bounds.length > 2'); + expect(layoutOut.xaxis3.rangebreaks[0].bounds.length).toBe(2, 'pick first two'); + expect(layoutOut.xaxis4.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); + expect(layoutOut.xaxis5.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); + expect(layoutOut.xaxis6.rangebreaks[0].enabled).toBe(false, 'reject bound > 24'); + expect(layoutOut.xaxis7.rangebreaks[0].enabled).toBe(true, 'do not reject bound <= 24'); + expect(layoutOut.xaxis8.rangebreaks[0].enabled).toBe(true, 'do not reject 24'); + }); }); describe('constraints relayout', function() { From 84c2a6fa29a7b015a010ab5b52033a1318b9fece Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 18:19:04 -0400 Subject: [PATCH 8/9] simplify default logic --- src/plots/cartesian/axis_defaults.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 2562b0afaf9..06a74ae1f30 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -160,12 +160,7 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { if(enabled) { var bnds = coerce('bounds'); - if(bnds && bnds.length >= 2) { - if(bnds.length > 2) { - itemOut.bounds = itemOut.bounds.slice(0, 2); - } - var dfltPattern = ''; var i, q; if(bnds.length === 2) { @@ -178,10 +173,6 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { } } var pattern = coerce('pattern', dfltPattern); - if(pattern && bnds.length !== 2) { - itemOut.enabled = false; - return; - } if(pattern === DAY_OF_WEEK) { for(i = 0; i < 2; i++) { q = indexOfDay(bnds[i]); From 9a0416aefb17fd0d5ac3bd26f91abb721b934a6d Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 23:06:19 -0400 Subject: [PATCH 9/9] correct axes default logic --- src/plots/cartesian/axis_defaults.js | 24 ++++++++++++++----- test/jasmine/tests/axes_test.js | 36 +++++++++++++++++++--------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 06a74ae1f30..b1cae96206d 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -188,23 +188,35 @@ function rangebreaksDefaults(itemIn, itemOut, containerOut) { q = bnds[i]; switch(pattern) { case DAY_OF_WEEK : - if(isNumeric(q)) q = Math.floor(q); + if(!isNumeric(q)) { + itemOut.enabled = false; + return; + } + q = +q; - q = Math.floor(+q); - if(!(q >= 0 && q < 7)) { + if( + q !== Math.floor(q) || // don't accept fractional days for mow + q < 0 || q >= 7 + ) { itemOut.enabled = false; return; } - // use int [0, 7) + // use number itemOut.bounds[i] = bnds[i] = q; break; case HOUR : - if(!(q >= 0 && q <= 24)) { // accept 24 + if(!isNumeric(q)) { + itemOut.enabled = false; + return; + } + q = +q; + + if(q < 0 || q > 24) { // accept 24 itemOut.enabled = false; return; } - // use float [0, 24] + // use number itemOut.bounds[i] = bnds[i] = q; break; } diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index a03d02020a6..ad06ff73e53 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1165,15 +1165,19 @@ describe('Test axes', function() { it('should validate inputs in respect to *day of week* pattern', function() { layoutIn = { - xaxis: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: ['6.999', '0'] }]}, + xaxis: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: ['6', '0'] }]}, xaxis2: {type: 'date', rangebreaks: [{bounds: ['Sunday'] }]}, xaxis3: {type: 'date', rangebreaks: [{bounds: ['sun', 'mon', 'tue'] }]}, xaxis4: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '-1'] }]}, - xaxis5: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '-.001'] }]}, + xaxis5: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '-.25'] }]}, xaxis6: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '7'] }]}, - xaxis7: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '6.999'] }]} + xaxis7: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, '6.75'] }]}, + xaxis8: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, ''] }]}, + xaxis9: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, null] }]}, + xaxis10: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, false] }]}, + xaxis11: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, true] }]} }; - layoutOut._subplots.xaxis.push('x2', 'x3', 'x4', 'x5', 'x6', 'x7'); + layoutOut._subplots.xaxis.push('x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11'); supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.xaxis.rangebreaks[0].enabled).toBe(true, 'valid'); @@ -1185,26 +1189,33 @@ describe('Test axes', function() { expect(layoutOut.xaxis4.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); expect(layoutOut.xaxis5.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); expect(layoutOut.xaxis6.rangebreaks[0].enabled).toBe(false, 'reject bound >= 7'); - expect(layoutOut.xaxis7.rangebreaks[0].enabled).toBe(true, 'do not reject bound < 7'); + expect(layoutOut.xaxis7.rangebreaks[0].enabled).toBe(false, 'reject bound < 7 - not supported yet'); + expect(layoutOut.xaxis8.rangebreaks[0].enabled).toBe(false, 'reject blank string'); + expect(layoutOut.xaxis9.rangebreaks[0].enabled).toBe(false, 'reject null'); + expect(layoutOut.xaxis10.rangebreaks[0].enabled).toBe(false, 'reject false'); + expect(layoutOut.xaxis11.rangebreaks[0].enabled).toBe(false, 'reject true'); }); it('should validate inputs in respect to *hour* pattern', function() { layoutIn = { - xaxis: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: ['23.999', '0'] }]}, + xaxis: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: ['24', '1e-3'] }]}, xaxis2: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1] }]}, xaxis3: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, 2, 3] }]}, xaxis4: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '-1'] }]}, xaxis5: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '-.001'] }]}, xaxis6: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '24.001'] }]}, xaxis7: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '23.999'] }]}, - xaxis8: {type: 'date', rangebreaks: [{pattern: 'hour', bounds: [1, '24'] }]} + xaxis8: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, ''] }]}, + xaxis9: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, null] }]}, + xaxis10: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, false] }]}, + xaxis11: {type: 'date', rangebreaks: [{pattern: 'day of week', bounds: [1, true] }]} }; - layoutOut._subplots.xaxis.push('x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8'); + layoutOut._subplots.xaxis.push('x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11'); supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.xaxis.rangebreaks[0].enabled).toBe(true, 'valid'); - expect(layoutOut.xaxis.rangebreaks[0].bounds[0]).toBe('23.999', 'do not cast float to int'); - expect(layoutOut.xaxis.rangebreaks[0].bounds[1]).toBe('0', 'do not cast string to int'); + expect(layoutOut.xaxis.rangebreaks[0].bounds[0]).toBe(24, 'accept 24'); + expect(layoutOut.xaxis.rangebreaks[0].bounds[1]).toBe(0.001, 'cast string to float'); expect(layoutOut.xaxis2.rangebreaks[0].enabled).toBe(false, 'reject bounds.length < 2'); expect(layoutOut.xaxis3.rangebreaks[0].enabled).toBe(true, 'do not reject bounds.length > 2'); expect(layoutOut.xaxis3.rangebreaks[0].bounds.length).toBe(2, 'pick first two'); @@ -1212,7 +1223,10 @@ describe('Test axes', function() { expect(layoutOut.xaxis5.rangebreaks[0].enabled).toBe(false, 'reject bound < 0'); expect(layoutOut.xaxis6.rangebreaks[0].enabled).toBe(false, 'reject bound > 24'); expect(layoutOut.xaxis7.rangebreaks[0].enabled).toBe(true, 'do not reject bound <= 24'); - expect(layoutOut.xaxis8.rangebreaks[0].enabled).toBe(true, 'do not reject 24'); + expect(layoutOut.xaxis8.rangebreaks[0].enabled).toBe(false, 'reject blank string'); + expect(layoutOut.xaxis9.rangebreaks[0].enabled).toBe(false, 'reject null'); + expect(layoutOut.xaxis10.rangebreaks[0].enabled).toBe(false, 'reject false'); + expect(layoutOut.xaxis11.rangebreaks[0].enabled).toBe(false, 'reject true'); }); });