WebdriverIO
02 / 02

Page Objects, Custom Commands & Multiremote

Page Objects, Custom Commands & Multiremote

Page Object Pattern

// pages/login.page.js
class LoginPage {
  get emailInput() { return $('#email'); }
  get passwordInput() { return $('#password'); }
  get submitButton() { return $('button[type=submit]'); }

  async login(email, password) {
    await this.emailInput.setValue(email);
    await this.passwordInput.setValue(password);
    await this.submitButton.click();
  }
}
export default new LoginPage();

// test
import loginPage from '../pages/login.page.js';
it('logs in', async () => {
  await loginPage.login('user@example.com', 'secret123');
  await expect($('.dashboard')).toBeDisplayed();
});

Custom Commands

// wdio.conf.js — onPrepare or a separate setup file
browser.addCommand('login', async function (email, password) {
  await $('#email').setValue(email);
  await $('#password').setValue(password);
  await $('button[type=submit]').click();
  // Let a failure here (e.g. the form never appearing) propagate as a
  // clear error — don't swallow it, since every test calling login()
  // now depends on this being an accurate signal
});

// Usage in any test:
await browser.login('user@example.com', 'secret123');

Multiremote (Multi-Session) Testing

// wdio.conf.js
export const config = {
  capabilities: {
    userA: { capabilities: { browserName: 'chrome' } },
    userB: { capabilities: { browserName: 'firefox' } },
  },
};

// test — two independent sessions driven from one test
it('chat message syncs between users', async () => {
  await multiremotebrowser.userA.url('https://chat.example.com');
  await multiremotebrowser.userB.url('https://chat.example.com');

  await multiremotebrowser.userA.$('#message').setValue('hello');
  await multiremotebrowser.userA.$('#send').click();

  await expect(multiremotebrowser.userB.$('.messages')).toHaveText('hello');
});

Mobile Testing via Appium

WebdriverIO drives mobile apps through Appium using the same $/browser API, extended with mobile-specific capabilities (platformName, app path). Teams testing both web and mobile often standardize on WebdriverIO specifically for this shared API surface.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free