/**
* Unit tests for VChart specifications
*/
import { createLineChartSpec } from '../specs/line-chart';
import { createBarChartSpec } from '../specs/bar-chart';
import { createPieChartSpec } from '../specs/pie-chart';
import { createDashboardSpec } from '../specs/dashboard';
import type { TikTokVideoData } from '../types';
// Sample test data
const mockData: TikTokVideoData[] = [
{
videoId: '123',
title: 'Test Video 1',
views: 1000000,
likes: 50000,
comments: 2000,
shares: 1000,
watchPercent: 75,
datePublished: '2025-01-15',
duration: 45
},
{
videoId: '124',
title: 'Test Video 2',
views: 2000000,
likes: 100000,
comments: 4000,
shares: 2000,
watchPercent: 80,
datePublished: '2025-01-16',
duration: 60
},
{
videoId: '125',
title: 'Test Video 3',
views: 1500000,
likes: 75000,
comments: 3000,
shares: 1500,
watchPercent: 78,
datePublished: '2025-01-17',
duration: 50
}
];
describe('Line Chart Spec', () => {
test('should create valid line chart specification', () => {
const spec = createLineChartSpec(mockData);
expect(spec).toBeDefined();
expect(spec.type).toBe('line');
expect(spec.data).toBeDefined();
expect(spec.data.values).toBeInstanceOf(Array);
});
test('should sort data by date', () => {
const spec = createLineChartSpec(mockData);
const values = spec.data.values as any[];
expect(values.length).toBe(mockData.length);
// First item should be earliest date
expect(values[0].date).toBeDefined();
});
test('should include title', () => {
const spec = createLineChartSpec(mockData);
expect(spec.title).toBeDefined();
expect(spec.title.visible).toBe(true);
expect(spec.title.text).toBe('Views Over Time');
});
test('should configure axes', () => {
const spec = createLineChartSpec(mockData);
expect(spec.axes).toBeDefined();
expect(spec.axes).toBeInstanceOf(Array);
expect(spec.axes.length).toBeGreaterThan(0);
});
test('should handle empty data', () => {
const spec = createLineChartSpec([]);
expect(spec).toBeDefined();
expect(spec.data.values).toEqual([]);
});
});
describe('Bar Chart Spec', () => {
test('should create valid bar chart specification', () => {
const spec = createBarChartSpec(mockData);
expect(spec).toBeDefined();
expect(spec.type).toBe('bar');
expect(spec.data).toBeDefined();
expect(spec.data.values).toBeInstanceOf(Array);
});
test('should limit to top 10 videos', () => {
const manyVideos = Array.from({ length: 20 }, (_, i) => ({
...mockData[0],
videoId: `video-${i}`,
views: Math.random() * 1000000
}));
const spec = createBarChartSpec(manyVideos);
const values = spec.data.values as any[];
expect(values.length).toBeLessThanOrEqual(10);
});
test('should sort videos by views descending', () => {
const spec = createBarChartSpec(mockData);
const values = spec.data.values as any[];
// After reverse, highest should be at the end
if (values.length > 1) {
expect(values[values.length - 1].views).toBeGreaterThanOrEqual(values[0].views);
}
});
test('should truncate long titles', () => {
const longTitle = 'A'.repeat(50);
const dataWithLongTitle = [{
...mockData[0],
title: longTitle
}];
const spec = createBarChartSpec(dataWithLongTitle);
const values = spec.data.values as any[];
expect(values[0].title.length).toBeLessThan(longTitle.length);
expect(values[0].title).toContain('...');
});
test('should use horizontal direction', () => {
const spec = createBarChartSpec(mockData);
expect(spec.direction).toBe('horizontal');
});
});
describe('Pie Chart Spec', () => {
test('should create valid pie chart specification', () => {
const spec = createPieChartSpec(mockData);
expect(spec).toBeDefined();
expect(spec.type).toBe('pie');
expect(spec.data).toBeDefined();
expect(spec.data.values).toBeInstanceOf(Array);
});
test('should aggregate engagement metrics', () => {
const spec = createPieChartSpec(mockData);
const values = spec.data.values as any[];
expect(values.length).toBe(3); // Likes, Comments, Shares
expect(values.find(v => v.type === 'Likes')).toBeDefined();
expect(values.find(v => v.type === 'Comments')).toBeDefined();
expect(values.find(v => v.type === 'Shares')).toBeDefined();
});
test('should calculate correct totals', () => {
const spec = createPieChartSpec(mockData);
const values = spec.data.values as any[];
const totalLikes = mockData.reduce((sum, d) => sum + d.likes, 0);
const likesData = values.find(v => v.type === 'Likes');
expect(likesData?.value).toBe(totalLikes);
});
test('should configure as donut chart', () => {
const spec = createPieChartSpec(mockData);
expect(spec.radius).toBeDefined();
expect(spec.innerRadius).toBeDefined();
expect(spec.innerRadius).toBeGreaterThan(0);
});
test('should include legend', () => {
const spec = createPieChartSpec(mockData);
expect(spec.legends).toBeDefined();
expect(spec.legends).toBeInstanceOf(Array);
expect(spec.legends[0].visible).toBe(true);
});
});
describe('Dashboard Spec', () => {
test('should create valid dashboard specification', () => {
const spec = createDashboardSpec(mockData);
expect(spec).toBeDefined();
expect(spec.type).toBe('common');
expect(spec.layout).toBeDefined();
});
test('should use grid layout', () => {
const spec = createDashboardSpec(mockData);
expect(spec.layout.type).toBe('grid');
expect(spec.layout.col).toBeDefined();
expect(spec.layout.row).toBeDefined();
});
test('should include multiple chart types', () => {
const spec = createDashboardSpec(mockData);
expect(spec.series).toBeDefined();
expect(spec.series.length).toBeGreaterThan(1);
const seriesTypes = spec.series.map(s => s.type);
expect(seriesTypes).toContain('line');
expect(seriesTypes).toContain('bar');
expect(seriesTypes).toContain('pie');
});
test('should define regions for each chart', () => {
const spec = createDashboardSpec(mockData);
expect(spec.region).toBeDefined();
expect(spec.region.length).toBeGreaterThan(0);
});
test('should include axes configuration', () => {
const spec = createDashboardSpec(mockData);
expect(spec.axes).toBeDefined();
expect(spec.axes).toBeInstanceOf(Array);
});
test('should have dashboard title', () => {
const spec = createDashboardSpec(mockData);
expect(spec.title).toBeDefined();
expect(spec.title.visible).toBe(true);
expect(spec.title.text).toContain('Dashboard');
});
});
describe('Chart Specifications - Common Features', () => {
test('all specs should enable animations', () => {
const lineSpec = createLineChartSpec(mockData);
const barSpec = createBarChartSpec(mockData);
const pieSpec = createPieChartSpec(mockData);
expect(lineSpec.animation).toBeDefined();
expect(barSpec.animation).toBeDefined();
expect(pieSpec.animation).toBeDefined();
});
test('all specs should have tooltips', () => {
const lineSpec = createLineChartSpec(mockData);
const barSpec = createBarChartSpec(mockData);
const pieSpec = createPieChartSpec(mockData);
expect(lineSpec.tooltip).toBeDefined();
expect(barSpec.tooltip).toBeDefined();
expect(pieSpec.tooltip).toBeDefined();
});
test('all specs should use TikTok color scheme', () => {
const lineSpec = createLineChartSpec(mockData);
const barSpec = createBarChartSpec(mockData);
const pieSpec = createPieChartSpec(mockData);
// Check that specs use color configurations
expect(lineSpec.line?.style?.stroke).toBeDefined();
expect(barSpec.bar?.style?.fill).toBeDefined();
expect(pieSpec.color).toBeDefined();
});
});