From 82e03d3a593b34a26ca2c2ebc1b6a97eb98ab5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Benitte?= Date: Thu, 30 Aug 2018 09:59:40 +0900 Subject: [PATCH] feat(line): fix line slices for time scales --- packages/line/src/LineSlices.js | 28 ++- packages/line/src/LineSlicesItem.js | 2 +- packages/line/stories/line.stories.js | 1 + .../tests/__snapshots__/Line.test.js.snap | 146 ++++++++++++- packages/scales/src/compute.js | 52 ++--- packages/scales/src/timeHelpers.js | 61 ++++++ packages/scales/src/timeScale.js | 13 +- packages/scales/tests/compute.test.js | 200 ++++++++---------- packages/scales/tests/timeHelpers.test.js | 60 ++++++ 9 files changed, 405 insertions(+), 158 deletions(-) create mode 100644 packages/scales/src/timeHelpers.js create mode 100644 packages/scales/tests/timeHelpers.test.js diff --git a/packages/line/src/LineSlices.js b/packages/line/src/LineSlices.js index c2fe5c910..24cfca49d 100644 --- a/packages/line/src/LineSlices.js +++ b/packages/line/src/LineSlices.js @@ -21,20 +21,18 @@ const LineSlices = ({ tooltipFormat, }) => ( - {slices.map(slice => { - return ( - - ) - })} + {slices.map(slice => ( + + ))} ) @@ -49,7 +47,7 @@ LineSlices.propTypes = { x: PropTypes.number.isRequired, data: PropTypes.arrayOf( PropTypes.shape({ - normalized: PropTypes.shape({ + data: PropTypes.shape({ x: PropTypes.oneOfType([ PropTypes.number, PropTypes.string, diff --git a/packages/line/src/LineSlicesItem.js b/packages/line/src/LineSlicesItem.js index 9577ae617..0e64fda3a 100644 --- a/packages/line/src/LineSlicesItem.js +++ b/packages/line/src/LineSlicesItem.js @@ -42,7 +42,7 @@ const LineSlicesItem = ({ slice, height, showTooltip, hideTooltip, isHover }) => x={-20} width={40} height={height} - fill="#000" + fill="#F00" fillOpacity={0} onMouseEnter={showTooltip} onMouseMove={showTooltip} diff --git a/packages/line/stories/line.stories.js b/packages/line/stories/line.stories.js index 2495c2b30..d4ef5e64a 100644 --- a/packages/line/stories/line.stories.js +++ b/packages/line/stories/line.stories.js @@ -131,6 +131,7 @@ stories.add( xScale={{ type: 'time', format: '%Y-%m-%d', + precision: 'day', }} yScale={{ type: 'linear', diff --git a/packages/line/tests/__snapshots__/Line.test.js.snap b/packages/line/tests/__snapshots__/Line.test.js.snap index 4648df0ff..a896b2682 100644 --- a/packages/line/tests/__snapshots__/Line.test.js.snap +++ b/packages/line/tests/__snapshots__/Line.test.js.snap @@ -6008,7 +6008,78 @@ exports[`should render a basic line chart 1`] = ` strokeWidth={2} /> - + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + (axis === 'x' ? 'y' : 'x') @@ -23,14 +24,7 @@ export const compareDateValues = (a, b) => a.getTime() === b.getTime() export const computeXYScalesForSeries = (_series, xScaleSpec, yScaleSpec, width, height) => { const series = _series.map(serie => ({ ...serie, - data: serie.data.map(d => ({ - data: d, - normalized: { - ...d, - x: d.x, - y: d.y, - }, - })), + data: serie.data.map(d => ({ data: d })), })) let xy = generateSeriesXY(series, xScaleSpec, yScaleSpec) @@ -49,20 +43,20 @@ export const computeXYScalesForSeries = (_series, xScaleSpec, yScaleSpec, width, d.position = { x: xScale.stacked === true - ? d.normalized.xStacked === null + ? d.data.xStacked === null ? null - : xScale(d.normalized.xStacked) - : d.normalized.x === null + : xScale(d.data.xStacked) + : d.data.x === null ? null - : xScale(d.normalized.x), + : xScale(d.data.x), y: yScale.stacked === true - ? d.normalized.yStacked === null + ? d.data.yStacked === null ? null - : yScale(d.normalized.yStacked) - : d.normalized.y === null + : yScale(d.data.yStacked) + : d.data.y === null ? null - : yScale(d.normalized.y), + : yScale(d.data.y), } }) }) @@ -86,18 +80,22 @@ export const generateSeriesXY = (series, xScaleSpec, yScaleSpec) => ({ y: generateSeriesAxis(series, 'y', yScaleSpec), }) +/** + * Normalize data according to scale type, (time => Date, linear => Number) + * compute sorted unique values and min/max. + */ export const generateSeriesAxis = (series, axis, scaleSpec) => { if (scaleSpec.type === 'linear') { series.forEach(serie => { serie.data.forEach(d => { - d.normalized[axis] = d.data[axis] === null ? null : parseFloat(d.data[axis]) + d.data[axis] = d.data[axis] === null ? null : parseFloat(d.data[axis]) }) }) } else if (scaleSpec.type === 'time' && scaleSpec.format !== 'native') { - const parseTime = timeParse(scaleSpec.format) + const parseTime = createDateNormalizer(scaleSpec) series.forEach(serie => { serie.data.forEach(d => { - d.normalized[axis] = d.data[axis] === null ? null : parseTime(d.data[axis]) + d.data[axis] = d.data[axis] === null ? null : parseTime(d.data[axis]) }) }) } @@ -105,17 +103,18 @@ export const generateSeriesAxis = (series, axis, scaleSpec) => { let all = [] series.forEach(serie => { serie.data.forEach(d => { - all.push(d.normalized[axis]) + all.push(d.data[axis]) }) }) - all = uniq(all) let min, max if (scaleSpec.type === 'linear') { + all = uniq(all) all = sortBy(all, v => v) min = Math.min(...all) max = Math.max(...all) } else if (scaleSpec.type === 'time') { + all = uniqBy(all, v => v.getTime()) all = all .slice(0) .sort((a, b) => b - a) @@ -123,6 +122,7 @@ export const generateSeriesAxis = (series, axis, scaleSpec) => { min = all[0] max = last(all) } else { + all = uniq(all) min = all[0] max = last(all) } @@ -138,11 +138,11 @@ export const stackAxis = (axis, otherType, xy, series) => { const compare = isDate(v) ? compareDateValues : compareValues const stack = [] series.forEach(serie => { - const datum = serie.data.find(d => compare(d.normalized[otherAxis], v)) + const datum = serie.data.find(d => compare(d.data[otherAxis], v)) let value = null let stackValue = null if (datum !== undefined) { - value = datum.normalized[axis] + value = datum.data[axis] if (value !== null) { const head = last(stack) if (head === undefined) { @@ -151,7 +151,7 @@ export const stackAxis = (axis, otherType, xy, series) => { stackValue = head + value } } - datum.normalized[`${axis}Stacked`] = stackValue + datum.data[`${axis}Stacked`] = stackValue } stack.push(stackValue) all.push(stackValue) @@ -177,7 +177,7 @@ export const computeAxisSlices = (axis, data) => { } const compare = isDate(v) ? compareDateValues : compareValues data.series.forEach(serie => { - const datum = serie.data.find(d => compare(d.normalized[otherAxis], v)) + const datum = serie.data.find(d => compare(d.data[otherAxis], v)) if (datum !== undefined) { slice.data.push({ ...datum, diff --git a/packages/scales/src/timeHelpers.js b/packages/scales/src/timeHelpers.js new file mode 100644 index 000000000..400081872 --- /dev/null +++ b/packages/scales/src/timeHelpers.js @@ -0,0 +1,61 @@ +/* + * This file is part of the nivo project. + * + * Copyright 2016-present, Raphaël Benitte. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +import { timeParse } from 'd3-time-format' + +export const TIME_PRECISION_MILLISECOND = 'millisecond' +export const TIME_PRECISION_SECOND = 'second' +export const TIME_PRECISION_MINUTE = 'minute' +export const TIME_PRECISION_HOUR = 'hour' +export const TIME_PRECISION_DAY = 'day' +export const TIME_PRECISION_MONTH = 'month' +export const TIME_PRECISION_YEAR = 'year' + +export const timePrecisions = [ + TIME_PRECISION_MILLISECOND, + TIME_PRECISION_SECOND, + TIME_PRECISION_MINUTE, + TIME_PRECISION_HOUR, + TIME_PRECISION_DAY, + TIME_PRECISION_MONTH, + TIME_PRECISION_YEAR, +] + +export const precisionCutOffs = [ + date => date.setMilliseconds(0), + date => date.setSeconds(0), + date => date.setMinutes(0), + date => date.setHours(0), + date => date.setDate(1), + date => date.setMonth(0), +] + +export const precisionCutOffsByType = { + [TIME_PRECISION_MILLISECOND]: [], + [TIME_PRECISION_SECOND]: precisionCutOffs.slice(0, 1), + [TIME_PRECISION_MINUTE]: precisionCutOffs.slice(0, 2), + [TIME_PRECISION_HOUR]: precisionCutOffs.slice(0, 3), + [TIME_PRECISION_DAY]: precisionCutOffs.slice(0, 4), + [TIME_PRECISION_MONTH]: precisionCutOffs.slice(0, 5), + [TIME_PRECISION_YEAR]: precisionCutOffs.slice(0, 6), +} + +export const createPrecisionMethod = precision => date => { + precisionCutOffsByType[precision].forEach(cutOff => { + cutOff(date) + }) + return date +} + +export const createDateNormalizer = ({ format = 'native', precision = 'millisecond' }) => { + const precisionFn = createPrecisionMethod(precision) + if (format === 'native') return v => precisionFn(v) + + const parseTime = timeParse(format) + return v => precisionFn(parseTime(v)) +} diff --git a/packages/scales/src/timeScale.js b/packages/scales/src/timeScale.js index a951f95b5..707dbdab8 100644 --- a/packages/scales/src/timeScale.js +++ b/packages/scales/src/timeScale.js @@ -7,11 +7,11 @@ * file that was distributed with this source code. */ import { scaleTime } from 'd3-scale' -import { timeParse } from 'd3-time-format' import PropTypes from 'prop-types' +import { createDateNormalizer, timePrecisions, TIME_PRECISION_MILLISECOND } from './timeHelpers' export const timeScale = ( - { axis, format = 'native', min = 'auto', max = 'auto' }, + { axis, format = 'native', precision = TIME_PRECISION_MILLISECOND, min = 'auto', max = 'auto' }, xy, width, height @@ -19,20 +19,20 @@ export const timeScale = ( const values = xy[axis] const size = axis === 'x' ? width : height - const parseTime = format === 'native' ? undefined : timeParse(format) + const normalize = createDateNormalizer({ format, precision }) let minValue = min if (min === 'auto') { minValue = values.min } else if (format !== 'native') { - minValue = parseTime(values.min) + minValue = normalize(values.min) } let maxValue = max if (max === 'auto') { maxValue = values.max } else if (format !== 'native') { - maxValue = parseTime(values.max) + maxValue = normalize(values.max) } const scale = scaleTime() @@ -46,5 +46,6 @@ export const timeScale = ( export const timeScalePropTypes = { type: PropTypes.oneOf(['time']).isRequired, - format: PropTypes.string.isRequired, + format: PropTypes.string, + precision: PropTypes.oneOf(timePrecisions), } diff --git a/packages/scales/tests/compute.test.js b/packages/scales/tests/compute.test.js index bafc2deab..8fb0f27cd 100644 --- a/packages/scales/tests/compute.test.js +++ b/packages/scales/tests/compute.test.js @@ -1,3 +1,11 @@ +/* + * This file is part of the nivo project. + * + * Copyright 2016-present, Raphaël Benitte. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ import { generateSeriesAxis, stackAxis, computeAxisSlices } from '../src/compute' const axes = ['x', 'y'] @@ -37,17 +45,17 @@ describe('generateSeriesAxis', () => { { id: 'A', data: [ - { normalized: { [axis]: 'a' } }, - { normalized: { [axis]: 'b' } }, - { normalized: { [axis]: 'c' } }, + { data: { [axis]: 'a' } }, + { data: { [axis]: 'b' } }, + { data: { [axis]: 'c' } }, ], }, { id: 'B', data: [ - { normalized: { [axis]: 'c' } }, - { normalized: { [axis]: 'd' } }, - { normalized: { [axis]: 'e' } }, + { data: { [axis]: 'c' } }, + { data: { [axis]: 'd' } }, + { data: { [axis]: 'e' } }, ], }, ], @@ -64,17 +72,17 @@ describe('generateSeriesAxis', () => { { id: 'A', data: [ - { data: { [axis]: 0 }, normalized: {} }, - { data: { [axis]: '1' }, normalized: {} }, - { data: { [axis]: '02' }, normalized: {} }, + { data: { [axis]: 0 } }, + { data: { [axis]: '1' } }, + { data: { [axis]: '02' } }, ], }, { id: 'B', data: [ - { data: { [axis]: 2 }, normalized: {} }, - { data: { [axis]: '3' }, normalized: {} }, - { data: { [axis]: '04' }, normalized: {} }, + { data: { [axis]: 2 } }, + { data: { [axis]: '3' } }, + { data: { [axis]: '04' } }, ], }, ], @@ -91,17 +99,17 @@ describe('generateSeriesAxis', () => { { id: 'A', data: [ - { data: { [axis]: '1' }, normalized: {} }, - { data: { [axis]: '02' }, normalized: {} }, - { data: { [axis]: 0 }, normalized: {} }, + { data: { [axis]: '1' } }, + { data: { [axis]: '02' } }, + { data: { [axis]: 0 } }, ], }, { id: 'B', data: [ - { data: { [axis]: '04' }, normalized: {} }, - { data: { [axis]: 2 }, normalized: {} }, - { data: { [axis]: '3' }, normalized: {} }, + { data: { [axis]: '04' } }, + { data: { [axis]: 2 } }, + { data: { [axis]: '3' } }, ], }, ], @@ -119,16 +127,13 @@ describe('generateSeriesAxis', () => { id: 'A', data: [ { - data: {}, - normalized: { [axis]: new Date(2018, 3, 1, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 1, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 2, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 2, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 3, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 3, 0, 0, 0, 0) }, }, ], }, @@ -136,16 +141,13 @@ describe('generateSeriesAxis', () => { id: 'B', data: [ { - data: {}, - normalized: { [axis]: new Date(2018, 3, 4, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 4, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 5, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 5, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 6, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 6, 0, 0, 0, 0) }, }, ], }, @@ -164,16 +166,13 @@ describe('generateSeriesAxis', () => { id: 'A', data: [ { - data: {}, - normalized: { [axis]: new Date(2018, 3, 3, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 3, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 1, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 1, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 2, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 2, 0, 0, 0, 0) }, }, ], }, @@ -181,16 +180,13 @@ describe('generateSeriesAxis', () => { id: 'B', data: [ { - data: {}, - normalized: { [axis]: new Date(2018, 3, 6, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 6, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 4, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 4, 0, 0, 0, 0) }, }, { - data: {}, - normalized: { [axis]: new Date(2018, 3, 5, 0, 0, 0, 0) }, + data: { [axis]: new Date(2018, 3, 5, 0, 0, 0, 0) }, }, ], }, @@ -210,15 +206,12 @@ describe('generateSeriesAxis', () => { data: [ { data: { [axis]: '2018-4-1 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-2 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-3 0:0:0' }, - normalized: {}, }, ], }, @@ -227,15 +220,12 @@ describe('generateSeriesAxis', () => { data: [ { data: { [axis]: '2018-4-4 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-5 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-6 0:0:0' }, - normalized: {}, }, ], }, @@ -255,15 +245,12 @@ describe('generateSeriesAxis', () => { data: [ { data: { [axis]: '2018-4-3 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-1 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-2 0:0:0' }, - normalized: {}, }, ], }, @@ -272,15 +259,12 @@ describe('generateSeriesAxis', () => { data: [ { data: { [axis]: '2018-4-6 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-4 0:0:0' }, - normalized: {}, }, { data: { [axis]: '2018-4-5 0:0:0' }, - normalized: {}, }, ], }, @@ -310,17 +294,17 @@ describe('stackAxis', () => { { id: 'A', data: [ - { normalized: { [otherAxis]: 'a', [axis]: 10 } }, - { normalized: { [otherAxis]: 'b', [axis]: 20 } }, - { normalized: { [otherAxis]: 'c', [axis]: 30 } }, + { data: { [otherAxis]: 'a', [axis]: 10 } }, + { data: { [otherAxis]: 'b', [axis]: 20 } }, + { data: { [otherAxis]: 'c', [axis]: 30 } }, ], }, { id: 'B', data: [ - { normalized: { [otherAxis]: 'a', [axis]: 1 } }, - { normalized: { [otherAxis]: 'b', [axis]: 2 } }, - { normalized: { [otherAxis]: 'c', [axis]: 3 } }, + { data: { [otherAxis]: 'a', [axis]: 1 } }, + { data: { [otherAxis]: 'b', [axis]: 2 } }, + { data: { [otherAxis]: 'c', [axis]: 3 } }, ], }, ] @@ -332,21 +316,21 @@ describe('stackAxis', () => { id: 'A', data: [ { - normalized: { + data: { [otherAxis]: 'a', [axis]: 10, [`${axis}Stacked`]: 10, }, }, { - normalized: { + data: { [otherAxis]: 'b', [axis]: 20, [`${axis}Stacked`]: 20, }, }, { - normalized: { + data: { [otherAxis]: 'c', [axis]: 30, [`${axis}Stacked`]: 30, @@ -357,9 +341,9 @@ describe('stackAxis', () => { { id: 'B', data: [ - { normalized: { [otherAxis]: 'a', [axis]: 1, [`${axis}Stacked`]: 11 } }, - { normalized: { [otherAxis]: 'b', [axis]: 2, [`${axis}Stacked`]: 22 } }, - { normalized: { [otherAxis]: 'c', [axis]: 3, [`${axis}Stacked`]: 33 } }, + { data: { [otherAxis]: 'a', [axis]: 1, [`${axis}Stacked`]: 11 } }, + { data: { [otherAxis]: 'b', [axis]: 2, [`${axis}Stacked`]: 22 } }, + { data: { [otherAxis]: 'c', [axis]: 3, [`${axis}Stacked`]: 33 } }, ], }, ]) @@ -376,17 +360,17 @@ describe('stackAxis', () => { { id: 'A', data: [ - { normalized: { [otherAxis]: 1, [axis]: 10 } }, - { normalized: { [otherAxis]: 2, [axis]: 20 } }, - { normalized: { [otherAxis]: 3, [axis]: 30 } }, + { data: { [otherAxis]: 1, [axis]: 10 } }, + { data: { [otherAxis]: 2, [axis]: 20 } }, + { data: { [otherAxis]: 3, [axis]: 30 } }, ], }, { id: 'B', data: [ - { normalized: { [otherAxis]: 1, [axis]: 1 } }, - { normalized: { [otherAxis]: 2, [axis]: 2 } }, - { normalized: { [otherAxis]: 3, [axis]: 3 } }, + { data: { [otherAxis]: 1, [axis]: 1 } }, + { data: { [otherAxis]: 2, [axis]: 2 } }, + { data: { [otherAxis]: 3, [axis]: 3 } }, ], }, ] @@ -397,17 +381,17 @@ describe('stackAxis', () => { { id: 'A', data: [ - { normalized: { [otherAxis]: 1, [axis]: 10, [`${axis}Stacked`]: 10 } }, - { normalized: { [otherAxis]: 2, [axis]: 20, [`${axis}Stacked`]: 20 } }, - { normalized: { [otherAxis]: 3, [axis]: 30, [`${axis}Stacked`]: 30 } }, + { data: { [otherAxis]: 1, [axis]: 10, [`${axis}Stacked`]: 10 } }, + { data: { [otherAxis]: 2, [axis]: 20, [`${axis}Stacked`]: 20 } }, + { data: { [otherAxis]: 3, [axis]: 30, [`${axis}Stacked`]: 30 } }, ], }, { id: 'B', data: [ - { normalized: { [otherAxis]: 1, [axis]: 1, [`${axis}Stacked`]: 11 } }, - { normalized: { [otherAxis]: 2, [axis]: 2, [`${axis}Stacked`]: 22 } }, - { normalized: { [otherAxis]: 3, [axis]: 3, [`${axis}Stacked`]: 33 } }, + { data: { [otherAxis]: 1, [axis]: 1, [`${axis}Stacked`]: 11 } }, + { data: { [otherAxis]: 2, [axis]: 2, [`${axis}Stacked`]: 22 } }, + { data: { [otherAxis]: 3, [axis]: 3, [`${axis}Stacked`]: 33 } }, ], }, ]) @@ -429,19 +413,19 @@ describe('stackAxis', () => { id: 'A', data: [ { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 1, 0, 0, 0, 0), [axis]: 10, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 2, 0, 0, 0, 0), [axis]: 20, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 3, 0, 0, 0, 0), [axis]: 30, }, @@ -452,19 +436,19 @@ describe('stackAxis', () => { id: 'B', data: [ { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 1, 0, 0, 0, 0), [axis]: 1, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 2, 0, 0, 0, 0), [axis]: 2, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 3, 0, 0, 0, 0), [axis]: 3, }, @@ -480,21 +464,21 @@ describe('stackAxis', () => { id: 'A', data: [ { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 1, 0, 0, 0, 0), [axis]: 10, [`${axis}Stacked`]: 10, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 2, 0, 0, 0, 0), [axis]: 20, [`${axis}Stacked`]: 20, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 3, 0, 0, 0, 0), [axis]: 30, [`${axis}Stacked`]: 30, @@ -506,21 +490,21 @@ describe('stackAxis', () => { id: 'B', data: [ { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 1, 0, 0, 0, 0), [axis]: 1, [`${axis}Stacked`]: 11, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 2, 0, 0, 0, 0), [axis]: 2, [`${axis}Stacked`]: 22, }, }, { - normalized: { + data: { [otherAxis]: new Date(2018, 3, 3, 0, 0, 0, 0), [axis]: 3, [`${axis}Stacked`]: 33, @@ -542,17 +526,17 @@ describe('stackAxis', () => { { id: 'A', data: [ - { normalized: { [otherAxis]: 1, [axis]: 10 } }, - { normalized: { [otherAxis]: 2, [axis]: null } }, - { normalized: { [otherAxis]: 3, [axis]: 30 } }, + { data: { [otherAxis]: 1, [axis]: 10 } }, + { data: { [otherAxis]: 2, [axis]: null } }, + { data: { [otherAxis]: 3, [axis]: 30 } }, ], }, { id: 'B', data: [ - { normalized: { [otherAxis]: 1, [axis]: 1 } }, - { normalized: { [otherAxis]: 2, [axis]: 2 } }, - { normalized: { [otherAxis]: 3, [axis]: null } }, + { data: { [otherAxis]: 1, [axis]: 1 } }, + { data: { [otherAxis]: 2, [axis]: 2 } }, + { data: { [otherAxis]: 3, [axis]: null } }, ], }, ] @@ -566,24 +550,24 @@ describe('stackAxis', () => { { id: 'A', data: [ - { normalized: { [otherAxis]: 1, [axis]: 10, [`${axis}Stacked`]: 10 } }, + { data: { [otherAxis]: 1, [axis]: 10, [`${axis}Stacked`]: 10 } }, { - normalized: { + data: { [otherAxis]: 2, [axis]: null, [`${axis}Stacked`]: null, }, }, - { normalized: { [otherAxis]: 3, [axis]: 30, [`${axis}Stacked`]: 30 } }, + { data: { [otherAxis]: 3, [axis]: 30, [`${axis}Stacked`]: 30 } }, ], }, { id: 'B', data: [ - { normalized: { [otherAxis]: 1, [axis]: 1, [`${axis}Stacked`]: 11 } }, - { normalized: { [otherAxis]: 2, [axis]: 2, [`${axis}Stacked`]: null } }, + { data: { [otherAxis]: 1, [axis]: 1, [`${axis}Stacked`]: 11 } }, + { data: { [otherAxis]: 2, [axis]: 2, [`${axis}Stacked`]: null } }, { - normalized: { + data: { [otherAxis]: 3, [axis]: null, [`${axis}Stacked`]: null, @@ -606,17 +590,17 @@ describe('computeAxisSlices', () => { const serieA = { id: 'A', data: [ - { normalized: { [otherAxis]: 1, [axis]: 10, [`${axis}Stacked`]: 10 } }, - { normalized: { [otherAxis]: 2, [axis]: 20, [`${axis}Stacked`]: 20 } }, - { normalized: { [otherAxis]: 3, [axis]: 30, [`${axis}Stacked`]: 30 } }, + { data: { [otherAxis]: 1, [axis]: 10, [`${axis}Stacked`]: 10 } }, + { data: { [otherAxis]: 2, [axis]: 20, [`${axis}Stacked`]: 20 } }, + { data: { [otherAxis]: 3, [axis]: 30, [`${axis}Stacked`]: 30 } }, ], } const serieB = { id: 'B', data: [ - { normalized: { [otherAxis]: 1, [axis]: 1, [`${axis}Stacked`]: 11 } }, - { normalized: { [otherAxis]: 2, [axis]: 2, [`${axis}Stacked`]: 22 } }, - { normalized: { [otherAxis]: 3, [axis]: 3, [`${axis}Stacked`]: 33 } }, + { data: { [otherAxis]: 1, [axis]: 1, [`${axis}Stacked`]: 11 } }, + { data: { [otherAxis]: 2, [axis]: 2, [`${axis}Stacked`]: 22 } }, + { data: { [otherAxis]: 3, [axis]: 3, [`${axis}Stacked`]: 33 } }, ], } diff --git a/packages/scales/tests/timeHelpers.test.js b/packages/scales/tests/timeHelpers.test.js new file mode 100644 index 000000000..10094d6ea --- /dev/null +++ b/packages/scales/tests/timeHelpers.test.js @@ -0,0 +1,60 @@ +/* + * This file is part of the nivo project. + * + * Copyright 2016-present, Raphaël Benitte. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +import { + createPrecisionMethod, + TIME_PRECISION_MILLISECOND, + TIME_PRECISION_SECOND, + TIME_PRECISION_MINUTE, + TIME_PRECISION_HOUR, + TIME_PRECISION_DAY, + TIME_PRECISION_MONTH, + TIME_PRECISION_YEAR, +} from '../src/timeHelpers' + +describe('createPrecisionMethod', () => { + const input = new Date(2018, 9, 30, 15, 33, 47, 29) + const testCases = [ + { + precision: TIME_PRECISION_MILLISECOND, + expected: input, + }, + { + precision: TIME_PRECISION_SECOND, + expected: new Date(2018, 9, 30, 15, 33, 47, 0), + }, + { + precision: TIME_PRECISION_MINUTE, + expected: new Date(2018, 9, 30, 15, 33, 0, 0), + }, + { + precision: TIME_PRECISION_HOUR, + expected: new Date(2018, 9, 30, 15, 0, 0, 0), + }, + { + precision: TIME_PRECISION_DAY, + expected: new Date(2018, 9, 30, 0, 0, 0, 0), + }, + { + precision: TIME_PRECISION_MONTH, + expected: new Date(2018, 9, 1, 0, 0, 0, 0), + }, + { + precision: TIME_PRECISION_YEAR, + expected: new Date(2018, 0, 1, 0, 0, 0, 0), + }, + ] + + testCases.forEach(({ precision, expected }) => { + it(`should support ${precision} precision`, () => { + const date = new Date(input.getTime()) + createPrecisionMethod(precision)(date) + expect(date.getTime()).toBe(expected.getTime()) + }) + }) +})