tutorial

Monitoring WebdriverIO Test Suites with Vigilmon: Catch Silent Automation Failures

Use Vigilmon heartbeat monitors to detect silent WebdriverIO failures — scheduled suite drift, stuck browser sessions, and test runs that stop executing entirely.

Your WebdriverIO nightly suite has been reporting green for weeks. What nobody realized was that it stopped actually running two weeks ago — a YAML indentation error in the CI config caused the job to be skipped silently. All tests passed because no tests ran. The regression was discovered in production.

This is the silent test automation failure problem. Status badges only reflect the last run; they can't tell you when runs stop happening. The fix is heartbeat monitoring: WebdriverIO pings a unique URL at the end of every successful run, and if Vigilmon doesn't receive that ping within the expected window, you get alerted.

This tutorial shows you how to instrument WebdriverIO with Vigilmon heartbeat monitors so you always know when your browser automation stops running.

What You'll Cover

  • Heartbeat monitoring for scheduled WebdriverIO test runs
  • Catching suites that stop triggering entirely
  • Alerting on hanging browser sessions
  • Multi-capability and multi-environment monitoring
  • Detecting suite drift in remote grid and CI environments

Prerequisites


The Problem: What Standard WebdriverIO Monitoring Misses

WebdriverIO's built-in reporters record test outcomes — but they won't alert you when:

  • The cron job or CI trigger invoking wdio is removed or disabled
  • A misconfigured specs glob pattern matches zero files (suite exits 0)
  • A Selenium Grid or Appium server goes offline and WDIO fails to queue work
  • Browser session acquisition hangs indefinitely without a runner timeout
  • A test environment variable is missing, causing silent capability fallback

Vigilmon's heartbeat pattern closes all of these gaps.


Step 1: Create a Heartbeat Monitor in Vigilmon

A heartbeat monitor expects a ping on a regular interval. No ping → alert.

  1. Log in to Vigilmon and click New Monitor → Heartbeat.
  2. Give it a name like WebdriverIO — Nightly Regression.
  3. Set the Expected interval to match your test schedule. For a nightly suite, use 24 hours. For pre-deploy smoke tests, use 2 hours with a 20-minute grace period.
  4. Set the Grace period to 1 hour for long cross-browser suites.
  5. Save and copy the Ping URL — it looks like https://vigilmon.online/api/heartbeat/<unique-id>.

Step 2: Create a Vigilmon Reporter Plugin

WebdriverIO's service and reporter hooks are the cleanest integration points. Create a custom reporter:

// wdio/vigilmon-reporter.js
const https = require("https");

function pingVigilmon(url) {
  return new Promise((resolve, reject) => {
    const req = https.request(url, { method: "POST" }, () => resolve());
    req.on("error", reject);
    req.setTimeout(10000, () => {
      req.destroy(new Error("Vigilmon ping timed out"));
    });
    req.end();
  });
}

class VigilmonReporter {
  constructor(options) {
    this.heartbeatUrl = process.env.VIGILMON_HEARTBEAT_URL;
    this.hasFailed = false;
  }

  onTestFail() {
    this.hasFailed = true;
  }

  onTestError() {
    this.hasFailed = true;
  }

  async onRunnerEnd(stats) {
    if (!this.heartbeatUrl) return;

    const allPassed =
      !this.hasFailed &&
      stats.failures === 0 &&
      (stats.retries === undefined || stats.retries === 0);

    if (allPassed) {
      try {
        await pingVigilmon(this.heartbeatUrl);
        console.log("\nVigilmon heartbeat sent");
      } catch (e) {
        console.error("\nVigilmon heartbeat failed:", e.message);
      }
    }
  }
}

module.exports = VigilmonReporter;

Register the reporter in wdio.conf.js:

// wdio.conf.js
const VigilmonReporter = require("./wdio/vigilmon-reporter");

exports.config = {
  runner: "local",
  specs: ["./test/specs/**/*.js"],

  capabilities: [
    {
      browserName: "chrome",
      "goog:chromeOptions": { args: ["--headless", "--no-sandbox"] },
    },
  ],

  reporters: [
    "spec",
    [VigilmonReporter, {}],
  ],

  framework: "mocha",
  mochaOpts: {
    ui: "bdd",
    timeout: 60000,
  },
};

Step 3: Use the WDIO Service Hook (Alternative Approach)

For suites where individual test outcomes are less important than overall suite health, a WDIO service is simpler:

// wdio/services/VigilmonService.js
const https = require("https");

class VigilmonService {
  constructor(options, capabilities, config) {
    this.heartbeatUrl = process.env.VIGILMON_HEARTBEAT_URL;
    this.failed = false;
  }

  beforeTest(test, context) {}

  afterTest(test, context, { error }) {
    if (error) this.failed = true;
  }

  onComplete(exitCode, config, capabilities, results) {
    if (!this.heartbeatUrl) return;
    if (exitCode !== 0 || this.failed) return;

    // Synchronous ping using Node child_process since onComplete may not await
    const { execSync } = require("child_process");
    try {
      execSync(
        `curl -fsS -X POST "${this.heartbeatUrl}" --max-time 10 --retry 3`,
        { stdio: "ignore" }
      );
      console.log("Vigilmon heartbeat sent");
    } catch (e) {
      console.error("Vigilmon heartbeat failed:", e.message);
    }
  }
}

