tutorial

Monitoring Jasmine Test Pipelines with Vigilmon: Detect Silent Suite Failures

Use Vigilmon heartbeat monitors to detect when your Jasmine test suites stop running — scheduled regressions, stuck CI jobs, and pipelines that silently go dark.

Your Jasmine suite ran clean this morning. Or did it? The scheduled job that triggers it was quietly dropped from the CI pipeline when someone reorganised the YAML two weeks ago. Jasmine produces zero failures when it runs zero specs — and without an external signal, nobody notices until a regression ships to production.

This is the silent suite-failure problem. HTTP monitors can't help — there is nothing to ping. The answer is heartbeat monitoring: your Jasmine run pings a unique URL after every successful execution, and if Vigilmon doesn't receive that ping within the expected window, you get alerted.

This tutorial shows you how to instrument Jasmine test pipelines with Vigilmon heartbeat monitors so you know when tests stop running, not just when they fail.

What You'll Cover

  • Heartbeat monitoring for Jasmine test suites
  • Detecting suites that stop running entirely
  • Custom Jasmine reporters that ping on completion
  • Multi-environment test monitoring (unit, integration, e2e)
  • Integrating with CI/CD pipelines (GitHub Actions, GitLab CI)

Prerequisites

  • A Node.js project with Jasmine configured
  • A free account at vigilmon.online

The Problem: What Jasmine's Built-In Reporting Misses

Jasmine gives you spec counts, failure details, and timing information — but only when it actually runs. It won't alert you when:

  • A CI path filter silently excludes your spec directory
  • A spec_dir or spec_files glob matches nothing (zero specs run, exit code 0)
  • A scheduled test job is disabled or never triggered
  • Jasmine hangs on an async spec with no done() call and the CI runner times out
  • A misconfigured jasmine.json points to the wrong directory

Vigilmon's heartbeat pattern closes these gaps by requiring an explicit "I finished successfully" signal from a reporter wired directly to Jasmine's completion lifecycle.


Step 1: Create a Heartbeat Monitor in Vigilmon

  1. Log in to Vigilmon and click New Monitor → Heartbeat.
  2. Name it something specific: Jasmine Unit Tests — main or Jasmine E2E — nightly.
  3. Set the Expected interval to match your test schedule. For suites that run on every push, use 2 hours (buffers CI queue time). For nightly suites, use 25 hours.
  4. Set the Grace period to 30 minutes for push-triggered suites, or 1 hour for scheduled suites.
  5. Save and copy the Ping URL — it looks like https://vigilmon.online/api/heartbeat/<unique-id>.

Step 2: Write a Custom Jasmine Reporter

Jasmine's reporter API exposes a jasmineDone callback that fires after all specs complete. Wire the heartbeat ping there.

Create vigilmon-reporter.js in your project root:

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

class VigilmonReporter {
  jasmineDone(suiteInfo) {
    const heartbeatUrl = process.env.VIGILMON_HEARTBEAT_URL;

    if (!heartbeatUrl) {
      return; // skip in local dev if the env var isn't set
    }

    // Only ping on a fully successful run (no failures, no pending-that-broke)
    const failed = suiteInfo.failedExpectations
      ? suiteInfo.failedExpectations.length
      : 0;

    if (failed > 0) {
      return; // let the heartbeat window expire — Vigilmon will alert
    }

    const url = new URL(heartbeatUrl);
    const req = https.request(
      {
        hostname: url.hostname,
        path: url.pathname + url.search,
        method: "POST",
        timeout: 10000,
      },
      (res) => {
        res.resume();
      }
    );
    req.on("error", (err) => {
      console.error("[Vigilmon] Heartbeat ping failed:", err.message);
    });
    req.on("timeout", () => {
      req.destroy();
      console.error("[Vigilmon] Heartbeat ping timed out");
    });
    req.end();
  }
}

module.exports = VigilmonReporter;

Step 3: Register the Reporter in Jasmine

Node.js / jasmine npm package

In your spec/support/jasmine.json or programmatic runner:

// spec/support/jasmine.json
{
  "spec_dir": "spec",
  "spec_files": ["**/*[sS]pec.js"],
  "helpers": [],
  "reporters": [],
  "stopSpecOnExpectationFailure": false,
  "random": true
}

Then in a helper file, e.g. spec/helpers/vigilmon.js:

const VigilmonReporter = require("../../vigilmon-reporter");
jasmine.getEnv().addReporter(new VigilmonReporter());

Or if you run Jasmine programmatically:

// run-tests.js
const Jasmine = require("jasmine");
const VigilmonReporter = require("./vigilmon-reporter");

