feat: enhance Tauri charts with smooth curves and forecasting
- Implemented a smooth curve rendering for the TauriLineChart using a cubic Bezier path. - Added a forecasting feature to project trends based on recent data points. - Updated TauriDashboardView to pass the current month for accurate forecasting. - Refactored TauriLineChart to handle actual and forecasted data points distinctly. - Introduced gradient strokes and glow effects to align with ApexCharts styling. - Enhanced user interaction with hover markers and tooltips for forecasted data. - Added a new test suite for ClinicDetailPage to ensure proper rendering and functionality.
This commit is contained in:
@@ -88,4 +88,80 @@ describe('TauriLineChart', () => {
|
||||
expect(screen.queryByText(EMPTY)).not.toBeInTheDocument();
|
||||
expect(container.querySelector('svg path')).toBeTruthy();
|
||||
});
|
||||
|
||||
/** سبک «gradient line»: خط از گرادیان افقی رنگ میگیرد، نه یک رنگ ثابت. */
|
||||
it('paints the line with the horizontal gradient and a glow', () => {
|
||||
const { container } = render(<TauriLineChart data={real} />);
|
||||
const line = container.querySelectorAll('svg path')[1] as SVGPathElement;
|
||||
|
||||
expect(line.getAttribute('stroke')).toBe('url(#tdIncomeStroke)');
|
||||
expect(line.getAttribute('filter')).toBe('url(#tdIncomeGlow)');
|
||||
expect(container.querySelector('#tdIncomeStroke')).toBeTruthy();
|
||||
expect(container.querySelector('#tdIncomeGlow feDropShadow')).toBeTruthy();
|
||||
});
|
||||
|
||||
/** نقطه و تولتیپ برای هر داده ساخته میشود و با هاور نمایان میشود. */
|
||||
it('renders a hover marker and value tooltip per point', () => {
|
||||
const { container } = render(<TauriLineChart data={real} />);
|
||||
|
||||
expect(container.querySelectorAll('.td-hit')).toHaveLength(real.length);
|
||||
expect(container.querySelectorAll('.td-dot')).toHaveLength(real.length);
|
||||
// مقدارها با ارقام فارسی در تولتیپ
|
||||
expect(screen.getByText('۴۸')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* ماههای نیامده صفر برمیگردند؛ رسمکردنشان یک خط صاف تا انتهای سال میساخت.
|
||||
* از آخرین دادهٔ واقعی به بعد باید روند نقطهچین ادامه پیدا کند.
|
||||
*/
|
||||
describe('TauriLineChart — ادامهٔ پیشبینی', () => {
|
||||
/** ۴ ماه واقعیِ صعودی + ۸ ماه نیامده (صفر) */
|
||||
const year: ChartPoint[] = Array.from({ length: 12 }, (_, i) => ({
|
||||
label: `ماه ${i + 1}`,
|
||||
value: i < 4 ? (i + 1) * 10 : 0,
|
||||
}));
|
||||
|
||||
it('بدون actualCount خط پیشبینی ندارد (رفتار قبلی حفظ میشود)', () => {
|
||||
const { container } = render(<TauriLineChart data={year} />);
|
||||
expect(container.querySelector('.td-forecast')).toBeNull();
|
||||
expect(screen.queryByText('نقطهچین: پیشبینی')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('با actualCount ماههای باقیمانده را نقطهچین ادامه میدهد', () => {
|
||||
const { container } = render(<TauriLineChart data={year} actualCount={4} />);
|
||||
|
||||
const forecast = container.querySelector('.td-forecast');
|
||||
expect(forecast).toBeTruthy();
|
||||
expect(forecast!.getAttribute('stroke')).toBe('var(--accent)');
|
||||
expect(screen.getByText('نقطهچین: پیشبینی')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('روند صعودی را ادامه میدهد و صفرها را رسم نمیکند', () => {
|
||||
render(<TauriLineChart data={year} actualCount={4} />);
|
||||
// شیب ۱۰ در ماه، آخرین واقعی ۴۰ ⇒ ماه پنجم ۵۰
|
||||
expect(screen.getByText('پیشبینی: ۵۰')).toBeInTheDocument();
|
||||
// آخرین ماه: ۴۰ + ۸×۱۰ = ۱۲۰
|
||||
expect(screen.getByText('پیشبینی: ۱۲۰')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('پیشبینی هرگز منفی نمیشود', () => {
|
||||
const falling: ChartPoint[] = Array.from({ length: 12 }, (_, i) => ({
|
||||
label: `ماه ${i + 1}`,
|
||||
value: i < 3 ? 100 - i * 45 : 0,
|
||||
}));
|
||||
const { container } = render(<TauriLineChart data={falling} actualCount={3} />);
|
||||
|
||||
const tips = Array.from(container.querySelectorAll('.td-tip'))
|
||||
.map((el) => el.textContent ?? '')
|
||||
.filter((t) => t.startsWith('پیشبینی'));
|
||||
expect(tips.length).toBeGreaterThan(0);
|
||||
expect(tips.some((t) => t.includes('-') || t.includes('−'))).toBe(false);
|
||||
});
|
||||
|
||||
it('سال کامل (actualCount برابر طول داده) پیشبینی ندارد', () => {
|
||||
const full: ChartPoint[] = Array.from({ length: 12 }, (_, i) => ({ label: `ماه ${i + 1}`, value: 10 + i }));
|
||||
const { container } = render(<TauriLineChart data={full} actualCount={12} />);
|
||||
expect(container.querySelector('.td-forecast')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user