module.exports = VigilmonService;

Register in wdio.conf.js:

services: [
  ["./wdio/services/VigilmonService", {}],
],

Step 4: Add Heartbeat Monitoring to CI Pipelines

GitHub Actions

# .github/workflows/wdio.yml
name: WebdriverIO Tests

on:
  schedule:
    - cron: "0 1 * * *"  # 01:00 UTC nightly
  push:
    branches: [main]

jobs:
  wdio:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Install Chrome
        uses: browser-actions/setup-chrome@latest

      - name: Start application
        run: npm run start:ci &

      - name: Wait for app
        run: npx wait-on http://localhost:3000 --timeout 30000

      - name: Run WebdriverIO tests
        env:
          VIGILMON_HEARTBEAT_URL: ${{ secrets.VIGILMON_WDIO_HEARTBEAT_URL }}
        run: npx wdio run wdio.conf.js

      # Heartbeat fires automatically via the VigilmonReporter on full success.

Store VIGILMON_WDIO_HEARTBEAT_URL under Settings → Secrets and variables → Actions.

Running against Selenium Grid

For remote Selenium Grid execution, also monitor the Grid hub directly with an HTTP monitor (see the Selenium Grid tutorial):

// wdio.conf.js (remote grid)
exports.config = {
  hostname: process.env.SELENIUM_GRID_HOST || "localhost",
  port: 4444,
  path: "/wd/hub",

  capabilities: [
    { browserName: "chrome" },
    { browserName: "firefox" },
  ],

  // ... rest of config
};

Set the heartbeat URL per capability run:

SELENIUM_GRID_HOST=grid.internal \
VIGILMON_HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/<id>" \
  npx wdio run wdio.conf.js

Step 5: Multi-Capability Heartbeat Monitoring

For suites that test multiple browsers or devices, create one heartbeat monitor per capability group:

| Capability | Monitor name | Interval | |---|---|---| | Chrome desktop (nightly) | WDIO — Chrome — Nightly | 25 h | | Firefox desktop (nightly) | WDIO — Firefox — Nightly | 25 h | | Mobile emulation (nightly) | WDIO — Mobile — Nightly | 25 h | | Chrome smoke (pre-deploy) | WDIO — Smoke — Chrome | 2 h |

Parameterize with environment variables:

// wdio.conf.chrome.js
process.env.VIGILMON_HEARTBEAT_URL = process.env.VIGILMON_CHROME_HEARTBEAT_URL;
const base = require("./wdio.conf");
base.config.capabilities = [{ browserName: "chrome" }];
module.exports = base;
# Chrome run
VIGILMON_CHROME_HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/<chrome-id>" \
  npx wdio run wdio.conf.chrome.js

# Firefox run
VIGILMON_FIREFOX_HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/<firefox-id>" \
  npx wdio run wdio.conf.firefox.js

Step 6: Detect Test Suite Drift with Spec Count Validation

Protect against the "zero specs matched" silent success by adding a spec count check to the reporter:

// Add to VigilmonReporter
async onRunnerEnd(stats) {
  if (!this.heartbeatUrl) return;

  const specsRan = stats.specs || 0;
  const minSpecs = parseInt(process.env.VIGILMON_MIN_SPECS || "1", 10);

  if (specsRan < minSpecs) {
    console.warn(
      `Vigilmon: skipping heartbeat — only ${specsRan} spec(s) ran (minimum: ${minSpecs})`
    );
    return;
  }

  if (!this.hasFailed && stats.failures === 0) {
    await pingVigilmon(this.heartbeatUrl).catch(console.error);
  }
}

Set the minimum expected spec count:

VIGILMON_MIN_SPECS=50 VIGILMON_HEARTBEAT_URL="..." npx wdio run wdio.conf.js

If the spec glob breaks and zero files are found, the heartbeat is suppressed even though WDIO exits 0 — Vigilmon will alert after the grace period.


Step 7: Alert Channels

In Vigilmon, go to Notifications → New Channel and configure:

  • Email — immediate alert when a heartbeat is missed
  • Slack webhook — ping your #qa-alerts or #wdio-tests channel

When a suite stops pinging:

🔴 MISSED HEARTBEAT: WebdriverIO — Nightly Regression
Last ping: 26 hours ago
Expected interval: 24 hours

When it recovers:

✅ HEARTBEAT RECOVERED: WebdriverIO — Nightly Regression
Gap: 26 hours

What You're Now Catching

| Silent failure mode | How Vigilmon detects it | |---|---| | CI trigger for WDIO is removed/disabled | No ping arrives → alert after grace period | | Specs glob matches zero files (exits 0) | VIGILMON_MIN_SPECS check suppresses ping → alert | | Selenium Grid unreachable, sessions queue forever | Suite timeout → no ping → alert | | Browser session hangs on a slow network | Runner timeout → no ping → alert | | Capability fallback silently skips browsers | Per-capability monitors catch missing pings | | Test environment variable missing | Suite fails → no ping → alert |


WebdriverIO gives you flexible, multi-browser test automation — until the runner quietly disappears from your pipeline. Vigilmon's heartbeat monitors give you the external signal that WebdriverIO itself can't provide: a definitive alert when your browser automation hasn't run in longer than expected.

Add heartbeat monitoring to your WebdriverIO suite today — register free at vigilmon.online.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →