Core Concepts
Before using Atomic Testing, familiarize yourself with the following key concepts:
Component Driver
At the heart of Atomic Testing are component drivers. They define how to programmatically interact with UI components, such as clicking a button, selecting a value from a dropdown, or reading a row from a grid.
A growing number of component drivers are available for popular UI frameworks like Material UI. Each component driver offers a set of methods for interacting with the component. When using TypeScript for writing tests, auto-completion can help discover available methods.
Refer to the API Reference for a list of available component drivers.
Locator
Locators help find components on a page, using various locator strategies such as byDataTestId
and byRole
.
The use of the data-testid attribute is recommended for locating components on a page. Refer to Best Practices for more details. Use the byDataTestId(value)
API as the recommended approach for building locators.
ScenePart
A ScenePart is a map describing all components of interest (part) within a scene (a page or a rich UI component). Each entry in a ScenePart outlines the part name, the component locator, and the component driver.
A sample ScenePart of a typical login screen
import { HTMLAnchorDriver, HTMLElementDriver } from '@atomic-testing/component-driver-html';
import { ButtonDriver, TextFieldDriver } from '@atomic-testing/component-driver-mui-v5';
import { ScenePart, byDataTestId } from '@atomic-testing/core';
const loginScenePart: ScenePart = {
username: {
locator: byDataTestId('username'),
driver: TextFieldDriver,
},
password: {
locator: byDataTestId('password'),
driver: TextFieldDriver,
},
error: {
locator: byDataTestId('error-display'),
driver: HTMLElementDriver,
},
submit: {
locator: byDataTestId('submit'),
driver: ButtonDriver,
},
forgetPassword: {
locator: byDataTestId('forget-password'),
driver: HTMLAnchorDriver,
},
} satisfies ScenePart;
Test Engine
The Test Engine is where all the pieces come together. It is responsible for rendering a scene, locating all the components in the scene, and providing a set of methods to interact with the components.
Use createTestEngine
to create a Test Engine instance. The createTestEngine
function is specific to each rendering framework, such as React, Cypress, and Playwright.
The examples below demonstrate how to create a Test Engine for the loginScenePart described earlier.
- React 18+
- React 17
- Playwright
- Cypress
import { createTestEngine } from '@atomic-testing/react';
import { loginScenePart } from './loginScenePart';
import { Login } from './components/Login';
const testEngine = createTestEngine(<Login />, loginScenePart);
import { createLegacyTestEngine } from '@atomic-testing/react/dist/createLegacyTestEngine';
import { loginScenePart } from './loginScenePart';
import { Login } from './components/Login';
const testEngine = createLegacyTestEngine(<Login />, loginScenePart);
import { createTestEngine } from '@atomic-testing/playwright';
import { loginScenePart } from './loginScenePart';
await page.goto('/login');
const testEngine = createTestEngine(page, loginScenePart);
import { createTestEngine } from '@atomic-testing/cypress';
import { loginScenePart } from './loginScenePart';
cy.visit('/login');
const testEngine = createTestEngine(loginScenePart);
Once the test engine is created, it can be used to interact with the components in the scene.
// Test code is agnostic to the rendering framework
await testEngine.parts.username.setValue('john@example.com');
await testEngine.parts.password.setValue('');
await testEngine.parts.submit.click();
const error = await testEngine.parts.error.getText();
expect(error).toEqual('Password is required'); // Jest assertion, but any assertion library can be used