},
ticks: {
autoSkip: false,
- mode: 'linear', // 'linear|series'
- source: 'auto' // 'auto|labels'
+
+ /**
+ * Ticks distribution along the scale:
+ * - 'linear': ticks and data are spread according to their time (distances can vary),
+ * - 'series': ticks and data are spread at the same distance from each other.
+ * @see https://github.com/chartjs/Chart.js/pull/4507
+ * @since 2.7.0
+ */
+ mode: 'linear',
+
+ /**
+ * Ticks generation input values:
+ * - 'labels': generates ticks from user given `data.labels` values ONLY.
+ * - 'auto': generates "optimal" ticks based on scale size and time options.
+ * @see https://github.com/chartjs/Chart.js/pull/4507
+ * @since 2.7.0
+ */
+ source: 'auto',
+
+ /**
+ * Ticks boundary strategy (bypassed by min/max time options)
+ * - `data`: make sure data are fully visible, labels outside are removed
+ * - `labels`: make sure labels are fully visible, data outside are truncated
+ * @see https://github.com/chartjs/Chart.js/pull/4556
+ * @since 2.7.0
+ */
+ bounds: 'data'
}
};
var chart = me.chart;
var options = me.options;
var datasets = chart.data.datasets || [];
- var min = MAX_INTEGER;
- var max = MIN_INTEGER;
+ var min = parse(options.time.min, me) || MAX_INTEGER;
+ var max = parse(options.time.max, me) || MIN_INTEGER;
var timestamps = [];
var labels = [];
var i, j, ilen, jlen, data, timestamp;
}
}
- // Enforce limits with user min/max options
- min = parse(options.time.min, me) || min;
- max = parse(options.time.max, me) || max;
-
// In case there is no valid min/max, let's use today limits
min = min === MAX_INTEGER ? +moment().startOf('day') : min;
max = max === MIN_INTEGER ? +moment().endOf('day') + 1 : max;
- me._model = {
- datasets: timestamps,
- horizontal: me.isHorizontal(),
- labels: labels.sort(sorter), // Sort labels **after** data have been converted
- min: Math.min(min, max), // Make sure that max is **strictly** higher ...
- max: Math.max(min + 1, max), // ... than min (required by the lookup table)
- table: []
- };
+ // Make sure that max is strictly higher than min (required by the lookup table)
+ me.min = Math.min(min, max);
+ me.max = Math.max(min + 1, max);
+
+ // PRIVATE
+ me._datasets = timestamps;
+ me._horizontal = me.isHorizontal();
+ me._labels = labels.sort(sorter); // Sort labels **after** data have been converted
+ me._table = [];
},
buildTicks: function() {
var me = this;
- var model = me._model;
- var min = model.min;
- var max = model.max;
+ var min = me.min;
+ var max = me.max;
var timeOpts = me.options.time;
var ticksOpts = me.options.ticks;
var formats = timeOpts.displayFormats;
|| determineStepSize(min, max, unit, capacity);
timestamps = generate(min, max, unit, majorUnit, stepSize, timeOpts);
-
- // Expand min/max to the generated ticks
- min = helpers.isNullOrUndef(timeOpts.min) && timestamps.length ? timestamps[0] : min;
- max = helpers.isNullOrUndef(timeOpts.max) && timestamps.length ? timestamps[timestamps.length - 1] : max;
} else {
- timestamps = model.labels;
+ timestamps = me._labels;
+ }
+
+ if (ticksOpts.bounds === 'labels' && timestamps.length) {
+ min = timestamps[0];
+ max = timestamps[timestamps.length - 1];
}
+ // Enforce limits with user min/max options
+ min = parse(timeOpts.min, me) || min;
+ max = parse(timeOpts.max, me) || max;
+
// Remove ticks outside the min/max range
for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
timestamp = timestamps[i];
me.ticks = ticks;
me.min = min;
me.max = max;
- me.unit = unit;
- me.majorUnit = majorUnit;
- me.displayFormat = formats[unit];
- me.majorDisplayFormat = formats[majorUnit];
- model.table = buildLookupTable(ticks, min, max, ticksOpts.mode === 'linear');
+ // PRIVATE
+ me._unit = unit;
+ me._majorUnit = majorUnit;
+ me._displayFormat = formats[unit];
+ me._majorDisplayFormat = formats[majorUnit];
+ me._table = buildLookupTable(ticks, min, max, ticksOpts.mode === 'linear');
},
getLabelForIndex: function(index, datasetIndex) {
var me = this;
var options = me.options;
var time = tick.valueOf();
- var majorUnit = me.majorUnit;
- var majorFormat = me.majorDisplayFormat;
- var majorTime = tick.clone().startOf(me.majorUnit).valueOf();
+ var majorUnit = me._majorUnit;
+ var majorFormat = me._majorDisplayFormat;
+ var majorTime = tick.clone().startOf(me._majorUnit).valueOf();
var major = majorUnit && majorFormat && time === majorTime;
- var formattedTick = tick.format(major ? majorFormat : me.displayFormat);
+ var formattedTick = tick.format(major ? majorFormat : me._displayFormat);
var tickOpts = major ? options.ticks.major : options.ticks.minor;
var formatter = helpers.valueOrDefault(tickOpts.callback, tickOpts.userCallback);
*/
getPixelForOffset: function(time) {
var me = this;
- var model = me._model;
- var size = model.horizontal ? me.width : me.height;
- var start = model.horizontal ? me.left : me.top;
- var pos = interpolate(model.table, 'time', time, 'pos');
+ var size = me._horizontal ? me.width : me.height;
+ var start = me._horizontal ? me.left : me.top;
+ var pos = interpolate(me._table, 'time', time, 'pos');
return start + size * pos;
},
var time = null;
if (index !== undefined && datasetIndex !== undefined) {
- time = me._model.datasets[datasetIndex][index];
+ time = me._datasets[datasetIndex][index];
}
if (time === null) {
getValueForPixel: function(pixel) {
var me = this;
- var model = me._model;
- var size = model.horizontal ? me.width : me.height;
- var start = model.horizontal ? me.left : me.top;
+ var size = me._horizontal ? me.width : me.height;
+ var start = me._horizontal ? me.left : me.top;
var pos = size ? (pixel - start) / size : 0;
- var time = interpolate(model.table, 'pos', pos, 'time');
+ var time = interpolate(me._table, 'pos', pos, 'time');
return moment(time);
},
getLabelCapacity: function(exampleTime) {
var me = this;
- me.displayFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation
+ me._displayFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation
var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, []).value;
var tickLabelWidth = me.getLabelWidth(exampleLabel);
mirror: false,
mode: 'linear',
source: 'auto',
+ bounds: 'data',
padding: 0,
reverse: false,
display: true,
scale.update(1000, 200);
var ticks = getTicksValues(scale.ticks);
- expect(ticks).toEqual(['Jan 2015', 'Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10', 'Jan 11']);
+ // `ticks.bounds === 'data'`: first and last ticks removed since outside the data range
+ expect(ticks).toEqual(['Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10']);
});
it('should accept labels as date objects', function() {
scale.update(1000, 200);
var ticks = getTicksValues(scale.ticks);
- expect(ticks).toEqual(['Jan 2015', 'Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10', 'Jan 11']);
+ // `ticks.bounds === 'data'`: first and last ticks removed since outside the data range
+ expect(ticks).toEqual(['Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10']);
});
it('should accept data as xy points', function() {
xScale.update(800, 200);
var ticks = getTicksValues(xScale.ticks);
- expect(ticks).toEqual(['Jan 2015', 'Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10', 'Jan 11']);
+ // `ticks.bounds === 'data'`: first and last ticks removed since outside the data range
+ expect(ticks).toEqual(['Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10']);
});
it('should accept data as ty points', function() {
tScale.update(800, 200);
var ticks = getTicksValues(tScale.ticks);
- expect(ticks).toEqual(['Jan 2015', 'Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10', 'Jan 11']);
+ // `ticks.bounds === 'data'`: first and last ticks removed since outside the data range
+ expect(ticks).toEqual(['Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10']);
});
});
var chart = window.acquireChart({
type: 'line',
data: {
+ labels: ['foo', 'bar'],
datasets: [{
xAxisID: 'xScale0',
- data: [{
- x: 375068900,
- y: 1
- }]
+ data: [0, 1]
}],
},
options: {
unit: 'day',
round: true,
parser: function(label) {
- return moment.unix(label);
+ return label === 'foo' ?
+ moment(946771200000) : // 02/01/2000 @ 12:00am (UTC)
+ moment(1462665600000); // 05/08/2016 @ 12:00am (UTC)
}
+ },
+ ticks: {
+ source: 'labels'
}
}],
}
var xScale = chart.scales.xScale0;
// Counts down because the lines are drawn top to bottom
- expect(xScale.ticks[0].value).toEqualOneOf(['Nov 19', 'Nov 20', 'Nov 21']); // handle time zone changes
- expect(xScale.ticks[1].value).toEqualOneOf(['Nov 19', 'Nov 20', 'Nov 21']); // handle time zone changes
+ expect(xScale.ticks[0].value).toBe('Jan 2');
+ expect(xScale.ticks[1].value).toBe('May 8');
});
it('should build ticks using the config unit', function() {
labels: ['2015-01-01T20:00:00', '2015-01-02T21:00:00'], // days
};
- var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
- config.time.minUnit = 'day';
+ var config = Chart.helpers.mergeIf({
+ time: {
+ minUnit: 'day'
+ },
+ ticks: {
+ bounds: 'labels'
+ }
+ }, Chart.scaleService.getScaleDefaults('time'));
var scale = createScale(mockData, config);
var ticks = getTicksValues(scale.ticks);
labels: ['2015-01-01T20:00:00', '2015-02-02T21:00:00', '2015-02-21T01:00:00'], // days
};
- var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
- config.time.unit = 'week';
- config.time.round = 'week';
+ var config = Chart.helpers.mergeIf({
+ time: {
+ unit: 'week',
+ round: 'week'
+ },
+ ticks: {
+ bounds: 'labels'
+ }
+ }, Chart.scaleService.getScaleDefaults('time'));
var scale = createScale(mockData, config);
scale.update(800, 200);
labels: ['2015-01-01T20:00:00', '2015-01-01T21:00:00'],
};
- var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
- config.time.unit = 'hour';
- config.time.stepSize = 2;
+ var config = Chart.helpers.mergeIf({
+ time: {
+ unit: 'hour',
+ stepSize: 2
+ },
+ ticks: {
+ bounds: 'labels'
+ }
+ }, Chart.scaleService.getScaleDefaults('time'));
var scale = createScale(mockData, config);
scale.update(2500, 200);
]
};
- var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
- config.time.unit = 'week';
- // Wednesday
- config.time.isoWeekday = 3;
+ var config = Chart.helpers.mergeIf({
+ time: {
+ unit: 'week',
+ isoWeekday: 3 // Wednesday
+ },
+ ticks: {
+ bounds: 'labels'
+ }
+ }, Chart.scaleService.getScaleDefaults('time'));
+
var scale = createScale(mockData, config);
var ticks = getTicksValues(scale.ticks);
});
describe('when rendering several days', function() {
- var chart = window.acquireChart({
- type: 'line',
- data: {
- datasets: [{
- xAxisID: 'xScale0',
- data: []
- }],
- labels: ['2015-01-01T20:00:00', '2015-01-02T21:00:00', '2015-01-03T22:00:00', '2015-01-05T23:00:00', '2015-01-07T03:00', '2015-01-08T10:00', '2015-01-10T12:00'], // days
- },
- options: {
- scales: {
- xAxes: [{
- id: 'xScale0',
- type: 'time',
- position: 'bottom'
+ beforeEach(function() {
+ this.chart = window.acquireChart({
+ type: 'line',
+ data: {
+ datasets: [{
+ xAxisID: 'xScale0',
+ data: []
}],
+ labels: [
+ '2015-01-01T20:00:00',
+ '2015-01-02T21:00:00',
+ '2015-01-03T22:00:00',
+ '2015-01-05T23:00:00',
+ '2015-01-07T03:00',
+ '2015-01-08T10:00',
+ '2015-01-10T12:00'
+ ]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ id: 'xScale0',
+ type: 'time',
+ position: 'bottom'
+ }],
+ }
}
- }
- });
+ });
- var xScale = chart.scales.xScale0;
+ this.scale = this.chart.scales.xScale0;
+ });
it('should be bounded by the nearest week beginnings', function() {
- expect(xScale.getValueForPixel(xScale.left)).toBeGreaterThan(moment(chart.data.labels[0]).startOf('week'));
- expect(xScale.getValueForPixel(xScale.right)).toBeLessThan(moment(chart.data.labels[chart.data.labels.length - 1]).add(1, 'week').endOf('week'));
+ var chart = this.chart;
+ var scale = this.scale;
+ expect(scale.getValueForPixel(scale.left)).toBeGreaterThan(moment(chart.data.labels[0]).startOf('week'));
+ expect(scale.getValueForPixel(scale.right)).toBeLessThan(moment(chart.data.labels[chart.data.labels.length - 1]).add(1, 'week').endOf('week'));
});
it('should convert between screen coordinates and times', function() {
- var timeRange = moment(xScale.max).valueOf() - moment(xScale.min).valueOf();
- var msPerPix = timeRange / xScale.width;
- var firstPointOffsetMs = moment(chart.config.data.labels[0]).valueOf() - xScale.min;
- var firstPointPixel = xScale.left + firstPointOffsetMs / msPerPix;
- var lastPointOffsetMs = moment(chart.config.data.labels[chart.config.data.labels.length - 1]).valueOf() - xScale.min;
- var lastPointPixel = xScale.left + lastPointOffsetMs / msPerPix;
-
- expect(xScale.getPixelForValue('', 0, 0)).toBeCloseToPixel(firstPointPixel);
- expect(xScale.getPixelForValue(chart.data.labels[0])).toBeCloseToPixel(firstPointPixel);
- expect(xScale.getValueForPixel(firstPointPixel)).toBeCloseToTime({
+ var chart = this.chart;
+ var scale = this.scale;
+ var timeRange = moment(scale.max).valueOf() - moment(scale.min).valueOf();
+ var msPerPix = timeRange / scale.width;
+ var firstPointOffsetMs = moment(chart.config.data.labels[0]).valueOf() - scale.min;
+ var firstPointPixel = scale.left + firstPointOffsetMs / msPerPix;
+ var lastPointOffsetMs = moment(chart.config.data.labels[chart.config.data.labels.length - 1]).valueOf() - scale.min;
+ var lastPointPixel = scale.left + lastPointOffsetMs / msPerPix;
+
+ expect(scale.getPixelForValue('', 0, 0)).toBeCloseToPixel(firstPointPixel);
+ expect(scale.getPixelForValue(chart.data.labels[0])).toBeCloseToPixel(firstPointPixel);
+ expect(scale.getValueForPixel(firstPointPixel)).toBeCloseToTime({
value: moment(chart.data.labels[0]),
unit: 'hour',
});
- expect(xScale.getPixelForValue('', 6, 0)).toBeCloseToPixel(lastPointPixel);
- expect(xScale.getValueForPixel(lastPointPixel)).toBeCloseToTime({
+ expect(scale.getPixelForValue('', 6, 0)).toBeCloseToPixel(lastPointPixel);
+ expect(scale.getValueForPixel(lastPointPixel)).toBeCloseToTime({
value: moment(chart.data.labels[6]),
unit: 'hour'
});
});
describe('when rendering several years', function() {
- var chart = window.acquireChart({
- type: 'line',
- data: {
- labels: ['2005-07-04', '2017-01-20'],
- },
- options: {
- scales: {
- xAxes: [{
- id: 'xScale0',
- type: 'time',
- position: 'bottom'
- }],
+ beforeEach(function() {
+ this.chart = window.acquireChart({
+ type: 'line',
+ data: {
+ labels: ['2005-07-04', '2017-01-20'],
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ id: 'xScale0',
+ type: 'time',
+ position: 'bottom',
+ ticks: {
+ bounds: 'labels'
+ }
+ }],
+ }
}
- }
- });
-
- var xScale = chart.scales.xScale0;
- xScale.update(800, 200);
+ });
- var step = xScale.ticks[1].time - xScale.ticks[0].time;
- var stepsAmount = Math.floor((xScale.max - xScale.min) / step);
+ this.scale = this.chart.scales.xScale0;
+ this.scale.update(800, 200);
+ });
it('should be bounded by nearest step\'s year start and end', function() {
- expect(xScale.getValueForPixel(xScale.left)).toBeCloseToTime({
- value: moment(xScale.min).startOf('year'),
+ var scale = this.scale;
+ var step = scale.ticks[1].time - scale.ticks[0].time;
+ var stepsAmount = Math.floor((scale.max - scale.min) / step);
+
+ expect(scale.getValueForPixel(scale.left)).toBeCloseToTime({
+ value: moment(scale.min).startOf('year'),
unit: 'hour',
});
- expect(xScale.getValueForPixel(xScale.right)).toBeCloseToTime({
- value: moment(xScale.min + step * stepsAmount).endOf('year'),
+ expect(scale.getValueForPixel(scale.right)).toBeCloseToTime({
+ value: moment(scale.min + step * stepsAmount).endOf('year'),
unit: 'hour',
});
});
it('should build the correct ticks', function() {
// Where 'correct' is a two year spacing.
- expect(getTicksValues(xScale.ticks)).toEqual(['2005', '2007', '2009', '2011', '2013', '2015', '2017', '2019']);
+ expect(getTicksValues(this.scale.ticks)).toEqual(['2005', '2007', '2009', '2011', '2013', '2015', '2017', '2019']);
});
it('should have ticks with accurate labels', function() {
- var ticks = xScale.ticks;
- var pixelsPerYear = xScale.width / 14;
+ var scale = this.scale;
+ var ticks = scale.ticks;
+ var pixelsPerYear = scale.width / 14;
for (var i = 0; i < ticks.length - 1; i++) {
var offset = 2 * pixelsPerYear * i;
- expect(xScale.getValueForPixel(xScale.left + offset)).toBeCloseToTime({
+ expect(scale.getValueForPixel(scale.left + offset)).toBeCloseToTime({
value: moment(ticks[i].value + '-01-01'),
unit: 'day',
threshold: 0.5,
expect(scale.min).toEqual(+moment('2012', 'YYYY'));
expect(scale.max).toEqual(+moment('2051', 'YYYY'));
- expect(getTicksValues(this.chart.scales.x.ticks)).toEqual([
+ expect(getTicksValues(scale.ticks)).toEqual([
'2017', '2019', '2020', '2025', '2042']);
});
it ('should remove ticks that are not inside the min and max time range', function() {
expect(scale.min).toEqual(+moment('2022', 'YYYY'));
expect(scale.max).toEqual(+moment('2032', 'YYYY'));
- expect(getTicksValues(this.chart.scales.x.ticks)).toEqual([
+ expect(getTicksValues(scale.ticks)).toEqual([
'2025']);
});
it ('should not duplicate ticks if min and max are the labels limits', function() {
expect(scale.min).toEqual(+moment('2017', 'YYYY'));
expect(scale.max).toEqual(+moment('2042', 'YYYY'));
- expect(getTicksValues(this.chart.scales.x.ticks)).toEqual([
+ expect(getTicksValues(scale.ticks)).toEqual([
'2017', '2019', '2020', '2025', '2042']);
});
it ('should correctly handle empty `data.labels`', function() {
expect(scale.min).toEqual(+moment().startOf('day'));
expect(scale.max).toEqual(+moment().endOf('day') + 1);
- expect(getTicksValues(this.chart.scales.x.ticks)).toEqual([]);
+ expect(getTicksValues(scale.ticks)).toEqual([]);
});
});
});
});
});
});
+
+ describe('when ticks.bounds', function() {
+ describe('is "data"', function() {
+ it ('should preserve the data range', function() {
+ var chart = window.acquireChart({
+ type: 'line',
+ data: {
+ labels: ['02/20 08:00', '02/21 09:00', '02/22 10:00', '02/23 11:00'],
+ datasets: [{data: [0, 1, 2, 3, 4, 5]}]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ id: 'x',
+ type: 'time',
+ time: {
+ parser: 'MM/DD HH:mm',
+ unit: 'day'
+ },
+ ticks: {
+ bounds: 'data'
+ }
+ }],
+ yAxes: [{
+ display: false
+ }]
+ }
+ }
+ });
+
+ var scale = chart.scales.x;
+
+ expect(scale.min).toEqual(+moment('02/20 08:00', 'MM/DD HH:mm'));
+ expect(scale.max).toEqual(+moment('02/23 11:00', 'MM/DD HH:mm'));
+ expect(scale.getPixelForValue('02/20 08:00')).toBeCloseToPixel(scale.left);
+ expect(scale.getPixelForValue('02/23 11:00')).toBeCloseToPixel(scale.left + scale.width);
+ expect(getTicksValues(scale.ticks)).toEqual([
+ 'Feb 21', 'Feb 22', 'Feb 23']);
+ });
+ });
+
+ describe('is "labels"', function() {
+ it('should preserve the label range', function() {
+ var chart = window.acquireChart({
+ type: 'line',
+ data: {
+ labels: ['02/20 08:00', '02/21 09:00', '02/22 10:00', '02/23 11:00'],
+ datasets: [{data: [0, 1, 2, 3, 4, 5]}]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ id: 'x',
+ type: 'time',
+ time: {
+ parser: 'MM/DD HH:mm',
+ unit: 'day'
+ },
+ ticks: {
+ bounds: 'labels'
+ }
+ }],
+ yAxes: [{
+ display: false
+ }]
+ }
+ }
+ });
+
+ var scale = chart.scales.x;
+ var ticks = scale.ticks;
+
+ expect(scale.min).toEqual(ticks[0].time);
+ expect(scale.max).toEqual(ticks[ticks.length - 1].time);
+ expect(scale.getPixelForValue('02/20 08:00')).toBeCloseToPixel(77);
+ expect(scale.getPixelForValue('02/23 11:00')).toBeCloseToPixel(412);
+ expect(getTicksValues(scale.ticks)).toEqual([
+ 'Feb 20', 'Feb 21', 'Feb 22', 'Feb 23', 'Feb 24']);
+ });
+ });
+ });
+
+ describe('when time.min and/or time.max are defined', function() {
+ ['auto', 'labels'].forEach(function(source) {
+ ['data', 'labels'].forEach(function(bounds) {
+ describe('and source is "' + source + '" and bounds "' + bounds + '"', function() {
+ beforeEach(function() {
+ this.chart = window.acquireChart({
+ type: 'line',
+ data: {
+ labels: ['02/20 08:00', '02/21 09:00', '02/22 10:00', '02/23 11:00'],
+ datasets: [{data: [0, 1, 2, 3, 4, 5]}]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ id: 'x',
+ type: 'time',
+ time: {
+ parser: 'MM/DD HH:mm',
+ unit: 'day'
+ },
+ ticks: {
+ source: source,
+ bounds: bounds
+ }
+ }],
+ yAxes: [{
+ display: false
+ }]
+ }
+ }
+ });
+ });
+
+ it ('should expand scale to the min/max range', function() {
+ var chart = this.chart;
+ var scale = chart.scales.x;
+ var options = chart.options.scales.xAxes[0];
+ var min = '02/19 07:00';
+ var max = '02/24 08:00';
+
+ options.time.min = min;
+ options.time.max = max;
+ chart.update();
+
+ expect(scale.min).toEqual(+moment(min, 'MM/DD HH:mm'));
+ expect(scale.max).toEqual(+moment(max, 'MM/DD HH:mm'));
+ expect(scale.getPixelForValue(min)).toBeCloseToPixel(scale.left);
+ expect(scale.getPixelForValue(max)).toBeCloseToPixel(scale.left + scale.width);
+ });
+ it ('should shrink scale to the min/max range', function() {
+ var chart = this.chart;
+ var scale = chart.scales.x;
+ var options = chart.options.scales.xAxes[0];
+ var min = '02/21 07:00';
+ var max = '02/22 20:00';
+
+ options.time.min = min;
+ options.time.max = max;
+ chart.update();
+
+ expect(scale.min).toEqual(+moment(min, 'MM/DD HH:mm'));
+ expect(scale.max).toEqual(+moment(max, 'MM/DD HH:mm'));
+ expect(scale.getPixelForValue(min)).toBeCloseToPixel(scale.left);
+ expect(scale.getPixelForValue(max)).toBeCloseToPixel(scale.left + scale.width);
+ });
+ });
+ });
+ });
+ });
});