# Fix the locale QA agent missing truncated German strings overflowing buttons

## TL;DR

German strings run long and the agent only checks pixels, so add an overflow assertion per element. Truncated text looks fine in a screenshot diff when the baseline is also truncated. Check scrollWidth against clientWidth on key elements, and fail when text overflows.

## The error

```text
Locale QA agent: missed truncated German button labels
buttons show "Speichern..." cut off, test passed anyway
```

## Fix it

### Step 1: Reproduce the overflow check manually

```bash
node -e "console.log('in the browser: document.querySelectorAll(\"button\").forEach(b => b.scrollWidth > b.clientWidth && console.log(b.textContent))')"
```

Expected: You see which buttons overflow.

### Step 2: Add overflow assertions to the QA agent

```bash
grep -n "assert\|check" scripts/qa-agent.js | head -5
```

Expected: You find where to add the check.

### Step 3: Fail on scrollWidth exceeding clientWidth

```bash
node -e "console.log('pattern: for each button, nav item, and chip: fail when scrollWidth exceeds clientWidth plus 1px tolerance')"
```

Expected: Overflows become failures.

### Step 4: Re-run the German QA pass

```bash
node scripts/qa-agent.js --locale de | tail -3
```

Expected: Truncated buttons now fail the test.

## When to use this

- A QA agent misses truncated German strings
- Buttons overflow but tests pass

## When NOT to use this

- The truncation is intentional with ellipsis styling, allowlist those
- Text overflows in all languages, fix the layout

## Tool and version compatibility

- DOM overflow measurement, scrollWidth vs clientWidth
- German long-word expansion

## Variant phrasings

### overflow in nav items not buttons

Same assertion on nav selectors. Any fixed-width element with translated text qualifies.

### ellipsis is the design

Then assert the ellipsis renders, title attribute holds the full text. Truncation with affordance is fine.

## Why it happens

Screenshot diffs compare against baselines, and if the baseline already shows truncated text, the diff passes. Pixel comparison cannot know the text is cut, only DOM measurement can.

## Edge cases

- 1px tolerance avoids subpixel false positives
- Dynamic content needs the check after data loads, not on initial render
- Some languages overflow by design in tight chips, set per-component budgets

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_OXUaNOSceguqHl-FVYP5iA
