Watchlog DocsWatchlog Docs
Home
Get Started
Integrations
Log Watchlist
Home
Get Started
Integrations
Log Watchlist
  • Watchlog
  • Get Started
  • Custom Events
  • APM
  • Kubernetes Cluster Monitoring
  • AI Traces Client Libraries Documentation
  • Browser Synthetic Tests

Browser Synthetic Tests

With Watchlog Synthetic Tests, you can execute your most important web journeys—login, search, checkout, dashboards—every few minutes. Watchlog captures step-by-step screenshots, tracks duration (Avg/P95), stores run history, and sends alerts when something breaks.

This guide explains all available actions (steps) and the Import/Export JSON format. It does not require any API knowledge.


Quick start

  1. Create a Browser Synthetic Test.
  2. Add steps with the UI: goto → waitForNetworkIdle → fill → click → waitFor.
  3. Pick a schedule (e.g., every 5 minutes) and configure alert channels (Email, Slack, Telegram, Custom Webhook).
  4. Save. Watchlog will execute on schedule and keep screenshots & history.

Minimal example for a login check:

{
  "name": "Watchlog login test",
  "options": {
    "viewport": { "width": 1366, "height": 768 },
    "timeoutMs": 5000
  },
  "steps": [
    { "action": "goto", "url": "https://app.watchlog.io/account/login", "waitUntil": "domcontentloaded" },
    { "action": "waitForNetworkIdle" },
    { "action": "fill", "selector": "#email", "value": "[email protected]" },
    { "action": "fill", "selector": "#password", "value": "••••••••" },
    { "action": "click", "selector": "text=login" },
    { "action": "waitFor", "selector": "text=Dashboards" }
  ]
}

Concepts

  • Steps: A test is an ordered list of actions executed in the browser.
  • Per‑step timeout: Each step respects options.timeoutMs (default commonly 30000). If a step exceeds the limit, the run fails and a full‑page error screenshot is captured.
  • Viewport: Controls the browser size. Presets are available in the UI.
  • Screenshots: After every successful step, a screenshot is taken. On the first failure, a full‑page screenshot is taken.
  • History & trends: Watch success rate for the last 30 days and recent runs with duration.
  • Alerts: Notify Email, Slack, Telegram, or your own webhook on status changes (e.g., OK → FAIL, FAIL → OK). You can optionally override the default messages.

Actions reference

Actions are the browser operations executed during a run. Each action has its own fields. Below you’ll find the purpose, fields, and examples for each action.

Selectors
Use stable CSS selectors (e.g., [data-test=login]) or Playwright text selectors such as text=Login. Avoid brittle selectors based on layout classes.

1) goto — open a URL

Purpose: Navigate to a URL and wait until a specific page readiness event.

Fields

  • url (required, string): Absolute page URL.
  • waitUntil (optional, enum): When to consider the navigation complete. Default: domcontentloaded
    Allowed values:
    • load → after the window.load event (all resources loaded).
    • domcontentloaded → when the DOM is ready (fast, stable default).
    • networkidle → when the network has been idle for a short period (great for SPAs).

Example

{ "action": "goto", "url": "https://example.com", "waitUntil": "domcontentloaded" }

2) waitForNetworkIdle — wait for network to settle

Purpose: After a goto or click, pages (especially SPAs) may issue many requests. This waits until the network is idle to reduce flakiness.

Fields: none

Example

{ "action": "waitForNetworkIdle" }

3) waitForURL — wait until the URL matches

Purpose: Pause until the current URL matches a string or regular expression (useful for redirects or route changes).

Fields

  • urlOrRegex (required, string): e.g., "https://example.com/home" or "/\\/Home$/"

Example

{ "action": "waitForURL", "urlOrRegex": "/\\/Home$/" }

Regex format: Provide as a string that looks like JS regex literal: "/pattern/flags". For example, "/^https:\\/\\/app\\.example\\.com\\/home$/".


4) waitFor — wait for an element

Purpose: Wait until the target element exists (and is visible enough for interaction).

Fields

  • selector (required, string)

Example

{ "action": "waitFor", "selector": "text=Dashboards" }

5) fill — enter text in a field

Purpose: Fill input fields such as email and password.

Fields

  • selector (required, string)
  • value (required, string).

Examples

{ "action": "fill", "selector": "#email", "value": "[email protected]" }
{ "action": "fill", "selector": "#password", "value": "********" }

Heads‑up: If you fill a visible text input, the screenshot will include what’s on screen. Prefer password fields or pages that mask sensitive text.


6) click — click an element

Purpose: Click a button/link/element.

Fields

  • selector (required, string)

Example

{ "action": "click", "selector": "text=login" }

7) assertVisible — element must be visible

Purpose: Ensure an element is actually visible (not only present in the DOM).

