Skip to main content
Pre-1.0Portable UI testing for React · Vue · Playwright

Write your UI tests
once. Run them anywhere.

Atomic Testing composes tiny, reusable component drivers into portable test scenes — so the same semantic test runs across frameworks, libraries, and environments. Learn once, test any UI.

$pnpm add @atomic-testing/core @atomic-testing/react-19 @atomic-testing/component-driver-html
Why Atomic Testing — and when NOT to use it →
byDataTestId()HTMLButtonDriverengine.parts
The magic

One test. Every framework.

Switch the runtime tab — notice the scene definition and the test body never change. Only the import and mount line differ.

welcome.test.ts
import { createTestEngine } from '@atomic-testing/react-19';
import { HTMLButtonDriver, HTMLElementDriver } from '@atomic-testing/component-driver-html';
import { byDataTestId } from '@atomic-testing/core';

// One scene definition — reused on every runtime
const scene = {
greeting: { locator: byDataTestId('greeting'), driver: HTMLElementDriver },
button: { locator: byDataTestId('welcome-btn'), driver: HTMLButtonDriver },
};

it('welcomes the user on click', async () => {
const engine = createTestEngine(<Welcome name="Alice" />, scene);

expect(await engine.parts.greeting.getText()).toBe('Hello Alice!');
await engine.parts.button.click();
expect(await engine.parts.button.getText()).toBe('Welcome!');

await engine.cleanUp();
});
✓ identical scene & assertions— your testing knowledge transfers completely.
Composable by design

Small atoms. Infinite tests.

Each primitive is tiny and replaceable. Compose them like atoms into molecules — locators and drivers snap into scenes, scenes into engines, engines into suites that outlive any framework.

Locator
byDataTestId('btn')
Finds the element — by test id, role, text or CSS.
Driver
HTMLButtonDriver
Semantic API — .click(), .getText().
Scene → Engine
engine.parts.btn
Orchestrates the whole test, any runtime.
Result
✓ Passing everywhere
React · Vue · Playwright · DOM.

Why teams adopt it

Write once, test everywhere

The same test code works across React, Vue, Playwright and DOM testing. Learn once, test any UI framework.

High-level semantic APIs

select.selectByLabel('Option 2') instead of brittle DOM queries. Focus on behavior, not implementation.

Framework-agnostic drivers

Reuse component drivers across Material-UI, Bootstrap and custom components. Component library changes don’t break your tests.

Future-proof architecture

Framework migrations, library upgrades and environment changes become trivial. Your testing investment scales with your app.

✓ verifiableNot just a claim: this repo's own *.suite.ts test logic runs unmodified under Jest and across Chromium, Firefox & WebKit via Playwright — see package-tests/ in this monorepo.

What just happened?

Four building blocks orchestrate every test.

01
ScenePart

Declare which components matter to the test.

02
Locators

Find components with byDataTestId() & friends.

03
Drivers

Use semantic APIs instead of DOM manipulation.

04
TestEngine

Orchestrates everything together, in any runtime.

Is it for you?

Honest tradeoffs

Atomic Testing adds a driver layer on top of RTL, Vue Test Utils and Playwright — that's a learning curve and a dependency, not a free lunch. It's a poor fit for a single throwaway component, a prototype you'll never maintain, or a team unwilling to invest in the pattern up front.

Test once. Ship with confidence.

Get your first portable test running in five minutes.