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