}>
  **Lesson 9 of 10**: This lesson defines the test strategy that keeps primitive wrappers stable as your team grows.

## Why quality gates matter

Primitives reduce risk, but wrapper drift can still introduce breakages:

* keyboard interactions regress,
* focus restoration breaks,
* semantics disappear after refactors,
* visual state attributes stop matching CSS rules.

A clear test strategy catches these before release.

***

## Test pyramid for primitive wrappers

1. Unit/integration: wrapper behavior and event contracts.
2. Accessibility assertions: role/name/state checks.
3. End-to-end keyboard flows: realistic user journeys.
4. Visual snapshots: state-specific styling checks.

Do not rely on only one layer.

***

## Example interaction test

```tsx
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

it('restores focus to trigger after dialog close', async () => {
  const user = userEvent.setup()
  render(<DeleteProjectDialog />)

  const trigger = screen.getByRole('button', { name: /delete project/i })
  await user.click(trigger)
  await user.keyboard('{Escape}')

  expect(trigger).toHaveFocus()
})
```

***

## Accessibility assertion examples

Assert:

* correct role (`dialog`, `menu`, `menuitem`, etc.),
* accessible name from title/label,
* state attributes (`aria-expanded`, `aria-checked`),
* disabled behavior.

When possible, run an automated a11y check and keep manual SR audits in release checklist.

***

## Regression suites for overlays

Create dedicated scenarios for:

* nested dialog inside dialog,
* popover inside dialog,
* menu inside popover,
* async close guards,
* reduced-motion mode.

Most regressions happen at composition boundaries.

***

## CI quality gates

Minimum recommended gates:

1. Typecheck.
2. Lint.
3. Wrapper tests.
4. Critical keyboard e2e flows.
5. Accessibility smoke checks.

If any gate fails, block merge.

***

## Internal registry note

If you run an internal design system, create a separate internal registry package (or docs section) that stores vetted primitive wrapper examples.

Suggested structure:

* `registry/primitives/dialog/*`
* `registry/primitives/popover/*`
* `registry/primitives/menu/*`
* each entry with: source, usage examples, known constraints, test links.

This gives teams a trusted, reusable catalog instead of ad hoc snippets.

***

## Lab

1. Add one interaction + one a11y assertion test for `Dialog` wrapper.
2. Add one keyboard e2e flow for menu navigation.
3. Create a first internal-registry entry for one primitive wrapper.

}>
  Next: [Lesson 10 - Operations, Migration, and Internal Registry](/duck-primitives/course/10-operations-migration)