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
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Deeper D3 test patterns split out of the SKILL spine: the update join (enter / update / exit) and SVG accessibility metadata.
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).
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.