Writing Your First Test
Write, run, and understand your first Mobilewright test — the screen fixture, taps, fills, and your first assertion.
The Anatomy of a Test
Every Mobilewright test uses two imports: test defines a test case, and expect makes assertions. Each test receives a screen fixture — your window into the device. You use it to find elements and interact with them.
import { test, expect } from '@mobilewright/test';
test('app launches and shows home screen', async ({ screen }) => {
// Find the element by its visible text, then assert it is visible.
// The assertion retries automatically until it passes.
await expect(screen.getByText('Welcome')).toBeVisible();
});
const { test, expect } = require('@mobilewright/test');
test('app launches and shows home screen', async ({ screen }) => {
// Find the element by its visible text, then assert it is visible.
// The assertion retries automatically until it passes.
await expect(screen.getByText('Welcome')).toBeVisible();
});
Read it out loud and it almost explains itself: "expect the text 'Welcome' on the screen to be visible." The assertion auto-waits — it keeps checking until the text appears or the timeout (5 seconds by default) expires. No sleeps needed.
A Real Login Test
Let's write something more useful: fill in a login form, tap the button, and verify the result. This shows the three moves you will use in almost every test — fill, tap, and expect:
import { test, expect } from '@mobilewright/test';
test('user can sign in', async ({ screen }) => {
// Fill the form fields (fill taps to focus, then types)
await screen.getByLabel('Email').fill('user@example.com');
await screen.getByLabel('Password').fill('secret');
// Tap the sign-in button by its role and name
await screen.getByRole('button', { name: 'Sign In' }).tap();
// Verify we landed on the dashboard
await expect(screen.getByText('Dashboard')).toBeVisible();
});
const { test, expect } = require('@mobilewright/test');
test('user can sign in', async ({ screen }) => {
// Fill the form fields (fill taps to focus, then types)
await screen.getByLabel('Email').fill('user@example.com');
await screen.getByLabel('Password').fill('secret');
// Tap the sign-in button by its role and name
await screen.getByRole('button', { name: 'Sign In' }).tap();
// Verify we landed on the dashboard
await expect(screen.getByText('Dashboard')).toBeVisible();
});
getByRole('button', { name: 'Sign In' })) instead of raw text where you can — they survive UI copy changes better and work identically on iOS and Android.Grouping Tests with describe
Related tests belong together. test.describe groups them under one name, which makes reports easier to read and lets you configure the whole group at once:
import { test, expect } from '@mobilewright/test';
test.describe('login flow', () => {
test('shows login form', async ({ screen }) => {
await expect(screen.getByLabel('Email')).toBeVisible();
await expect(screen.getByLabel('Password')).toBeVisible();
});
test('rejects invalid credentials', async ({ screen }) => {
await screen.getByLabel('Email').fill('bad@example.com');
await screen.getByLabel('Password').fill('wrong');
await screen.getByRole('button', { name: 'Sign In' }).tap();
await expect(screen.getByText('Invalid credentials')).toBeVisible();
});
});
const { test, expect } = require('@mobilewright/test');
test.describe('login flow', () => {
test('shows login form', async ({ screen }) => {
await expect(screen.getByLabel('Email')).toBeVisible();
await expect(screen.getByLabel('Password')).toBeVisible();
});
test('rejects invalid credentials', async ({ screen }) => {
await screen.getByLabel('Email').fill('bad@example.com');
await screen.getByLabel('Password').fill('wrong');
await screen.getByRole('button', { name: 'Sign In' }).tap();
await expect(screen.getByText('Invalid credentials')).toBeVisible();
});
});
Running Your Tests
Run everything, one file, or only tests whose name matches a pattern:
# Run all tests
npx mobilewright test
# Run one file or one folder
npx mobilewright test tests/login.test.ts
npx mobilewright test tests/checkout/
# Run tests whose name matches a pattern
npx mobilewright test --grep "sign in"
# List tests without running them
npx mobilewright test --list
Exit code 0 means all tests passed, 1 means something failed. That's it — you have written and run real mobile tests. Next up: finding any element reliably with locators.
Written by PV
© 2026 All Rights Reserved