---
url: https://chartbuddy.io/embed/docs/quality-assurance/visual-qa.md
---
# Visual QA

You cannot judge ChartBuddy charts from `chartData` alone. Mount, look, then adjust.

## Layout first

Before judging labels or annotations, confirm the **host box**:

* Host has a definite size (fixed px, or `width` + `aspect-ratio` – not bare `height: 100%` in nested/flex/slide layouts). See [Canvas & sizing](/concepts/canvas).
* Chart fills the host (not cramped, letterboxed, or tiny in the corner).
* Size stays stable when a slide/panel becomes visible (remeasure or remount after layout if needed).

Feature-present PNGs are not enough if the container geometry is wrong.

## Loop

1. Mount with a realistic container size (e.g. `800×450` or `aspect-ratio: 16 / 9`) and a stable `instanceId`
2. `await insight.ready` (or `insight.on('ready', …)`)
3. Observe via return values (preferred):

```js
const insight = window.__CHARTBUDDY_INSIGHTS__['revenue'];
const cd = insight.getChartData();
// Default underlay is #ffffff; pass any CSS color for dark decks, etc.
const png = await insight.toPngBase64({ background: '#ffffff' });
```

4. Fix config (orientation, subtitle, ticks, container height) with a **partial** update:

```js
insight.setData([['', 'Q1'], ['Revenue', 120]]);
insight.update({ subtitle: { visible: false, text: '' } });
```

5. Write PNG / JSON into the workspace yourself — do not rely on `downloadPng()` Save dialogs

Prefer **`toPngBase64` / `getChartData`** over screenshots or `downloadPng()` for automated checks.

`chartData.backgroundColor` does **not** bake into PNGs. Use the `background` export option.

Unknown `chartType` values throw at the API boundary — treat that as a validation error to fix in `chartData`, not as a blank chart to debug. Pre-check with [`validateChartData`](/quality-assurance/validation) when configs are generated or assembled.

## PNG for slides

```js
// Human Save dialog — transparent by default (good for Slides overlays)
await insight.downloadPng();

// Opaque white (or any CSS color) when you need a solid slide asset:
await insight.downloadPng({ background: '#ffffff' });

// Programmatic path (no Save dialog; defaults to #ffffff):
const b64 = await insight.toPngBase64({ background: '#ffffff' });
```

Or use **Download** on the hover ball. Paste the PNG into PowerPoint or Slides. Prefer ChartBuddy export over DevTools SVG screenshots for final assets.

## Probe

```js
insight.chart.cd.chartType
insight.chart.cd.orientation
insight.chart.cd.axes
insight.getChartData()
insight.isDirty()
```

For horizontal bars, confirm domain is on the left and primary range on the bottom.

## Fixture hygiene

* Unique stable `instanceId` per mount (duplicates throw)
* Host CSS: definite width/height (prefer aspect-ratio or fixed px for decks)
* `subtitle: { visible: false, text: '' }` unless you want a subtitle
* `isDataTransposed: true` for bar / line / stackedArea layouts in the docs
* Horizontal bars need `orientation: 'horizontal'`
* Prefer `setData` / `update` for refreshes – `chartType` is optional on partials
* Run [`validateChartData()`](/quality-assurance/validation) on generated configs before mounting

## Chartbuddy Hub

For **advanced visual QA** through Chartbuddy MCP (live Hub windows, `list_charts`, desktop editing), and for connecting charts to other apps, install **[Chartbuddy Hub](https://chartbuddy.io/hub/docs/getting-started/installation)** and follow [Connect MCP](https://chartbuddy.io/hub/docs/connect-mcp/). Embed `toPngBase64` / `getChartData` cover npm and static HTML loops; Hub MCP is the desktop path when you need more than mount-and-snapshot.
