Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import { Dict } from '@visactor/vutils';
import { getChartSpecWithContext } from '../../src/atom/chartGenerator/spec';
import type { GenerateChartCellContext } from '../../src/atom/chartGenerator/type';
import { ChartType } from '../../src/types';
import { BASIC_HEAT_MAP_COLOR_THEMES } from '../../src/atom/chartGenerator/spec/constants';
import { builtinThemeMap } from '../../src/atom/chartGenerator/const';
import { BuiltinThemeType } from '../../src/atom/chartGenerator/const';
import { COLOR_THEMES } from '../../src/atom/chartGenerator/spec/constants';

const CHART_TYPE_LIST = [
'Bar Chart',
'Line Chart',
'Area Chart',
'Pie Chart',
'Scatter Plot',
'Word Cloud',
'Rose Chart',
'Radar Chart',
'Sankey Chart',
'Funnel Chart',
'Dual Axis Chart',
'Waterfall Chart',
'Box Plot',
'Linear Progress chart',
'Circular Progress chart',
'Liquid Chart',
'Bubble Circle Packing',
'Map Chart',
'Range Column Chart',
'Sunburst Chart',
'Treemap Chart',
'Gauge Chart',
'Basic Heat Map',
'Venn Chart',
'Dynamic Bar Chart'
];

const items = [
'Asset Liability Ratio',
'Asset Liability Ratio (Deducting Advance Payments)',
'Debt-to-long Capital Ratio',
'Long Term Asset Suitability Ratio',
'Equity Multiplier',
'Equity Ratio of Current Liability',
'Interest Bearing Debt / Fully Invested Capital',
'Current Liability / Total Liabilities',
'Capital Fixation Ratio',
'Expected Default Frequency'
];
const rawData = [
1.0, 0.594527, 0.492963, -0.160995, 0.723664, 0.658646, -0.857474, 0.320706, -0.284634, -0.091423, 0.594527, 1.0,
0.724546, -0.099318, 0.540639, 0.49214, -0.554039, 0.17127, -0.265259, 0.068577, 0.492963, 0.724546, 1.0, -0.091338,
0.450542, 0.375839, -0.524955, 0.300627, -0.198362, 0.033209, -0.160995, -0.099318, -0.091338, 1.0, -0.049872,
-0.028452, 0.157157, 0.009742, -0.162374, 0.155095, 0.723664, 0.540639, 0.450542, -0.049872, 1.0, 0.951933, -0.651767,
0.079052, -0.535984, 0.00798, 0.658646, 0.49214, 0.375839, -0.028452, 0.951933, 1.0, -0.543147, -0.106139, -0.52232,
0.011466, -0.857474, -0.554039, -0.524955, 0.157157, -0.651767, -0.543147, 1.0, -0.595016, 0.310521, 0.066397,
0.320706, 0.17127, 0.300627, 0.009742, 0.079052, -0.106139, -0.595016, 1.0, -0.105199, -0.064886, -0.284634,
-0.265259, -0.198362, -0.162374, -0.535984, -0.52232, 0.310521, -0.105199, 1.0, -0.080153, -0.091423, 0.068577,
0.033209, 0.155095, 0.00798, 0.011466, 0.066397, -0.064886, -0.080153, 1.0
];
interface DataPoint {
var1: string;
var2: string;
value: number;
}
const data: DataPoint[] = [];
for (let i = 0; i < items.length; i++) {
for (let j = 0; j < items.length; j++) {
data.push({
var1: items[i],
var2: items[j],
value: rawData[i * items.length + j]
});
}
}

describe('getChartSpecWithContext', () => {
const baseContext = {
chartTypeList: CHART_TYPE_LIST,
cell: { x: 'var1', y: 'var2', size: 'value' },
dataTable: data,
chartType: ChartType.BasicHeatMap.toUpperCase(),
totalTime: 5
};

// test for `basicHeatMapColor`
it('should generate correct linear color scale for heatmap', () => {
const context = { ...baseContext };
const result = getChartSpecWithContext(context);

expect(result.spec.color).toEqual({
type: 'linear',
domain: [
{
dataId: 'data',
fields: [context.cell.size]
}
],
range: BASIC_HEAT_MAP_COLOR_THEMES
});
});

// test for `basicHeatMapSeries`
it('should generate correct series dimension for heatmap', () => {
const context = { ...baseContext };
const result = getChartSpecWithContext(context);

expect(result.spec.series[0]).toEqual({
type: 'heatmap',
regionId: 'region0',
xField: context.cell.x,
yField: context.cell.y,
valueField: context.cell.size,
cell: {
style: {
fill: {
field: context.cell.size,
scale: 'color'
}
}
}
});
});

// test for `basicHeatMapRegion`
it('should generate correct region dimensions for heatmap', () => {
const context = { ...baseContext };
const result = getChartSpecWithContext(context);

expect(result.spec.region).toEqual([
{
id: 'region0',
width: 200,
height: 200,
padding: { top: 40 }
}
]);
});

// test for `basicHeatMapAxes`
it('should generate axes with correct rotation and dimensions', () => {
const context = { ...baseContext };
const result = getChartSpecWithContext(context);

expect(result.spec.axes[0]).toMatchObject({
orient: 'bottom',
type: 'band',
label: {
space: 10,
style: {
textAlign: 'left',
textBaseline: 'middle',
angle: 90,
fontSize: 8
}
},
height: expect.any(Function)
});

expect(result.spec.axes[1]).toMatchObject({
orient: 'left',
type: 'band',
grid: { visible: false },
domainLine: { visible: false },
label: { space: 10, style: { fontSize: 8 } },
bandPadding: 0
});

const heightFunc = result.spec.axes[0].height;
expect(heightFunc({ height: 400 })).toBe(400 - 314);
});

// test for `basicHeatMapLegend`
it('should position legend on the right for heatmap', () => {
const context = { ...baseContext };
const result = getChartSpecWithContext(context);

expect(result.spec.legends).toEqual({
visible: true,
orient: 'right',
position: 'start',
type: 'color',
field: 'value'
});
});

it('should handle missing cell fields gracefully', () => {
const context = {
chartTypeList: CHART_TYPE_LIST,
cell: {},
dataTable: data,
chartType: ChartType.BasicHeatMap.toUpperCase()
};

const result = getChartSpecWithContext(context);
expect(result.spec).toBeDefined();
expect(result.spec.type).toBe('heatmap');
});

it('should handle missing dataTable fields gracefully', () => {
const context = {
chartTypeList: CHART_TYPE_LIST,
cell: { x: 'var1', y: 'var2', size: 'value' },
dataTable: [{}],
chartType: ChartType.BasicHeatMap.toUpperCase()
};

const result = getChartSpecWithContext(context);
expect(result.spec).toBeDefined();
expect(result.spec.type).toBe('heatmap');
});
});