CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/chart-render-tests

Chart-render regression testing across the three chart-library families - Canvas (Chart.js: locator screenshot snapshot + `canvas.toDataURL()` diff with animations disabled), SVG (D3: `outerHTML` structural snapshot with generated-ID normalization + per-element data-binding tests), and declarative specs (Vega / Vega-Lite: JSON Schema validation + Vega-Lite → Vega compile test). Detects the family from package.json imports (chart.js / d3 / vega-lite), then applies the matching recipe; full per-library depth with citations in references/chartjs.md, references/d3.md, references/vega.md. Use when a dashboard or data product renders charts and their output needs regression coverage - before a chart-library major upgrade, after a theming change, or when runtime-generated Vega specs must be proven valid before render.

74

Quality

93%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

d3-advanced-tests.mdreferences/

D3 - advanced correctness tests

Deeper D3 test patterns split out of the SKILL spine: the update join (enter / update / exit) and SVG accessibility metadata.

Update join correctness

D3's update join (enter / update / exit) is the hardest D3 concept to test. Test the three states:

test('update join handles insert + remove + reorder', async ({ page }) => {
  await page.goto('https://localhost:3000/d3-update');

  // Initial: [A, B, C]
  await page.evaluate(() => (window as any).updateChart(['A', 'B', 'C']));
  expect(await page.locator('rect[data-key="A"]').count()).toBe(1);

  // After: [A, B, D] - remove C, add D
  await page.evaluate(() => (window as any).updateChart(['A', 'B', 'D']));
  expect(await page.locator('rect[data-key="C"]').count()).toBe(0);
  expect(await page.locator('rect[data-key="D"]').count()).toBe(1);

  // After: [B, D, A] - reorder; element identity preserved
  await page.evaluate(() => (window as any).updateChart(['B', 'D', 'A']));
  // 'A' should be the same DOM node (just repositioned)
  // Verify via attribute or event listener attached pre-reorder
});

Use a stable key function: data-bind by .data(arr, d => d.id).

Accessibility metadata

D3 generates SVG; SVG has accessibility primitives. Tests verify:

test('chart has title + desc for screen readers', async ({ page }) => {
  await page.goto('https://localhost:3000/d3-bar');

  await expect(page.locator('svg.bar-chart > title')).toContainText('Revenue by Quarter');
  await expect(page.locator('svg.bar-chart > desc')).toContainText('Bar chart showing');
});

test('rects have aria-labels', async ({ page }) => {
  const labels = await page.locator('svg.bar-chart rect').evaluateAll(els =>
    els.map(el => el.getAttribute('aria-label'))
  );
  expect(labels[0]).toBe('Q1 revenue: $10k');
});

Cross-ref qa-accessibility plugin for broader a11y patterns.

SKILL.md

tile.json