Advanced web test patterns: login flows, variable capture and custom metrics
How to handle multi-step logins, capture values from the page into variables, assert against them, and publish custom metrics to VerOps — illustrated with a real-world example.
This article walks through the features used to build a real-world synthetic web test that logs into Fieldwire, navigates to the People page, counts the number of users, asserts the count is within a threshold, and publishes the count as a VerOps metric. Each section covers one feature with a worked example.
Two-step login flows
Some applications split the login form across two pages — email on the first, password on the second. Model each screen as its own steps.
Step 1 — Navigate to the login page
Action type: Navigate
URL: https://app.fieldwire.com/auth/sign_in?lang=en
Step 2 — Type the email address
Action type: Type
Selector: input[type="email"]
Value: {{credential.Fieldwire.username}}
Step 3 — Click Continue
Action type: Click
Selector: button[type="submit"]
Step 4 — Wait for the password field
After clicking Continue the browser navigates to a new URL. Wait for the password field before proceeding.
Action type: Wait
Wait condition: Element Visible
Selector: input[type="password"]
Step 5 — Type the password
Action type: Type
Selector: input[type="password"]
Value: {{credential.Fieldwire.password}}
Step 6 — Click Sign In
Action type: Click
Selector: button[type="submit"]
Step 7 — Wait for the app to finish loading
Action type: Wait
Wait condition: Ajax Complete
---
Secure credentials
Credentials are stored encrypted in the VerOps vault and injected at run time. They are never stored in the test configuration and are masked in screenshots and logs.
Placeholder syntax
{{credential.CredentialName.field}}
where field is one of username, password, or totp.
Example
{{credential.Fieldwire.username}}
{{credential.Fieldwire.password}}
Allowed hosts — restrict each credential to the domains where it is valid (e.g. app.fieldwire.com). The agent refuses to resolve the placeholder on any other host.
Allow VerOps cloud agents — credentials are restricted to your own self-hosted agents by default. Enable this toggle to allow the credential to be resolved on VerOps cloud agents.
---
Capturing page values with Execute JavaScript
The Execute JavaScript step runs a script in the browser and stores the return value in a named variable. Any string or number returned by the script is captured.
Step 8 — Navigate to the People page
Action type: Navigate
URL: https://app.fieldwire.com/index/people
Step 9 — Wait for the list to render
Action type: Wait
Wait condition: Element Visible
Selector: td.user-name-cell
Step 10 — Count the users
Action type: Execute JavaScript
Variable Name: userCount
(function() { return document.querySelectorAll('td.user-name-cell').length.toString(); })()The value stored in userCount is available to all subsequent steps via ${userCount}.
Selector tip — prefer stable attributes over generated class names. data-e2e, data-testid, and semantic class names like user-name-cell survive most application updates. Avoid Angular's _ngcontent-* scoped attributes — they are regenerated with every build.
Publishing a custom metric from a test step
Any numeric value captured during a test can be published to VerOps as a metric via the OTLP HTTP endpoint. The trick is to navigate to the ingest domain before making the call so the fetch is same-origin and no CORS negotiation is required.
Step 11 — Navigate to the ingest domain
Action type: Navigate
URL: https://ingest.verops.io
Step 12 — POST the metric
Action type: Execute JavaScript
(function() {
return fetch('/v1/metrics', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{credential.VerOpsIngestAPI.password}}'
},
body: JSON.stringify({
resourceMetrics: [{
scopeMetrics: [{
metrics: [{
name: 'fieldwire_user_count',
gauge: {
dataPoints: [{
asDouble: parseInt('${userCount}'),
timeUnixNano: String(Date.now() * 1000000)
}]
}
}]
}]
}]
})
}).then(function(r) { return r.status.toString(); });
})()Store the ingest API key as a credential named VerOpsIngestAPI with ingest.verops.io as the allowed host and Allow
VerOps cloud agents enabled.
Once published, fieldwire_user_count appears in the metrics table and can be used in dashboards and alerts:
SELECT max(value) AS user_count FROM metrics WHERE metric_name = 'fieldwire_user_count' AND timestamp >= now() - INTERVAL 7 DAYAlerting on the metric
SELECT ifNull(max(value), 0) AS user_count FROM metrics WHERE metric_name = 'fieldwire_user_count' AND timestamp >= now() - INTERVAL 3 HOURSet the alert threshold to user_count >= 50 (or your chosen limit). Because the test runs on a schedule, the 3-hour
window ensures the most recent run is always captured.