Beginner Chapter 3 · 8 min read

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.

example.test.ts
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();
});
example.test.js
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:

login.test.ts
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();
});
login.test.js
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();
});
Tip: Use the built-in role locators (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:

login.test.ts
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();
  });
});
login.test.js
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:

Terminal
# 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.


Mobilewright Beginner First Test Basics

Written by PV

© 2026 All Rights Reserved