diff --git a/monitoring/scripts/datadog/monitors/synthetics/set_browser_monitor.py b/monitoring/scripts/datadog/monitors/synthetics/set_browser_monitor.py index 48bcdfeb..a2a68f66 100644 --- a/monitoring/scripts/datadog/monitors/synthetics/set_browser_monitor.py +++ b/monitoring/scripts/datadog/monitors/synthetics/set_browser_monitor.py @@ -1,246 +1,728 @@ #!/usr/bin/python + """ + DataDog Browser synthetic test. + + Replaces: New Relic Scripted Browser monitor (syntheticsCreateScriptBrowserMonitor, + Chrome 100 runtime, WebDriver-style $browser/$driver script). + + DataDog browser tests use a declarative "steps" array, not free-form -JavaScript. This module builds a single assertElementContent step from -whichever of two sources the CSV row provides: + +JavaScript. This module builds an assertion step from whichever of two + +sources the CSV row provides: + + Mode A — Browser_Query is set: the script is parsed (best-effort, + regex-based — not a JS engine): + - the start URL comes from CONFIG.URL (falls back to the row's URL column). + - the element locator comes from CONFIG.XPATH, passed to DataDog as a + userLocator (the hand-specified locator format — DataDog's recorder-only + multiLocator format can't be fabricated without a live browser session). + - the wait timeout comes from the $driver.waitForAndFindElement(...) call's + millisecond argument (default 20000ms if absent), converted to seconds. -This assumes the script has exactly one CONFIG block, one -waitForAndFindElement(...) call, and an xpath-based locator — true for -every Browser_Query in both CSVs today. Scripts that don't match (multiple -waits, non-xpath locators, no CONFIG block) are only partially translated: -a URL-only browser test is created (no content assertion) and a WARNING is -logged so it can be reviewed manually, rather than silently fabricating an -assertion that doesn't reflect the original script. + + - if the script also sets CONFIG.DISMISS_XPATH and calls .click() on the + + element found via that locator (e.g. dismissing a consent/warning modal + + that would otherwise leave the target element present-but-invisible — + + DataDog's assertElementContent fails with "Element located but it's + + invisible" in that case), a "click" step is inserted before the + + assertElementContent step to dismiss it first. + +This assumes the script has exactly one CONFIG block, and either one + +waitForAndFindElement(...) call (no dismiss step), or exactly two — the + +first for CONFIG.DISMISS_XPATH followed by .click(), the second for + +CONFIG.XPATH — and an xpath-based locator throughout. Scripts that don't + +match (more waits, non-xpath locators, no CONFIG block, a DISMISS_XPATH + +with no matching .click()) are only partially translated: a URL-only + +browser test is created (no content assertion) and a WARNING is logged so + +it can be reviewed manually, rather than silently fabricating an assertion + +that doesn't reflect the original script. + + Mode B — Browser_Query is empty but Validation_Text is set: some pages + (e.g. JS-rendered SPAs) have no script at all in the CSV, only a validation + string, and a raw HTTP body-contains check can't see JS-rendered content. -The URL comes straight from the row's URL column, the locator is a default -XPath `//*[contains(text(), '')]`, and the timeout -defaults to 20 seconds. + +The URL comes straight from the row's URL column, and the timeout defaults +to 20 seconds. Since there's no script, this is just a "does the page +contain this text" check (matching New Relic's plain validation) — +translated as an assertElementPresent step rather than assertElementContent, +since presence doesn't require the element to be visible (assertElementContent +does, and fails with "Element located but it's invisible" for text that's +present but currently hidden behind e.g. a consent modal — a real failure +mode hit on a page with no dismiss mechanism in either New Relic's original +config or this CSV). The "contains text" condition is encoded directly in +the XPath, since assertElementPresent takes no separate check/value. + +The locator is two ordered fallback candidates in userLocator.values, +rather than one fixed XPath: a heading (h1-h4) match first, then a plain +any-element match. Real pages often have more than one element containing +the same text -- e.g. a site's
repeating the page's own

text +as a logo/title, confirmed live on one page -- so matching "the first +element anywhere with this text" can land on a decorative duplicate +instead of the real content. Preferring headings avoids that without +excluding
/