Fields

  • selector (required, string)

Example

{ "action": "assertVisible", "selector": "[data-test=welcome-card]" }

8) assertHidden — element must be hidden (JSON‑only for now)

Purpose: Ensure an element is hidden (not visible to the user).

Fields

  • selector (required, string)

Example

{ "action": "assertHidden", "selector": ".spinner" }

This action is supported by the runner. If you don’t see it in the UI yet, you can still Import JSON with this step.


9) assertText — element must contain text

Purpose: Verify the selected element contains contains as a substring.

Fields

  • selector (required, string)
  • contains (required, string)

Example

{
  "action": "assertText",
  "selector": ".toast.success",
  "contains": "Welcome back"
}

Matching is substring-based.


10) assertCount — element count must match

Purpose: Verify that exactly count elements exist for the given selector.

Fields

  • selector (required, string)
  • count (required, number)

Example

{ "action": "assertCount", "selector": ".product-card", "count": 12 }

Authentication / Session (optional)

Sometimes you need to run steps as an authenticated user.

  • Cookies: Paste your browser cookie string (e.g., session=abc; other=1).
  • Extra HTTP headers: Add items like Authorization: Bearer <token>.
  • Domain hint: If cookies don’t carry a domain, we infer it from your Default URL (or the first goto).

Spec shape (set automatically when you configure in the UI):

{
  "session": {
    "cookieString": "session=abc123; other=1",
    "headers": { "Authorization": "Bearer <token>" },
    "domainHint": "app.example.com"
  }
}

Global test options

  • Viewport
    Default desktop is 1366×768. You can override via UI or JSON:

    { "options": { "viewport": { "width": 1366, "height": 768 } } }
    
  • Timeout
    Max time (ms) per step before failing:

    { "options": { "timeoutMs": 5000 } }
    

Import / Export JSON

Use Import JSON on the test editor to paste a full test definition—or export the current one with Copy JSON.

JSON structure

  • name (string) — test name
  • defaultUrl (optional, string) — used as cookie domain hint
  • options (object) — global settings
    • viewport.width (number)
    • viewport.height (number)
    • timeoutMs (number) — per‑step timeout
  • session (optional, object) — cookies & headers (see above)
  • steps (array) — ordered list of actions. Each step has:
    • action (enum) — one of:

      goto, waitForNetworkIdle, waitForURL, waitFor, fill, click, assertVisible, assertHidden, assertText, assertCount

    • The fields required by that action (see reference above).

Example (login to dashboard)

{
  "name": "Watchlog login test",
  "defaultUrl": "https://app.watchlog.io",
  "options": {
    "viewport": { "width": 1366, "height": 768 },
    "timeoutMs": 5000
  },
  "steps": [
    { "action": "goto", "url": "https://app.watchlog.io/account/login", "waitUntil": "domcontentloaded" },
    { "action": "waitForNetworkIdle" },
    { "action": "fill", "selector": "#email", "value": "[email protected]" },
    { "action": "fill", "selector": "#password", "value": "**********" },
    { "action": "click", "selector": "text=login" },
    { "action": "waitFor", "selector": "text=Dashboards" }
  ]
}

Example (redirect + assertion + count)

{
  "name": "Catalog smoke test",
  "options": { "viewport": { "width": 1440, "height": 900 }, "timeoutMs": 8000 },
  "steps": [
    { "action": "goto", "url": "https://shop.example.com", "waitUntil": "domcontentloaded" },
    { "action": "waitForNetworkIdle" },
    { "action": "click", "selector": "text=Browse All" },
    { "action": "waitForURL", "urlOrRegex": "/\\/catalog$/" },
    { "action": "assertText", "selector": "h1", "contains": "Catalog" },
    { "action": "assertCount", "selector": ".product-card", "count": 12 }
  ]
}

Validations & common errors

  • Unknown action → step will fail with Unknown action: ....
  • Missing required field → step validation error (e.g., selector is required).
  • Invalid type → e.g., count must be a number.
  • Timeouts → increase options.timeoutMs or add waitForNetworkIdle after navigations or heavy actions.
  • Selectors not found → inspect your page and prefer robust selectors like [data-test=...].

Best practices

  • Prefer stable selectors: [data-test=...], text=.... Avoid layout classes.
  • Reduce flakiness: Add waitForNetworkIdle after navigations or clicks that trigger heavy network activity.
  • Smaller tests: Keep flows focused (login check, search check, checkout happy path).
  • Screenshots: Use the per‑step gallery and the error full‑page capture to spot what went wrong quickly.

Need an action that isn’t here yet? Tell us and we’ll add it.

Last Updated:: 8/15/25, 2:50 AM
Contributors: mohammad
Prev
AI Traces Client Libraries Documentation