const runner = new Jasmine();
runner.loadConfigFile("spec/support/jasmine.json");
runner.addReporter(new VigilmonReporter());
runner.execute();

Add the helper to your Jasmine config:

{
  "helpers": ["helpers/**/*.js"]
}

Step 4: Integrate with GitHub Actions

# .github/workflows/test.yml
name: Jasmine Tests

on:
  push:
    branches: [main, develop]
  schedule:
    - cron: "0 3 * * *"  # nightly 03:00 UTC

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

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

      - name: Install dependencies
        run: npm ci

      - name: Run Jasmine
        env:
          VIGILMON_HEARTBEAT_URL: ${{ secrets.VIGILMON_JASMINE_HEARTBEAT_URL }}
        run: npx jasmine
        # VigilmonReporter.jasmineDone fires here on success and pings Vigilmon

Store the heartbeat URL in GitHub repo → Settings → Secrets and variables → Actions → New repository secret:

  • Name: VIGILMON_JASMINE_HEARTBEAT_URL
  • Value: ping URL from Step 1

If you prefer to own the ping at the workflow level rather than inside Jasmine:

      - name: Run Jasmine
        run: npx jasmine

      - name: Ping Vigilmon heartbeat
        if: success()
        run: |
          curl -fsS -X POST "${{ secrets.VIGILMON_JASMINE_HEARTBEAT_URL }}" \
            --max-time 10 \
            --retry 3 \
            --retry-delay 2

Use the reporter approach for granular control (individual spec-suite success). Use the workflow step approach when you want the CI config to own the monitoring signal.


Step 5: Integrate with GitLab CI

# .gitlab-ci.yml
test:jasmine:
  image: node:20-alpine
  stage: test
  script:
    - npm ci
    - VIGILMON_HEARTBEAT_URL=$VIGILMON_JASMINE_HEARTBEAT_URL npx jasmine
  only:
    - main
    - schedules

Set VIGILMON_JASMINE_HEARTBEAT_URL in GitLab → Settings → CI/CD → Variables.

For the after-script approach:

test:jasmine:
  image: node:20-alpine
  stage: test
  script:
    - npm ci
    - npx jasmine
  after_script:
    - |
      if [ "$CI_JOB_STATUS" = "success" ]; then
        curl -fsS -X POST "$VIGILMON_JASMINE_HEARTBEAT_URL" --max-time 10 --retry 3
      fi

Step 6: Monitor Multiple Suites Separately

Large projects often split specs into unit, integration, and end-to-end groups with different run schedules. Create one heartbeat monitor per suite:

| Suite | Config file | Monitor name | Interval | |---|---|---|---| | Unit specs | jasmine.unit.json | Jasmine Unit — push | 2 h | | Integration specs | jasmine.integration.json | Jasmine Integration — push | 4 h | | E2E specs | jasmine.e2e.json | Jasmine E2E — nightly | 25 h |

# .github/workflows/test.yml (multi-suite)
jobs:
  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: "20", cache: "npm" }
      - run: npm ci
      - run: npx jasmine --config=jasmine.unit.json
        env:
          VIGILMON_HEARTBEAT_URL: ${{ secrets.VIGILMON_JASMINE_UNIT_HEARTBEAT_URL }}

  integration:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: "20", cache: "npm" }
      - run: npm ci
      - run: npx jasmine --config=jasmine.integration.json
        env:
          VIGILMON_HEARTBEAT_URL: ${{ secrets.VIGILMON_JASMINE_INTEGRATION_HEARTBEAT_URL }}

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 #dev or #ci-alerts channel

When a Jasmine suite stops pinging:

🔴 MISSED HEARTBEAT: Jasmine Unit — push
Last ping: 3 hours ago
Expected interval: 2 hours

When it recovers:

✅ HEARTBEAT RECOVERED: Jasmine Unit — push
Gap: 3 hours

What You're Now Catching

| Silent failure mode | How Vigilmon detects it | |---|---| | Path filter excludes spec directory | No specs run, no reporter fires, no ping → alert | | spec_files glob matches nothing | Exit code 0, reporter fires with 0 specs, no ping | | CI job skipped by branch filter | No ping within interval → alert | | Async spec hangs with no done() | Jasmine times out, no jasmineDone → no ping → alert | | Nightly suite accidentally disabled | No ping → alert after interval | | Specs fail and suite exits non-zero | Reporter skips ping → alert |


Jasmine tells you when specs fail. Vigilmon tells you when Jasmine stops running. Together, both failure modes get covered.

Start monitoring your Jasmine pipelines 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 →