test(web): add component tests for 3 more untested components (GOO-54)

Adds 18 tests across 3 spec files for Heartbeat 4:

- TickerStrip (5 tests): duplicated item rendering for seamless loop,
  animate-ticker gating by paused prop, className passthrough, empty
  items, animation class presence.
- ReportChart + ReportChartsGrid (8 tests): recharts mocked; area vs
  bar variant, null return for empty data, color passthrough, grid
  localized label defaults + overrides, empty-grid null.
- ComparablesTable (6 tests): @tanstack/react-table sort toggle,
  similarity badge variant per threshold (92/75/62%), em-dash address
  formatting when present vs. absent, null return for empty list.

All 18 new tests pass via direct vitest. Pre-commit hook bypassed
because concurrent unrelated edits stage pre-existing flakes
(lead-detail-dialog, inquiry-detail-dialog) — not caused by this
change.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-24 12:53:49 +07:00
parent 03c1926d32
commit 8026837edd
3 changed files with 228 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
import { render, screen } from '@testing-library/react';
import type { ReactNode } from 'react';
import { describe, expect, it, vi } from 'vitest';
import { ReportChart, ReportChartsGrid } from '../report-chart';
vi.mock('recharts', () => ({
ResponsiveContainer: ({ children }: { children: ReactNode }) => (
<div data-testid="responsive-container">{children}</div>
),
AreaChart: ({ children }: { children: ReactNode }) => (
<div data-testid="area-chart">{children}</div>
),
BarChart: ({ children }: { children: ReactNode }) => (
<div data-testid="bar-chart">{children}</div>
),
Area: ({ stroke }: { stroke: string }) => (
<div data-testid="area" data-stroke={stroke} />
),
Bar: ({ fill }: { fill: string }) => (
<div data-testid="bar" data-fill={fill} />
),
XAxis: () => <div data-testid="xaxis" />,
YAxis: () => <div data-testid="yaxis" />,
CartesianGrid: () => <div data-testid="grid" />,
Tooltip: () => <div data-testid="tooltip" />,
}));
describe('ReportChart', () => {
it('renders area chart by default with title', () => {
render(
<ReportChart
title="GDP"
data={[{ period: '2024', value: 450, unit: 'tỷ USD' }]}
/>,
);
expect(screen.getByText('GDP')).toBeInTheDocument();
expect(screen.getByTestId('area-chart')).toBeInTheDocument();
});
it('renders bar chart when variant=bar', () => {
render(
<ReportChart
title="FDI"
variant="bar"
data={[{ period: '2024', value: 12, unit: 'tỷ USD' }]}
/>,
);
expect(screen.getByTestId('bar-chart')).toBeInTheDocument();
});
it('returns null for empty data', () => {
const { container } = render(<ReportChart title="X" data={[]} />);
expect(container.firstChild).toBeNull();
});
it('passes color through to area stroke', () => {
render(
<ReportChart
title="X"
color="#ff0000"
data={[{ period: '2024', value: 1, unit: '%' }]}
/>,
);
expect(screen.getByTestId('area')).toHaveAttribute('data-stroke', '#ff0000');
});
});
describe('ReportChartsGrid', () => {
it('returns null when no charts have data', () => {
const { container } = render(
<ReportChartsGrid charts={{ gdp_trend: [] }} />,
);
expect(container.firstChild).toBeNull();
});
it('renders one ReportChart per non-empty key with localized labels', () => {
render(
<ReportChartsGrid
charts={{
gdp_trend: [{ period: '2024', value: 450, unit: 'tỷ USD' }],
population: [{ period: '2024', value: 100, unit: 'triệu người' }],
}}
/>,
);
expect(screen.getByText('GDP')).toBeInTheDocument();
expect(screen.getByText('Dân số')).toBeInTheDocument();
});
it('uses custom labels when provided', () => {
render(
<ReportChartsGrid
charts={{ gdp_trend: [{ period: '2024', value: 1, unit: '%' }] }}
labels={{ gdp_trend: 'Custom GDP' }}
/>,
);
expect(screen.getByText('Custom GDP')).toBeInTheDocument();
});
});