From 94e0133a9551018c4d53d4f6494c29720327c698 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Apr 2016 10:35:51 +0200 Subject: [PATCH 1/9] #189 adding axis attributes to cartesian plots and gl3d plots --- src/plots/cartesian/layout_attributes.js | 30 ++++++++++++++++++++++++ src/plots/gl3d/layout/axis_attributes.js | 29 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 731d9b9d81d..f2842bad7c5 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -465,6 +465,36 @@ module.exports = { 'Only has an effect if `anchor` is set to *free*.' ].join(' ') }, + categorymode: { + valType: 'enumerated', + values: [ + 'trace', 'category ascending', 'category descending', 'array' + /*, 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later + ], + dflt: 'trace', + role: 'info', + description: [ + 'Specifies the ordering logic for the case of categorical variables.', + 'By default, plotly uses *trace*, which specifies the order that is present in the data supplied.', + 'Set `categorymode` to *category ascending* or *category descending* if order should be determined by', + 'the alphanumerical order of the category names.', + /*'Set `categorymode` to *value ascending* or *value descending* if order should be determined by the', + 'numerical order of the values.',*/ // // value ascending / descending to be implemented later + 'Set `categorymode` to *array* to derive the ordering from the attribute `categorylist`. If a category', + 'is not found in the `categorylist` array, the sorting behavior for that attribute will be identical to', + 'the *trace* mode. The unspecified categories will follow the categories in `categorylist`.' + ].join(' ') + }, + categorylist: { + valType: 'data_array', + role: 'info', + description: [ + 'Sets the order in which categories on this axis appear.', + 'Only has an effect if `categorymode` is set to *array*.', + 'Used with `categorymode`.' + ].join(' ') + }, + _deprecated: { autotick: { diff --git a/src/plots/gl3d/layout/axis_attributes.js b/src/plots/gl3d/layout/axis_attributes.js index 15bfb6b483a..be4abcb5e0f 100644 --- a/src/plots/gl3d/layout/axis_attributes.js +++ b/src/plots/gl3d/layout/axis_attributes.js @@ -68,6 +68,35 @@ module.exports = { description: 'Sets whether or not this axis is labeled' }, color: axesAttrs.color, + categorymode: { + valType: 'enumerated', + values: [ + 'trace', 'category ascending', 'category descending', 'array' + /*, 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later + ], + dflt: 'trace', + role: 'info', + description: [ + 'Specifies the ordering logic for the case of categorical variables.', + 'By default, plotly uses *trace*, which specifies the order that is present in the data supplied.', + 'Set `categorymode` to *category ascending* or *category descending* if order should be determined by', + 'the alphanumerical order of the category names.', + /*'Set `categorymode` to *value ascending* or *value descending* if order should be determined by the', + 'numerical order of the values.',*/ // // value ascending / descending to be implemented later + 'Set `categorymode` to *array* to derive the ordering from the attribute `categorylist`. If a category', + 'is not found in the `categorylist` array, the sorting behavior for that attribute will be identical to', + 'the *trace* mode. The unspecified categories will follow the categories in `categorylist`.' + ].join(' ') + }, + categorylist: { + valType: 'data_array', + role: 'info', + description: [ + 'Sets the order in which categories on this axis appear.', + 'Only has an effect if `categorymode` is set to *array*.', + 'Used with `categorymode`.' + ].join(' ') + }, title: axesAttrs.title, titlefont: axesAttrs.titlefont, type: axesAttrs.type, From e36d1633769b77e4d28568546b41941781ca5b0d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Apr 2016 10:40:12 +0200 Subject: [PATCH 2/9] #189 category ordering - final, bisecting version --- src/plots/cartesian/ordered_categories.js | 77 +++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/plots/cartesian/ordered_categories.js diff --git a/src/plots/cartesian/ordered_categories.js b/src/plots/cartesian/ordered_categories.js new file mode 100644 index 00000000000..5f9f25a485c --- /dev/null +++ b/src/plots/cartesian/ordered_categories.js @@ -0,0 +1,77 @@ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +// flattenUniqueSort :: String -> Function -> [[String]] -> [String] +function flattenUniqueSort(axisLetter, sortFunction, data) { + + // Bisection based insertion sort of distinct values for logarithmic time complexity. + // Can't use a hashmap, which is O(1), because ES5 maps coerce keys to strings. If it ever becomes a bottleneck, + // code can be separated: a hashmap (JS object) based version if all values encountered are strings; and + // downgrading to this O(log(n)) array on the first encounter of a non-string value. + + var categoryArray = []; + + var traceLines = data.map(function(d) {return d[axisLetter];}); + + var i, j, tracePoints, category, insertionIndex; + + var bisector = d3.bisector(sortFunction).left; + + for(i = 0; i < traceLines.length; i++) { + + tracePoints = traceLines[i]; + + for(j = 0; j < tracePoints.length; j++) { + + category = tracePoints[j]; + + // skip loop: ignore null and undefined categories + if(category === null || category === undefined) continue; + + insertionIndex = bisector(categoryArray, category); + + // skip loop on already encountered values + if(insertionIndex < categoryArray.length - 1 && categoryArray[insertionIndex] === category) continue; + + // insert value + categoryArray.splice(insertionIndex, 0, category); + } + } + + return categoryArray; +} + + +/** + * This pure function returns the ordered categories for specified axisLetter, categorymode, categorylist and data. + * + * If categorymode is 'array', the result is a fresh copy of categorylist, or if unspecified, an empty array. + * + * If categorymode is 'category ascending' or 'category descending', the result is an array of ascending or descending + * order of the unique categories encountered in the data for specified axisLetter. + * + * See cartesian/layout_attributes.js for the definition of categorymode and categorylist + * + */ + +// orderedCategories :: String -> String -> [String] -> [[String]] -> [String] +module.exports = function orderedCategories(axisLetter, categorymode, categorylist, data) { + + switch(categorymode) { + case 'array': return Array.isArray(categorylist) ? categorylist.slice() : []; + case 'category ascending': return flattenUniqueSort(axisLetter, d3.ascending, data); + case 'category descending': return flattenUniqueSort(axisLetter, d3.descending, data); + case 'trace': return []; + default: return []; + } +}; From df9ee94c412eda079916b68c98a8aa11125bcb24 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Apr 2016 10:45:41 +0200 Subject: [PATCH 3/9] #189 categorymode defaults --- src/plots/cartesian/category_mode_defaults.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/plots/cartesian/category_mode_defaults.js diff --git a/src/plots/cartesian/category_mode_defaults.js b/src/plots/cartesian/category_mode_defaults.js new file mode 100644 index 00000000000..d671941d5ee --- /dev/null +++ b/src/plots/cartesian/category_mode_defaults.js @@ -0,0 +1,39 @@ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var layoutAttributes = require('./layout_attributes'); + +module.exports = function handleCategoryModeDefaults(containerIn, containerOut, coerce) { + + if(containerIn.type !== 'category') return; + + var validCategories = layoutAttributes.categorymode.values; + + var properCategoryList = Array.isArray(containerIn.categorylist) && containerIn.categorylist.length > 0; + + if(validCategories.indexOf(containerIn.categorymode) === -1 && properCategoryList) { + + // when unspecified or invalid, use the default, unless categorylist implies 'array' + coerce('categorymode', 'array'); // promote to 'array' + + } else if(containerIn.categorymode === 'array' && !properCategoryList) { + + // when mode is 'array' but no list is given, revert to default + + containerIn.categorymode = 'trace'; // revert to default + coerce('categorymode'); + + } else { + + // otherwise use the supplied mode, or the default one if unsupplied or invalid + coerce('categorymode'); + + } +}; From eb499d4aa7a0eb3cb37313b5b50bb0d8b640d016 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Apr 2016 10:47:25 +0200 Subject: [PATCH 4/9] #189 putting categorymode, categorylist and coercion into use --- src/plot_api/plot_api.js | 4 ++-- src/plots/cartesian/axis_defaults.js | 7 +++++++ src/plots/cartesian/set_convert.js | 5 +++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index f94b03c959a..983d6e85bfb 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -854,10 +854,10 @@ function doCalcdata(gd) { fullLayout._piecolormap = {}; fullLayout._piedefaultcolorcount = 0; - // delete category list, if there is one, so we start over + // initialize the category list, if there is one, so we start over // to be filled in later by ax.d2c for(i = 0; i < axList.length; i++) { - axList[i]._categories = []; + axList[i]._categories = axList[i]._initialCategories.slice(); } for(i = 0; i < fullData.length; i++) { diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index f7aa309e20b..e210261c461 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -20,7 +20,9 @@ var layoutAttributes = require('./layout_attributes'); var handleTickValueDefaults = require('./tick_value_defaults'); var handleTickMarkDefaults = require('./tick_mark_defaults'); var handleTickLabelDefaults = require('./tick_label_defaults'); +var handleCategoryModeDefaults = require('./category_mode_defaults'); var setConvert = require('./set_convert'); +var orderedCategories = require('./ordered_categories'); var cleanDatum = require('./clean_datum'); var axisIds = require('./axis_ids'); @@ -72,6 +74,10 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, } } + containerOut._initialCategories = axType === 'category' ? + orderedCategories(letter, containerIn.categorymode, containerIn.categorylist, options.data) : + []; + setConvert(containerOut); var dfltColor = coerce('color'); @@ -105,6 +111,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, handleTickValueDefaults(containerIn, containerOut, coerce, axType); handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); handleTickMarkDefaults(containerIn, containerOut, coerce, options); + handleCategoryModeDefaults(containerIn, containerOut, coerce); var lineColor = coerce2('linecolor', dfltColor), lineWidth = coerce2('linewidth'), diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js index e35c039429e..e601ee80062 100644 --- a/src/plots/cartesian/set_convert.js +++ b/src/plots/cartesian/set_convert.js @@ -182,8 +182,9 @@ module.exports = function setConvert(ax) { // encounters them, ie all the categories from the // first data set, then all the ones from the second // that aren't in the first etc. - // TODO: sorting options - do the sorting - // progressively here as we insert? + // it is assumed that this function is being invoked in the + // already sorted category order; otherwise there would be + // a disconnect between the array and the index returned if(v !== null && v !== undefined && ax._categories.indexOf(v) === -1) { ax._categories.push(v); From c7fb84ba649e7468e9f33ff13aaa90bad7e3e514 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Apr 2016 10:47:45 +0200 Subject: [PATCH 5/9] #189 jasmine tests --- test/jasmine/tests/axes_test.js | 130 +++- test/jasmine/tests/calcdata_test.js | 881 +++++++++++++++++++++++++++- 2 files changed, 1001 insertions(+), 10 deletions(-) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index f820e830263..cfa72ec3c3b 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -8,8 +8,8 @@ var tinycolor = require('tinycolor2'); var handleTickValueDefaults = require('@src/plots/cartesian/tick_value_defaults'); var Axes = PlotlyInternal.Axes; -var createGraph = require('../assets/create_graph_div'); -var destroyGraph = require('../assets/destroy_graph_div'); +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); describe('Test axes', function() { @@ -384,15 +384,137 @@ describe('Test axes', function() { }); }); + describe('categorymode', function() { + + var gd; + + beforeEach(function() { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + describe('setting, or not setting categorymode if it is not explicitly declared', function() { + + it('should set categorymode to default if categorymode and categorylist are not supplied', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], {xaxis: {type: 'category'}}); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + + it('should set categorymode to default even if type is not set to category explicitly', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}]); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + + it('should NOT set categorymode to default if type is not category', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}]); + expect(gd._fullLayout.yaxis.categorymode).toBe(undefined); + }); + + it('should set categorymode to default if type is overridden to be category', function() { + PlotlyInternal.plot(gd, [{x: [1,2,3,4,5], y: [15,11,12,13,14]}], {yaxis: {type: 'category'}}); + expect(gd._fullLayout.xaxis.categorymode).toBe(undefined); + expect(gd._fullLayout.yaxis.categorymode).toBe('trace'); + }); + + }); + + describe('setting categorymode to "array"', function() { + + it('should leave categorymode on "array" if it is supplied', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'array', categorylist: ['b','a','d','e','c']} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('array'); + }); + + it('should switch categorymode on "array" if it is not supplied but categorylist is supplied', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorylist: ['b','a','d','e','c']} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('array'); + }); + + it('should revert categorymode to "trace" if "array" is supplied but there is no list', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'array'} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + + }); + + describe('do not set categorymode to "array" if list exists but empty', function() { + + it('should switch categorymode to default if list is not supplied', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'array', categorylist: []} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + + it('should not switch categorymode on "array" if categorylist is supplied but empty', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorylist: []} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + }); + + describe('do NOT set categorymode to "array" if it has some other proper value', function() { + + it('should use specified categorymode if it is supplied even if categorylist exists', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'trace', categorylist: ['b','a','d','e','c']} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + + it('should use specified categorymode if it is supplied even if categorylist exists', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'category ascending', categorylist: ['b','a','d','e','c']} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('category ascending'); + }); + + it('should use specified categorymode if it is supplied even if categorylist exists', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'category descending', categorylist: ['b','a','d','e','c']} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('category descending'); + }); + + }); + + describe('setting categorymode to the default if the value is unexpected', function() { + + it('should switch categorymode to "trace" if mode is supplied but invalid', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'invalid value'} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + }); + + it('should switch categorymode to "array" if mode is supplied but invalid and list is supplied', function() { + PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { + xaxis: {type: 'category', categorymode: 'invalid value', categorylist: ['b','a','d','e','c']} + }); + expect(gd._fullLayout.xaxis.categorymode).toBe('array'); + }); + + }); + + }); + describe('handleTickDefaults', function() { var data = [{ x: [1,2,3], y: [3,4,5] }], gd; beforeEach(function() { - gd = createGraph(); + gd = createGraphDiv(); }); - afterEach(destroyGraph); + afterEach(destroyGraphDiv); it('should set defaults on bad inputs', function() { var layout = { diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index df134e774cc..8c20fca44d6 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -4,15 +4,16 @@ var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); describe('calculated data and points', function() { - describe('connectGaps', function() { - var gd; + var gd; - beforeEach(function() { - gd = createGraphDiv(); - }); + beforeEach(function() { + gd = createGraphDiv(); + }); - afterEach(destroyGraphDiv); + 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]}], {}); @@ -28,4 +29,872 @@ describe('calculated data and points', function() { expect(gd.calcdata[0][3]).toEqual({ x: false, y: false}); }); }); + + describe('category ordering', function() { + + describe('default category ordering reified', function() { + + it('should output categories in the given order by default', function() { + + 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); + }); + + it('should output categories in the given order if `trace` order is explicitly specified', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'trace' + // Also, if axis tick order is made configurable, shouldn't we make trace order configurable? + // 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); + }); + }); + + describe('domain alphanumerical category ordering', function() { + + it('should output categories in ascending domain alphanumerical order', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: '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})); + }); + + it('should output categories in descending domain alphanumerical order', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: '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})); + }); + + it('should output categories in ascending domain alphanumerical order even if categories are all numbers', function() { + + Plotly.plot(gd, [{x: [3,1,5,2,4], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: '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})); + }); + + it('should output categories in categorymode order even if category array is defined', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'category ascending', + categorylist: ['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})); + }); + + it('should output categories in ascending domain alphanumerical order, excluding undefined', function() { + + Plotly.plot(gd, [{x: ['c',undefined,'e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: '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})); + }); + }); + +/* + describe('codomain numerical category ordering', function() { + + it('should output categories in ascending codomain numerical order', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'value ascending' + }}); + + expect(gd.calcdata[0][0].y).toEqual(11); + expect(gd.calcdata[0][1].y).toEqual(12); + expect(gd.calcdata[0][2].y).toEqual(13); + expect(gd.calcdata[0][3].y).toEqual(14); + expect(gd.calcdata[0][4].y).toEqual(15); + }); + + it('should output categories in descending codomain numerical order', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'value descending' + }}); + + expect(gd.calcdata[0][0].y).toEqual(15); + expect(gd.calcdata[0][1].y).toEqual(14); + expect(gd.calcdata[0][2].y).toEqual(13); + expect(gd.calcdata[0][3].y).toEqual(12); + expect(gd.calcdata[0][4].y).toEqual(11); + }); + + it('should output categories in descending codomain numerical order, excluding nulls', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,null,13,14]}], { xaxis: { + type: 'category', + categorymode: 'value descending' + }}); + + expect(gd.calcdata[0][0].y).toEqual(15); + expect(gd.calcdata[0][1].y).toEqual(14); + expect(gd.calcdata[0][2].y).toEqual(12); + expect(gd.calcdata[0][3].y).toEqual(11); + + }); + }); +*/ + + describe('explicit category ordering', function() { + + it('should output categories in explicitly supplied order, independent of trace order', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['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})); + }); + + it('should output categories in explicitly supplied order even if category values are all numbers', function() { + + Plotly.plot(gd, [{x: [3,1,5,2,4], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: [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})); + }); + + it('should output categories in explicitly supplied order, independent of trace order, pruned', function() { + + Plotly.plot(gd, [{x: ['c',undefined,'e','b','d'], y: [15,11,12,null,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['b','a','d','e','c'] + }}); + + expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); + expect(gd.calcdata[0][1]).toEqual({ x: false, y: false}); + expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); + expect(gd.calcdata[0][3]).toEqual({ x: false, y: false}); + expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); + }); + + it('should output categories in explicitly supplied order even if not all categories are present', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['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})); + }); + + it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categorylist', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['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})); + + // 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;}); + + expect(domTickTexts).toEqual(['b', 'x', 'a', 'd', 'z', 'e', 'c']); // y, q and k has no data points + }); + + it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categorylist', function() { + + // 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 + + Plotly.plot(gd, [{x: ['c','a','e','b','d', 'y'], y: [15,11,12,13,14, null]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['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})); + + 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 + }); + + it('should output categories in explicitly supplied order even if not all categories are present, and should interact with a null value orthogonally', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,null,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['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({x: false, y: false}); + 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})); + }); + + it('should output categories in explicitly supplied order first, if not all categories are covered', function() { + + Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { + type: 'category', + categorymode: 'array', + categorylist: ['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_ categorymode and + // categories effective; categories would take precedence and the remaining items would be sorted + // based on the categorymode. This of course means that the mere presence of categories triggers this + // behavior, rather than an explicit 'explicit' categorymode. + }); + }); + + describe('ordering tests in the presence of multiple traces - mutually exclusive', function() { + + it('baseline testing for the unordered, disjunct case', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Seals']; + + Plotly.plot(gd, [ + {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})); + }); + + it('category order follows the trace order (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'trace', + categorylist: ['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})); + }); + + it('category order is category ascending (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'category ascending', + categorylist: ['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})); + }); + + it('category order is category descending (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'category descending', + categorylist: ['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})); + }); + + it('category order follows categorylist', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'array', + categorylist: ['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})); + }); + }); + + describe('ordering tests in the presence of multiple traces - partially overlapping', function() { + + it('baseline testing for the unordered, partially overlapping case', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; + + Plotly.plot(gd, [ + {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})); + }); + + it('category order follows the trace order (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'trace', + categorylist: ['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})); + }); + + it('category order is category ascending (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'category ascending', + categorylist: ['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})); + }); + + it('category order is category descending (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'category descending', + categorylist: ['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})); + }); + + it('category order follows categorylist', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'array', + categorylist: ['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})); + }); + }); + + describe('ordering tests in the presence of multiple traces - fully overlapping', function() { + + it('baseline testing for the unordered, fully overlapping case', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {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: 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})); + }); + + it('category order follows the trace order (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'trace', + categorylist: ['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: 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})); + }); + + it('category order is category ascending (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'category ascending', + categorylist: ['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})); + + 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})); + }); + + it('category order is category descending (even if categorylist is specified)', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {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;})} + ], { xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'category descending', + categorylist: ['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})); + + 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})); + }); + + it('category order follows categorylist', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {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;})} + ], { + xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'array', + categorylist: ['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})); + + 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})); + }); + + it('category order follows categorylist even if data is sparse', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {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;})} + ], { + xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'array', + categorylist: ['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: 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})); + }); + }); + + describe('ordering and stacking combined', function() { + + it('partially overlapping category order follows categorylist and stacking produces expected results', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; + var x3 = ['Pump', 'Leak', 'Bearing', 'Seals']; + + Plotly.plot(gd, [ + {x: x1, y: x1.map(function(d, i) {return i + 10;}), type: 'bar'}, + {x: x2, y: x2.map(function(d, i) {return i + 20;}), type: 'bar'}, + {x: x3, y: x3.map(function(d, i) {return i + 30;}), type: 'bar'} + ], { + barmode: 'stack', + xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'array', + categorylist: ['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})); + }); + + it('fully overlapping - category order follows categorylist and stacking produces expected results', function() { + + var x1 = ['Gear', 'Bearing', 'Motor']; + var x2 = ['Bearing', 'Gear', 'Motor']; + var x3 = ['Motor', 'Gear', 'Bearing']; + + Plotly.plot(gd, [ + {x: x1, y: x1.map(function(d, i) {return i + 10;}), type: 'bar'}, + {x: x2, y: x2.map(function(d, i) {return i + 20;}), type: 'bar'}, + {x: x3, y: x3.map(function(d, i) {return i + 30;}), type: 'bar'} + ], { + barmode: 'stack', + xaxis: { + // type: 'category', // commented out to rely on autotyping for added realism + categorymode: 'array', + categorylist: ['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})); + + 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})); + }); + }); + }); }); From 02ed858d05d8f77f1219193a3278b7ec3a80d6ac Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Apr 2016 10:48:10 +0200 Subject: [PATCH 6/9] #189 image test mocks and baseline images --- .../baselines/axes_category_ascending.png | Bin 0 -> 26925 bytes .../baselines/axes_category_categorylist.png | Bin 0 -> 21133 bytes ..._category_categorylist_truncated_tails.png | Bin 0 -> 31892 bytes .../baselines/axes_category_descending.png | Bin 0 -> 25538 bytes .../axes_category_descending_with_gaps.png | Bin 0 -> 17460 bytes test/image/mocks/axes_category_ascending.json | 13 +++++ .../mocks/axes_category_categorylist.json | 46 ++++++++++++++++++ ...category_categorylist_truncated_tails.json | 13 +++++ .../image/mocks/axes_category_descending.json | 41 ++++++++++++++++ .../axes_category_descending_with_gaps.json | 41 ++++++++++++++++ 10 files changed, 154 insertions(+) create mode 100644 test/image/baselines/axes_category_ascending.png create mode 100644 test/image/baselines/axes_category_categorylist.png create mode 100644 test/image/baselines/axes_category_categorylist_truncated_tails.png create mode 100644 test/image/baselines/axes_category_descending.png create mode 100644 test/image/baselines/axes_category_descending_with_gaps.png create mode 100644 test/image/mocks/axes_category_ascending.json create mode 100644 test/image/mocks/axes_category_categorylist.json create mode 100644 test/image/mocks/axes_category_categorylist_truncated_tails.json create mode 100644 test/image/mocks/axes_category_descending.json create mode 100644 test/image/mocks/axes_category_descending_with_gaps.json diff --git a/test/image/baselines/axes_category_ascending.png b/test/image/baselines/axes_category_ascending.png new file mode 100644 index 0000000000000000000000000000000000000000..f6252c4594b4e17e6a0343a35ed341a19e3f5093 GIT binary patch literal 26925 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 He&xRazhdSc literal 0 HcmV?d00001 diff --git a/test/image/baselines/axes_category_categorylist.png b/test/image/baselines/axes_category_categorylist.png new file mode 100644 index 0000000000000000000000000000000000000000..b29a3262d6dc69ac4c01c9b4d70a4ea87c43c4ee GIT binary patch literal 21133 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 E0ErLsYXATM literal 0 HcmV?d00001 diff --git a/test/image/baselines/axes_category_categorylist_truncated_tails.png b/test/image/baselines/axes_category_categorylist_truncated_tails.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c0bbc461bf3cc002ae556fa16a578319e58d2e GIT binary patch literal 31892 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

