mirror of
https://github.com/apache/superset.git
synced 2026-05-12 19:35:17 +00:00
test(plugin-chart-echarts): regression guards for temporal x-axis labels on timeseries charts (#39208)
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
AnnotationSourceType,
|
||||
AnnotationStyle,
|
||||
AnnotationType,
|
||||
AxisType,
|
||||
ComparisonType,
|
||||
DataRecord,
|
||||
EventAnnotationLayer,
|
||||
@@ -1472,6 +1473,118 @@ test('x-axis formatter deduplicates consecutive identical labels for coarse time
|
||||
expect(label4).toBe('');
|
||||
});
|
||||
|
||||
test('numeric x coltype routes through the number formatter (not the time formatter)', () => {
|
||||
// Regression guard for echarts-timeseries-epoch-x-axis-labels investigation.
|
||||
// When the query reports a Numeric x-axis coltype (including epoch-ms-like
|
||||
// values), Timeseries transformProps must pick the Value axis and run the
|
||||
// label through getNumberFormatter, not the time formatter. If this ever
|
||||
// changes, epoch-ms values that arrive as Numeric would suddenly be treated
|
||||
// as Date instances and could render "NaN" — the symptom that prompted this
|
||||
// investigation.
|
||||
const ts1 = 1745784000000;
|
||||
const ts2 = 1745870400000;
|
||||
const chartProps = createTestChartProps({
|
||||
formData: {
|
||||
metrics: ['metric'],
|
||||
granularity_sqla: 'ds',
|
||||
x_axis: '__timestamp',
|
||||
},
|
||||
queriesData: [
|
||||
createTestQueryData(
|
||||
[
|
||||
{ __timestamp: ts1, metric: 10 },
|
||||
{ __timestamp: ts2, metric: 20 },
|
||||
],
|
||||
{
|
||||
colnames: ['__timestamp', 'metric'],
|
||||
coltypes: [GenericDataType.Numeric, GenericDataType.Numeric],
|
||||
},
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
const { echartOptions } = transformProps(chartProps);
|
||||
const xAxis = echartOptions.xAxis as {
|
||||
type: string;
|
||||
axisLabel: { formatter: (v: number) => string };
|
||||
};
|
||||
|
||||
expect(xAxis.type).toBe(AxisType.Value);
|
||||
const label = xAxis.axisLabel.formatter(ts1);
|
||||
expect(typeof label).toBe('string');
|
||||
expect(label).not.toMatch(/NaN/);
|
||||
});
|
||||
|
||||
test('xAxisForceCategorical forces Category axis regardless of Numeric coltype', () => {
|
||||
const ts1 = 1745784000000;
|
||||
const ts2 = 1745870400000;
|
||||
const chartProps = createTestChartProps({
|
||||
formData: {
|
||||
metrics: ['metric'],
|
||||
granularity_sqla: 'ds',
|
||||
x_axis: '__timestamp',
|
||||
xAxisForceCategorical: true,
|
||||
},
|
||||
queriesData: [
|
||||
createTestQueryData(
|
||||
[
|
||||
{ __timestamp: ts1, metric: 10 },
|
||||
{ __timestamp: ts2, metric: 20 },
|
||||
],
|
||||
{
|
||||
colnames: ['__timestamp', 'metric'],
|
||||
coltypes: [GenericDataType.Numeric, GenericDataType.Numeric],
|
||||
},
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
const { echartOptions } = transformProps(chartProps);
|
||||
const xAxis = echartOptions.xAxis as { type: string };
|
||||
|
||||
expect(xAxis.type).toBe(AxisType.Category);
|
||||
});
|
||||
|
||||
test('temporal x coltype wires the time formatter and Time axis', () => {
|
||||
// Regression guard: the happy path for time-series charts. Ensures that
|
||||
// Temporal coltype keeps routing through the TimeFormatter so a refactor
|
||||
// does not accidentally drop Date handling (the feared regression that
|
||||
// sparked this investigation).
|
||||
const ts1 = 1745784000000;
|
||||
const ts2 = 1745870400000;
|
||||
const chartProps = createTestChartProps({
|
||||
formData: {
|
||||
metrics: ['metric'],
|
||||
granularity_sqla: 'ds',
|
||||
x_axis: '__timestamp',
|
||||
},
|
||||
queriesData: [
|
||||
createTestQueryData(
|
||||
[
|
||||
{ __timestamp: ts1, metric: 10 },
|
||||
{ __timestamp: ts2, metric: 20 },
|
||||
],
|
||||
{
|
||||
colnames: ['__timestamp', 'metric'],
|
||||
coltypes: [GenericDataType.Temporal, GenericDataType.Numeric],
|
||||
},
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
const { echartOptions } = transformProps(chartProps);
|
||||
const xAxis = echartOptions.xAxis as {
|
||||
type: string;
|
||||
axisLabel: { formatter: (v: Date) => string };
|
||||
};
|
||||
|
||||
expect(xAxis.type).toBe(AxisType.Time);
|
||||
const label = xAxis.axisLabel.formatter(new Date(ts1));
|
||||
expect(typeof label).toBe('string');
|
||||
expect(label).not.toMatch(/NaN/);
|
||||
expect(label).not.toBe(String(ts1));
|
||||
});
|
||||
|
||||
test('should assign distinct dash patterns for multiple time offsets consistently', () => {
|
||||
const queriesDataWithMultipleOffsets = [
|
||||
createTestQueryData([
|
||||
|
||||
Reference in New Issue
Block a user