Skip to content

syamphaneendra/webdriverio9-boilerplate

Repository files navigation

WebdriverIO 9 + TypeScript + Cucumber + Appium (Android/iOS)

A production-ready mobile test automation framework with support for both Android and iOS platforms, featuring comprehensive logging, reporting, and app-to-web navigation capabilities.

Table of Contents

Prerequisites

  • Node.js (v20+)
  • Java JDK (v11+)
  • Android SDK (for Android testing)
  • iOS Simulator/Device + Xcode (for iOS testing)
  • Android Emulator or Physical Device
  • nvm (Node Version Manager)

Setup

  1. Switch to Node.js v20:
nvm use 20
  1. Install dependencies:
npm install
  1. Install Appium drivers:
# For Android
px appium driver install uiautomator2

# For iOS
px appium driver install xcuitest
  1. Place your app files (optional):
    • Android APK: ./app/android/app.apk
    • iOS IPA: ./app/ios/app.ipa
    • Currently using pre-installed Settings app for both platforms

Configuration

Device Configuration

Update device.config.ts to configure your test device:

For Android:

export const deviceConfig = androidConfig; // Switch to this

For iOS:

export const deviceConfig = iosConfig; // Switch to this

Update device details:

export const androidConfig: DeviceConfig = {
  platformName: 'Android',
  deviceName: 'sdk_gphone64_arm64',  // Your device name
  platformVersion: '13.0',            // Your Android version
  automationName: 'UiAutomator2',
  appPackage: 'com.android.settings',
  appActivity: '.Settings',
  newCommandTimeout: 240
};

Environment Configuration

Update env.config.ts for different environments:

export const env = {
  baseUrl: process.env.BASE_URL || 'https://api.example.com',
  timeout: parseInt(process.env.TIMEOUT || '10000'),
  environment: process.env.ENV || 'dev'
};

Get Device Info

For Android:

~/Library/Android/sdk/platform-tools/adb devices -l
~/Library/Android/sdk/platform-tools/adb shell getprop ro.product.model
~/Library/Android/sdk/platform-tools/adb shell getprop ro.build.version.release

For iOS:

# List available simulators
xcrun simctl list devices

# Get device info
instruments -s devices

Running Tests

Run all tests:

nvm use 20
npm test

Run specific feature:

npm test -- --spec=src/features/sample.feature

Run with tags:

# Run app-to-web tests
npm run test:app-to-web

# Run smoke tests
npm run test:smoke

# Run all tests except app-to-web
npm run test:regression

# Custom tag expression
npm test -- --cucumberOpts.tagExpression='@smoke and not @app-to-web'

View Test Reports:

npm run report

Features

✅ Logging

  • Winston logger for detailed test execution logs
  • Logs saved to logs/test.log
  • Console and file output
  • Timestamped log entries

✅ Reporting

  • Allure reports with rich test details
  • Automatic screenshot capture on test failure
  • Test execution history
  • Trend analysis

✅ Fresh App State

  • Each scenario runs with a fresh app state
  • Automatic app termination and relaunch between scenarios
  • Configurable reset behavior (noReset, fullReset)

✅ Multi-Platform Support

  • Easy switching between Android and iOS
  • Platform-specific configurations
  • Shared test code across platforms

✅ Page Object Model

  • Clean and maintainable test structure
  • Reusable page objects
  • Separation of test logic and page interactions

✅ Mobile Gestures

Reusable gesture utilities:

  • Scroll up/down
  • Swipe left/right
  • Long press
  • Hide keyboard

✅ Retry Mechanism

  • Automatically retry failed scenarios (configurable)
  • Reduces flaky test failures
  • Configurable retry count

✅ Environment Management

  • Support for multiple environments (dev, staging, prod)
  • Environment-specific configurations
  • Environment variables support

✅ App-to-Web Navigation

  • Seamless context switching between native app and webview
  • Support for external browser navigation (Chrome/Safari)
  • Automatic platform detection for browser switching
  • WebView interaction utilities

Project Structure

├── src/
│   ├── features/           # Cucumber feature files
│   │   ├── sample.feature
│   │   └── app-to-web.feature
│   ├── steps/              # Step definitions
│   │   ├── sample.steps.ts
│   │   └── app-to-web.steps.ts
│   ├── pages/              # Page objects
│   │   ├── BasePage.ts
│   │   ├── SettingsPage.ts
│   │   └── WebViewPage.ts
│   └── utils/              # Utilities
│       ├── logger.ts       # Winston logger
│       ├── MobileGestures.ts  # Gesture utilities
│       └── ContextSwitcher.ts # App/Web context switching
├── app/
│   ├── android/            # Android APK files
│   └── ios/                # iOS IPA files
├── logs/                   # Test execution logs
├── allure-results/         # Allure test results
├── device.config.ts        # Device configurations (Android/iOS)
├── env.config.ts           # Environment configurations
├── wdio.conf.ts            # WebdriverIO configuration
├── tsconfig.json           # TypeScript configuration
└── package.json            # Dependencies and scripts

