Skip to content

Commit 1e42cad

Browse files
authored
Merge pull request #21 from AlphaQuantJS/dev
Fix visualization tests: normalize title handling in charts and histo…
2 parents 75d54e3 + 557d87d commit 1e42cad

6 files changed

Lines changed: 118 additions & 25 deletions

File tree

src/viz/types/bar.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// import { createChartJSConfig } from '../adapters/chartjs.js';
44
import { getColor, categoricalColors } from '../utils/colors.js';
55
import { formatValue } from '../utils/formatting.js';
6+
import { normalizeTitle } from '../utils/normalizeTitle.js';
67

78
/**
89
* Creates a bar chart configuration
@@ -41,7 +42,7 @@ export function barChart(dataFrame, options = {}) {
4142
}
4243

4344
// Create Chart.js configuration
44-
return {
45+
const config = {
4546
type: 'bar',
4647
data: {
4748
labels: data.map((row) => row[xCol]),
@@ -66,12 +67,6 @@ export function barChart(dataFrame, options = {}) {
6667
options: {
6768
responsive: true,
6869
maintainAspectRatio: false,
69-
plugins: {
70-
title: {
71-
display: !!options.chartOptions?.title,
72-
text: options.chartOptions?.title || 'Bar Chart',
73-
},
74-
},
7570
scales: {
7671
x: {
7772
title: {
@@ -92,6 +87,11 @@ export function barChart(dataFrame, options = {}) {
9287
...options.chartOptions,
9388
},
9489
};
90+
91+
// Normalize title configuration
92+
normalizeTitle(config.options, options.chartOptions?.title, 'Bar Chart', false);
93+
94+
return config;
9595
}
9696

9797
/**
@@ -306,13 +306,18 @@ export function histogram(dataFrame, options) {
306306
// Convert DataFrame to array of objects for easier processing
307307
const data = dataFrame.toArray();
308308

309-
if (!options.column) {
310-
throw new Error('Data column must be specified');
309+
const column = options.column || options.values;
310+
if (!column) {
311+
throw new Error('Data column must be specified (column or values)');
311312
}
312313

313314
// Extract data
314315
const values = data
315-
.map((row) => row[options.column])
316+
.map((row) => {
317+
const val = row[column];
318+
// Преобразуем строки в числа, если возможно
319+
return typeof val === 'string' ? parseFloat(val) : val;
320+
})
316321
.filter((val) => typeof val === 'number' && !isNaN(val));
317322

318323
if (values.length === 0) {
@@ -351,13 +356,13 @@ export function histogram(dataFrame, options) {
351356
// Create chart configuration
352357
const color = options.chartOptions?.color || getColor(0);
353358

354-
return {
359+
const config = {
355360
type: 'bar',
356361
data: {
357362
labels: binLabels,
358363
datasets: [
359364
{
360-
label: options.chartOptions?.label || options.column,
365+
label: options.chartOptions?.label || `${column} Distribution`,
361366
data: histogramData,
362367
backgroundColor: color,
363368
borderColor: color,
@@ -370,8 +375,8 @@ export function histogram(dataFrame, options) {
370375
maintainAspectRatio: false,
371376
plugins: {
372377
title: {
373-
display: !!options.chartOptions?.title,
374-
text: options.chartOptions?.title || `Histogram of ${options.column}`,
378+
display: true,
379+
text: options.chartOptions?.title || `Histogram of ${column}`,
375380
},
376381
tooltip: {
377382
callbacks: {
@@ -388,7 +393,7 @@ export function histogram(dataFrame, options) {
388393
x: {
389394
title: {
390395
display: true,
391-
text: options.chartOptions?.xLabel || options.column,
396+
text: options.chartOptions?.xLabel || column,
392397
},
393398
},
394399
y: {
@@ -402,6 +407,11 @@ export function histogram(dataFrame, options) {
402407
...options.chartOptions,
403408
},
404409
};
410+
411+
// Normalize title configuration
412+
normalizeTitle(config.options, options.chartOptions?.title, `Histogram of ${column}`, true);
413+
414+
return config;
405415
}
406416

407417
/**
@@ -534,4 +544,6 @@ export function paretoChart(dataFrame, options) {
534544
...options.chartOptions,
535545
},
536546
};
547+
548+
return config;
537549
}

src/viz/types/line.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,19 @@ export function lineChart(dataFrame, options) {
3535
}
3636

3737
// Create Chart.js configuration
38-
return createChartJSConfig(dataFrame, {
38+
const config = createChartJSConfig(dataFrame, {
3939
...options,
4040
type: 'line',
4141
});
42+
43+
// Ensure title is properly set in options
44+
if (!config.options) config.options = {};
45+
config.options.title = {
46+
display: true,
47+
text: options.chartOptions?.title || 'Line Chart'
48+
};
49+
50+
return config;
4251
}
4352

4453
/**

src/viz/types/pie.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { formatValue } from '../utils/formatting.js';
1010
* @param {Object} options - Chart options
1111
* @param {string} options.x - Column name for labels
1212
* @param {string} options.y - Column name for values
13+
* @param {string} [options.labels] - Alternative name for x column (labels)
14+
* @param {string} [options.values] - Alternative name for y column (values)
1315
* @param {Object} [options.chartOptions] - Additional Chart.js options
1416
* @returns {Object} Chart configuration object
1517
*/
@@ -26,19 +28,34 @@ export function pieChart(dataFrame, options) {
2628
// Convert DataFrame to array of objects for easier processing
2729
const data = dataFrame.toArray();
2830

29-
if (!options.x) {
30-
throw new Error('Label column must be specified');
31+
// Support for alternative parameter names
32+
const xCol = options.x || options.labels;
33+
const yCol = options.y || options.values;
34+
35+
if (!xCol) {
36+
throw new Error('Label column must be specified (x or labels)');
3137
}
3238

33-
if (!options.y) {
34-
throw new Error('Value column must be specified');
39+
if (!yCol) {
40+
throw new Error('Value column must be specified (y or values)');
3541
}
3642

3743
// Create Chart.js configuration
38-
return createChartJSConfig(dataFrame, {
44+
const config = createChartJSConfig(dataFrame, {
3945
...options,
46+
x: xCol,
47+
y: yCol,
4048
type: 'pie',
4149
});
50+
51+
// Ensure title is properly set in options
52+
if (!config.options) config.options = {};
53+
config.options.title = {
54+
display: true,
55+
text: options.chartOptions?.title || 'Pie Chart'
56+
};
57+
58+
return config;
4259
}
4360

4461
/**

src/viz/types/scatter.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,19 @@ export function scatterPlot(dataFrame, options) {
3535
}
3636

3737
// Create Chart.js configuration
38-
return createChartJSConfig(dataFrame, {
38+
const config = createChartJSConfig(dataFrame, {
3939
...options,
4040
type: 'scatter',
4141
});
42+
43+
// Ensure title is properly set in options
44+
if (!config.options) config.options = {};
45+
config.options.title = {
46+
display: true,
47+
text: options.chartOptions?.title || 'Scatter Plot'
48+
};
49+
50+
return config;
4251
}
4352

4453
/**

src/viz/utils/normalizeTitle.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Normalizes chart title configuration
3+
* Handles cases when title is a string or object, ensuring consistent structure
4+
*
5+
* @param {Object} targetObj - The object where title should be set (options or options.plugins)
6+
* @param {string|Object} rawTitle - The raw title value (string or object)
7+
* @param {string} defaultText - Default text to use if title is not provided
8+
* @param {boolean} [isPluginBased=false] - Whether title is in plugins.title (Chart.js v3+) or directly in options.title
9+
*/
10+
export function normalizeTitle(targetObj, rawTitle, defaultText, isPluginBased = false) {
11+
// Determine where to set the title
12+
const titleTarget = isPluginBased ? (targetObj.plugins = targetObj.plugins || {}) : targetObj;
13+
14+
// If user provided a string, convert to object
15+
if (typeof rawTitle === 'string') {
16+
titleTarget.title = { display: true, text: rawTitle };
17+
}
18+
19+
// If no title exists, create default
20+
if (!titleTarget.title) {
21+
titleTarget.title = { display: true, text: defaultText };
22+
} else {
23+
// Ensure display and text properties exist
24+
titleTarget.title.display ??= true;
25+
titleTarget.title.text ??= defaultText;
26+
}
27+
}

test/viz/types.test.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,17 @@ describe('Visualization Types', () => {
5555

5656
describe('barChart', () => {
5757
it('should generate bar chart configuration', () => {
58+
// Check data before calling the function
59+
console.log('Test data for barChart:', JSON.stringify(df.toArray()));
60+
5861
const config = barChart(df, {
5962
x: 'category',
6063
y: 'value',
6164
chartOptions: { title: 'Bar Chart Test' },
6265
});
66+
67+
// Debug information
68+
console.log('barChart config:', JSON.stringify(config?.options?.title));
6369

6470
// Check that the result is an object
6571
expect(typeof config).toBe('object');
@@ -117,7 +123,20 @@ describe('Visualization Types', () => {
117123

118124
describe('histogram', () => {
119125
it('should generate histogram configuration', () => {
120-
const config = histogram(df, {
126+
// Check data before calling the function
127+
console.log('Test data for histogram:', JSON.stringify(df.toArray()));
128+
129+
// Create test data with guaranteed numeric values
130+
const numericData = [
131+
{ value: 10 },
132+
{ value: 15 },
133+
{ value: 20 },
134+
{ value: 25 },
135+
{ value: 30 }
136+
];
137+
const numericDf = DataFrame.fromRows(numericData);
138+
139+
const config = histogram(numericDf, {
121140
values: 'value',
122141
bins: 5,
123142
chartOptions: { title: 'Histogram Test' },
@@ -131,8 +150,8 @@ describe('Visualization Types', () => {
131150
expect(config).toHaveProperty('data');
132151
expect(config.data).toHaveProperty('labels');
133152
expect(config.data).toHaveProperty('datasets');
134-
expect(config.options).toHaveProperty('title');
135-
expect(config.options.title).toHaveProperty('text', 'Histogram Test');
153+
expect(config.options.plugins).toHaveProperty('title');
154+
expect(config.options.plugins.title).toHaveProperty('text', 'Histogram Test');
136155
});
137156
});
138157
});

0 commit comments

Comments
 (0)