From d1ea8968f94af6ceab035aef954c1270ac687f9a Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Thu, 2 Oct 2025 09:42:49 -0600 Subject: [PATCH] add some tests around formatting dates --- .../useSeriesOptions/barSeriesBuilder.test.ts | 215 +++++++++++++++++- .../useSeriesOptions/barSeriesBuilder.ts | 8 +- .../hooks/useSeriesOptions/createTickDate.ts | 3 + .../lineSeriesBuilder.test.ts | 1 + 4 files changed, 220 insertions(+), 7 deletions(-) diff --git a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.test.ts b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.test.ts index 21f15aee9..7441208fe 100644 --- a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.test.ts +++ b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.test.ts @@ -1,13 +1,9 @@ -import { - type ColumnLabelFormat, - DEFAULT_COLUMN_LABEL_FORMAT, - DEFAULT_COLUMN_SETTINGS, -} from '@buster/server-shared/metrics'; +import { type ColumnLabelFormat, DEFAULT_COLUMN_SETTINGS } from '@buster/server-shared/metrics'; import { describe, expect, it } from 'vitest'; import type { BusterChartProps } from '../../../BusterChart.types'; import type { DatasetOption } from '../../../chartHooks'; import type { DatasetOptionsWithTicks } from '../../../chartHooks/useDatasetOptions/interfaces'; -import { barSeriesBuilder } from './barSeriesBuilder'; +import { barSeriesBuilder, barSeriesBuilder_labels } from './barSeriesBuilder'; import type { SeriesBuilderProps } from './interfaces'; describe('barSeriesBuilder', () => { @@ -313,3 +309,210 @@ describe('percentage mode logic', () => { expect(result).toBe(false); }); }); + +describe('barSeriesBuilder_labels - dateTicks', () => { + it('should return date ticks when columnLabelFormat has date style and single xAxis', () => { + // Arrange + const mockDatasetOptions: DatasetOptionsWithTicks = { + datasets: [], + ticks: [['2024-01-01'], ['2024-02-01'], ['2024-03-01']], + ticksKey: [{ key: 'date', value: '' }], + }; + + const columnLabelFormats = { + date: { + columnType: 'date', + style: 'date', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + multiplier: 1, + prefix: '', + suffix: '', + replaceMissingDataWith: 0, + makeLabelHumanReadable: true, + } as ColumnLabelFormat, + }; + + // Act + const result = barSeriesBuilder_labels({ + datasetOptions: mockDatasetOptions, + columnLabelFormats, + xAxisKeys: ['date'], + }); + + // Assert + expect(result).toHaveLength(3); + expect(result[0]).toBeInstanceOf(Date); + expect(result[1]).toBeInstanceOf(Date); + expect(result[2]).toBeInstanceOf(Date); + }); + + it('should return quarter ticks when columnLabelFormat has quarter convertNumberTo and single xAxis', () => { + // Arrange + const mockDatasetOptions: DatasetOptionsWithTicks = { + datasets: [], + ticks: [[1], [2], [3], [4]], + ticksKey: [{ key: 'quarter', value: '' }], + }; + + const columnLabelFormats = { + quarter: { + columnType: 'number', + style: 'date', + convertNumberTo: 'quarter', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + multiplier: 1, + prefix: '', + suffix: '', + replaceMissingDataWith: 0, + makeLabelHumanReadable: true, + } as ColumnLabelFormat, + }; + + // Act + const result = barSeriesBuilder_labels({ + datasetOptions: mockDatasetOptions, + columnLabelFormats, + xAxisKeys: ['quarter'], + }); + + // Assert + expect(result).toHaveLength(4); + expect(result[0]).toBe('Q1'); + expect(result[1]).toBe('Q2'); + expect(result[2]).toBe('Q3'); + expect(result[3]).toBe('Q4'); + }); + + it('should return quarter ticks with double xAxis when one is quarter and one is number', () => { + // Arrange + const mockDatasetOptions: DatasetOptionsWithTicks = { + datasets: [], + ticks: [ + [1, 2023], + [2, 2023], + [3, 2023], + ], + ticksKey: [ + { key: 'quarter', value: '' }, + { key: 'year', value: '' }, + ], + }; + + const columnLabelFormats = { + quarter: { + columnType: 'number', + style: 'date', + convertNumberTo: 'quarter', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + multiplier: 1, + prefix: '', + suffix: '', + replaceMissingDataWith: 0, + makeLabelHumanReadable: true, + } as ColumnLabelFormat, + year: { + columnType: 'number', + style: 'number', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + multiplier: 1, + prefix: '', + suffix: '', + numberSeparatorStyle: null, + replaceMissingDataWith: 0, + makeLabelHumanReadable: true, + } as ColumnLabelFormat, + }; + + // Act + const result = barSeriesBuilder_labels({ + datasetOptions: mockDatasetOptions, + columnLabelFormats, + xAxisKeys: ['quarter', 'year'], + }); + + console.log('result', result[0]); + + // Assert + expect(result).toHaveLength(3); + expect(result[0]).toContain('Q1'); + expect(result[0]).toContain('2023'); + expect(result[1]).toContain('Q2'); + expect(result[2]).toContain('Q3'); + }); + + it('should return null dateTicks when columnLabelFormat does not have date style', () => { + // Arrange + const mockDatasetOptions: DatasetOptionsWithTicks = { + datasets: [], + ticks: [['Product A'], ['Product B'], ['Product C']], + ticksKey: [{ key: 'product', value: '' }], + }; + + const columnLabelFormats = { + product: { + columnType: 'string', + style: 'string', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + multiplier: 1, + prefix: '', + suffix: '', + replaceMissingDataWith: 0, + makeLabelHumanReadable: true, + } as unknown as ColumnLabelFormat, + }; + + // Act + const result = barSeriesBuilder_labels({ + datasetOptions: mockDatasetOptions, + columnLabelFormats, + xAxisKeys: ['product'], + }); + + // Assert + expect(result).toHaveLength(3); + expect(result[0]).toBe('Product A'); + expect(result[1]).toBe('Product B'); + expect(result[2]).toBe('Product C'); + }); + + it('should return date ticks when columnType is number but style is date', () => { + // Arrange + const mockDatasetOptions: DatasetOptionsWithTicks = { + datasets: [], + ticks: [['2024-01-15'], ['2024-01-16'], ['2024-01-17']], + ticksKey: [{ key: 'timestamp', value: '' }], + }; + + const columnLabelFormats = { + timestamp: { + columnType: 'number', + style: 'date', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + multiplier: 1, + prefix: '', + suffix: '', + replaceMissingDataWith: 0, + makeLabelHumanReadable: true, + } as ColumnLabelFormat, + }; + + // Act + const result = barSeriesBuilder_labels({ + datasetOptions: mockDatasetOptions, + columnLabelFormats, + xAxisKeys: ['timestamp'], + }); + + // Assert + expect(result).toHaveLength(3); + expect(result[0]).toBeInstanceOf(Date); + expect(result[1]).toBeInstanceOf(Date); + expect(result[2]).toBeInstanceOf(Date); + }); +}); diff --git a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts index 22837d26b..3da9c1d55 100644 --- a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts +++ b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts @@ -360,6 +360,12 @@ export const barSeriesBuilder_labels = ({ return dateTicks; } + const containsADateStyle = datasetOptions.ticksKey.some((tick) => { + const selectedColumnLabelFormat = columnLabelFormats[tick.key]; + return selectedColumnLabelFormat?.style === 'date'; + }); + const selectedJoinCharacter = containsADateStyle ? JOIN_CHARACTER_DATE : JOIN_CHARACTER; + const labels = datasetOptions.ticks.flatMap((item) => { return item .map((item, index) => { @@ -367,7 +373,7 @@ export const barSeriesBuilder_labels = ({ const columnLabelFormat = columnLabelFormats[key]; return formatLabel(item, columnLabelFormat); }) - .join(JOIN_CHARACTER); + .join(selectedJoinCharacter); }); return labels; diff --git a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/createTickDate.ts b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/createTickDate.ts index 38f5cbbb4..65883d89b 100644 --- a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/createTickDate.ts +++ b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/createTickDate.ts @@ -45,6 +45,7 @@ export const createTickDates = ( } const isDoubleXAxis = xAxisKeys.length === 2; + console.log('isDoubleXAxis', isDoubleXAxis); if (isDoubleXAxis) { const oneIsAQuarter = xColumnLabelFormats.findIndex( (format) => format.convertNumberTo === 'quarter' && format.columnType === 'number' @@ -52,6 +53,8 @@ export const createTickDates = ( const oneIsANumber = xColumnLabelFormats.findIndex( (format) => format.columnType === 'number' && format.style === 'number' ); + console.log('oneIsAQuarter', oneIsAQuarter); + console.log('oneIsANumber', oneIsANumber); if (oneIsAQuarter !== -1 && oneIsANumber !== -1) { return createQuarterTickDates(ticks, xColumnLabelFormats, oneIsAQuarter); } diff --git a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/lineSeriesBuilder.test.ts b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/lineSeriesBuilder.test.ts index d7665f2e9..0a80756c1 100644 --- a/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/lineSeriesBuilder.test.ts +++ b/apps/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/lineSeriesBuilder.test.ts @@ -330,6 +330,7 @@ describe('lineSeriesBuilder', () => { const labels = lineSeriesBuilder_labels(props); expect(labels).toHaveLength(3); + console.log('labels', labels[0]); expect(labels[0]).toBe('formatted-2023-01-01 formatted-A'); expect(labels[1]).toBe('formatted-2023-01-02 formatted-B'); expect(labels[2]).toBe('formatted-2023-01-03 formatted-A');