Usage Examples

Mobile Gestures

import { MobileGestures } from '../utils/MobileGestures';

// Scroll down
await MobileGestures.scrollDown();

// Swipe left
await MobileGestures.swipeLeft();

// Long press on element
const element = await $('~myElement');
await MobileGestures.longPress(element, 3000);

// Hide keyboard
await MobileGestures.hideKeyboard();

App-to-Web Navigation

import { ContextSwitcher } from '../utils/ContextSwitcher';
import WebViewPage from '../pages/WebViewPage';

// Switch to browser (auto-detects platform)
await ContextSwitcher.switchToBrowser();

// Navigate to URL
await WebViewPage.navigateToUrl('https://example.com');

// Interact with web elements
await WebViewPage.fillInput('#username', 'testuser');
await WebViewPage.clickElement('#login');

// Switch back to app
await ContextSwitcher.switchBackToApp(appPackage, bundleId);

// Switch to webview (in-app)
await ContextSwitcher.switchToWebView();

// Switch to native app
await ContextSwitcher.switchToNativeApp();

Logging

import logger from '../utils/logger';

logger.info('Test step started');
logger.error('Test failed with error');
logger.warn('Warning message');

Page Object Pattern

import { BasePage } from './BasePage';

class LoginPage extends BasePage {
  get usernameInput() {
    return $('~username');
  }

  async login(username: string, password: string) {
    await this.tap('~username');
    await this.usernameInput.setValue(username);
    await this.tap('~password');
    await $('~password').setValue(password);
    await this.tap('~loginButton');
  }
}

export default new LoginPage();

Known Issues

App-to-Web Navigation Limitation

External Browser Context Issue: When opening Chrome/Safari as an external app from the Settings app, Appium cannot access the browser's webview context. This is a limitation of Appium's architecture.

Workaround: The app-to-web feature works best when:

  1. Your app has an embedded WebView (hybrid app)
  2. You're testing a web app directly (not launching from native app)
  3. Your app opens URLs in an in-app browser (not external Chrome/Safari)

For external browser testing:

  • Use native app automation to open the browser
  • Switch to the browser app context
  • Use UI Automator selectors to interact with browser elements (limited functionality)

Example for in-app WebView:

// This works - in-app webview
await ContextSwitcher.switchToWebView();
await driver.url('https://example.com');

// This doesn't work - external Chrome browser
await ContextSwitcher.switchToChrome(); // Opens Chrome but can't access webview

To test the app-to-web feature, you need an app with embedded WebView support.

expect-webdriverio Module Issue

The expect-webdriverio v5.6.2 package has a structure issue where the entry point is missing. This is automatically fixed by the postinstall script that creates a symlink:

node_modules/expect-webdriverio/lib/index.js → src/index.js

What's the problem?

  • WebdriverIO's @wdio/runner tries to import: expect-webdriverio/lib/index.js
  • But the actual compiled file is located at: expect-webdriverio/lib/src/index.js
  • The package's package.json exports field points to /lib/index.js, but this file doesn't exist
  • This appears to be a build/packaging issue in the expect-webdriverio v5.6.2 release

How is it fixed?

  • The postinstall script in package.json automatically creates a symbolic link
  • This link makes lib/index.js point to the actual file at lib/src/index.js
  • The symlink is recreated automatically every time you run npm install

Error you might see without the fix:

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 
'/path/to/node_modules/expect-webdriverio/lib/index.js'

If you encounter module not found errors after npm install, the postinstall script will handle it automatically.

Project Structure

├── src/
│   ├── features/       # Cucumber feature files
│   ├── steps/          # Step definitions
│   ├── pages/          # Page objects
│   └── utils/          # Utilities (logger)
├── app/
│   ├── android/        # Android APK files
│   └── ios/            # iOS IPA files
├── logs/               # Test execution logs
├── allure-results/     # Allure test results
├── device.config.ts    # Device configurations (Android/iOS)
├── wdio.conf.ts        # WebdriverIO configuration
├── tsconfig.json       # TypeScript configuration
└── package.json        # Dependencies and scripts

Features

  • Logging: Winston logger for detailed test execution logs
  • Reporting: Allure reports with screenshots on failure
  • Fresh App State: Each scenario runs with a fresh app state
  • Multi-Platform: Easy switching between Android and iOS
  • Page Object Model: Clean and maintainable test structure
  • Mobile Gestures: Reusable gesture utilities (scroll, swipe, long press)
  • Retry Mechanism: Automatically retry failed scenarios
  • Environment Config: Manage different test environments
  • App-to-Web Navigation: Seamless context switching between native app and webview/browser

About

WebdriverIO 9 + TypeScript + Cucumber + Appium mobile test automation framework

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors