diff --git a/bower.json b/bower.json
index 0e9e03c554587..ff6f7b9c673a9 100644
--- a/bower.json
+++ b/bower.json
@@ -42,7 +42,7 @@
"leaflet": "0.7.3",
"lesshat": "~3.0.2",
"lodash": "~2.4.1",
- "moment": "~2.5.1",
+ "moment": "~2.9.0",
"moment-timezone": "~0.0.3",
"ng-clip": "~0.2.4",
"require-css": "~0.1.2",
diff --git a/src/kibana/components/agg_response/point_series/_ordered_date_axis.js b/src/kibana/components/agg_response/point_series/_ordered_date_axis.js
index 06e28aec27127..3fbd64517cfd1 100644
--- a/src/kibana/components/agg_response/point_series/_ordered_date_axis.js
+++ b/src/kibana/components/agg_response/point_series/_ordered_date_axis.js
@@ -1,31 +1,25 @@
define(function (require) {
return function PointSeriesOrderedDateAxis(timefilter) {
var moment = require('moment');
- var interval = require('utils/interval');
- return function orderedDateAxis(vis, table, chart) {
+ return function orderedDateAxis(vis, chart) {
var aspects = chart.aspects;
- var bounds = timefilter.getBounds();
- var format = interval.calculate(
- moment(bounds.min.valueOf()),
- moment(bounds.max.valueOf()),
- table.rows.length
- ).format;
+ var buckets = aspects.x.agg.buckets;
+ var format = buckets.getScaledDateFormat();
chart.xAxisFormatter = function (val) {
return moment(val).format(format);
};
- var xAggOutput = aspects.x.agg.write();
chart.ordered = {
date: true,
- interval: interval.toMs(xAggOutput.params.interval)
+ interval: buckets.getInterval(),
};
- if (vis.indexPattern.timeFieldName) {
- var timeBounds = timefilter.getBounds();
- chart.ordered.min = timeBounds.min.valueOf();
- chart.ordered.max = timeBounds.max.valueOf();
+ var bounds = buckets.getBounds();
+ if (bounds) {
+ chart.ordered.min = bounds.min;
+ chart.ordered.max = bounds.max;
}
};
};
diff --git a/src/kibana/components/agg_response/point_series/point_series.js b/src/kibana/components/agg_response/point_series/point_series.js
index 3e13fd4975152..eece0f4b22fab 100644
--- a/src/kibana/components/agg_response/point_series/point_series.js
+++ b/src/kibana/components/agg_response/point_series/point_series.js
@@ -20,7 +20,7 @@ define(function (require) {
var datedX = aspects.x.agg.type.ordered && aspects.x.agg.type.ordered.date;
if (datedX) {
- setupOrderedDateXAxis(vis, table, chart);
+ setupOrderedDateXAxis(vis, chart);
}
chart.series = getSeries(table.rows, chart);
diff --git a/src/kibana/components/agg_types/_agg_type.js b/src/kibana/components/agg_types/_agg_type.js
index 858f9fa13dc90..ae34b14905a15 100644
--- a/src/kibana/components/agg_types/_agg_type.js
+++ b/src/kibana/components/agg_types/_agg_type.js
@@ -102,6 +102,12 @@ define(function (require) {
* or undefined
*/
this.getResponseAggs = config.getResponseAggs || _.noop;
+
+ /**
+ * A function that will be called each time an aggConfig of this type
+ * is created, giving the agg type a chance to modify the agg config
+ */
+ this.decorateAggConfig = config.decorateAggConfig || null;
}
return AggType;
diff --git a/src/kibana/components/agg_types/buckets/_interval_options.js b/src/kibana/components/agg_types/buckets/_interval_options.js
index 19d0d991becec..2e2fd220113cc 100644
--- a/src/kibana/components/agg_types/buckets/_interval_options.js
+++ b/src/kibana/components/agg_types/buckets/_interval_options.js
@@ -1,6 +1,7 @@
define(function (require) {
return function IntervalOptionsService(Private) {
var moment = require('moment');
+ require('directives/input_whole_number');
// shorthand
var ms = function (type) { return moment.duration(1, type).asMilliseconds(); };
@@ -15,38 +16,31 @@ define(function (require) {
},
{
display: 'Second',
- val: 'second',
- ms: ms('second')
+ val: 'second'
},
{
display: 'Minute',
- val: 'minute',
- ms: ms('minute')
+ val: 'minute'
},
{
display: 'Hourly',
- val: 'hour',
- ms: ms('hour')
+ val: 'hour'
},
{
display: 'Daily',
- val: 'day',
- ms: ms('day')
+ val: 'day'
},
{
display: 'Weekly',
- val: 'week',
- ms: ms('week')
+ val: 'week'
},
{
display: 'Monthly',
- val: 'month',
- ms: ms('month')
+ val: 'month'
},
{
display: 'Yearly',
- val: 'year',
- ms: ms('year')
+ val: 'year'
}
];
};
diff --git a/src/kibana/components/agg_types/buckets/create_filter/date_histogram.js b/src/kibana/components/agg_types/buckets/create_filter/date_histogram.js
index f2b7f4ec89fd2..acbecec937102 100644
--- a/src/kibana/components/agg_types/buckets/create_filter/date_histogram.js
+++ b/src/kibana/components/agg_types/buckets/create_filter/date_histogram.js
@@ -1,18 +1,16 @@
define(function (require) {
- var moment = require('moment');
- var interval = require('utils/interval');
- var buildRangeFilter = require('components/filter_manager/lib/range');
-
return function createDateHistogramFilterProvider(Private) {
- var calculateInterval = Private(require('components/agg_types/param_types/_calculate_interval'));
- return function (aggConfig, key) {
- var result = calculateInterval(aggConfig);
- var date = moment(key).add(result.interval, 'ms');
+ var moment = require('moment');
+ var buildRangeFilter = require('components/filter_manager/lib/range');
+
+ return function (agg, key) {
+ var start = moment(key);
+ var interval = agg.buckets.getInterval();
- return buildRangeFilter(aggConfig.params.field, {
- gte: parseInt(key, 10),
- lte: date.valueOf()
- }, aggConfig.vis.indexPattern);
+ return buildRangeFilter(agg.params.field, {
+ gte: start.valueOf(),
+ lte: start.add(interval).subtract(1, 'ms').valueOf()
+ }, agg.vis.indexPattern);
};
};
diff --git a/src/kibana/components/agg_types/buckets/date_histogram.js b/src/kibana/components/agg_types/buckets/date_histogram.js
index 28419d9ee2807..c0b933b82510a 100644
--- a/src/kibana/components/agg_types/buckets/date_histogram.js
+++ b/src/kibana/components/agg_types/buckets/date_histogram.js
@@ -2,18 +2,13 @@ define(function (require) {
return function DateHistogramAggType(timefilter, config, Private) {
var _ = require('lodash');
var moment = require('moment');
- var interval = require('utils/interval');
var BucketAggType = Private(require('components/agg_types/buckets/_bucket_agg_type'));
- var calculateInterval = Private(require('components/agg_types/param_types/_calculate_interval'));
-
+ var TimeBuckets = Private(require('components/time_buckets/time_buckets'));
var createFilter = Private(require('components/agg_types/buckets/create_filter/date_histogram'));
- require('filters/field_type');
+ var tzOffset = moment().format('Z');
- var pickInterval = function (bounds, targetBuckets) {
- bounds || (bounds = timefilter.getBounds());
- return interval.calculate(bounds.min, bounds.max, targetBuckets);
- };
+ require('filters/field_type');
return new BucketAggType({
name: 'date_histogram',
@@ -21,26 +16,34 @@ define(function (require) {
ordered: {
date: true
},
- makeLabel: function (aggConfig) {
- var output = this.params.write(aggConfig);
+ makeLabel: function (agg) {
+ var output = this.params.write(agg);
var params = output.params;
-
- if (output.metricScaleText) return params.field + ' per ' + output.metricScaleText;
-
- var aggInterval = _.find(this.params.byName.interval.options, {
- ms: interval.toMs(params.interval)
- });
-
- if (aggInterval) return aggInterval.display + ' ' + params.field;
- else return params.field + ' per ' + interval.describe(params.interval);
+ return params.field + ' per ' + (output.metricScaleText || output.bucketInterval.description);
},
createFilter: createFilter,
+ decorateAggConfig: function () {
+ var buckets;
+ return {
+ buckets: {
+ configurable: true,
+ get: function () {
+ if (buckets) return buckets;
+
+ buckets = new TimeBuckets();
+ buckets.setInterval(_.get(this, ['params', 'interval']));
+ buckets.setBounds(timefilter.getActiveBounds());
+ return buckets;
+ }
+ }
+ };
+ },
params: [
{
name: 'field',
filterFieldTypes: 'date',
- default: function (aggConfig) {
- return aggConfig.vis.indexPattern.timeFieldName;
+ default: function (agg) {
+ return agg.vis.indexPattern.timeFieldName;
}
},
@@ -50,40 +53,35 @@ define(function (require) {
default: 'auto',
options: Private(require('components/agg_types/buckets/_interval_options')),
editor: require('text!components/agg_types/controls/interval.html'),
- write: function (aggConfig, output, locals) {
- // Get the selection
- var selection = aggConfig.params.interval;
-
- // If the selection isn't an object then it's going to be
- // a string so we need to make it look like an object.
- if (!_.isObject(selection)) {
- // custom selection
- selection = {
- display: selection,
- val: selection
- };
+ onRequest: function (agg) {
+ // flag that prevents us from clobbering on subsequest calls to write()
+ agg.buckets._sentToEs = true;
+ agg.buckets.setBounds(timefilter.getActiveBounds());
+ },
+ write: function (agg, output) {
+ if (!agg.buckets._sentToEs) {
+ agg.buckets.setBounds(timefilter.getActiveBounds());
}
- // If the selection is set to auto and the locals.renderBot
- // exists we need to blow up (for some unknown reason)
- if (selection.val === 'auto' && locals.renderBot) {
- throw new Error('not implemented');
- }
+ agg.buckets.setInterval(agg.params.interval);
- // Calculate the actual interval
- var result = calculateInterval(aggConfig);
+ var interval = agg.buckets.getInterval();
+ output.bucketInterval = interval;
+ output.params.interval = interval.expression;
+ output.params.pre_zone = tzOffset;
+ output.params.pre_zone_adjust_large_interval = true;
- // Set the output params interval along with the metric scale and
- // the metric scale test which is used in the label
- output.params.interval = result.interval + 'ms';
- if (result.metricScale) output.metricScale = result.metricScale;
- output.metricScaleText = result.description;
+ var scaleMetrics = interval.scaled && interval.scale < 1;
+ if (scaleMetrics) {
+ scaleMetrics = _.every(agg.vis.aggs.bySchemaGroup.metrics, function (agg) {
+ return agg.type.name === 'count' || agg.type.name === 'sum';
+ });
+ }
- // Since this is side effecting on output
- // we will return right here.
- // TODO: refactor so it's not side effecting so we can write tests
- // around it.
- return;
+ if (scaleMetrics) {
+ output.metricScale = interval.scale;
+ output.metricScaleText = interval.preScaled.description;
+ }
}
},
@@ -99,19 +97,23 @@ define(function (require) {
{
name: 'extended_bounds',
default: {},
- write: function (aggConfig, output) {
- var val = aggConfig.params.extended_bounds;
+ write: function (agg, output) {
+ var val = agg.params.extended_bounds;
if (val.min != null || val.max != null) {
output.params.extended_bounds = {
min: moment(val.min).valueOf(),
max: moment(val.max).valueOf()
};
- } else if (aggConfig.vis.indexPattern.timeFieldName) {
- var tfBounds = timefilter.getBounds();
+
+ return;
+ }
+
+ var bounds = timefilter.getActiveBounds();
+ if (bounds) {
output.params.extended_bounds = {
- min: moment(tfBounds.min).valueOf(),
- max: moment(tfBounds.max).valueOf()
+ min: moment(bounds.min).valueOf(),
+ max: moment(bounds.max).valueOf()
};
}
}
diff --git a/src/kibana/components/agg_types/controls/interval.html b/src/kibana/components/agg_types/controls/interval.html
index d7f56dfb7195d..7a417a39836e3 100644
--- a/src/kibana/components/agg_types/controls/interval.html
+++ b/src/kibana/components/agg_types/controls/interval.html
@@ -1,8 +1,17 @@
-
+
diff --git a/src/kibana/plugins/settings/sections/advanced/index.js b/src/kibana/plugins/settings/sections/advanced/index.js
index d9c85cd17f56c..d202021988072 100644
--- a/src/kibana/plugins/settings/sections/advanced/index.js
+++ b/src/kibana/plugins/settings/sections/advanced/index.js
@@ -22,8 +22,8 @@ define(function (require) {
var NORMAL_EDITOR = ['number', 'string', 'null', 'undefined'];
function getEditorType(conf) {
- if (_.contains(NORMAL_EDITOR, conf.type)) return 'normal';
if (_.contains(NAMED_EDITORS, conf.type)) return conf.type;
+ if (_.contains(NORMAL_EDITOR, conf.type)) return 'normal';
}
function isTypeComplex(conf) {
diff --git a/src/kibana/plugins/vis_types/controls/vislib_basic_options.html b/src/kibana/plugins/vis_types/controls/vislib_basic_options.html
index ea208be4efde2..4e31615dd8516 100644
--- a/src/kibana/plugins/vis_types/controls/vislib_basic_options.html
+++ b/src/kibana/plugins/vis_types/controls/vislib_basic_options.html
@@ -11,4 +11,10 @@
Show Legend
+
+
+
\ No newline at end of file
diff --git a/src/kibana/plugins/vis_types/vislib/area.js b/src/kibana/plugins/vis_types/vislib/area.js
index 99b12a7f61063..04b097804b1be 100644
--- a/src/kibana/plugins/vis_types/vislib/area.js
+++ b/src/kibana/plugins/vis_types/vislib/area.js
@@ -16,7 +16,8 @@ define(function (require) {
shareYAxis: true,
addTooltip: true,
addLegend: true,
- mode: 'stacked'
+ mode: 'stacked',
+ defaultYExtents: false
},
modes: ['stacked', 'overlap', 'percentage', 'wiggle', 'silhouette'],
editor: require('text!plugins/vis_types/vislib/editors/area.html')
diff --git a/src/kibana/plugins/vis_types/vislib/editors/histogram.html b/src/kibana/plugins/vis_types/vislib/editors/histogram.html
index 2e7ce2a23c176..74ded7c8eaad5 100644
--- a/src/kibana/plugins/vis_types/vislib/editors/histogram.html
+++ b/src/kibana/plugins/vis_types/vislib/editors/histogram.html
@@ -5,5 +5,4 @@
-
diff --git a/src/kibana/plugins/vis_types/vislib/histogram.js b/src/kibana/plugins/vis_types/vislib/histogram.js
index be99dc4b01ac8..16f88d8b5411e 100644
--- a/src/kibana/plugins/vis_types/vislib/histogram.js
+++ b/src/kibana/plugins/vis_types/vislib/histogram.js
@@ -14,7 +14,8 @@ define(function (require) {
shareYAxis: true,
addTooltip: true,
addLegend: true,
- mode: 'stacked'
+ mode: 'stacked',
+ defaultYExtents: false
},
modes: ['stacked', 'percentage', 'grouped'],
editor: require('text!plugins/vis_types/vislib/editors/histogram.html')
diff --git a/src/kibana/plugins/vis_types/vislib/line.js b/src/kibana/plugins/vis_types/vislib/line.js
index 9d42b94229728..3931c43861a36 100644
--- a/src/kibana/plugins/vis_types/vislib/line.js
+++ b/src/kibana/plugins/vis_types/vislib/line.js
@@ -14,6 +14,7 @@ define(function (require) {
shareYAxis: true,
addTooltip: true,
addLegend: true,
+ defaultYExtents: false
},
editor: require('text!plugins/vis_types/vislib/editors/basic.html')
},
diff --git a/src/kibana/services/timefilter.js b/src/kibana/services/timefilter.js
index cfbfcdae12508..f674eedcbfe2e 100644
--- a/src/kibana/services/timefilter.js
+++ b/src/kibana/services/timefilter.js
@@ -86,6 +86,10 @@ define(function (require) {
};
};
+ Timefilter.prototype.getActiveBounds = function () {
+ if (this.enabled) return this.getBounds();
+ };
+
return new Timefilter();
});
diff --git a/src/kibana/utils/_mixins_chainable.js b/src/kibana/utils/_mixins_chainable.js
index c84981a8d785e..b3b8ceb4277e7 100644
--- a/src/kibana/utils/_mixins_chainable.js
+++ b/src/kibana/utils/_mixins_chainable.js
@@ -247,6 +247,14 @@ define(function (require) {
});
return buckets;
- }
+ },
+
+ /**
+ * Shortcut for the simple version of _.deepGet
+ * @return {any}
+ */
+ get: function (obj, path) {
+ return _.deepGet(obj, path);
+ },
};
});
diff --git a/src/kibana/utils/datemath.js b/src/kibana/utils/datemath.js
index eee4db5dd33cb..1cb2da10e3039 100644
--- a/src/kibana/utils/datemath.js
+++ b/src/kibana/utils/datemath.js
@@ -2,8 +2,14 @@ define(function (require) {
var _ = require('lodash');
var moment = require('moment');
+ var units = ['y', 'M', 'w', 'd', 'h', 'm', 's'];
+ var unitsAsc = _.sortBy(units, function (unit) {
+ return moment.duration(1, unit).valueOf();
+ });
+ var unitsDesc = unitsAsc.reverse();
+
/* This is a simplified version of elasticsearch's date parser */
- var parse = function (text, roundUp) {
+ function parse(text, roundUp) {
if (!text) return undefined;
if (moment.isMoment(text)) return text;
if (_.isDate(text)) return moment(text);
@@ -33,11 +39,10 @@ define(function (require) {
}
return parseDateMath(mathString, time, roundUp);
- };
+ }
- var parseDateMath = function (mathString, time, roundUp) {
- var dateTime = time,
- spans = ['s', 'm', 'h', 'd', 'w', 'M', 'y'];
+ function parseDateMath(mathString, time, roundUp) {
+ var dateTime = time;
for (var i = 0; i < mathString.length;) {
var c = mathString.charAt(i++),
@@ -71,22 +76,26 @@ define(function (require) {
}
unit = mathString.charAt(i++);
- if (!_.contains(spans, unit)) {
+ if (!_.contains(units, unit)) {
return undefined;
} else {
if (type === 0) {
roundUp ? dateTime.endOf(unit) : dateTime.startOf(unit);
} else if (type === 1) {
- dateTime.add(unit, num);
+ dateTime.add(num, unit);
} else if (type === 2) {
- dateTime.subtract(unit, num);
+ dateTime.subtract(num, unit);
}
}
}
return dateTime;
- };
+ }
return {
- parse: parse
+ parse: parse,
+
+ units: Object.freeze(units),
+ unitsAsc: Object.freeze(unitsAsc),
+ unitsDesc: Object.freeze(unitsDesc)
};
});
\ No newline at end of file
diff --git a/src/kibana/utils/interval.js b/src/kibana/utils/interval.js
deleted file mode 100644
index e78b3ce01348c..0000000000000
--- a/src/kibana/utils/interval.js
+++ /dev/null
@@ -1,126 +0,0 @@
-define(function (require) {
- var _ = require('lodash');
- var moment = require('moment');
- var datemath = require('utils/datemath');
-
- require('directives/input_whole_number');
-
- /**
- * Calculate a graph interval
- *
- * from:: Moment object containing the start time
- * to:: Moment object containing the finish time
- * target:: Calculate to approximately this many bars
- * round:: Round to a nice value (default: true)
- *
- *
- */
- var calculate = function (from, to, target, round) {
- var rawInterval;
- round = round || true;
- from = datemath.parse(from).valueOf();
- to = datemath.parse(to, true).valueOf();
- rawInterval = ((to - from) / target);
- var rounded = roundInterval(rawInterval);
- if (!round) rounded.interval = rawInterval;
- return rounded;
- };
-
- // these are the rounding rules used by roundInterval()
- var roundingRules = [
- // bound, interval/desc, format
- ['500ms', '100 ms', 'hh:mm:ss.SSS'],
- ['5s', 'second', 'HH:mm:ss'],
- ['7.5s', '5 sec', 'HH:mm:ss'],
- ['15s', '10 sec', 'HH:mm:ss'],
- ['45s', '30 sec', 'HH:mm:ss'],
- ['3m', 'minute', 'HH:mm'],
- ['9m', '5 min', 'HH:mm'],
- ['20m', '10 min', 'HH:mm'],
- ['45m', '30 min', 'YYYY-MM-DD HH:mm'],
- ['2h', 'hour', 'YYYY-MM-DD HH:mm'],
- ['6h', '3 hours', 'YYYY-MM-DD HH:mm'],
- ['24h', '12 hours', 'YYYY-MM-DD HH:mm'],
- ['1w', '1 day', 'YYYY-MM-DD'],
- ['3w', '1 week', 'YYYY-MM-DD'],
- ['1y', '1 month', 'YYYY-MM'],
- [null, '1 year', 'YYYY'] // default
- ];
- var boundCache = {};
-
- /**
- * Round a millisecond interval to the closest "clean" interval,
- *
- * @param {ms} interval - interval in milliseconds
- * @return {[type]} [description]
- */
- var roundInterval = function (interval) {
- var rule = _.find(roundingRules, function (rule, i, rules) {
- var remaining = rules.length - i - 1;
- // no bound? then succeed
- if (!rule[0]) return true;
-
- var bound = boundCache[rule[0]] || (boundCache[rule[0]] = toMs(rule[0]));
- // check that we are below or equal to the bounds
- if (remaining > 1 && interval <= bound) return true;
- // the last rule before the default shouldn't include the default (which is the bound)
- if (remaining === 1 && interval < bound) return true;
- });
- return {
- description: rule[1],
- interval: toMs(rule[1]),
- format: rule[2]
- };
- };
-
- // map of moment's short/long unit ids and elasticsearch's long unit ids
- // to their value in milliseconds
- var vals = _.transform([
- ['ms', 'milliseconds', 'millisecond'],
- ['s', 'seconds', 'second', 'sec'],
- ['m', 'minutes', 'minute', 'min'],
- ['h', 'hours', 'hour'],
- ['d', 'days', 'day'],
- ['w', 'weeks', 'week'],
- ['M', 'months', 'month'],
- ['quarter'],
- ['y', 'years', 'year']
- ], function (vals, units) {
- var normal = moment.normalizeUnits(units[0]);
- var val = moment.duration(1, normal).asMilliseconds();
- [].concat(normal, units).forEach(function (unit) {
- vals[unit] = val;
- });
- }, {});
- // match any key from the vals object prececed by an optional number
- var parseRE = new RegExp('^(\\d+(?:\\.\\d*)?)?\\s*(' + _.keys(vals).join('|') + ')$');
-
- // Months and years are not handled here since they have sort of fuzzy values
- var describe = function (intervalString) {
- var totalMs = toMs(intervalString);
- var weeks = parseInt(totalMs / (1000 * 60 * 60 * 24 * 7));
- var days = parseInt((totalMs / (1000 * 60 * 60 * 24))) % 7;
- var hours = parseInt(totalMs / 3600000) % 24;
- var minutes = parseInt(totalMs / 60000) % 60;
- var seconds = parseInt(totalMs / 1000) % 60;
- var ms = totalMs % 1000;
-
- return ((weeks ? weeks + 'w ' : '') +
- (days ? days + 'd ' : '') +
- (hours ? hours + 'h ' : '') +
- (minutes ? minutes + 'm ' : '') +
- (seconds ? seconds + 's ' : '') +
- (ms ? ms + 'ms' : '')).trim();
- };
-
- var toMs = function (expr) {
- var match = expr.match(parseRE);
- if (match) return parseFloat(match[1] || 1) * vals[match[2]];
- };
-
- return {
- toMs: toMs,
- calculate: calculate,
- describe: describe
- };
-});
\ No newline at end of file
diff --git a/test/unit/fixtures/agg_resp/date_histogram.js b/test/unit/fixtures/agg_resp/date_histogram.js
new file mode 100644
index 0000000000000..3c66a87dd4bec
--- /dev/null
+++ b/test/unit/fixtures/agg_resp/date_histogram.js
@@ -0,0 +1,252 @@
+define(function () {
+ return {
+ 'took': 35,
+ 'timed_out': false,
+ '_shards': {
+ 'total': 2,
+ 'successful': 2,
+ 'failed': 0
+ },
+ 'hits': {
+ 'total': 32899,
+ 'max_score': 0,
+ 'hits': []
+ },
+ 'aggregations': {
+ '1': {
+ 'buckets': [
+ {
+ 'key_as_string': '2015-01-30T01:00:00.000Z',
+ 'key': 1422579600000,
+ 'doc_count': 18
+ },
+ {
+ 'key_as_string': '2015-01-30T02:00:00.000Z',
+ 'key': 1422583200000,
+ 'doc_count': 68
+ },
+ {
+ 'key_as_string': '2015-01-30T03:00:00.000Z',
+ 'key': 1422586800000,
+ 'doc_count': 146
+ },
+ {
+ 'key_as_string': '2015-01-30T04:00:00.000Z',
+ 'key': 1422590400000,
+ 'doc_count': 149
+ },
+ {
+ 'key_as_string': '2015-01-30T05:00:00.000Z',
+ 'key': 1422594000000,
+ 'doc_count': 363
+ },
+ {
+ 'key_as_string': '2015-01-30T06:00:00.000Z',
+ 'key': 1422597600000,
+ 'doc_count': 555
+ },
+ {
+ 'key_as_string': '2015-01-30T07:00:00.000Z',
+ 'key': 1422601200000,
+ 'doc_count': 878
+ },
+ {
+ 'key_as_string': '2015-01-30T08:00:00.000Z',
+ 'key': 1422604800000,
+ 'doc_count': 1133
+ },
+ {
+ 'key_as_string': '2015-01-30T09:00:00.000Z',
+ 'key': 1422608400000,
+ 'doc_count': 1438
+ },
+ {
+ 'key_as_string': '2015-01-30T10:00:00.000Z',
+ 'key': 1422612000000,
+ 'doc_count': 1719
+ },
+ {
+ 'key_as_string': '2015-01-30T11:00:00.000Z',
+ 'key': 1422615600000,
+ 'doc_count': 1813
+ },
+ {
+ 'key_as_string': '2015-01-30T12:00:00.000Z',
+ 'key': 1422619200000,
+ 'doc_count': 1790
+ },
+ {
+ 'key_as_string': '2015-01-30T13:00:00.000Z',
+ 'key': 1422622800000,
+ 'doc_count': 1582
+ },
+ {
+ 'key_as_string': '2015-01-30T14:00:00.000Z',
+ 'key': 1422626400000,
+ 'doc_count': 1439
+ },
+ {
+ 'key_as_string': '2015-01-30T15:00:00.000Z',
+ 'key': 1422630000000,
+ 'doc_count': 1154
+ },
+ {
+ 'key_as_string': '2015-01-30T16:00:00.000Z',
+ 'key': 1422633600000,
+ 'doc_count': 847
+ },
+ {
+ 'key_as_string': '2015-01-30T17:00:00.000Z',
+ 'key': 1422637200000,
+ 'doc_count': 588
+ },
+ {
+ 'key_as_string': '2015-01-30T18:00:00.000Z',
+ 'key': 1422640800000,
+ 'doc_count': 374
+ },
+ {
+ 'key_as_string': '2015-01-30T19:00:00.000Z',
+ 'key': 1422644400000,
+ 'doc_count': 152
+ },
+ {
+ 'key_as_string': '2015-01-30T20:00:00.000Z',
+ 'key': 1422648000000,
+ 'doc_count': 140
+ },
+ {
+ 'key_as_string': '2015-01-30T21:00:00.000Z',
+ 'key': 1422651600000,
+ 'doc_count': 73
+ },
+ {
+ 'key_as_string': '2015-01-30T22:00:00.000Z',
+ 'key': 1422655200000,
+ 'doc_count': 28
+ },
+ {
+ 'key_as_string': '2015-01-30T23:00:00.000Z',
+ 'key': 1422658800000,
+ 'doc_count': 9
+ },
+ {
+ 'key_as_string': '2015-01-31T00:00:00.000Z',
+ 'key': 1422662400000,
+ 'doc_count': 29
+ },
+ {
+ 'key_as_string': '2015-01-31T01:00:00.000Z',
+ 'key': 1422666000000,
+ 'doc_count': 38
+ },
+ {
+ 'key_as_string': '2015-01-31T02:00:00.000Z',
+ 'key': 1422669600000,
+ 'doc_count': 70
+ },
+ {
+ 'key_as_string': '2015-01-31T03:00:00.000Z',
+ 'key': 1422673200000,
+ 'doc_count': 136
+ },
+ {
+ 'key_as_string': '2015-01-31T04:00:00.000Z',
+ 'key': 1422676800000,
+ 'doc_count': 173
+ },
+ {
+ 'key_as_string': '2015-01-31T05:00:00.000Z',
+ 'key': 1422680400000,
+ 'doc_count': 370
+ },
+ {
+ 'key_as_string': '2015-01-31T06:00:00.000Z',
+ 'key': 1422684000000,
+ 'doc_count': 545
+ },
+ {
+ 'key_as_string': '2015-01-31T07:00:00.000Z',
+ 'key': 1422687600000,
+ 'doc_count': 845
+ },
+ {
+ 'key_as_string': '2015-01-31T08:00:00.000Z',
+ 'key': 1422691200000,
+ 'doc_count': 1070
+ },
+ {
+ 'key_as_string': '2015-01-31T09:00:00.000Z',
+ 'key': 1422694800000,
+ 'doc_count': 1419
+ },
+ {
+ 'key_as_string': '2015-01-31T10:00:00.000Z',
+ 'key': 1422698400000,
+ 'doc_count': 1725
+ },
+ {
+ 'key_as_string': '2015-01-31T11:00:00.000Z',
+ 'key': 1422702000000,
+ 'doc_count': 1801
+ },
+ {
+ 'key_as_string': '2015-01-31T12:00:00.000Z',
+ 'key': 1422705600000,
+ 'doc_count': 1823
+ },
+ {
+ 'key_as_string': '2015-01-31T13:00:00.000Z',
+ 'key': 1422709200000,
+ 'doc_count': 1657
+ },
+ {
+ 'key_as_string': '2015-01-31T14:00:00.000Z',
+ 'key': 1422712800000,
+ 'doc_count': 1454
+ },
+ {
+ 'key_as_string': '2015-01-31T15:00:00.000Z',
+ 'key': 1422716400000,
+ 'doc_count': 1131
+ },
+ {
+ 'key_as_string': '2015-01-31T16:00:00.000Z',
+ 'key': 1422720000000,
+ 'doc_count': 810
+ },
+ {
+ 'key_as_string': '2015-01-31T17:00:00.000Z',
+ 'key': 1422723600000,
+ 'doc_count': 583
+ },
+ {
+ 'key_as_string': '2015-01-31T18:00:00.000Z',
+ 'key': 1422727200000,
+ 'doc_count': 384
+ },
+ {
+ 'key_as_string': '2015-01-31T19:00:00.000Z',
+ 'key': 1422730800000,
+ 'doc_count': 165
+ },
+ {
+ 'key_as_string': '2015-01-31T20:00:00.000Z',
+ 'key': 1422734400000,
+ 'doc_count': 135
+ },
+ {
+ 'key_as_string': '2015-01-31T21:00:00.000Z',
+ 'key': 1422738000000,
+ 'doc_count': 72
+ },
+ {
+ 'key_as_string': '2015-01-31T22:00:00.000Z',
+ 'key': 1422741600000,
+ 'doc_count': 8
+ }
+ ]
+ }
+ }
+ };
+});
\ No newline at end of file
diff --git a/test/unit/specs/components/agg_response/point_series/_ordered_date_axis.js b/test/unit/specs/components/agg_response/point_series/_ordered_date_axis.js
index 1ebbd0a7d0525..d36d2fb44f6a7 100644
--- a/test/unit/specs/components/agg_response/point_series/_ordered_date_axis.js
+++ b/test/unit/specs/components/agg_response/point_series/_ordered_date_axis.js
@@ -2,7 +2,7 @@ define(function (require) {
return ['orderedDateAxis', function () {
var moment = require('moment');
var _ = require('lodash');
- var interval = require('utils/interval');
+ var sinon = require('test_utils/auto_release_sinon');
var baseArgs = {
vis: {
@@ -10,14 +10,15 @@ define(function (require) {
timeFieldName: '@timestamp'
}
},
- table: {
- rows: new Array(50)
- },
chart: {
aspects: {
x: {
agg: {
- write: _.constant({ params: { interval: '10m' } })
+ buckets: {
+ getScaledDateFormat: _.constant('hh:mm:ss'),
+ getInterval: _.constant(moment.duration(15, 'm')),
+ getBounds: _.constant({ min: moment().subtract(15, 'm'), max: moment() })
+ }
}
}
}
@@ -34,7 +35,7 @@ define(function (require) {
describe('xAxisFormatter', function () {
it('sets the xAxisFormatter', function () {
var args = _.cloneDeep(baseArgs);
- orderedDateAxis(args.vis, args.table, args.chart);
+ orderedDateAxis(args.vis, args.chart);
expect(args.chart).to.have.property('xAxisFormatter');
expect(args.chart.xAxisFormatter).to.be.a('function');
@@ -42,7 +43,7 @@ define(function (require) {
it('formats values using moment, and returns strings', function () {
var args = _.cloneDeep(baseArgs);
- orderedDateAxis(args.vis, args.table, args.chart);
+ orderedDateAxis(args.vis, args.chart);
var val = '2014-08-06T12:34:01';
expect(args.chart.xAxisFormatter(val))
@@ -53,7 +54,7 @@ define(function (require) {
describe('ordered object', function () {
it('sets date: true', function () {
var args = _.cloneDeep(baseArgs);
- orderedDateAxis(args.vis, args.table, args.chart);
+ orderedDateAxis(args.vis, args.chart);
expect(args.chart)
.to.have.property('ordered');
@@ -62,26 +63,26 @@ define(function (require) {
.to.have.property('date', true);
});
- it('sets interval after parsing the output of the x.agg', function () {
+ it('relies on agg.buckets for the interval', function () {
var args = _.cloneDeep(baseArgs);
- orderedDateAxis(args.vis, args.table, args.chart);
- expect(args.chart.ordered.interval).to.be(interval.toMs('10m'));
+ var spy = sinon.spy(args.chart.aspects.x.agg.buckets, 'getInterval');
+ orderedDateAxis(args.vis, args.chart);
+ expect(spy).to.have.property('callCount', 1);
});
- it('sets the min and max when the indexPattern has a timeField', function () {
+ it('sets the min/max when the buckets are bounded', function () {
var args = _.cloneDeep(baseArgs);
- orderedDateAxis(args.vis, args.table, args.chart);
-
- expect(args.chart.ordered.min).to.be.a('number');
- expect(args.chart.ordered.max).to.be.a('number');
-
- args = _.cloneDeep(baseArgs);
- delete args.vis.indexPattern.timeFieldName;
- orderedDateAxis(args.vis, args.table, args.chart);
+ orderedDateAxis(args.vis, args.chart);
+ expect(moment.isMoment(args.chart.ordered.min)).to.be(true);
+ expect(moment.isMoment(args.chart.ordered.max)).to.be(true);
+ });
- expect(args.chart.ordered)
- .to.not.have.property('min')
- .and.not.have.property('max');
+ it('does not set the min/max when the buckets are unbounded', function () {
+ var args = _.cloneDeep(baseArgs);
+ args.chart.aspects.x.agg.buckets.getBounds = _.constant();
+ orderedDateAxis(args.vis, args.chart);
+ expect(args.chart.ordered).to.not.have.property('min');
+ expect(args.chart.ordered).to.not.have.property('max');
});
});
}];
diff --git a/test/unit/specs/components/agg_types/buckets/_date_histogram.js b/test/unit/specs/components/agg_types/buckets/_date_histogram.js
index 0c92c2b3fc81a..1061c38afae03 100644
--- a/test/unit/specs/components/agg_types/buckets/_date_histogram.js
+++ b/test/unit/specs/components/agg_types/buckets/_date_histogram.js
@@ -5,50 +5,99 @@ define(function (require) {
describe('params', function () {
var paramWriter;
+ var aggTypes;
+ var AggConfig;
+ var setTimeBounds;
beforeEach(module('kibana'));
- beforeEach(inject(function (Private) {
+ beforeEach(inject(function (Private, $injector) {
var AggParamWriter = Private(require('test_utils/agg_param_writer'));
+ var timefilter = $injector.get('timefilter');
+
+ aggTypes = Private(require('components/agg_types/index'));
+ AggConfig = Private(require('components/vis/_agg_config'));
+
paramWriter = new AggParamWriter({ aggType: 'date_histogram' });
+
+ var now = moment();
+ setTimeBounds = function (n, units) {
+ timefilter.enabled = true;
+ timefilter.getBounds = _.constant({
+ min: now.clone().subtract(n, units),
+ max: now.clone()
+ });
+ };
}));
describe('interval', function () {
- it('should accept a valid interval', function () {
+ it('accepts a valid interval', function () {
var output = paramWriter.write({ interval: 'day' });
- expect(output.params).to.have.property('interval', '86400000ms');
+ expect(output.params).to.have.property('interval', '1d');
});
- it('should throw an error if an invalid interval is given', function () {
- expect(function () {
- paramWriter.write({ interval: 'foo' });
- }).to.throwError();
+ it('ignores invalid intervals', function () {
+ var output = paramWriter.write({ interval: 'foo' });
+ expect(output.params).to.have.property('interval', '0ms');
});
- it('should automatically pick an interval', function () {
+ it('automatically picks an interval', function () {
+ setTimeBounds(15, 'minutes');
var output = paramWriter.write({ interval: 'auto' });
- expect(output.params.interval).to.be('30000ms');
- expect(output.metricScaleText).to.be('30 sec');
+ expect(output.params.interval).to.be('30s');
});
- it('should scale if there are too many buckets', function () {
+ it('scales up the interval if it will make too many buckets', function () {
+ setTimeBounds(30, 'minutes');
var output = paramWriter.write({ interval: 'second' });
- expect(output.params.interval).to.be('10000ms');
+ expect(output.params.interval).to.be('10s');
expect(output.metricScaleText).to.be('second');
expect(output.metricScale).to.be(0.1);
});
- it('should not scale if there are too many buckets and the metric is not sum or count', function () {
- paramWriter.vis.aggs.bySchemaGroup.metrics[0].type.name = 'average';
- var output = paramWriter.write({ interval: 'second' });
- expect(output).to.not.have.property('metricScale');
-
- paramWriter.vis.aggs.bySchemaGroup.metrics[0].type.name = 'max';
- output = paramWriter.write({ interval: 'second' });
- expect(output).to.not.have.property('metricScale');
+ it('does not scale down the interval', function () {
+ setTimeBounds(1, 'minutes');
+ var output = paramWriter.write({ interval: 'hour' });
+ expect(output.params.interval).to.be('1h');
+ expect(output.metricScaleText).to.be(undefined);
+ expect(output.metricScale).to.be(undefined);
+ });
- paramWriter.vis.aggs.bySchemaGroup.metrics[0].type.name = 'sum';
- output = paramWriter.write({ interval: 'second' });
- expect(output).to.have.property('metricScale');
+ describe('only scales when all metrics are sum or count', function () {
+ var tests = [
+ [ false, 'avg', 'count', 'sum' ],
+ [ true, 'count', 'sum' ],
+ [ false, 'count', 'cardinality' ]
+ ];
+
+ tests.forEach(function (test) {
+ var should = test.shift();
+ var typeNames = test.slice();
+
+ it(typeNames.join(', ') + ' should ' + (should ? '' : 'not') + ' scale', function () {
+ setTimeBounds(1, 'year');
+
+ var vis = paramWriter.vis;
+ vis.aggs.splice(0);
+
+ var histoConfig = new AggConfig(vis, {
+ type: aggTypes.byName.date_histogram,
+ schema: 'segment',
+ params: { interval: 'second' }
+ });
+
+ vis.aggs.push(histoConfig);
+
+ typeNames.forEach(function (type) {
+ vis.aggs.push(new AggConfig(vis, {
+ type: aggTypes.byName[type],
+ schema: 'metric'
+ }));
+ });
+
+ var output = histoConfig.write();
+ expect(_.has(output, 'metricScale')).to.be(should);
+ });
+ });
});
});
diff --git a/test/unit/specs/components/agg_types/buckets/create_filter/date_histogram.js b/test/unit/specs/components/agg_types/buckets/create_filter/date_histogram.js
index dca71f349ab1d..4fb3901b785fc 100644
--- a/test/unit/specs/components/agg_types/buckets/create_filter/date_histogram.js
+++ b/test/unit/specs/components/agg_types/buckets/create_filter/date_histogram.js
@@ -1,55 +1,100 @@
define(function (require) {
- var _ = require('lodash');
- var moment = require('moment');
describe('AggConfig Filters', function () {
- describe('date_historgram', function () {
- var AggConfig;
- var indexPattern;
- var Vis;
- var createFilter;
+ describe('date_histogram', function () {
+ var _ = require('lodash');
+ var moment = require('moment');
+ var sinon = require('test_utils/auto_release_sinon');
+ var aggResp = require('fixtures/agg_resp/date_histogram');
+
+ var vis;
+ var agg;
+ var field;
+ var filter;
+ var bucketKey;
+ var bucketStart;
+ var getIntervalStub;
+ var intervalOptions;
+
+ var init;
beforeEach(module('kibana'));
- beforeEach(inject(function (Private) {
- Vis = Private(require('components/vis/vis'));
- AggConfig = Private(require('components/vis/_agg_config'));
- indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
- createFilter = Private(require('components/agg_types/buckets/create_filter/date_histogram'));
- }));
+ beforeEach(inject(function (Private, $injector) {
+ var Vis = Private(require('components/vis/vis'));
+ var indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
+ var createFilter = Private(require('components/agg_types/buckets/create_filter/date_histogram'));
+ var TimeBuckets = Private(require('components/time_buckets/time_buckets'));
+ intervalOptions = Private(require('components/agg_types/buckets/_interval_options'));
- var runTest = function (intervalString, interval) {
- it('should return a range filter for ' + intervalString, function () {
- var vis = new Vis(indexPattern, {
+ init = function (interval, duration) {
+ interval = interval || 'auto';
+ duration = duration || moment.duration(15, 'minutes');
+ field = _.sample(indexPattern.fields.byType.date);
+ vis = new Vis(indexPattern, {
type: 'histogram',
aggs: [
{
type: 'date_histogram',
schema: 'segment',
- params: { field: '@timestamp', interval: intervalString }
+ params: { field: field.name, interval: interval }
}
]
});
- var aggConfig = vis.aggs.byTypeName.date_histogram[0];
- var date = moment('2014-01-01 12:00');
- var max = date.clone().add(interval, 'ms');
- var filter = createFilter(aggConfig, date.valueOf());
- expect(filter).to.have.property('range');
- expect(filter).to.have.property('meta');
- expect(filter.range).to.have.property('@timestamp');
- expect(filter.range['@timestamp']).to.have.property('gte', date.valueOf());
- expect(filter.range['@timestamp']).to.have.property('lte', max.valueOf());
- expect(filter.meta).to.have.property('index', indexPattern.id);
- });
- };
- runTest('auto', 30000);
- runTest('second', 10000);
- runTest('minute', 60000);
- runTest('hour', 3600000);
- runTest('day', 86400000);
- runTest('week', 604800000);
- runTest('month', 2592000000);
- runTest('year', 31536000000);
+ agg = vis.aggs[0];
+ bucketKey = _.sample(aggResp.aggregations['1'].buckets).key;
+ bucketStart = moment(bucketKey);
+
+ var timePad = moment.duration(duration / 2);
+ agg.buckets.setBounds({
+ min: bucketStart.clone().subtract(timePad),
+ max: bucketStart.clone().add(timePad),
+ });
+ agg.buckets.setInterval(interval);
+
+ filter = createFilter(agg, bucketKey);
+ };
+ }));
+
+ it('creates a valid range filter', function () {
+ init();
+
+ expect(filter).to.have.property('range');
+ expect(filter.range).to.have.property(field.name);
+ var fieldParams = filter.range[field.name];
+ expect(fieldParams).to.have.property('gte');
+ expect(fieldParams.gte).to.be.a('number');
+
+ expect(fieldParams).to.have.property('lte');
+ expect(fieldParams.lte).to.be.a('number');
+
+ expect(fieldParams.gte).to.be.lessThan(fieldParams.lte);
+
+ expect(filter).to.have.property('meta');
+ expect(filter.meta).to.have.property('index', vis.indexPattern.id);
+ });
+
+
+ it('extends the filter edge to 1ms before the next bucket for all interval options', function () {
+ intervalOptions.forEach(function (option) {
+ var duration;
+ if (moment(1, option.val).isValid()) {
+ duration = moment.duration(10, option.val);
+
+ if (+duration < 10) {
+ throw new Error('unable to create interval for ' + option.val);
+ }
+ }
+
+ init(option.val, duration);
+
+ var interval = agg.buckets.getInterval();
+ var params = filter.range[field.name];
+
+ expect(params.gte).to.be(+bucketStart);
+ expect(params.lte).to.be(+bucketStart.clone().add(interval).subtract(1, 'ms'));
+ });
+ });
});
});
});
diff --git a/test/unit/specs/plugins/vis_types/vislib/_renderbot.js b/test/unit/specs/plugins/vis_types/vislib/_renderbot.js
index e7ccdc20dfcda..4cabe77f9f9cd 100644
--- a/test/unit/specs/plugins/vis_types/vislib/_renderbot.js
+++ b/test/unit/specs/plugins/vis_types/vislib/_renderbot.js
@@ -24,7 +24,6 @@ define(function (require) {
Renderbot = Private(require('plugins/vis_types/_renderbot'));
VislibRenderbot = Private(require('plugins/vis_types/vislib/_vislib_renderbot'));
normalizeChartData = Private(require('components/agg_response/index'));
-
});
}
@@ -85,7 +84,7 @@ define(function (require) {
}
}, mockVisType)
};
- var $el = 'element';
+ var $el = $('testing
');
var createVisSpy;
var getParamsStub;
var renderbot;
diff --git a/test/unit/specs/utils/interval.js b/test/unit/specs/utils/interval.js
deleted file mode 100644
index bf5e4b2d47ddd..0000000000000
--- a/test/unit/specs/utils/interval.js
+++ /dev/null
@@ -1,138 +0,0 @@
-define(function (require) {
- var interval = require('utils/interval');
- var moment = require('moment');
- var _ = require('lodash');
- var sinon = require('sinon/sinon');
-
- describe('interval', function () {
-
- describe('toMs', function () {
- it('return the number of milliseconds represented by the string', function () {
- expect(interval.toMs('1ms')).to.be(1);
- expect(interval.toMs('1s')).to.be(1000);
- expect(interval.toMs('1m')).to.be(60000);
- expect(interval.toMs('1h')).to.be(3600000);
- expect(interval.toMs('1d')).to.be(86400000);
- expect(interval.toMs('1w')).to.be(604800000);
- expect(interval.toMs('1M')).to.be(2592000000); // actually 30d
- expect(interval.toMs('1y')).to.be(31536000000); // 1000*60*60*24*365
- });
- });
-
- describe('description', function () {
- it('returns a readable description for an interval', function () {
- expect(interval.describe('1s')).to.be('1s');
- expect(interval.describe('1m')).to.be('1m');
- expect(interval.describe('1h')).to.be('1h');
- expect(interval.describe('1d')).to.be('1d');
- expect(interval.describe('1w')).to.be('1w');
-
- expect(interval.describe('2w')).to.be('2w');
- expect(interval.describe('86400000ms')).to.be('1d');
- expect(interval.describe('86400001ms')).to.be('1d 1ms');
- expect(interval.describe('90000000ms')).to.be('1d 1h');
- expect(interval.describe('90060000ms')).to.be('1d 1h 1m');
- expect(interval.describe('90061000ms')).to.be('1d 1h 1m 1s');
- expect(interval.describe('90061300ms')).to.be('1d 1h 1m 1s 300ms');
- });
- });
-
- describe('rounding', function () {
- var mmnt, date, string, now, clock, then;
-
- beforeEach(function () {
- clock = sinon.useFakeTimers();
- now = moment();
- then = moment();
- });
-
- afterEach(function () {
- clock.restore();
- });
-
- it('should calculate an appropriate interval for 10s', function () {
- var _t = then.subtract(10, 'seconds');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('100ms'));
- });
-
- it('should calculate an appropriate interval for 1m', function () {
- var _t = then.subtract(1, 'minute');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1s'));
- });
-
- it('should calculate an appropriate interval for 10m', function () {
- var _t = then.subtract(10, 'minutes');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('5s'));
- });
-
- it('should calculate an appropriate interval for 15m', function () {
- var _t = then.subtract(15, 'minutes');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('10s'));
- });
-
- it('should calculate an appropriate interval for 1h', function () {
- var _t = then.subtract(1, 'hour');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('30s'));
- });
-
- it('should calculate an appropriate interval for 90m', function () {
- var _t = then.subtract(90, 'minutes');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1m'));
- });
-
- it('should calculate an appropriate interval for 6h', function () {
- var _t = then.subtract(6, 'hours');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('5m'));
- });
-
- it('should calculate an appropriate interval for 24h', function () {
- var _t = then.subtract(24, 'hours');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('10m'));
- });
-
- it('should calculate an appropriate interval for 3d', function () {
- var _t = then.subtract(3, 'days');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('30m'));
- });
-
- it('should calculate an appropriate interval for 1w', function () {
- var _t = then.subtract(1, 'week');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1h'));
- });
-
- it('should calculate an appropriate interval for 2w', function () {
- var _t = then.subtract(2, 'weeks');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('3h'));
- });
-
- it('should calculate an appropriate interval for 1M', function () {
- var _t = then.subtract(1, 'month');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('12h'));
- });
-
- it('should calculate an appropriate interval for 4M', function () {
- var _t = then.subtract(4, 'months');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1d'));
- });
-
- it('should calculate an appropriate interval for 2y', function () {
- var _t = then.subtract(2, 'years');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1w'));
- });
-
- it('should calculate an appropriate interval for 25y', function () {
- var _t = then.subtract(25, 'years');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1M'));
- });
-
-
- it('should calculate an appropriate interval for a 100y', function () {
- var _t = then.subtract(100, 'years');
- expect(interval.calculate(_t, now, 100).interval).to.be(interval.toMs('1y'));
- });
-
- });
-
- });
-
-});
\ No newline at end of file
diff --git a/test/unit/specs/vislib/components/tooltip/_positioning.js b/test/unit/specs/vislib/components/tooltip/_positioning.js
index f6a1b1709a573..bc087ecad9df8 100644
--- a/test/unit/specs/vislib/components/tooltip/_positioning.js
+++ b/test/unit/specs/vislib/components/tooltip/_positioning.js
@@ -70,7 +70,7 @@ define(function (require) {
var w = sinon.spy($.fn, 'outerWidth');
var h = sinon.spy($.fn, 'outerHeight');
- posTT.getTtSize($tooltip, $sizer);
+ posTT.getTtSize($tooltip.html(), $sizer);
[w, h].forEach(function (spy) {
expect(spy).to.have.property('callCount', 1);
@@ -84,7 +84,7 @@ define(function (require) {
describe('getBasePosition()', function () {
it('calculates the offset values for the four positions', function () {
- var size = posTT.getTtSize($tooltip, $sizer);
+ var size = posTT.getTtSize($tooltip.html(), $sizer);
var pos = posTT.getBasePosition(size, makeEvent());
positions.forEach(function (p) {
@@ -114,7 +114,7 @@ define(function (require) {
// size the tooltip very small so it won't collide with the edges
$tooltip.css({ width: 15, height: 15 });
$sizer.css({ width: 15, height: 15 });
- var size = posTT.getTtSize($tooltip, $sizer);
+ var size = posTT.getTtSize($tooltip.html(), $sizer);
expect(size).to.have.property('width', 15);
expect(size).to.have.property('height', 15);
@@ -131,7 +131,7 @@ define(function (require) {
});
it('identifies an overflow with a positive value in that direction', function () {
- var size = posTT.getTtSize($tooltip, $sizer);
+ var size = posTT.getTtSize($tooltip.html(), $sizer);
// position the element based on a mouse that is in the bottom right hand courner of the chart
var pos = posTT.getBasePosition(size, makeEvent(0.99, 0.99));
diff --git a/test/unit/specs/vislib/fixture/mock_data/date_histogram/_series_neg.js b/test/unit/specs/vislib/fixture/mock_data/date_histogram/_series_neg.js
new file mode 100644
index 0000000000000..746c011778d18
--- /dev/null
+++ b/test/unit/specs/vislib/fixture/mock_data/date_histogram/_series_neg.js
@@ -0,0 +1,152 @@
+define(function (require) {
+ var moment = require('moment');
+
+ return {
+ 'label': '',
+ 'xAxisLabel': '@timestamp per 30 sec',
+ 'ordered': {
+ 'date': true,
+ 'min': 1411761457636,
+ 'max': 1411762357636,
+ 'interval': 30000
+ },
+ 'yAxisLabel': 'Count of documents',
+ 'series': [
+ {
+ 'values': [
+ {
+ 'x': 1411761450000,
+ 'y': -41
+ },
+ {
+ 'x': 1411761480000,
+ 'y': -18
+ },
+ {
+ 'x': 1411761510000,
+ 'y': -22
+ },
+ {
+ 'x': 1411761540000,
+ 'y': -17
+ },
+ {
+ 'x': 1411761570000,
+ 'y': -17
+ },
+ {
+ 'x': 1411761600000,
+ 'y': -21
+ },
+ {
+ 'x': 1411761630000,
+ 'y': -16
+ },
+ {
+ 'x': 1411761660000,
+ 'y': -17
+ },
+ {
+ 'x': 1411761690000,
+ 'y': -15
+ },
+ {
+ 'x': 1411761720000,
+ 'y': -19
+ },
+ {
+ 'x': 1411761750000,
+ 'y': -11
+ },
+ {
+ 'x': 1411761780000,
+ 'y': -13
+ },
+ {
+ 'x': 1411761810000,
+ 'y': -24
+ },
+ {
+ 'x': 1411761840000,
+ 'y': -20
+ },
+ {
+ 'x': 1411761870000,
+ 'y': -20
+ },
+ {
+ 'x': 1411761900000,
+ 'y': -21
+ },
+ {
+ 'x': 1411761930000,
+ 'y': -17
+ },
+ {
+ 'x': 1411761960000,
+ 'y': -20
+ },
+ {
+ 'x': 1411761990000,
+ 'y': -13
+ },
+ {
+ 'x': 1411762020000,
+ 'y': -14
+ },
+ {
+ 'x': 1411762050000,
+ 'y': -25
+ },
+ {
+ 'x': 1411762080000,
+ 'y': -17
+ },
+ {
+ 'x': 1411762110000,
+ 'y': -14
+ },
+ {
+ 'x': 1411762140000,
+ 'y': -22
+ },
+ {
+ 'x': 1411762170000,
+ 'y': -14
+ },
+ {
+ 'x': 1411762200000,
+ 'y': -19
+ },
+ {
+ 'x': 1411762230000,
+ 'y': -22
+ },
+ {
+ 'x': 1411762260000,
+ 'y': -17
+ },
+ {
+ 'x': 1411762290000,
+ 'y': -8
+ },
+ {
+ 'x': 1411762320000,
+ 'y': -15
+ },
+ {
+ 'x': 1411762350000,
+ 'y': -4
+ }
+ ]
+ }
+ ],
+ 'hits': 533,
+ 'xAxisFormatter': function (thing) {
+ return moment(thing);
+ },
+ 'tooltipFormatter': function (d) {
+ return d;
+ }
+ };
+});
diff --git a/test/unit/specs/vislib/fixture/mock_data/date_histogram/_series_pos_neg.js b/test/unit/specs/vislib/fixture/mock_data/date_histogram/_series_pos_neg.js
new file mode 100644
index 0000000000000..d514b93c31cd2
--- /dev/null
+++ b/test/unit/specs/vislib/fixture/mock_data/date_histogram/_series_pos_neg.js
@@ -0,0 +1,152 @@
+define(function (require) {
+ var moment = require('moment');
+
+ return {
+ 'label': '',
+ 'xAxisLabel': '@timestamp per 30 sec',
+ 'ordered': {
+ 'date': true,
+ 'min': 1411761457636,
+ 'max': 1411762357636,
+ 'interval': 30000
+ },
+ 'yAxisLabel': 'Count of documents',
+ 'series': [
+ {
+ 'values': [
+ {
+ 'x': 1411761450000,
+ 'y': 41
+ },
+ {
+ 'x': 1411761480000,
+ 'y': 18
+ },
+ {
+ 'x': 1411761510000,
+ 'y': -22
+ },
+ {
+ 'x': 1411761540000,
+ 'y': -17
+ },
+ {
+ 'x': 1411761570000,
+ 'y': -17
+ },
+ {
+ 'x': 1411761600000,
+ 'y': -21
+ },
+ {
+ 'x': 1411761630000,
+ 'y': -16
+ },
+ {
+ 'x': 1411761660000,
+ 'y': 17
+ },
+ {
+ 'x': 1411761690000,
+ 'y': 15
+ },
+ {
+ 'x': 1411761720000,
+ 'y': 19
+ },
+ {
+ 'x': 1411761750000,
+ 'y': 11
+ },
+ {
+ 'x': 1411761780000,
+ 'y': -13
+ },
+ {
+ 'x': 1411761810000,
+ 'y': -24
+ },
+ {
+ 'x': 1411761840000,
+ 'y': -20
+ },
+ {
+ 'x': 1411761870000,
+ 'y': -20
+ },
+ {
+ 'x': 1411761900000,
+ 'y': -21
+ },
+ {
+ 'x': 1411761930000,
+ 'y': 17
+ },
+ {
+ 'x': 1411761960000,
+ 'y': 20
+ },
+ {
+ 'x': 1411761990000,
+ 'y': -13
+ },
+ {
+ 'x': 1411762020000,
+ 'y': -14
+ },
+ {
+ 'x': 1411762050000,
+ 'y': 25
+ },
+ {
+ 'x': 1411762080000,
+ 'y': -17
+ },
+ {
+ 'x': 1411762110000,
+ 'y': -14
+ },
+ {
+ 'x': 1411762140000,
+ 'y': -22
+ },
+ {
+ 'x': 1411762170000,
+ 'y': -14
+ },
+ {
+ 'x': 1411762200000,
+ 'y': 19
+ },
+ {
+ 'x': 1411762230000,
+ 'y': 22
+ },
+ {
+ 'x': 1411762260000,
+ 'y': 17
+ },
+ {
+ 'x': 1411762290000,
+ 'y': 8
+ },
+ {
+ 'x': 1411762320000,
+ 'y': -15
+ },
+ {
+ 'x': 1411762350000,
+ 'y': -4
+ }
+ ]
+ }
+ ],
+ 'hits': 533,
+ 'xAxisFormatter': function (thing) {
+ return moment(thing);
+ },
+ 'tooltipFormatter': function (d) {
+ return d;
+ }
+ };
+});
diff --git a/test/unit/specs/vislib/lib/data.js b/test/unit/specs/vislib/lib/data.js
index c28437febfa4b..516a5a80e7892 100644
--- a/test/unit/specs/vislib/lib/data.js
+++ b/test/unit/specs/vislib/lib/data.js
@@ -230,20 +230,68 @@ define(function (require) {
colOut = colIn.flatten();
});
- it('should return an array of arrays', function () {
- expect(_.isArray(serOut)).to.be(true);
+ it('should return an array of value objects from every series', function () {
+ expect(serOut.every(_.isObject)).to.be(true);
});
- it('should return array length 3', function () {
- expect(serOut[0][0].length).to.be(3);
+ function testLength(inputData) {
+ return function () {
+ var data = new dataFactory(inputData, {});
+ var len = _.reduce(data.chartData(), function (sum, chart) {
+ return sum + chart.series.reduce(function (sum, series) {
+ return sum + series.values.length;
+ }, 0);
+ }, 0);
+
+ expect(data.flatten()).to.have.length(len);
+ };
+ }
+
+ it('should return all points from every series', testLength(seriesData));
+ it('should return all points from every series', testLength(rowsData));
+ it('should return all points from every series', testLength(colsData));
+ });
+
+ describe('getYMinValue method', function () {
+ var Data;
+ var dataSeries;
+ var stackedDataSeries;
+ var visData;
+ var stackedVisData;
+ var series;
+ var stackedSeries;
+ var minValue;
+ var stackedMinValue;
+
+ beforeEach(function () {
+ module('DataFactory');
});
- it('should return array length 3', function () {
- expect(rowOut[0][0].length).to.be(3);
+ beforeEach(function () {
+ inject(function (d3, Private) {
+ Data = Private(require('components/vislib/lib/data'));
+ dataSeries = require('vislib_fixtures/mock_data/date_histogram/_series');
+ stackedDataSeries = require('vislib_fixtures/mock_data/stacked/_stacked');
+ visData = new Data(dataSeries, {});
+ stackedVisData = new Data(stackedDataSeries, { type: 'histogram' });
+ series = _.pluck(visData.chartData(), 'series');
+ stackedSeries = _.pluck(stackedVisData.chartData(), 'series');
+ minValue = 4;
+ stackedMinValue = 15;
+ });
});
- it('should return array length 3', function () {
- expect(colOut[0][0].length).to.be(3);
+ // The first value in the time series is less than the min date in the
+ // date range. It also has the largest y value. This value should be excluded
+ // when calculating the Y max value since it falls outside of the range.
+ it('should return the Y domain min value', function () {
+ expect(visData.getYMinValue()).to.be(minValue);
+ expect(stackedVisData.getYMinValue()).to.be(stackedMinValue);
+ });
+
+ it('should have a minimum date value that is greater than the max value within the date range', function () {
+ expect(_.min(series.values, function (d) { return d.x; })).to.be.greaterThan(minValue);
+ expect(_.min(stackedSeries.values, function (d) { return d.x; })).to.be.greaterThan(stackedMinValue);
});
});
@@ -268,9 +316,9 @@ define(function (require) {
dataSeries = require('vislib_fixtures/mock_data/date_histogram/_series');
stackedDataSeries = require('vislib_fixtures/mock_data/stacked/_stacked');
visData = new Data(dataSeries, {});
- stackedVisData = new Data(stackedDataSeries, {});
- series = visData.flatten();
- stackedSeries = stackedVisData.flatten();
+ stackedVisData = new Data(stackedDataSeries, { type: 'histogram' });
+ series = _.pluck(visData.chartData(), 'series');
+ stackedSeries = _.pluck(stackedVisData.chartData(), 'series');
maxValue = 41;
stackedMaxValue = 115;
});
@@ -279,13 +327,9 @@ define(function (require) {
// The first value in the time series is less than the min date in the
// date range. It also has the largest y value. This value should be excluded
// when calculating the Y max value since it falls outside of the range.
- it('should return the Y domain max value', function () {
- series.forEach(function (data) {
- expect(visData._getYMax(data, visData._getY)).to.be(maxValue);
- });
- stackedSeries.forEach(function (data) {
- expect(stackedVisData._getYMax(data, visData._getYStack)).to.be(stackedMaxValue);
- });
+ it('should return the Y domain min value', function () {
+ expect(visData.getYMaxValue()).to.be(maxValue);
+ expect(stackedVisData.getYMaxValue()).to.be(stackedMaxValue);
});
it('should have a minimum date value that is greater than the max value within the date range', function () {
diff --git a/test/unit/specs/vislib/lib/dispatch.js b/test/unit/specs/vislib/lib/dispatch.js
index 2be2af0d84081..2e15e21bef952 100644
--- a/test/unit/specs/vislib/lib/dispatch.js
+++ b/test/unit/specs/vislib/lib/dispatch.js
@@ -20,9 +20,7 @@ define(function (require) {
vis = Private(require('vislib_fixtures/_vis_fixture'))();
require('css!components/vislib/styles/main');
- vis.on('brush', function (e) {
- console.log(e);
- });
+ vis.on('brush', _.noop);
vis.render(data);
});
@@ -36,12 +34,8 @@ define(function (require) {
describe('addEvent method', function () {
it('should return a function', function () {
vis.handler.charts.forEach(function (chart) {
- var clickEvent = function (e) {
- console.log(e);
- };
var addEvent = chart.events.addEvent;
-
- expect(_.isFunction(addEvent('click', clickEvent))).to.be(true);
+ expect(_.isFunction(addEvent('click', _.noop))).to.be(true);
});
});
});
diff --git a/test/unit/specs/vislib/lib/y_axis.js b/test/unit/specs/vislib/lib/y_axis.js
index ae89c3b9a2033..82e919bbd4f21 100644
--- a/test/unit/specs/vislib/lib/y_axis.js
+++ b/test/unit/specs/vislib/lib/y_axis.js
@@ -1,18 +1,42 @@
define(function (require) {
- var angular = require('angular');
var _ = require('lodash');
var d3 = require('d3');
var $ = require('jquery');
- angular.module('YAxisFactory', ['kibana']);
+ var YAxis;
+ var Data;
+ var el;
+ var yAxis;
+ var yAxisDiv;
- describe('Vislib yAxis Class Test Suite', function () {
- var YAxis;
- var Data;
- var yAxis;
- var el;
- var yAxisDiv;
- var dataObj;
+ var timeSeries = [
+ 1408734060000,
+ 1408734090000,
+ 1408734120000,
+ 1408734150000,
+ 1408734180000,
+ 1408734210000,
+ 1408734240000,
+ 1408734270000,
+ 1408734300000,
+ 1408734330000
+ ];
+
+ var defaultGraphData = [
+ [ 8, 23, 30, 28, 36, 30, 26, 22, 29, 24 ],
+ [ 2, 13, 20, 18, 26, 20, 16, 12, 19, 14 ]
+ ];
+
+ function makeSeriesData(data) {
+ return timeSeries.map(function (timestamp, i) {
+ return {
+ x: timestamp,
+ y: data[i] || 0
+ };
+ });
+ }
+
+ function createData(seriesData) {
var data = {
hits: 621,
label: 'test',
@@ -22,129 +46,51 @@ define(function (require) {
max: 1408734982458,
min: 1408734082458
},
- series: [
- {
- values: [
- {
- x: 1408734060000,
- y: 8
- },
- {
- x: 1408734090000,
- y: 23
- },
- {
- x: 1408734120000,
- y: 30
- },
- {
- x: 1408734150000,
- y: 28
- },
- {
- x: 1408734180000,
- y: 36
- },
- {
- x: 1408734210000,
- y: 30
- },
- {
- x: 1408734240000,
- y: 26
- },
- {
- x: 1408734270000,
- y: 22
- },
- {
- x: 1408734300000,
- y: 29
- },
- {
- x: 1408734330000,
- y: 24
- }
- ]
- },
- {
- values: [
- {
- x: 1408734060000,
- y: 8
- },
- {
- x: 1408734090000,
- y: 23
- },
- {
- x: 1408734120000,
- y: 30
- },
- {
- x: 1408734150000,
- y: 28
- },
- {
- x: 1408734180000,
- y: 36
- },
- {
- x: 1408734210000,
- y: 30
- },
- {
- x: 1408734240000,
- y: 26
- },
- {
- x: 1408734270000,
- y: 22
- },
- {
- x: 1408734300000,
- y: 29
- },
- {
- x: 1408734330000,
- y: 24
- }
- ]
- }
- ],
+ series: seriesData.map(function (series) {
+ return { values: makeSeriesData(series) };
+ }),
xAxisLabel: 'Date Histogram',
yAxisLabel: 'Count'
};
- beforeEach(module('YAxisFactory'));
- beforeEach(inject(function (d3, Private) {
- Data = Private(require('components/vislib/lib/data'));
- YAxis = Private(require('components/vislib/lib/y_axis'));
+ var node = $('').css({
+ height: 40,
+ width: 40
+ })
+ .appendTo('body')
+ .addClass('y-axis-wrapper')
+ .get(0);
- expect($('.y-axis-wrapper')).to.have.length(0);
+ el = d3.select(node).datum(data);
- var $node = $('
').css({
- height: 40,
- width: 40
- })
- .appendTo('body')
- .addClass('y-axis-wrapper');
+ yAxisDiv = el.append('div')
+ .attr('class', 'y-axis-div');
- var node = $node.get(0);
+ var dataObj = new Data(data, {
+ defaultYMin: true
+ });
- el = d3.select(node).datum(data);
+ yAxis = new YAxis({
+ el: node,
+ yMin: dataObj.getYMinValue(),
+ yMax: dataObj.getYMaxValue(),
+ _attr: {
+ margin: { top: 0, right: 0, bottom: 0, left: 0 }
+ }
+ });
+ }
- yAxisDiv = el.append('div')
- .attr('class', 'y-axis-div');
+ describe('Vislib yAxis Class Test Suite', function () {
+ var d3Provider;
- dataObj = new Data(data, {});
- yAxis = new YAxis({
- el: node,
- yMax: dataObj.getYMaxValue(),
- _attr: {
- margin: { top: 0, right: 0, bottom: 0, left: 0 }
- }
- });
+ beforeEach(module('kibana'));
+
+ beforeEach(inject(function (Private, _d3_) {
+ d3Provider = _d3_;
+ Data = Private(require('components/vislib/lib/data'));
+ YAxis = Private(require('components/vislib/lib/y_axis'));
+
+ expect($('.y-axis-wrapper')).to.have.length(0);
}));
afterEach(function () {
@@ -154,6 +100,7 @@ define(function (require) {
describe('render Method', function () {
beforeEach(function () {
+ createData(defaultGraphData);
expect(d3.select(yAxis.el).selectAll('.y-axis-div')).to.have.length(1);
yAxis.render();
});
@@ -173,26 +120,89 @@ define(function (require) {
describe('getYScale Method', function () {
var yScale;
+ var graphData;
var height = 50;
- beforeEach(function () {
- yScale = yAxis.getYScale(height);
+ function checkDomain(min, max) {
+ var domain = yScale.domain();
+ expect(domain[0]).to.be.lessThan(min + 1);
+ expect(domain[1]).to.be.greaterThan(max - 1);
+ return domain;
+ }
+
+ function checkRange() {
+ expect(yScale.range()[0]).to.be(height);
+ expect(yScale.range()[1]).to.be(0);
+ }
+
+ describe('API', function () {
+ beforeEach(function () {
+ createData(defaultGraphData);
+ yScale = yAxis.getYScale(height);
+ });
+
+ it('should return a function', function () {
+ expect(_.isFunction(yScale)).to.be(true);
+ });
});
- it('should return a function', function () {
- expect(_.isFunction(yScale)).to.be(true);
+ describe('positive values', function () {
+ beforeEach(function () {
+ graphData = defaultGraphData;
+ createData(graphData);
+ yScale = yAxis.getYScale(height);
+ });
+
+
+ it('should have domain between 0 and max value', function () {
+ var min = 0;
+ var max = _.max(_.flatten(graphData));
+ var domain = checkDomain(min, max);
+ expect(domain[1]).to.be.greaterThan(0);
+ checkRange();
+ });
});
- it('should return the correct domain', function () {
- expect(yScale.domain()[0]).to.be(0);
- // Should be greater than 36 since we are using .nice()
- expect(yScale.domain()[1]).to.be.greaterThan(36);
+ describe('negative values', function () {
+ beforeEach(function () {
+ graphData = [
+ [ -8, -23, -30, -28, -36, -30, -26, -22, -29, -24 ],
+ [ -22, -8, -30, -4, 0, 0, -3, -22, -14, -24 ]
+ ];
+ createData(graphData);
+ yScale = yAxis.getYScale(height);
+ });
+
+
+ it('should have domain between min value and 0', function () {
+ var min = _.min(_.flatten(graphData));
+ var max = 0;
+ var domain = checkDomain(min, max);
+ expect(domain[0]).to.be.lessThan(0);
+ checkRange();
+ });
+
});
- it('should return the correct range', function () {
- expect(yScale.range()[0]).to.be(height);
- // The yScale range should always start from 0
- expect(yScale.range()[1]).to.be(0);
+ describe('positive and negative values', function () {
+ beforeEach(function () {
+ graphData = [
+ [ 8, 23, 30, 28, 36, 30, 26, 22, 29, 24 ],
+ [ 22, 8, -30, -4, 0, 0, 3, -22, 14, 24 ]
+ ];
+ createData(graphData);
+ yScale = yAxis.getYScale(height);
+ });
+
+
+ it('should have domain between min and max values', function () {
+ var min = _.min(_.flatten(graphData));
+ var max = _.max(_.flatten(graphData));
+ var domain = checkDomain(min, max);
+ expect(domain[0]).to.be.lessThan(0);
+ expect(domain[1]).to.be.greaterThan(0);
+ checkRange();
+ });
});
});
@@ -201,6 +211,7 @@ define(function (require) {
var val;
beforeEach(function () {
+ createData(defaultGraphData);
val = yAxis.formatAxisLabel(num);
});
@@ -212,6 +223,7 @@ define(function (require) {
describe('getYAxis method', function () {
var mode, yMax, yScale;
beforeEach(function () {
+ createData(defaultGraphData);
mode = yAxis._attr.mode;
yMax = yAxis.yMax;
yScale = yAxis.getYScale;
@@ -244,12 +256,20 @@ define(function (require) {
});
describe('draw Method', function () {
+ beforeEach(function () {
+ createData(defaultGraphData);
+ });
+
it('should be a function', function () {
expect(_.isFunction(yAxis.draw())).to.be(true);
});
});
describe('tickScale Method', function () {
+ beforeEach(function () {
+ createData(defaultGraphData);
+ });
+
it('should return the correct number of ticks', function () {
expect(yAxis.tickScale(1000)).to.be(11);
expect(yAxis.tickScale(40)).to.be(3);
@@ -257,4 +277,4 @@ define(function (require) {
});
});
});
-});
+});
\ No newline at end of file
diff --git a/test/unit/specs/vislib/vis.js b/test/unit/specs/vislib/vis.js
index 3c55376bf94b5..ca4b37878ea3f 100644
--- a/test/unit/specs/vislib/vis.js
+++ b/test/unit/specs/vislib/vis.js
@@ -130,12 +130,8 @@ define(function (require) {
beforeEach(function () {
listeners = [];
- listener1 = function (e) {
- console.log(e, 'listener1');
- };
- listener2 = function (e) {
- console.log(e, 'listener2');
- };
+ listener1 = function () {};
+ listener2 = function () {};
listeners.push(listener1);
listeners.push(listener2);
@@ -198,12 +194,8 @@ define(function (require) {
beforeEach(function () {
listeners = [];
- listener1 = function (e) {
- console.log(e, 'listener1');
- };
- listener2 = function (e) {
- console.log(e, 'listener2');
- };
+ listener1 = function () {};
+ listener2 = function () {};
listeners.push(listener1);
listeners.push(listener2);
diff --git a/test/unit/specs/vislib/visualizations/area_chart.js b/test/unit/specs/vislib/visualizations/area_chart.js
index 810009b1bd307..3d2cc60eb2cf7 100644
--- a/test/unit/specs/vislib/visualizations/area_chart.js
+++ b/test/unit/specs/vislib/visualizations/area_chart.js
@@ -4,20 +4,26 @@ define(function (require) {
var $ = require('jquery');
// Data
- var series = require('vislib_fixtures/mock_data/date_histogram/_series');
+ var seriesPos = require('vislib_fixtures/mock_data/date_histogram/_series');
+ var seriesPosNeg = require('vislib_fixtures/mock_data/date_histogram/_series_pos_neg');
+ var seriesNeg = require('vislib_fixtures/mock_data/date_histogram/_series_neg');
var termColumns = require('vislib_fixtures/mock_data/terms/_columns');
var rangeRows = require('vislib_fixtures/mock_data/range/_rows');
var stackedSeries = require('vislib_fixtures/mock_data/date_histogram/_stacked_series');
var dataArray = [
- series,
+ seriesPos,
+ seriesPosNeg,
+ seriesNeg,
termColumns,
rangeRows,
stackedSeries,
];
var names = [
- 'series',
+ 'series pos',
+ 'series pos neg',
+ 'series neg',
'term columns',
'range rows',
'stackedSeries',
@@ -26,7 +32,8 @@ define(function (require) {
var visLibParams = {
type: 'area',
addLegend: true,
- addTooltip: true
+ addTooltip: true,
+ defaultYExtents: false
};
angular.module('AreaChartFactory', ['kibana']);
@@ -44,9 +51,7 @@ define(function (require) {
vis = Private(require('vislib_fixtures/_vis_fixture'))(visLibParams);
require('css!components/vislib/styles/main');
- vis.on('brush', function (e) {
- console.log(e);
- });
+ vis.on('brush', _.noop);
vis.render(data);
});
@@ -218,6 +223,25 @@ define(function (require) {
expect(_.isFunction(chart.draw())).to.be(true);
});
});
+
+ it('should return a yMin and yMax', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+
+ expect(yAxis.yMin).to.not.be(undefined);
+ expect(yAxis.yMax).to.not.be(undefined);
+ });
+ });
+
+ it('should render a zero axis line', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+
+ if (yAxis.yMin < 0 && yAxis.yMax > 0) {
+ expect($(chart.chartEl).find('line.zero-line').length).to.be(1);
+ }
+ });
+ });
});
describe('containerTooSmall error', function () {
@@ -234,6 +258,23 @@ define(function (require) {
});
});
});
+
+ describe('defaultYExtents is true', function () {
+ beforeEach(function () {
+ vis._attr.defaultYExtents = true;
+ vis.render(data);
+ });
+
+ it('should return yAxis extents equal to data extents', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+ var yVals = [vis.handler.data.getYMinValue(), vis.handler.data.getYMaxValue()];
+
+ expect(yAxis.yMin).to.equal(yVals[0]);
+ expect(yAxis.yMax).to.equal(yVals[1]);
+ });
+ });
+ });
});
});
});
diff --git a/test/unit/specs/vislib/visualizations/column_chart.js b/test/unit/specs/vislib/visualizations/column_chart.js
index bfb1b15a07052..49330f3c39547 100644
--- a/test/unit/specs/vislib/visualizations/column_chart.js
+++ b/test/unit/specs/vislib/visualizations/column_chart.js
@@ -6,22 +6,30 @@ define(function (require) {
// Data
var series = require('vislib_fixtures/mock_data/date_histogram/_series');
+ var seriesPosNeg = require('vislib_fixtures/mock_data/date_histogram/_series_pos_neg');
+ var seriesNeg = require('vislib_fixtures/mock_data/date_histogram/_series_neg');
var termsColumns = require('vislib_fixtures/mock_data/terms/_columns');
//var histogramRows = require('vislib_fixtures/mock_data/histogram/_rows');
var stackedSeries = require('vislib_fixtures/mock_data/date_histogram/_stacked_series');
var dataArray = [
series,
+ seriesPosNeg,
+ seriesNeg,
termsColumns,
//histogramRows,
stackedSeries
];
var names = [
'series',
+ 'series with positive and negative values',
+ 'series with negative values',
'terms columns',
//'histogram rows',
'stackedSeries'
];
var modes = [
+ 'stacked',
+ 'stacked',
'stacked',
'grouped',
//'percentage',
@@ -153,6 +161,25 @@ define(function (require) {
expect(_.isFunction(chart.draw())).to.be(true);
});
});
+
+ it('should return a yMin and yMax', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+
+ expect(yAxis.yMin).to.not.be(undefined);
+ expect(yAxis.yMax).to.not.be(undefined);
+ });
+ });
+
+ it('should render a zero axis line', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+
+ if (yAxis.yMin < 0 && yAxis.yMax > 0) {
+ expect($(chart.chartEl).find('line.zero-line').length).to.be(1);
+ }
+ });
+ });
});
describe('containerTooSmall error', function () {
@@ -169,6 +196,23 @@ define(function (require) {
});
});
});
+
+ describe('defaultYExtents is true', function () {
+ beforeEach(function () {
+ vis._attr.defaultYExtents = true;
+ vis.render(data);
+ });
+
+ it('should return yAxis extents equal to data extents', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+ var yVals = [vis.handler.data.getYMinValue(), vis.handler.data.getYMaxValue()];
+
+ expect(yAxis.yMin).to.equal(yVals[0]);
+ expect(yAxis.yMax).to.equal(yVals[1]);
+ });
+ });
+ });
});
});
});
diff --git a/test/unit/specs/vislib/visualizations/line_chart.js b/test/unit/specs/vislib/visualizations/line_chart.js
index 4c3f504fdc933..79edddeb5b9cd 100644
--- a/test/unit/specs/vislib/visualizations/line_chart.js
+++ b/test/unit/specs/vislib/visualizations/line_chart.js
@@ -4,18 +4,24 @@ define(function (require) {
var $ = require('jquery');
// Data
- var series = require('vislib_fixtures/mock_data/date_histogram/_series');
+ var seriesPos = require('vislib_fixtures/mock_data/date_histogram/_series');
+ var seriesPosNeg = require('vislib_fixtures/mock_data/date_histogram/_series_pos_neg');
+ var seriesNeg = require('vislib_fixtures/mock_data/date_histogram/_series_neg');
var histogramColumns = require('vislib_fixtures/mock_data/histogram/_columns');
var rangeRows = require('vislib_fixtures/mock_data/range/_rows');
var termSeries = require('vislib_fixtures/mock_data/terms/_series');
var dateHistogramArray = [
- series,
+ seriesPos,
+ seriesPosNeg,
+ seriesNeg,
histogramColumns,
rangeRows,
termSeries,
];
var names = [
- 'series',
+ 'series pos',
+ 'series pos neg',
+ 'series neg',
'histogram columns',
'range rows',
'term series',
@@ -41,9 +47,7 @@ define(function (require) {
vis = Private(require('vislib_fixtures/_vis_fixture'))(visLibParams);
require('css!components/vislib/styles/main');
- vis.on('brush', function (e) {
- console.log(e);
- });
+ vis.on('brush', _.noop);
vis.render(data);
});
@@ -133,6 +137,25 @@ define(function (require) {
expect(chart.draw()).to.be.a(Function);
});
});
+
+ it('should return a yMin and yMax', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+
+ expect(yAxis.yMin).to.not.be(undefined);
+ expect(yAxis.yMax).to.not.be(undefined);
+ });
+ });
+
+ it('should render a zero axis line', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+
+ if (yAxis.yMin < 0 && yAxis.yMax > 0) {
+ expect($(chart.chartEl).find('line.zero-line').length).to.be(1);
+ }
+ });
+ });
});
describe('containerTooSmall error', function () {
@@ -150,6 +173,22 @@ define(function (require) {
});
});
+ describe('defaultYExtents is true', function () {
+ beforeEach(function () {
+ vis._attr.defaultYExtents = true;
+ vis.render(data);
+ });
+
+ it('should return yAxis extents equal to data extents', function () {
+ vis.handler.charts.forEach(function (chart) {
+ var yAxis = chart.handler.yAxis;
+ var yVals = [vis.handler.data.getYMinValue(), vis.handler.data.getYMaxValue()];
+
+ expect(yAxis.yMin).to.equal(yVals[0]);
+ expect(yAxis.yMax).to.equal(yVals[1]);
+ });
+ });
+ });
});
});
});
diff --git a/test/utils/agg_param_writer.js b/test/utils/agg_param_writer.js
index fd01ed95aacd7..89e5102c46c97 100644
--- a/test/utils/agg_param_writer.js
+++ b/test/utils/agg_param_writer.js
@@ -91,6 +91,12 @@ define(function (require) {
return aggConfig.type === self.aggType;
});
+ aggConfig.type.params.forEach(function (param) {
+ if (param.onRequest) {
+ param.onRequest(aggConfig);
+ }
+ });
+
return aggConfig.type.params.write(aggConfig);
};