%&dt5 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 NC)IRR-yOT?{U4RIED!(y literal 0 HcmV?d00001 diff --git a/test/image/baselines/axes_category_descending.png b/test/image/baselines/axes_category_descending.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb5d95693bddb2c1e25a6995ef88cb36ca94cdc GIT binary patch literal 25538 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 Xg^o(^i-o&6R$1&jU{bK>M8v-Ukmmk7 literal 0 HcmV?d00001 diff --git a/test/image/baselines/axes_category_descending_with_gaps.png b/test/image/baselines/axes_category_descending_with_gaps.png new file mode 100644 index 0000000000000000000000000000000000000000..6981f01ca0b4641f6e5fe0dd3cf0993d58aaa9e3 GIT binary patch literal 17460 zcmeHvc|4nG`)@7NRuzNVYVD{pwb#^AOLVkMX{joz2yI8xj-8TNB2{B)ZSB<3TC2KJ zVkrqiEX549j3P8hNr~E$AVea`@6Nn4@67Ly^UwL5b3VWKeEcVmJoj=v*L^+T>$<+* z+&%ATC${h4zFoU^iJkf3)P-HU1aZ4|39Rqk4X%(pxTIaX)OMXYb@Cztx?CvoRw?2! zhUaleKJuILy`fvaw+){>NqPEfib{b%R@yfw>@J@AT2k_OirUkFJMT`ON)Z<~N=mtN zTQnnuY!IZC`soh#$!)be@&^!HK^-_N_9Xi^8wefamdRWz2u-|Lk6;aqEb{$+IU znZL)qgy8J|bFchqo*nU>K374Q{bS01eM<)yxBDL-FGyF>UW_h={bT>Y976y2xMPn0 zW9EpL{DxK{fqbQN`R%KMu%2(#Z*@LsexKX2{(Lo2>w=XyLWD_{-%iu;~49mxRJPtMsfVjIO`vJ zA-pw6?s7e`QtUI-1$dzKY2bW&P6|rhNNnx4+NfToKzQTr#C;sD*E$`JV28^L90hLZ z%LH!S0h^PQl1B(iSTTLKHc`CIFb;!|i{GBr_bW{|K8i+kYWKA5QT3|c`pqfsf*yW* zb+z1wQ}#aJ1bz1LvFA&89(Ohy9qY%~B(X*@IVA1|MmxlU{!Y5LC}zcjQx}X}^qgHQ z=EXL!SDJbo7b`uXtfAZ-8*#H|X{wO8EkhoM#Pe>UCF*C9c-+m|>TVU!X|Lj~_plz9 zqSdSgw0F#M-3WUH+_}J1hEG(p4B5l4U2;{WAxXRs#oUYBSs(86?L|D-e`{+11>G2j z6^F5xF}Y$U6IJgD$4k(AR1i;aD-mezZe_Sv)Nc;Znjy*+5Gh8E<5?r<9N)SxFYpZ3g#7qh)0Vhdtw`;5yU zy(|3CzX+`5w>7}q9tc~kz~o?SS)Vl_4N7s$X+O+lWcieo-pq+=A~uxVQ`xj~Im2`& zrH0<6=#GM@)a^}%6-Kyq^4KI^-0=Z7&p_8@R=ZqFNTTJnsZ_njS2G9GiWqNT*}C;( zPgh5yo|T06lQSVLOLYY32;ELO;$r90?{=!XBxaY%(Utswnlqi|l}6X!Ke}SB!bGWk z1w7}?gWHMl^pw~H;ll=5t=n5`<=@CW|90QiEHq?$TEaCn&p7ZhW7NO0;l)wd0E)ZT z8@*WJ&f#eVzzRZbqc&=by)B7RA8)>NrKTS{fUX<8T%M+EUcXI1aok-`kS9W84}1(C zu*4koa?Y8NIc>gg6>NoD10HoQn~KNBGCNc&?-621?5PEOsp)C@2`X-_$KQwjaTQ0g zL^lRaB;tTAdb=T9dJS-3H%jU^h+bVxRXM^ckJrQ`CzHp_T<8xpL1VQQ;3yyN zYHqFxZdz>QkY?en3k;G?@pQWR!#&Ek&PTP0LeEca^~3cb5eMdK2dtW6!NaVm-1{_{k zIT{GCS%s~l^jkoco1 zS}WKI#rlv-dhYECESDV|LnM~@+=}iGFRI;M-<*mGcFih1(5XD6RpzWl&IqM2`hw$X z8;z6_P3*lV64T7vLz9hH#>A1G%0#Bqfm*GU&}5U9A0xTE!A;xOP18w=WxuGR5w|`q z2cu#lD9pzLv2*r&XEK&bl2sae7Hvz4zPmZJ+O7zHO@5GxC0eY@#B`FCLes~LT4vRt z&dp5ropXkc!oqjg!9Fz-26BCLKi*63f1B+C?y{Na7)_; zbwf(tI38QBkZE{J<@BWykr}&Hdh8rEZnLTEhtmS--Cu1?!bu~tQ;1=;71J)VSSH>@ zLBo87)fN5%ynA>q{T6HQ%f9PW7oscOuz<0LUs}~gKRX013>QNdVT}AOj3rN--t*Yr zYqgKM*|OO@`#f^q(bv!C}LQgZax`5+sw`tA+ zL$|ZZsyu`lAxKGr-LWVjb-%S$s){E5CR#4n+EUQ@htl;^(_SOmD^*?IjauK)Z+uVb zriH>ol9eMb1x_zdWT#&pi)x9SKW;qcn=lJEA$M=muW_+Ng@Kl?x|xh?2gVScnWN<2 z6EzzozT5mI>=k>!P92NYI7yWKQDG1N;(O5Ze>zro(u+YaM)#q|*FhZVn>3d28 zktrEF(H8sEy+A+i(9$F|4jz#VcSS#U$aPE9Q4vTne`w=F=aqhrD3VJz$CYd2LNSIL zcVV97$7Bb+hG$2|%cDEJKOk^wEf22FiyMX?7}9DhY*)lHW%0Y@2545lZ@ERJV-=MP z$Qi-gSI5&7jE?3Mb_=MW&RT>k4s>^g50*!FnM^?n+7$_@o89icV#sESCH1w6#+Odz zsURg2rhLpR@DB6^kVojqM1;m*mi2*htS9@KrseDCO5>I@YAr9c_no(p_!yO8v;ysN zM|GN*zAv(Diav6Dr9BdO2-a#!u~S#&bV|4U)Adeo0&})jD~*l|nvhIaC3h17JB?mB zkF7LOTNa{55Vw2*7N}HtoDy|4rvy@;X{S9SM|^st3;#u1B{c;WfoD%r-Qd1t?bew( z{t1;o6_v3y6RpZ@-Q$*OxT4anx_@ST3{1gnnP&QR% zQ?4G&yz@@=$c*RFnTAnjWHREJ8uv0qdwOQ9UwO(`dKS`>eQ0HFcdBW3j%SdE%o4LJ z2}@R~eMicyQB@&7{$hGPKd@fGZ94t&OeNexP6?h)&OpVU^NNkJjg^gdMl?lCtgkK6 z!71?l8k~Y87$(cwN#s;$6Rlme_ngV(Ma~7+1J&3B#jmthLb@_1$Qd`YYM53NSVcvR zZ}-7o(z@6);#Xpe{SUmr`j2f92D+5rGiP5SbPn}g-~PpA;PSZYmLS`ivvn+iw-A>{ut*f@(d9?Ji z?HBPN2zz|Mjp;7htzXeux{Kfq_jbKr%IprHBW$;yUW!e0pJ+%&%ZiTDFWDU+_#X5+ zfi?{;&;;k00fNrjJ$H)S#tf4wWNV?RNV!Wv@wil83+u>T#I38Qa0EGzo}9!SP170; ztwdCsD0QmqH*4WKLMJ{*U^GFxb^*kQ7sCq|q<(c!v%fN7mVQSWu1!`L)}dZk_;L2whu>IfD2XVf&}nT}J4B4ZUKVq3dK z;hU9%J`p3Xmb%aB0ihP(OMbG(8u-Aen-myGOZ6ZWy*xiF(G;s9<)MYqioHE;_BB6Yfa- zdO)$;=q>$h;5L=1Vd0~0MP~VA4PH z)sG-o4J6(s^whH)(=KGFrr$B+2Vo7m2a9Q@jVeXwjf2ZPfF zrN2`Hv)rbXq=S{E)9T`?5-|~9F?JiQFNUtYniJm7ncHt^g9OV(Myiab-5w{T`4H_q zL4Y{F#!8Ai7osxy=ynN7zC`neHJD}BfQ_OgSlP5c$5%9Xao>WN?>vD#=iDbE&+1c% zPGW)OvX(4r6u`<9@b#JXwEDm&a||&~-Y1JUhG74O-#ZQ72D9ucN;dumtgM~DYLlHB zl^IrS9YlBcmF7tstmhl8?`McSLNdmqel!9rGl~mT4Fr+Rx^GdDb-XR=(lxOEYd;q~ z5dgCYSV#n(0xSC&%}CJ2RcOC5xn1IunQwPo6BrUUudpC(z+R|b`}I0l+4b#@Rv+7m z_3?QGlXd?)YgJuf|6O}6PYQuqgb*qpQ^3mh`Yi78M0mQN58h>iS24-_$q^W`f6!=H z(|2P8MtRT&4B5x5L%!vQf;AU}cgmqY_~Ml~1O2 zCB<0=sf-i=Ll%_4UOBZcl@Ii*=L19L(f!#sM1zUDe}a+*(IWjF2c?#H?T&N_7zxRGLr&QA_yx}j27|rZti?mtHB55#C&Pm4*j*1bb3Q;DT%yLs^TiH}<_0B$or=TJm+vL!a=xvi zRko3?BrCi1pICfT!(}aI9{rHSeKlnGbw}(15wH6axm+(3nLZTrK}26Uh2tG|3wWn( za`MT7_V(WTplR;}e1e1()+?6Y*-NEaahD}q0&zJy9v8YYl-WOr*BL$}yg&D;$_%1Q z;w>j=>zc9e7xuob80~Gw5z`NX&AoCq3`x-Otbe29-S{?5(WEkaQq!quq9>x(Yq-5> z_rpC(A=ZzN`Pq9^`JRkoeJF;CL$+x(Jv<9A4T*d*vz}T6`TY@S3k7YThK_4 zcXMkdle=NsF-X8*duJfF~+uakg8zsbTI)$5}~~0^`F7hluoNCeAnJ|a6O#TuS+k6S*<|OL%H4USzYS5}1|KMt5QDTqg-m89_4T#>W2+cA+!$elkN8T+{B{YXYQe5^20XMugZnm*kO9lG&{q%})uVcC zV@Yv>cR$Izx2m#W&RW&%vO+q}ci!#8m@T% zX@T>a_xD2EmV|l}GJ`g%zq*Vl;qFJi!U|tgWQiQU<8HuiUHw#=j|_<4nP$gmJD#?4 zZgzsre_-guIH33qF|+kSn_g!-W!DYRB+$!TAQAU-xYdmJ@3AACwwC(w z?v3E->e(*C9veTj?Wb<$d>6PRRnO zrn?HoEH8P2-cc4nr-^Ve+FXC3r=#ig&tahbl`E=`t6IX6Gqev(b*sd@5#X|tyCO; zX*=g;C)oT4hR(_^AK}GLIUlde=8caF-kw1XexUVyt&A7M_M689`i6k|ibN&b*aYvt zQaU?~o^-3^%nJF{GDeRkTcC)mFXRGdydm@%}rJ-rbGZ+GsrDz}9H zTAsb9U8zOzK_U6n9#2dVD9N?8iu=w>ykWV?k$5<2wknB3k-5%f`os0umj0=3l+~F8 zP$;<8R8JG{AQi%=JgnABB(g!T*{C=3GB#w|pntFlqX#%hfN|5p=WoC@8E2*D@3am* zcW@Bqy}K*jgun!Q$i(~g=7?OE7mf?%sn2H1dEtj7*#W%IVg2QBrLM=Z<-!Zn03{qb zmv<3`$kdUY(t`-E&Gl(hieiEupNRO$jQJ@cSGCT!?T+5SAQ9t%i0S=M8{zb1d5{`+ zf%G^L(A!eaY^VgniW4#8lx|QdiQ6QhP-d&YsyiH*@`g{=y?Pw5Yql#E?b4RCW+krj#J_dE0a;s@l2tmQ?s_fD$)5e=(6!oX=&g2-tmYiKEN9*y62gHEdb7p|Z*PHdN%VkW^ zJf_mucaOpP9yiXbOA||qG6#2u?FBjTB&f%uBp}-%TRrYA7sO3J-L3&GmaOqwSg!dB zwzL2-bGO3NWZl!I7}1?-LU;`+2;3G-z5m2~XOdGnsvFG@w&^z3+0| zFz8t%g(gikM*u3VU;ED@eiPWxX7ksuU##VXXI?6&%IWL*qnjh;s2jRc^Sa>0&Tlzv z3V-Zx0fmuB$Q!EHT~ObUSG}i?+UnJ?ry6!E)o#DCQ$^mAhs{rVlAZFLBfHZSJ~Tay zJ|c4Kq%WV=t8PW^&ZN#vwwxAh*6`h6ilMLwfm*x0yZQk+kDVOGyWp6Q3n!#lqmJ!_GxSj6-m|JqZ%7Bj@+EIOAoX`4Zo7d zp4`ugcd;syHD=ppXT%@uTDrDaPpj-A0ak7=pEi38a2snt#U|~~cGme0VC3g9!@B+( z=_fRVjP3*I5XgrP<&}+P1>yZ>+MKZd_m7QwBZ+~8vM3w8>$VUw)CTp0foZ{w6B_Tt zD+5$mj@hYS>{MfRN?1Duxt%KJPE9s2e8P2h!v*Trm8mK**;@Ttct5hNK`Go55so+< zbY(-bfzi6DHU*7WLW^XZr#*pMqxfWJHvJ#ESQCBHW} zr~#h%THibt?x4>uwiyPwuDyHX6kiSQZTe96_>yzg#Sox~!w zg=KXvod=4MOI_)TgdRro{3j`XA>-^L11v43sv!~MkV1{6nDbjbbr+`7o5a)^jk87g zEP~IiHTzs5`KDsF2YT}6vo6{RAxA#Q@cT0KTsA|1r}VZiE-Rz@T6d1&wXV0v?+}#F z3kJeSpMQI}Co491w4N6E8~yIS;N0ZRr9jZc$UCT95I)%N9W+fmJoq;|r`_|vv$OQX z(sJ5~3Y$%MEGD3u-srcG711=&iaGPd1n`HZLe_N{dqFSg4?flVmbv{ziv(Z*R%r$8 zAj|vSTA(GUdTc7a)>PUpP#Y{?73=Q=$W4}=W;2?#w8*;??L-YNQce+Qu0ZLpprGMW z#(1XE53o$#4$k<0g)@l79~}PHfWCzs0Hln`+cVW-wr~7R)>3$$2=<)?@3_LOvc%xZm*_i=z zDz4^(qj@&a07)A+kgp%2&6j58@bw~ozdt=atFF400xF1O&baOxzuq1`;fddtt!dk> znB~J`5k_D%pa!eEm3B4Q!yM@ZzOw>e62kgf+EELzk>DORKb{%?@!`3iL&-`PUYyG} zo(V^^wH*%OODlnDb8%Kkm1)gT_oLFp=O|D5D&+K`UX~xf&K!A18ORm3&1+2t>O6ib zkd=%3tf7v)i6($PFGc`oERF>F&@u{~41oYaru}vToV!KI{nq8hTf+>3lA0i0tD}j; zSqbY>fMqcVKBRVY>lM4+GCQTvQw`({^PaiyxOL{?k?hh;tB8|+&UW}8GA`qUSTp|4Rx1;_o}Jm8ZN zY~;-W{dk$Zh-8AqyB{PUnFK@m!Xd`-G&+!!HkF|}Qw3`nqn??=@=%zy$UBN|T;4%^ zQ`Kyar?}Qv+>f%*M;#Jzw1nAF&)|xcw}FjcUd&bmBmKvLcl&yp2JHsC^Zl|4=G(x% z%UUE4w;Vj$!v3!45NdJ}N^z=}XVF}2$AQF^Ly{>PFEkCk%5aTpF$HXRC3i=@2=~up zd>#<*F}uH$cQl%1Ct#bv^e!Q@BOw-YkP0#?6ZF}?X3lmgY)EX zz4rCL$5s;%7ZBC&&VI-j75>S{9|mf;3V}YGe<;KMuP%yxK>N(DT|#93?*jafT;R^4 ofP~~f*S~fi-~W)u$K;tQ#|C9&KRg6}4P@7u(~hSqzxTcKUsw}kZ2$lO literal 0 HcmV?d00001 diff --git a/test/image/mocks/axes_category_ascending.json b/test/image/mocks/axes_category_ascending.json new file mode 100644 index 00000000000..29f76d87465 --- /dev/null +++ b/test/image/mocks/axes_category_ascending.json @@ -0,0 +1,13 @@ +{ + "data": [{ + "x": ["c","a","e","b","d"], + "y": [15,11,12,13,14]} + ], + "layout": { + "xaxis": { + "title": "category ascending", + "type": "category", + "categorymode": "category ascending", + "categorylist": ["y","b","x","a","d","z","e","c", "q", "k"] + }} +} diff --git a/test/image/mocks/axes_category_categorylist.json b/test/image/mocks/axes_category_categorylist.json new file mode 100644 index 00000000000..9e13216b552 --- /dev/null +++ b/test/image/mocks/axes_category_categorylist.json @@ -0,0 +1,46 @@ +{ + "data": [ + { + "x": [ + 1, + 2, + null, + 4, + 5 + ], + "y": [ + 1, + 2, + 3, + 4, + 5 + ], + "connectgaps": false, + "uid": "8ac13a" + } + ], + "layout": { + "title": "categorylist", + "xaxis": { + "type": "category", + "range": [ + -0.18336673346693386, + 3.1833667334669338 + ], + "autorange": true, + "categorymode": "array", + "categorylist": [2,4,5,1] + }, + "yaxis": { + "type": "linear", + "range": [ + 0.7070063694267517, + 5.292993630573249 + ], + "autorange": true + }, + "height": 450, + "width": 1000, + "autosize": true + } +} diff --git a/test/image/mocks/axes_category_categorylist_truncated_tails.json b/test/image/mocks/axes_category_categorylist_truncated_tails.json new file mode 100644 index 00000000000..c2c9793bc9f --- /dev/null +++ b/test/image/mocks/axes_category_categorylist_truncated_tails.json @@ -0,0 +1,13 @@ +{ + "data": [{ + "x": ["c","a","e","b","d"], + "y": [15,11,12,13,14]} + ], + "layout": { + "title": "categorylist with truncated tails (y, q, k not plotted)", + "xaxis": { + "type": "category", + "categorymode": "array", + "categorylist": ["y","b","x","a","d","z","e","c", "q", "k"] + }} +} diff --git a/test/image/mocks/axes_category_descending.json b/test/image/mocks/axes_category_descending.json new file mode 100644 index 00000000000..0df8fc761ca --- /dev/null +++ b/test/image/mocks/axes_category_descending.json @@ -0,0 +1,41 @@ +{ + "data": [ + { + "x": [ + 5, + 1, + 3, + 2, + 4 + ], + "y": [ + 1, + 2, + 3, + 4, + 5 + ], + "connectgaps": false, + "uid": "8ac13a" + } + ], + "layout": { + "title": "category descending", + "xaxis": { + "type": "category", + "categorymode": "category descending", + "categorylist": [2,4,5,1] + }, + "yaxis": { + "type": "linear", + "range": [ + 0.7070063694267517, + 5.292993630573249 + ], + "autorange": true + }, + "height": 450, + "width": 1000, + "autosize": true + } +} diff --git a/test/image/mocks/axes_category_descending_with_gaps.json b/test/image/mocks/axes_category_descending_with_gaps.json new file mode 100644 index 00000000000..cea8a7b1a41 --- /dev/null +++ b/test/image/mocks/axes_category_descending_with_gaps.json @@ -0,0 +1,41 @@ +{ + "data": [ + { + "x": [ + 5, + null, + 3, + 2, + 4 + ], + "y": [ + 1, + 2, + 3, + null, + 5 + ], + "connectgaps": false, + "uid": "8ac13a" + } + ], + "layout": { + "title": "category descending", + "xaxis": { + "type": "category", + "categorymode": "category descending", + "categorylist": [2,4,5,1] + }, + "yaxis": { + "type": "linear", + "range": [ + 0.7070063694267517, + 5.292993630573249 + ], + "autorange": true + }, + "height": 450, + "width": 1000, + "autosize": true + } +} From 53f12da633fbdcffd23718974d204e9236c007aa Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Apr 2016 16:56:02 +0200 Subject: [PATCH 7/9] #189 PR feedback --- src/plots/gl3d/layout/axis_attributes.js | 31 +--------------- test/jasmine/tests/calcdata_test.js | 47 ------------------------ 2 files changed, 2 insertions(+), 76 deletions(-) diff --git a/src/plots/gl3d/layout/axis_attributes.js b/src/plots/gl3d/layout/axis_attributes.js index be4abcb5e0f..802a1188059 100644 --- a/src/plots/gl3d/layout/axis_attributes.js +++ b/src/plots/gl3d/layout/axis_attributes.js @@ -68,35 +68,8 @@ module.exports = { description: 'Sets whether or not this axis is labeled' }, color: axesAttrs.color, - categorymode: { - valType: 'enumerated', - values: [ - 'trace', 'category ascending', 'category descending', 'array' - /*, 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later - ], - dflt: 'trace', - role: 'info', - description: [ - 'Specifies the ordering logic for the case of categorical variables.', - 'By default, plotly uses *trace*, which specifies the order that is present in the data supplied.', - 'Set `categorymode` to *category ascending* or *category descending* if order should be determined by', - 'the alphanumerical order of the category names.', - /*'Set `categorymode` to *value ascending* or *value descending* if order should be determined by the', - 'numerical order of the values.',*/ // // value ascending / descending to be implemented later - 'Set `categorymode` to *array* to derive the ordering from the attribute `categorylist`. If a category', - 'is not found in the `categorylist` array, the sorting behavior for that attribute will be identical to', - 'the *trace* mode. The unspecified categories will follow the categories in `categorylist`.' - ].join(' ') - }, - categorylist: { - valType: 'data_array', - role: 'info', - description: [ - 'Sets the order in which categories on this axis appear.', - 'Only has an effect if `categorymode` is set to *array*.', - 'Used with `categorymode`.' - ].join(' ') - }, + categorymode: axesAttrs.categorymode, + categorylist: axesAttrs.categorylist, title: axesAttrs.title, titlefont: axesAttrs.titlefont, type: axesAttrs.type, diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index 8c20fca44d6..98be1206631 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -139,53 +139,6 @@ describe('calculated data and points', function() { }); }); -/* - describe('codomain numerical category ordering', function() { - - it('should output categories in ascending codomain numerical order', function() { - - Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { - type: 'category', - categorymode: 'value ascending' - }}); - - expect(gd.calcdata[0][0].y).toEqual(11); - expect(gd.calcdata[0][1].y).toEqual(12); - expect(gd.calcdata[0][2].y).toEqual(13); - expect(gd.calcdata[0][3].y).toEqual(14); - expect(gd.calcdata[0][4].y).toEqual(15); - }); - - it('should output categories in descending codomain numerical order', function() { - - Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { - type: 'category', - categorymode: 'value descending' - }}); - - expect(gd.calcdata[0][0].y).toEqual(15); - expect(gd.calcdata[0][1].y).toEqual(14); - expect(gd.calcdata[0][2].y).toEqual(13); - expect(gd.calcdata[0][3].y).toEqual(12); - expect(gd.calcdata[0][4].y).toEqual(11); - }); - - it('should output categories in descending codomain numerical order, excluding nulls', function() { - - Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,null,13,14]}], { xaxis: { - type: 'category', - categorymode: 'value descending' - }}); - - expect(gd.calcdata[0][0].y).toEqual(15); - expect(gd.calcdata[0][1].y).toEqual(14); - expect(gd.calcdata[0][2].y).toEqual(12); - expect(gd.calcdata[0][3].y).toEqual(11); - - }); - }); -*/ - describe('explicit category ordering', function() { it('should output categories in explicitly supplied order, independent of trace order', function() { From 14908d08b255965ab0f691b43ecb3f897a9ebe84 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 15 Apr 2016 16:00:37 +0200 Subject: [PATCH 8/9] #189 Renaming attributes --- src/plots/cartesian/axis_defaults.js | 6 +- src/plots/cartesian/category_mode_defaults.js | 39 ----- .../cartesian/category_order_defaults.js | 39 +++++ src/plots/cartesian/layout_attributes.js | 18 +-- src/plots/cartesian/ordered_categories.js | 14 +- src/plots/gl3d/layout/axis_attributes.js | 4 +- test/image/mocks/axes_category_ascending.json | 4 +- .../mocks/axes_category_categorylist.json | 4 +- ...category_categorylist_truncated_tails.json | 4 +- .../image/mocks/axes_category_descending.json | 4 +- .../axes_category_descending_with_gaps.json | 4 +- test/jasmine/tests/axes_test.js | 90 +++++------ test/jasmine/tests/calcdata_test.js | 148 +++++++++--------- 13 files changed, 189 insertions(+), 189 deletions(-) delete mode 100644 src/plots/cartesian/category_mode_defaults.js create mode 100644 src/plots/cartesian/category_order_defaults.js diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index e210261c461..45f34895978 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -20,7 +20,7 @@ var layoutAttributes = require('./layout_attributes'); var handleTickValueDefaults = require('./tick_value_defaults'); var handleTickMarkDefaults = require('./tick_mark_defaults'); var handleTickLabelDefaults = require('./tick_label_defaults'); -var handleCategoryModeDefaults = require('./category_mode_defaults'); +var handleCategoryOrderDefaults = require('./category_order_defaults'); var setConvert = require('./set_convert'); var orderedCategories = require('./ordered_categories'); var cleanDatum = require('./clean_datum'); @@ -75,7 +75,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, } containerOut._initialCategories = axType === 'category' ? - orderedCategories(letter, containerIn.categorymode, containerIn.categorylist, options.data) : + orderedCategories(letter, containerIn.categoryorder, containerIn.categoryarray, options.data) : []; setConvert(containerOut); @@ -111,7 +111,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, handleTickValueDefaults(containerIn, containerOut, coerce, axType); handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); handleTickMarkDefaults(containerIn, containerOut, coerce, options); - handleCategoryModeDefaults(containerIn, containerOut, coerce); + handleCategoryOrderDefaults(containerIn, containerOut, coerce); var lineColor = coerce2('linecolor', dfltColor), lineWidth = coerce2('linewidth'), diff --git a/src/plots/cartesian/category_mode_defaults.js b/src/plots/cartesian/category_mode_defaults.js deleted file mode 100644 index d671941d5ee..00000000000 --- a/src/plots/cartesian/category_mode_defaults.js +++ /dev/null @@ -1,39 +0,0 @@ -/** -* Copyright 2012-2016, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var layoutAttributes = require('./layout_attributes'); - -module.exports = function handleCategoryModeDefaults(containerIn, containerOut, coerce) { - - if(containerIn.type !== 'category') return; - - var validCategories = layoutAttributes.categorymode.values; - - var properCategoryList = Array.isArray(containerIn.categorylist) && containerIn.categorylist.length > 0; - - if(validCategories.indexOf(containerIn.categorymode) === -1 && properCategoryList) { - - // when unspecified or invalid, use the default, unless categorylist implies 'array' - coerce('categorymode', 'array'); // promote to 'array' - - } else if(containerIn.categorymode === 'array' && !properCategoryList) { - - // when mode is 'array' but no list is given, revert to default - - containerIn.categorymode = 'trace'; // revert to default - coerce('categorymode'); - - } else { - - // otherwise use the supplied mode, or the default one if unsupplied or invalid - coerce('categorymode'); - - } -}; diff --git a/src/plots/cartesian/category_order_defaults.js b/src/plots/cartesian/category_order_defaults.js new file mode 100644 index 00000000000..39da91ba992 --- /dev/null +++ b/src/plots/cartesian/category_order_defaults.js @@ -0,0 +1,39 @@ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var layoutAttributes = require('./layout_attributes'); + +module.exports = function handleCategoryOrderDefaults(containerIn, containerOut, coerce) { + + if(containerIn.type !== 'category') return; + + var validCategories = layoutAttributes.categoryorder.values; + + var propercategoryarray = Array.isArray(containerIn.categoryarray) && containerIn.categoryarray.length > 0; + + if(validCategories.indexOf(containerIn.categoryorder) === -1 && propercategoryarray) { + + // when unspecified or invalid, use the default, unless categoryarray implies 'array' + coerce('categoryorder', 'array'); // promote to 'array' + + } else if(containerIn.categoryorder === 'array' && !propercategoryarray) { + + // when mode is 'array' but no list is given, revert to default + + containerIn.categoryorder = 'trace'; // revert to default + coerce('categoryorder'); + + } else { + + // otherwise use the supplied mode, or the default one if unsupplied or invalid + coerce('categoryorder'); + + } +}; diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index f2842bad7c5..43de76d0ce1 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -465,7 +465,7 @@ module.exports = { 'Only has an effect if `anchor` is set to *free*.' ].join(' ') }, - categorymode: { + categoryorder: { valType: 'enumerated', values: [ 'trace', 'category ascending', 'category descending', 'array' @@ -476,22 +476,22 @@ module.exports = { description: [ 'Specifies the ordering logic for the case of categorical variables.', 'By default, plotly uses *trace*, which specifies the order that is present in the data supplied.', - 'Set `categorymode` to *category ascending* or *category descending* if order should be determined by', + 'Set `categoryorder` to *category ascending* or *category descending* if order should be determined by', 'the alphanumerical order of the category names.', - /*'Set `categorymode` to *value ascending* or *value descending* if order should be determined by the', + /*'Set `categoryorder` to *value ascending* or *value descending* if order should be determined by the', 'numerical order of the values.',*/ // // value ascending / descending to be implemented later - 'Set `categorymode` to *array* to derive the ordering from the attribute `categorylist`. If a category', - 'is not found in the `categorylist` array, the sorting behavior for that attribute will be identical to', - 'the *trace* mode. The unspecified categories will follow the categories in `categorylist`.' + 'Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category', + 'is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to', + 'the *trace* mode. The unspecified categories will follow the categories in `categoryarray`.' ].join(' ') }, - categorylist: { + categoryarray: { valType: 'data_array', role: 'info', description: [ 'Sets the order in which categories on this axis appear.', - 'Only has an effect if `categorymode` is set to *array*.', - 'Used with `categorymode`.' + 'Only has an effect if `categoryorder` is set to *array*.', + 'Used with `categoryorder`.' ].join(' ') }, diff --git a/src/plots/cartesian/ordered_categories.js b/src/plots/cartesian/ordered_categories.js index 5f9f25a485c..546578ecb15 100644 --- a/src/plots/cartesian/ordered_categories.js +++ b/src/plots/cartesian/ordered_categories.js @@ -53,22 +53,22 @@ function flattenUniqueSort(axisLetter, sortFunction, data) { /** - * This pure function returns the ordered categories for specified axisLetter, categorymode, categorylist and data. + * This pure function returns the ordered categories for specified axisLetter, categoryorder, categoryarray and data. * - * If categorymode is 'array', the result is a fresh copy of categorylist, or if unspecified, an empty array. + * If categoryorder is 'array', the result is a fresh copy of categoryarray, or if unspecified, an empty array. * - * If categorymode is 'category ascending' or 'category descending', the result is an array of ascending or descending + * If categoryorder is 'category ascending' or 'category descending', the result is an array of ascending or descending * order of the unique categories encountered in the data for specified axisLetter. * - * See cartesian/layout_attributes.js for the definition of categorymode and categorylist + * See cartesian/layout_attributes.js for the definition of categoryorder and categoryarray * */ // orderedCategories :: String -> String -> [String] -> [[String]] -> [String] -module.exports = function orderedCategories(axisLetter, categorymode, categorylist, data) { +module.exports = function orderedCategories(axisLetter, categoryorder, categoryarray, data) { - switch(categorymode) { - case 'array': return Array.isArray(categorylist) ? categorylist.slice() : []; + switch(categoryorder) { + case 'array': return Array.isArray(categoryarray) ? categoryarray.slice() : []; case 'category ascending': return flattenUniqueSort(axisLetter, d3.ascending, data); case 'category descending': return flattenUniqueSort(axisLetter, d3.descending, data); case 'trace': return []; diff --git a/src/plots/gl3d/layout/axis_attributes.js b/src/plots/gl3d/layout/axis_attributes.js index 802a1188059..f311e63d4c4 100644 --- a/src/plots/gl3d/layout/axis_attributes.js +++ b/src/plots/gl3d/layout/axis_attributes.js @@ -68,8 +68,8 @@ module.exports = { description: 'Sets whether or not this axis is labeled' }, color: axesAttrs.color, - categorymode: axesAttrs.categorymode, - categorylist: axesAttrs.categorylist, + categoryorder: axesAttrs.categoryorder, + categoryarray: axesAttrs.categoryarray, title: axesAttrs.title, titlefont: axesAttrs.titlefont, type: axesAttrs.type, diff --git a/test/image/mocks/axes_category_ascending.json b/test/image/mocks/axes_category_ascending.json index 29f76d87465..7d20ecef13a 100644 --- a/test/image/mocks/axes_category_ascending.json +++ b/test/image/mocks/axes_category_ascending.json @@ -7,7 +7,7 @@ "xaxis": { "title": "category ascending", "type": "category", - "categorymode": "category ascending", - "categorylist": ["y","b","x","a","d","z","e","c", "q", "k"] + "categoryorder": "category ascending", + "categoryarray": ["y","b","x","a","d","z","e","c", "q", "k"] }} } diff --git a/test/image/mocks/axes_category_categorylist.json b/test/image/mocks/axes_category_categorylist.json index 9e13216b552..0ad9112cd4e 100644 --- a/test/image/mocks/axes_category_categorylist.json +++ b/test/image/mocks/axes_category_categorylist.json @@ -28,8 +28,8 @@ 3.1833667334669338 ], "autorange": true, - "categorymode": "array", - "categorylist": [2,4,5,1] + "categoryorder": "array", + "categoryarray": [2,4,5,1] }, "yaxis": { "type": "linear", diff --git a/test/image/mocks/axes_category_categorylist_truncated_tails.json b/test/image/mocks/axes_category_categorylist_truncated_tails.json index c2c9793bc9f..782e9ba7934 100644 --- a/test/image/mocks/axes_category_categorylist_truncated_tails.json +++ b/test/image/mocks/axes_category_categorylist_truncated_tails.json @@ -7,7 +7,7 @@ "title": "categorylist with truncated tails (y, q, k not plotted)", "xaxis": { "type": "category", - "categorymode": "array", - "categorylist": ["y","b","x","a","d","z","e","c", "q", "k"] + "categoryorder": "array", + "categoryarray": ["y","b","x","a","d","z","e","c", "q", "k"] }} } diff --git a/test/image/mocks/axes_category_descending.json b/test/image/mocks/axes_category_descending.json index 0df8fc761ca..1c44a4ff1be 100644 --- a/test/image/mocks/axes_category_descending.json +++ b/test/image/mocks/axes_category_descending.json @@ -23,8 +23,8 @@ "title": "category descending", "xaxis": { "type": "category", - "categorymode": "category descending", - "categorylist": [2,4,5,1] + "categoryorder": "category descending", + "categoryarray": [2,4,5,1] }, "yaxis": { "type": "linear", diff --git a/test/image/mocks/axes_category_descending_with_gaps.json b/test/image/mocks/axes_category_descending_with_gaps.json index cea8a7b1a41..11afaf2d72e 100644 --- a/test/image/mocks/axes_category_descending_with_gaps.json +++ b/test/image/mocks/axes_category_descending_with_gaps.json @@ -23,8 +23,8 @@ "title": "category descending", "xaxis": { "type": "category", - "categorymode": "category descending", - "categorylist": [2,4,5,1] + "categoryorder": "category descending", + "categoryarray": [2,4,5,1] }, "yaxis": { "type": "linear", diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index cfa72ec3c3b..bc61b5603ed 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -384,7 +384,7 @@ describe('Test axes', function() { }); }); - describe('categorymode', function() { + describe('categoryorder', function() { var gd; @@ -394,112 +394,112 @@ describe('Test axes', function() { afterEach(destroyGraphDiv); - describe('setting, or not setting categorymode if it is not explicitly declared', function() { + describe('setting, or not setting categoryorder if it is not explicitly declared', function() { - it('should set categorymode to default if categorymode and categorylist are not supplied', function() { + it('should set categoryorder to default if categoryorder and categoryarray are not supplied', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], {xaxis: {type: 'category'}}); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); - it('should set categorymode to default even if type is not set to category explicitly', function() { + it('should set categoryorder to default even if type is not set to category explicitly', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}]); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); - it('should NOT set categorymode to default if type is not category', function() { + it('should NOT set categoryorder to default if type is not category', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}]); - expect(gd._fullLayout.yaxis.categorymode).toBe(undefined); + expect(gd._fullLayout.yaxis.categoryorder).toBe(undefined); }); - it('should set categorymode to default if type is overridden to be category', function() { + it('should set categoryorder to default if type is overridden to be category', function() { PlotlyInternal.plot(gd, [{x: [1,2,3,4,5], y: [15,11,12,13,14]}], {yaxis: {type: 'category'}}); - expect(gd._fullLayout.xaxis.categorymode).toBe(undefined); - expect(gd._fullLayout.yaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe(undefined); + expect(gd._fullLayout.yaxis.categoryorder).toBe('trace'); }); }); - describe('setting categorymode to "array"', function() { + describe('setting categoryorder to "array"', function() { - it('should leave categorymode on "array" if it is supplied', function() { + it('should leave categoryorder on "array" if it is supplied', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'array', categorylist: ['b','a','d','e','c']} + xaxis: {type: 'category', categoryorder: 'array', categoryarray: ['b','a','d','e','c']} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('array'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); }); - it('should switch categorymode on "array" if it is not supplied but categorylist is supplied', function() { + it('should switch categoryorder on "array" if it is not supplied but categoryarray is supplied', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorylist: ['b','a','d','e','c']} + xaxis: {type: 'category', categoryarray: ['b','a','d','e','c']} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('array'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); }); - it('should revert categorymode 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() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'array'} + xaxis: {type: 'category', categoryorder: 'array'} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); }); - describe('do not set categorymode to "array" if list exists but empty', function() { + describe('do not set categoryorder to "array" if list exists but empty', function() { - it('should switch categorymode to default if list is not supplied', function() { + it('should switch categoryorder to default if list is not supplied', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'array', categorylist: []} + xaxis: {type: 'category', categoryorder: 'array', categoryarray: []} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); - it('should not switch categorymode on "array" if categorylist is supplied but empty', function() { + it('should not switch categoryorder on "array" if categoryarray is supplied but empty', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorylist: []} + xaxis: {type: 'category', categoryarray: []} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); }); - describe('do NOT set categorymode to "array" if it has some other proper value', function() { + describe('do NOT set categoryorder to "array" if it has some other proper value', function() { - it('should use specified categorymode if it is supplied even if categorylist exists', function() { + it('should use specified categoryorder if it is supplied even if categoryarray exists', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'trace', categorylist: ['b','a','d','e','c']} + xaxis: {type: 'category', categoryorder: 'trace', categoryarray: ['b','a','d','e','c']} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); - it('should use specified categorymode if it is supplied even if categorylist exists', function() { + it('should use specified categoryorder if it is supplied even if categoryarray exists', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'category ascending', categorylist: ['b','a','d','e','c']} + xaxis: {type: 'category', categoryorder: 'category ascending', categoryarray: ['b','a','d','e','c']} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('category ascending'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('category ascending'); }); - it('should use specified categorymode if it is supplied even if categorylist exists', function() { + it('should use specified categoryorder if it is supplied even if categoryarray exists', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'category descending', categorylist: ['b','a','d','e','c']} + xaxis: {type: 'category', categoryorder: 'category descending', categoryarray: ['b','a','d','e','c']} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('category descending'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('category descending'); }); }); - describe('setting categorymode to the default if the value is unexpected', function() { + describe('setting categoryorder to the default if the value is unexpected', function() { - it('should switch categorymode to "trace" if mode is supplied but invalid', function() { + it('should switch categoryorder to "trace" if mode is supplied but invalid', function() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'invalid value'} + xaxis: {type: 'category', categoryorder: 'invalid value'} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('trace'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('trace'); }); - it('should switch categorymode 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() { PlotlyInternal.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { - xaxis: {type: 'category', categorymode: 'invalid value', categorylist: ['b','a','d','e','c']} + xaxis: {type: 'category', categoryorder: 'invalid value', categoryarray: ['b','a','d','e','c']} }); - expect(gd._fullLayout.xaxis.categorymode).toBe('array'); + expect(gd._fullLayout.xaxis.categoryorder).toBe('array'); }); }); diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index 98be1206631..d727f51c904 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -51,7 +51,7 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'trace' + categoryorder: 'trace' // Also, if axis tick order is made configurable, shouldn't we make trace order configurable? // 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 @@ -72,7 +72,7 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'category ascending' + categoryorder: 'category ascending' }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); @@ -86,7 +86,7 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'category descending' + categoryorder: 'category descending' }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); @@ -100,7 +100,7 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: [3,1,5,2,4], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'category ascending' + categoryorder: 'category ascending' }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 2, y: 15})); @@ -110,12 +110,12 @@ describe('calculated data and points', function() { expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); }); - it('should output categories in categorymode order even if category array is defined', function() { + it('should output categories in categoryorder order even if category array is defined', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'category ascending', - categorylist: ['b','a','d','e','c'] // These must be ignored. Alternative: error? + 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})); @@ -129,7 +129,7 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c',undefined,'e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'category ascending' + categoryorder: 'category ascending' }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 1, y: 15})); @@ -145,8 +145,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['b','a','d','e','c'] + categoryorder: 'array', + categoryarray: ['b','a','d','e','c'] }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); @@ -160,8 +160,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: [3,1,5,2,4], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: [2,1,4,5,3] + categoryorder: 'array', + categoryarray: [2,1,4,5,3] }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); @@ -175,8 +175,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c',undefined,'e','b','d'], y: [15,11,12,null,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['b','a','d','e','c'] + categoryorder: 'array', + categoryarray: ['b','a','d','e','c'] }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); @@ -190,8 +190,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['b','x','a','d','z','e','c'] + categoryorder: 'array', + categoryarray: ['b','x','a','d','z','e','c'] }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); @@ -201,12 +201,12 @@ describe('calculated data and points', function() { expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); }); - it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categorylist', function() { + it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categoryarray', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['y','b','x','a','d','z','e','c', 'q', 'k'] + 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})); @@ -224,7 +224,7 @@ describe('calculated data and points', function() { expect(domTickTexts).toEqual(['b', 'x', 'a', 'd', 'z', 'e', 'c']); // y, q and k has no data points }); - it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categorylist', function() { + it('should output categories in explicitly supplied order even if some missing categories were at the beginning or end of categoryarray', function() { // 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 @@ -232,8 +232,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d', 'y'], y: [15,11,12,13,14, null]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['y','b','x','a','d','z','e','c', 'q', 'k'] + 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})); @@ -252,8 +252,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,null,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['b','x','a','d','z','e','c'] + categoryorder: 'array', + categoryarray: ['b','x','a','d','z','e','c'] }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); @@ -267,8 +267,8 @@ describe('calculated data and points', function() { Plotly.plot(gd, [{x: ['c','a','e','b','d'], y: [15,11,12,13,14]}], { xaxis: { type: 'category', - categorymode: 'array', - categorylist: ['b','a','x','c'] + categoryorder: 'array', + categoryarray: ['b','a','x','c'] }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 3, y: 15})); @@ -277,10 +277,10 @@ describe('calculated data and points', function() { 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_ categorymode and + // 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 categorymode. This of course means that the mere presence of categories triggers this - // behavior, rather than an explicit 'explicit' categorymode. + // based on the categoryorder. This of course means that the mere presence of categories triggers this + // behavior, rather than an explicit 'explicit' categoryorder. }); }); @@ -313,7 +313,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); }); - it('category order follows the trace order (even if categorylist is specified)', function() { + it('category order follows the trace order (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -325,8 +325,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'trace', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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})); @@ -344,7 +344,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 10, y: 32})); }); - it('category order is category ascending (even if categorylist is specified)', function() { + it('category order is category ascending (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -356,8 +356,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'category ascending', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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'] }}); @@ -376,7 +376,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 9, y: 32})); }); - it('category order is category descending (even if categorylist is specified)', function() { + it('category order is category descending (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -388,8 +388,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'category descending', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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"] }}); @@ -408,7 +408,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); }); - it('category order follows categorylist', function() { + it('category order follows categoryarray', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -420,8 +420,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'array', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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})); @@ -470,7 +470,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 10, y: 33})); }); - it('category order follows the trace order (even if categorylist is specified)', function() { + it('category order follows the trace order (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -482,8 +482,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'trace', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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})); @@ -502,7 +502,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 10, y: 33})); }); - it('category order is category ascending (even if categorylist is specified)', function() { + it('category order is category ascending (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -514,8 +514,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'category ascending', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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'] }}); @@ -535,7 +535,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 9, y: 33})); }); - it('category order is category descending (even if categorylist is specified)', function() { + it('category order is category descending (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -547,8 +547,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'category descending', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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"] }}); @@ -568,7 +568,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 1, y: 33})); }); - it('category order follows categorylist', function() { + it('category order follows categoryarray', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -580,8 +580,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'array', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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})); @@ -628,7 +628,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); }); - it('category order follows the trace order (even if categorylist is specified)', function() { + it('category order follows the trace order (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; @@ -640,8 +640,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'trace', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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})); @@ -657,7 +657,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 1, y: 32})); }); - it('category order is category ascending (even if categorylist is specified)', function() { + it('category order is category ascending (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; @@ -669,8 +669,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'category ascending', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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'] }}); @@ -687,7 +687,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); }); - it('category order is category descending (even if categorylist is specified)', function() { + it('category order is category descending (even if categoryarray is specified)', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; @@ -699,8 +699,8 @@ describe('calculated data and points', function() { {x: x3, y: x3.map(function(d, i) {return i + 30;})} ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'category descending', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + 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"] }}); @@ -717,7 +717,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 2, y: 32})); }); - it('category order follows categorylist', function() { + it('category order follows categoryarray', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; @@ -730,8 +730,8 @@ describe('calculated data and points', function() { ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'array', - categorylist: ['Bearing','Motor','Gear'] + categoryorder: 'array', + categoryarray: ['Bearing','Motor','Gear'] } }); @@ -748,7 +748,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][2]).toEqual(jasmine.objectContaining({x: 0, y: 32})); }); - it('category order follows categorylist even if data is sparse', function() { + it('category order follows categoryarray even if data is sparse', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; @@ -761,8 +761,8 @@ describe('calculated data and points', function() { ], { xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'array', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + categoryorder: 'array', + categoryarray: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] } }); @@ -782,7 +782,7 @@ describe('calculated data and points', function() { describe('ordering and stacking combined', function() { - it('partially overlapping category order follows categorylist and stacking produces expected results', function() { + it('partially overlapping category order follows categoryarray and stacking produces expected results', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Switch', 'Plug', 'Cord', 'Fuse', 'Bulb']; @@ -796,8 +796,8 @@ describe('calculated data and points', function() { barmode: 'stack', xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'array', - categorylist: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] + categoryorder: 'array', + categoryarray: ['Switch','Bearing','Motor','Seals','Pump','Cord','Plug','Bulb','Fuse','Gear','Leak'] } }); @@ -817,7 +817,7 @@ describe('calculated data and points', function() { expect(gd.calcdata[2][3]).toEqual(jasmine.objectContaining({x: 3, y: 33})); }); - it('fully overlapping - category order follows categorylist and stacking produces expected results', function() { + it('fully overlapping - category order follows categoryarray and stacking produces expected results', function() { var x1 = ['Gear', 'Bearing', 'Motor']; var x2 = ['Bearing', 'Gear', 'Motor']; @@ -831,8 +831,8 @@ describe('calculated data and points', function() { barmode: 'stack', xaxis: { // type: 'category', // commented out to rely on autotyping for added realism - categorymode: 'array', - categorylist: ['Bearing','Motor','Gear'] + categoryorder: 'array', + categoryarray: ['Bearing','Motor','Gear'] } }); From b21ebb2163a98695b729bfce9d4209c3e3603969 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 15 Apr 2016 16:19:53 +0200 Subject: [PATCH 9/9] #189 Renamings in image plot titles and image test filenames --- .../baselines/axes_category_categoryarray.png | Bin 0 -> 21284 bytes ...s_category_categoryarray_truncated_tails.png | Bin 0 -> 32078 bytes .../baselines/axes_category_categorylist.png | Bin 21133 -> 0 bytes ...es_category_categorylist_truncated_tails.png | Bin 31892 -> 0 bytes ...st.json => axes_category_categoryarray.json} | 2 +- ...category_categoryarray_truncated_tails.json} | 2 +- 6 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 test/image/baselines/axes_category_categoryarray.png create mode 100644 test/image/baselines/axes_category_categoryarray_truncated_tails.png delete mode 100644 test/image/baselines/axes_category_categorylist.png delete mode 100644 test/image/baselines/axes_category_categorylist_truncated_tails.png rename test/image/mocks/{axes_category_categorylist.json => axes_category_categoryarray.json} (96%) rename test/image/mocks/{axes_category_categorylist_truncated_tails.json => axes_category_categoryarray_truncated_tails.json} (78%) diff --git a/test/image/baselines/axes_category_categoryarray.png b/test/image/baselines/axes_category_categoryarray.png new file mode 100644 index 0000000000000000000000000000000000000000..288c3446f8c293438f2259790e32f740a2723b43 GIT binary patch literal 21284 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 Cxk<+W literal 0 HcmV?d00001 diff --git a/test/image/baselines/axes_category_categoryarray_truncated_tails.png b/test/image/baselines/axes_category_categoryarray_truncated_tails.png new file mode 100644 index 0000000000000000000000000000000000000000..9ffed02481caaa169ec6e5618012866a9c324ebc GIT binary patch literal 32078 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 E0ErLsYXATM diff --git a/test/image/baselines/axes_category_categorylist_truncated_tails.png b/test/image/baselines/axes_category_categorylist_truncated_tails.png deleted file mode 100644 index f7c0bbc461bf3cc002ae556fa16a578319e58d2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31892 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

%&dt5 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 NC)IRR-yOT?{U4RIED!(y diff --git a/test/image/mocks/axes_category_categorylist.json b/test/image/mocks/axes_category_categoryarray.json similarity index 96% rename from test/image/mocks/axes_category_categorylist.json rename to test/image/mocks/axes_category_categoryarray.json index 0ad9112cd4e..3d96a0d53f5 100644 --- a/test/image/mocks/axes_category_categorylist.json +++ b/test/image/mocks/axes_category_categoryarray.json @@ -20,7 +20,7 @@ } ], "layout": { - "title": "categorylist", + "title": "categoryarray", "xaxis": { "type": "category", "range": [ diff --git a/test/image/mocks/axes_category_categorylist_truncated_tails.json b/test/image/mocks/axes_category_categoryarray_truncated_tails.json similarity index 78% rename from test/image/mocks/axes_category_categorylist_truncated_tails.json rename to test/image/mocks/axes_category_categoryarray_truncated_tails.json index 782e9ba7934..70f0ed7bfd4 100644 --- a/test/image/mocks/axes_category_categorylist_truncated_tails.json +++ b/test/image/mocks/axes_category_categoryarray_truncated_tails.json @@ -4,7 +4,7 @@ "y": [15,11,12,13,14]} ], "layout": { - "title": "categorylist with truncated tails (y, q, k not plotted)", + "title": "categoryarray with truncated tails (y, q, k not plotted)", "xaxis": { "type": "category", "categoryorder": "array",