Skip to content

Visualization Testing Strategy

This document outlines the testing approach for chart and visualization components in founderyOS.

The Challenge

Visualization libraries like Recharts render SVG elements that are difficult to test in jsdom environments:

  • SVG paths and coordinates are computed at render time
  • Canvas-based charts don't render in jsdom
  • Visual correctness requires actual browser rendering
  • Test assertions on SVG output are brittle and maintenance-heavy

1. Unit Tests (Vitest + jsdom)

Focus on component logic and structure, not visual output:

typescript
// ✅ DO: Test component behavior
it('renders chart container with aria-label', () => {
  render(<BurndownChart data={data} totalPoints={20} />);
  const chart = screen.getByRole('img');
  expect(chart).toHaveAttribute('aria-label', expect.stringContaining('Burndown'));
});

// ✅ DO: Test edge cases
it('renders nothing when data is empty', () => {
  const { container } = render(<BurndownChart data={[]} totalPoints={20} />);
  expect(container.firstChild).toBeNull();
});

// ✅ DO: Test accessibility
it('has descriptive aria-label for screen readers', () => {
  render(<BurndownChart data={data} totalPoints={42} />);
  expect(screen.getByRole('img')).toHaveAttribute('aria-label', expect.stringContaining('42'));
});

// ❌ DON'T: Test SVG internals
it('renders line with correct path', () => {
  // This is brittle and breaks with library updates
  expect(container.querySelector('path')).toHaveAttribute('d', 'M0,100L50,80...');
});

What to test in unit tests:

  • Component renders/doesn't render based on props
  • Accessibility attributes (aria-label, role)
  • Data handling edge cases (empty, null, NaN values)
  • Loading and error states
  • Prop changes trigger re-renders

2. Browser-Based E2E Tests (Playwright)

Use Playwright for visual verification of chart rendering:

typescript
// E2E test with Playwright
test('burndown chart displays correctly', async ({ page }) => {
  await page.goto('/backlog');

  // Wait for chart to render
  await page.waitForSelector('[data-testid="burndown-chart"]');

  // Screenshot comparison
  await expect(page.locator('[data-testid="burndown-chart"]')).toHaveScreenshot('burndown-active.png');
});

test('burndown chart shows ideal and actual lines', async ({ page }) => {
  await page.goto('/backlog');

  // Verify SVG elements are present
  const chart = page.locator('[data-testid="burndown-chart"]');
  await expect(chart.locator('path')).toHaveCount(2); // ideal + actual lines
});

What to test in E2E tests:

  • Visual rendering matches expectations (screenshot comparison)
  • Interactive elements work (tooltips, hover states)
  • Chart updates when data changes
  • Responsive behavior at different viewport sizes

3. Manual QA Testing

For complex visualizations, browser-based QA verification is essential:

markdown
## QA Checklist for Charts

- [ ] Chart renders with mock data
- [ ] Chart handles empty data gracefully
- [ ] Axis labels are readable
- [ ] Legend displays correctly
- [ ] Tooltips appear on hover
- [ ] Chart is responsive (resize browser)
- [ ] Colors meet accessibility contrast requirements

Implementation Example

See foundery-os-suite/src/components/backlog/__tests__/BurndownChart.test.tsx for a complete example.

Test coverage approach:

  • 20 unit tests for component logic
  • QA browser verification for visual correctness
  • E2E tests (future) for interactive behavior

Libraries Covered

This strategy applies to:

LibraryComponentTest Approach
RechartsBurndownChartUnit (logic) + QA (visual)
RechartsFuture chartsSame pattern
Chart.js(if used)Same pattern
D3.js(if used)Same pattern + E2E for interactions

References

Hello World Co-Op DAO