mirror of https://github.com/buster-so/buster.git
create unit tests for the tooltip helper and date ticks
This commit is contained in:
parent
572bbf72f5
commit
25f0c120fa
|
@ -41,8 +41,8 @@ describe('Chat API Requests', () => {
|
|||
];
|
||||
|
||||
// Setup mock response
|
||||
(mainApiV2.get as any).mockResolvedValueOnce({
|
||||
data: { data: mockChats }
|
||||
(mainApiV2.get as any).mockResolvedValueOnce({
|
||||
data: { data: mockChats },
|
||||
});
|
||||
|
||||
// Import the function we want to test
|
||||
|
|
|
@ -1,161 +1,133 @@
|
|||
import type { ColumnLabelFormat } from '@buster/server-shared/metrics';
|
||||
import type {
|
||||
BarControllerDatasetOptions,
|
||||
Chart,
|
||||
ChartDatasetProperties,
|
||||
TooltipItem,
|
||||
} from 'chart.js';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
import type { Chart, ChartTypeRegistry, TooltipItem } from 'chart.js';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { formatLabel } from '@/lib/columnFormatter';
|
||||
import { barAndLineTooltipHelper } from './barAndLineTooltipHelper';
|
||||
import { getPercentage } from './helpers';
|
||||
|
||||
type MockDataset = Partial<
|
||||
ChartDatasetProperties<'bar', number[]> & BarControllerDatasetOptions
|
||||
> & {
|
||||
type: 'bar';
|
||||
label: string;
|
||||
data: number[];
|
||||
tooltipData: { key: string; value: number }[][];
|
||||
yAxisKey: string;
|
||||
xAxisKeys: string[];
|
||||
};
|
||||
// Mock dependencies
|
||||
vi.mock('@/lib/columnFormatter', () => ({
|
||||
formatLabel: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('./helpers', () => ({
|
||||
getPercentage: vi.fn(),
|
||||
}));
|
||||
|
||||
const mockFormatLabel = vi.mocked(formatLabel);
|
||||
const mockGetPercentage = vi.mocked(getPercentage);
|
||||
|
||||
describe('barAndLineTooltipHelper', () => {
|
||||
// Mock data setup
|
||||
const mockChart = {
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
data: [100, 200, 300],
|
||||
label: 'Dataset 1',
|
||||
type: 'bar' as const,
|
||||
hidden: false,
|
||||
isTrendline: false,
|
||||
},
|
||||
{
|
||||
data: [150, 250, 350],
|
||||
label: 'Dataset 2',
|
||||
type: 'bar' as const,
|
||||
hidden: false,
|
||||
isTrendline: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
$totalizer: {
|
||||
stackTotals: [250, 450, 650],
|
||||
seriesTotals: [600, 750],
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
getPixelForValue: () => 0,
|
||||
},
|
||||
y: {
|
||||
getPixelForValue: () => 0,
|
||||
},
|
||||
},
|
||||
} as unknown as Chart;
|
||||
const mockChart = {} as Chart;
|
||||
const mockColumnLabelFormats = {} as NonNullable<ChartConfigProps['columnLabelFormats']>;
|
||||
const mockKeyToUsePercentage = ['percentage_metric'];
|
||||
|
||||
const mockColumnLabelFormats: Record<string, ColumnLabelFormat> = {
|
||||
value: {
|
||||
columnType: 'number',
|
||||
style: 'number',
|
||||
} as ColumnLabelFormat,
|
||||
percentage: {
|
||||
columnType: 'number',
|
||||
style: 'percent',
|
||||
} as ColumnLabelFormat,
|
||||
label: {
|
||||
columnType: 'text',
|
||||
style: 'string',
|
||||
} as ColumnLabelFormat,
|
||||
};
|
||||
|
||||
const createMockDataset = (overrides = {}): MockDataset => ({
|
||||
type: 'bar',
|
||||
label: 'Test Dataset',
|
||||
backgroundColor: '#FF0000',
|
||||
borderColor: '#FF0000',
|
||||
yAxisKey: 'value',
|
||||
data: [250, 300, 350],
|
||||
xAxisKeys: ['x'],
|
||||
barPercentage: 0.9,
|
||||
categoryPercentage: 0.8,
|
||||
tooltipData: [
|
||||
[
|
||||
{ key: 'value', value: 250 },
|
||||
{ key: 'percentage', value: 25 },
|
||||
],
|
||||
],
|
||||
hidden: false,
|
||||
...overrides,
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockFormatLabel.mockReturnValue('formatted_value');
|
||||
mockGetPercentage.mockReturnValue('25%');
|
||||
});
|
||||
|
||||
const createMockDataPoint = (overrides = {}): TooltipItem<'bar'> => ({
|
||||
datasetIndex: 0,
|
||||
dataIndex: 0,
|
||||
dataset: createMockDataset(),
|
||||
parsed: { x: 0, y: 250 },
|
||||
raw: 250,
|
||||
formattedValue: '250',
|
||||
label: 'Test Dataset',
|
||||
chart: mockChart,
|
||||
element: {} as any,
|
||||
...overrides,
|
||||
});
|
||||
it('should format single dataset tooltip correctly when hasMultipleShownDatasets is false', () => {
|
||||
// Arrange
|
||||
const mockDataPoints: TooltipItem<keyof ChartTypeRegistry>[] = [
|
||||
{
|
||||
dataset: {
|
||||
label: 'Revenue Dataset',
|
||||
backgroundColor: '#ff0000',
|
||||
tooltipData: [[{ key: 'revenue', value: 1000 }]],
|
||||
yAxisKey: 'revenue',
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 0,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
];
|
||||
|
||||
it('should correctly format tooltip items', () => {
|
||||
const keyToUsePercentage = ['percentage'];
|
||||
const hasMultipleShownDatasets = true;
|
||||
const mockDataPoint = createMockDataPoint();
|
||||
mockFormatLabel
|
||||
.mockReturnValueOnce('Revenue') // for formattedLabel
|
||||
.mockReturnValueOnce('$1,000'); // for formattedValue
|
||||
mockGetPercentage.mockReturnValue('50%');
|
||||
|
||||
// Act
|
||||
const result = barAndLineTooltipHelper(
|
||||
[mockDataPoint],
|
||||
mockDataPoints,
|
||||
mockChart,
|
||||
mockColumnLabelFormats,
|
||||
keyToUsePercentage,
|
||||
hasMultipleShownDatasets,
|
||||
[],
|
||||
false, // hasMultipleShownDatasets = false
|
||||
undefined
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
// Check the value item
|
||||
// Assert
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual({
|
||||
seriesType: 'bar',
|
||||
color: '#FF0000',
|
||||
color: '#ff0000',
|
||||
usePercentage: false,
|
||||
formattedLabel: 'Test Dataset',
|
||||
formattedLabel: 'Revenue',
|
||||
values: [
|
||||
{
|
||||
formattedValue: '250',
|
||||
formattedLabel: 'Test Dataset',
|
||||
formattedPercentage: '100%',
|
||||
formattedValue: '$1,000',
|
||||
formattedLabel: 'Revenue',
|
||||
formattedPercentage: '50%',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle stacked percentage mode', () => {
|
||||
it('should use dataset label when hasMultipleShownDatasets is true', () => {
|
||||
// Arrange
|
||||
const mockDataPoints: TooltipItem<keyof ChartTypeRegistry>[] = [
|
||||
{
|
||||
dataset: {
|
||||
label: 'Revenue Dataset',
|
||||
backgroundColor: '#ff0000',
|
||||
tooltipData: [[{ key: 'revenue', value: 1000 }]],
|
||||
yAxisKey: 'revenue',
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 0,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
];
|
||||
|
||||
mockFormatLabel.mockReturnValue('$1,000');
|
||||
mockGetPercentage.mockReturnValue('25%');
|
||||
|
||||
// Act
|
||||
const result = barAndLineTooltipHelper(
|
||||
[createMockDataPoint()],
|
||||
mockDataPoints,
|
||||
mockChart,
|
||||
mockColumnLabelFormats,
|
||||
[],
|
||||
true,
|
||||
'stacked'
|
||||
true, // hasMultipleShownDatasets = true
|
||||
undefined
|
||||
);
|
||||
|
||||
expect(result.every((item) => item.usePercentage)).toBe(true);
|
||||
result.forEach((item) => {
|
||||
expect(item.values[0].formattedPercentage).toBeDefined();
|
||||
});
|
||||
// Assert
|
||||
expect(mockFormatLabel).toHaveBeenCalledTimes(1); // Only for formattedValue
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].formattedLabel).toBe('Revenue Dataset'); // Uses dataset.label
|
||||
expect(result[0].values[0].formattedLabel).toBe('Revenue Dataset');
|
||||
});
|
||||
|
||||
it('should handle empty tooltip data', () => {
|
||||
const emptyDataset = createMockDataset({ tooltipData: [[]] });
|
||||
const emptyDataPoint = createMockDataPoint({ dataset: emptyDataset });
|
||||
it('should return empty array when tooltipData is missing', () => {
|
||||
// Arrange
|
||||
const mockDataPoints: TooltipItem<keyof ChartTypeRegistry>[] = [
|
||||
{
|
||||
dataset: {
|
||||
label: 'Revenue Dataset',
|
||||
backgroundColor: '#ff0000',
|
||||
tooltipData: [null], // No data at this index
|
||||
yAxisKey: 'revenue',
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 0,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
];
|
||||
|
||||
// Act
|
||||
const result = barAndLineTooltipHelper(
|
||||
[emptyDataPoint],
|
||||
mockDataPoints,
|
||||
mockChart,
|
||||
mockColumnLabelFormats,
|
||||
[],
|
||||
|
@ -163,15 +135,33 @@ describe('barAndLineTooltipHelper', () => {
|
|||
undefined
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(result).toHaveLength(0);
|
||||
expect(mockFormatLabel).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use default color when yAxisKey does not match item key', () => {
|
||||
const modifiedDataset = createMockDataset({ yAxisKey: 'different_key' });
|
||||
const modifiedDataPoint = createMockDataPoint({ dataset: modifiedDataset });
|
||||
it('should use backgroundColor when yAxisKey matches item key', () => {
|
||||
// Arrange
|
||||
const mockDataPoints: TooltipItem<keyof ChartTypeRegistry>[] = [
|
||||
{
|
||||
dataset: {
|
||||
label: 'Revenue Dataset',
|
||||
backgroundColor: '#ff0000',
|
||||
borderColor: '#00ff00',
|
||||
tooltipData: [[{ key: 'revenue', value: 1000 }]],
|
||||
yAxisKey: 'revenue', // Matches item.key
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 0,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
];
|
||||
|
||||
mockFormatLabel.mockReturnValue('formatted');
|
||||
mockGetPercentage.mockReturnValue('30%');
|
||||
|
||||
// Act
|
||||
const result = barAndLineTooltipHelper(
|
||||
[modifiedDataPoint],
|
||||
mockDataPoints,
|
||||
mockChart,
|
||||
mockColumnLabelFormats,
|
||||
[],
|
||||
|
@ -179,6 +169,93 @@ describe('barAndLineTooltipHelper', () => {
|
|||
undefined
|
||||
);
|
||||
|
||||
expect(result.every((item) => item.color === undefined)).toBe(true);
|
||||
// Assert
|
||||
expect(result[0].color).toBe('#ff0000'); // Uses backgroundColor since yAxisKey matches
|
||||
});
|
||||
|
||||
it('should use undefined color when yAxisKey does not match item key', () => {
|
||||
// Arrange
|
||||
const mockDataPoints: TooltipItem<keyof ChartTypeRegistry>[] = [
|
||||
{
|
||||
dataset: {
|
||||
label: 'Revenue Dataset',
|
||||
backgroundColor: '#ff0000',
|
||||
tooltipData: [[{ key: 'revenue', value: 1000 }]],
|
||||
yAxisKey: 'different_key', // Does NOT match item.key
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 0,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
];
|
||||
|
||||
mockFormatLabel.mockReturnValue('formatted');
|
||||
mockGetPercentage.mockReturnValue('30%');
|
||||
|
||||
// Act
|
||||
const result = barAndLineTooltipHelper(
|
||||
mockDataPoints,
|
||||
mockChart,
|
||||
mockColumnLabelFormats,
|
||||
[],
|
||||
false,
|
||||
undefined
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(result[0].color).toBeUndefined(); // Color is undefined when yAxisKey doesn't match
|
||||
});
|
||||
|
||||
it('should handle percentage mode with data reversal and usePercentage flags', () => {
|
||||
// Arrange
|
||||
const mockDataPoints: TooltipItem<keyof ChartTypeRegistry>[] = [
|
||||
{
|
||||
dataset: {
|
||||
label: 'First Dataset',
|
||||
backgroundColor: '#ff0000',
|
||||
tooltipData: [[{ key: 'revenue', value: 500 }]],
|
||||
yAxisKey: 'revenue',
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 0,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
{
|
||||
dataset: {
|
||||
label: 'percentage_metric', // This should trigger usePercentage via keyToUsePercentage
|
||||
backgroundColor: '#00ff00',
|
||||
tooltipData: [[{ key: 'percentage', value: 75 }]],
|
||||
yAxisKey: 'percentage',
|
||||
},
|
||||
dataIndex: 0,
|
||||
datasetIndex: 1,
|
||||
} as unknown as TooltipItem<keyof ChartTypeRegistry>,
|
||||
];
|
||||
|
||||
mockFormatLabel.mockReturnValue('formatted');
|
||||
mockGetPercentage.mockReturnValue('40%');
|
||||
|
||||
// Act
|
||||
const result = barAndLineTooltipHelper(
|
||||
mockDataPoints,
|
||||
mockChart,
|
||||
mockColumnLabelFormats,
|
||||
['percentage_metric'],
|
||||
true,
|
||||
'stacked' // percentageMode = 'stacked'
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
// Due to percentageMode='stacked', dataPoints are reversed
|
||||
// First result should be from 'percentage_metric' dataset (originally second)
|
||||
expect(result[0].usePercentage).toBe(true); // Due to both percentageMode AND keyToUsePercentage
|
||||
expect(result[0].formattedLabel).toBe('percentage_metric');
|
||||
|
||||
// Second result should be from 'First Dataset' (originally first)
|
||||
expect(result[1].usePercentage).toBe(true); // Due to percentageMode
|
||||
expect(result[1].formattedLabel).toBe('First Dataset');
|
||||
|
||||
// Verify getPercentage was called for both items
|
||||
expect(mockGetPercentage).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
import type { ColumnLabelFormat } from '@buster/server-shared/metrics';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { createTickDates } from './createTickDate';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@/lib/date', () => ({
|
||||
createDayjsDate: vi.fn((dateStr) => ({
|
||||
toDate: () => new Date(dateStr),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/columnFormatter', () => ({
|
||||
formatLabel: vi.fn((value, format) => {
|
||||
if (format.columnType === 'number' && format.style === 'number') {
|
||||
return String(value);
|
||||
}
|
||||
if (format.columnType === 'date' && format.style === 'date') {
|
||||
return String(value);
|
||||
}
|
||||
return String(value);
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('createTickDates', () => {
|
||||
const createMockFormat = (overrides: Partial<ColumnLabelFormat>): ColumnLabelFormat => ({
|
||||
columnType: 'text',
|
||||
style: 'string',
|
||||
displayName: '',
|
||||
numberSeparatorStyle: ',',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
multiplier: 1,
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
replaceMissingDataWith: 0,
|
||||
useRelativeTime: false,
|
||||
isUTC: false,
|
||||
makeLabelHumanReadable: true,
|
||||
compactNumbers: false,
|
||||
currency: 'USD',
|
||||
dateFormat: 'auto',
|
||||
convertNumberTo: null,
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it('should return null when no date labels are used (text column)', () => {
|
||||
const ticks = [['2023-01-01', '2023-02-01']];
|
||||
const xAxisKeys = ['date'];
|
||||
const columnLabelFormats = {
|
||||
date: createMockFormat({ columnType: 'text', style: 'string' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when no date labels are used (number column with number style)', () => {
|
||||
const ticks = [['100', '200']];
|
||||
const xAxisKeys = ['value'];
|
||||
const columnLabelFormats = {
|
||||
value: createMockFormat({ columnType: 'number', style: 'number' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should process single date axis with date column type and date style', () => {
|
||||
const ticks = [['2023-01-01'], ['2023-02-01'], ['2023-03-01']];
|
||||
const xAxisKeys = ['date'];
|
||||
const columnLabelFormats = {
|
||||
date: createMockFormat({ columnType: 'date', style: 'date' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result?.[0]).toBeInstanceOf(Date);
|
||||
expect(result?.[1]).toBeInstanceOf(Date);
|
||||
expect(result?.[2]).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should process single date axis with number column type and date style', () => {
|
||||
const ticks = [['2023-01-01'], ['2023-02-01']];
|
||||
const xAxisKeys = ['timestamp'];
|
||||
const columnLabelFormats = {
|
||||
timestamp: createMockFormat({ columnType: 'number', style: 'date' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result?.[0]).toBeInstanceOf(Date);
|
||||
expect(result?.[1]).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should process single quarter axis correctly', () => {
|
||||
const ticks = [
|
||||
['2023', '1'],
|
||||
['2023', '2'],
|
||||
['2023', '3'],
|
||||
['2023', '4'],
|
||||
];
|
||||
const xAxisKeys = ['year', 'quarter'];
|
||||
const columnLabelFormats = {
|
||||
year: createMockFormat({ columnType: 'number', style: 'number' }),
|
||||
quarter: createMockFormat({
|
||||
columnType: 'number',
|
||||
style: 'date',
|
||||
convertNumberTo: 'quarter',
|
||||
}),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toHaveLength(4);
|
||||
expect(result?.[0]).toBe('2023 Q1');
|
||||
expect(result?.[1]).toBe('2023 Q2');
|
||||
expect(result?.[2]).toBe('2023 Q3');
|
||||
expect(result?.[3]).toBe('2023 Q4');
|
||||
});
|
||||
|
||||
it('should handle single axis with quarter format (single x-axis)', () => {
|
||||
const ticks = [['1'], ['2'], ['3'], ['4']];
|
||||
const xAxisKeys = ['quarter'];
|
||||
const columnLabelFormats = {
|
||||
quarter: createMockFormat({
|
||||
columnType: 'number',
|
||||
convertNumberTo: 'quarter',
|
||||
style: 'date', // Need this to trigger useDateLabels condition
|
||||
}),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
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 handle double axis with quarter and number combination', () => {
|
||||
const ticks = [
|
||||
['2023', '1'],
|
||||
['2023', '2'],
|
||||
['2024', '1'],
|
||||
];
|
||||
const xAxisKeys = ['year', 'quarter'];
|
||||
const columnLabelFormats = {
|
||||
year: createMockFormat({ columnType: 'number', style: 'number' }),
|
||||
quarter: createMockFormat({
|
||||
columnType: 'number',
|
||||
convertNumberTo: 'quarter',
|
||||
style: 'date', // Need this to trigger useDateLabels condition
|
||||
}),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result?.[0]).toBe('2023 Q1');
|
||||
expect(result?.[1]).toBe('2023 Q2');
|
||||
expect(result?.[2]).toBe('2024 Q1');
|
||||
});
|
||||
|
||||
it('should return null for double axis without quarter and number combination', () => {
|
||||
const ticks = [
|
||||
['A', 'B'],
|
||||
['C', 'D'],
|
||||
];
|
||||
const xAxisKeys = ['col1', 'col2'];
|
||||
const columnLabelFormats = {
|
||||
col1: createMockFormat({ columnType: 'text', style: 'string' }),
|
||||
col2: createMockFormat({ columnType: 'text', style: 'string' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should use default column label format when key is missing', () => {
|
||||
const ticks = [['2023-01-01']];
|
||||
const xAxisKeys = ['missingKey'];
|
||||
const columnLabelFormats = {}; // Empty object
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toBeNull(); // Should return null because default format is text/string
|
||||
});
|
||||
|
||||
it('should handle multiple ticks in single axis date scenario', () => {
|
||||
const ticks = [
|
||||
['2023-01-01', '2023-01-02'],
|
||||
['2023-02-01', '2023-02-02'],
|
||||
['2023-03-01', '2023-03-02'],
|
||||
];
|
||||
const xAxisKeys = ['date'];
|
||||
const columnLabelFormats = {
|
||||
date: createMockFormat({ columnType: 'date', style: 'date' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toHaveLength(6); // 3 ticks * 2 items each = 6 dates
|
||||
expect(result?.[0]).toBeInstanceOf(Date);
|
||||
expect(result?.[1]).toBeInstanceOf(Date);
|
||||
expect(result?.[2]).toBeInstanceOf(Date);
|
||||
expect(result?.[3]).toBeInstanceOf(Date);
|
||||
expect(result?.[4]).toBeInstanceOf(Date);
|
||||
expect(result?.[5]).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should handle quarter format with correct index positioning', () => {
|
||||
const ticks = [
|
||||
['1', '2023'],
|
||||
['2', '2023'],
|
||||
];
|
||||
const xAxisKeys = ['quarter', 'year'];
|
||||
const columnLabelFormats = {
|
||||
quarter: createMockFormat({
|
||||
columnType: 'number',
|
||||
convertNumberTo: 'quarter',
|
||||
style: 'date', // Need this to trigger useDateLabels condition
|
||||
}),
|
||||
year: createMockFormat({ columnType: 'number', style: 'number' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result?.[0]).toBe('Q1 2023'); // Quarter is at index 0
|
||||
expect(result?.[1]).toBe('Q2 2023');
|
||||
});
|
||||
|
||||
it('should return null for more than 2 x-axis keys', () => {
|
||||
const ticks = [['A', 'B', 'C']];
|
||||
const xAxisKeys = ['col1', 'col2', 'col3'];
|
||||
const columnLabelFormats = {
|
||||
col1: createMockFormat({ columnType: 'date', style: 'date' }),
|
||||
col2: createMockFormat({ columnType: 'date', style: 'date' }),
|
||||
col3: createMockFormat({ columnType: 'date', style: 'date' }),
|
||||
};
|
||||
|
||||
const result = createTickDates(ticks, xAxisKeys, columnLabelFormats);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
|
@ -73,7 +73,7 @@ const createQuarterTickDates = (
|
|||
// Format is '[Q]Q' - keep [Q] literal, replace the second Q
|
||||
// Then remove the brackets to get clean output like Q1, Q2, etc.
|
||||
return DEFAULT_DATE_FORMAT_QUARTER.replace(/(?<!\[)Q(?!\])/g, String(item)).replace(
|
||||
/[\[\]]/g,
|
||||
/[[\]]/g,
|
||||
''
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue