From 3b75919cf5f8092528ed1eaa71842c0a12022f47 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:16:04 +0000 Subject: [PATCH 1/9] Initial plan From 8aebddbe938853e3bcf25176158832c85a02afb2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:21:12 +0000 Subject: [PATCH 2/9] Add Fabric.js and canvas dependencies, create annotateScreenshot module, integrate with saveScreenshot Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- core/package-lock.json | 1081 +++++++++++++++++++++++++- core/package.json | 2 + core/src/tests/annotateScreenshot.js | 540 +++++++++++++ core/src/tests/saveScreenshot.js | 21 + 4 files changed, 1625 insertions(+), 19 deletions(-) create mode 100644 core/src/tests/annotateScreenshot.js diff --git a/core/package-lock.json b/core/package-lock.json index c71e9d8..ab1cf68 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -19,9 +19,11 @@ "appium-geckodriver": "^2.1.2", "appium-safari-driver": "^4.1.2", "axios": "^1.13.2", + "canvas": "^2.11.2", "doc-detective-common": "^3.6.0", "doc-detective-resolver": "^3.6.1", "dotenv": "^17.2.3", + "fabric": "^6.0.0", "geckodriver": "^6.1.0", "jq-web": "^0.6.2", "json-schema-faker": "^0.5.9", @@ -1274,6 +1276,51 @@ "jsep": "^0.4.0||^1.0.0" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1358,6 +1405,16 @@ "text-hex": "1.0.x" } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -1726,6 +1783,20 @@ "node": ">=18.0.0" } }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1751,6 +1822,43 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "optional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "optional": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -16572,6 +16680,12 @@ "node": ">= 14" } }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC" + }, "node_modules/archiver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", @@ -16680,6 +16794,34 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -17175,6 +17317,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -17275,6 +17432,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -17415,6 +17581,15 @@ "node": ">=12.20" } }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/color/node_modules/color-convert": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.2.tgz", @@ -17477,7 +17652,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/consola": { @@ -17666,6 +17840,33 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "license": "MIT", + "optional": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "license": "MIT", + "optional": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "license": "MIT", + "optional": true + }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", @@ -17675,6 +17876,31 @@ "node": ">= 14" } }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -17704,6 +17930,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT", + "optional": true + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "license": "MIT", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/deepmerge-ts": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", @@ -17748,6 +17993,12 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, "node_modules/depcheck": { "version": "1.4.7", "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz", @@ -17927,7 +18178,6 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -18019,6 +18269,20 @@ ], "license": "BSD-2-Clause" }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "license": "MIT", + "optional": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", @@ -18552,6 +18816,19 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/fabric": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/fabric/-/fabric-6.0.0.tgz", + "integrity": "sha512-Kc187rYtOuTAXCMs+RRP8UEr09pZgJx0rusKMfv0wWFcbVakv3WKNB7lBhuWXjJk/gfxQHp2h+7f7AF1FGIGcg==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + }, + "optionalDependencies": { + "canvas": "^2.11.2", + "jsdom": "^20.0.1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -18797,6 +19074,36 @@ "node": ">= 0.8" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/ftp-response-parser": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ftp-response-parser/-/ftp-response-parser-1.0.1.tgz", @@ -18835,6 +19142,74 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/geckodriver": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-6.1.0.tgz", @@ -19109,6 +19484,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -19203,23 +19584,49 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/htmlfy": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.8.1.tgz", - "integrity": "sha512-xWROBw9+MEGwxpotll0h672KCaLrKKiCYzsyN8ZgL9cQbVumFnyvsk2JqiB9ELAV1GLj1GG/jxZUjV9OZZi/yQ==", - "license": "MIT" - }, - "node_modules/htmlparser2": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", - "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "license": "MIT", + "optional": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-encoding-sniffer/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlfy": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.8.1.tgz", + "integrity": "sha512-xWROBw9+MEGwxpotll0h672KCaLrKKiCYzsyN8ZgL9cQbVumFnyvsk2JqiB9ELAV1GLj1GG/jxZUjV9OZZi/yQ==", + "license": "MIT" + }, + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", @@ -19389,6 +19796,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -19514,6 +19932,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "license": "MIT", + "optional": true + }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -19608,6 +20033,117 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/jsdom/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/jsep": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", @@ -20051,6 +20587,30 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -20164,6 +20724,18 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -20196,12 +20768,49 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mocha": { "version": "11.7.5", "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", @@ -20447,6 +21056,12 @@ "node": "*" } }, + "node_modules/nan": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.24.0.tgz", + "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -20493,6 +21108,63 @@ "node": ">= 0.4.0" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -20523,6 +21195,19 @@ "node": ">=0.10.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -20535,6 +21220,22 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/nwsapi": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -20863,6 +21564,15 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -21117,6 +21827,19 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "optional": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -21127,6 +21850,16 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -21148,6 +21881,13 @@ "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", "license": "MIT" }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT", + "optional": true + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -21321,6 +22061,13 @@ "dev": true, "license": "MIT" }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT", + "optional": true + }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -21413,6 +22160,65 @@ "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", "license": "MIT" }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -21501,6 +22307,19 @@ "truncate-utf8-bytes": "^1.0.0" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "license": "ISC", + "optional": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -21806,6 +22625,37 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "license": "MIT", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -22188,6 +23038,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "license": "MIT", + "optional": true + }, "node_modules/tagged-tag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", @@ -22200,6 +23057,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", @@ -22225,6 +23099,15 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/teen_process": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", @@ -22284,6 +23167,35 @@ "node": ">=0.6" } }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -22361,6 +23273,16 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/unorm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", @@ -22379,6 +23301,17 @@ "node": ">= 0.8" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/urlpattern-polyfill": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", @@ -22438,6 +23371,19 @@ "node": ">= 0.8" } }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "license": "MIT", + "optional": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/wait-port": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz", @@ -22588,6 +23534,16 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -22609,6 +23565,20 @@ "node": ">=18" } }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", @@ -22624,6 +23594,56 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/winston": { "version": "3.18.3", "resolved": "https://registry.npmjs.org/winston/-/winston-3.18.3.tgz", @@ -22839,6 +23859,16 @@ } } }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -22848,6 +23878,13 @@ "node": ">=8.0" } }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "license": "MIT", + "optional": true + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -22857,6 +23894,12 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, "node_modules/yaml": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", diff --git a/core/package.json b/core/package.json index d1d0c53..019f3e3 100644 --- a/core/package.json +++ b/core/package.json @@ -36,9 +36,11 @@ "appium-geckodriver": "^2.1.2", "appium-safari-driver": "^4.1.2", "axios": "^1.13.2", + "canvas": "^2.11.2", "doc-detective-common": "^3.6.0", "doc-detective-resolver": "^3.6.1", "dotenv": "^17.2.3", + "fabric": "^6.0.0", "geckodriver": "^6.1.0", "jq-web": "^0.6.2", "json-schema-faker": "^0.5.9", diff --git a/core/src/tests/annotateScreenshot.js b/core/src/tests/annotateScreenshot.js new file mode 100644 index 0000000..702a7fb --- /dev/null +++ b/core/src/tests/annotateScreenshot.js @@ -0,0 +1,540 @@ +const { fabric } = require("fabric"); +const { createCanvas, loadImage } = require("canvas"); +const { findElement } = require("./findElement"); +const { log } = require("../utils"); +const fs = require("fs"); + +exports.annotateScreenshot = annotateScreenshot; + +async function annotateScreenshot({ config, filePath, annotations, driver }) { + try { + log(config, "debug", `Starting annotation of screenshot: ${filePath}`); + + // Load the screenshot image + const image = await loadImage(filePath); + const width = image.width; + const height = image.height; + + // Create a node-canvas + const nodeCanvas = createCanvas(width, height); + const ctx = nodeCanvas.getContext("2d"); + ctx.drawImage(image, 0, 0); + + // Create Fabric.js canvas using the node-canvas + const fabricCanvas = new fabric.Canvas(nodeCanvas); + fabricCanvas.setWidth(width); + fabricCanvas.setHeight(height); + + // Get pixel density for scaling + const pixelDensity = await driver.execute(() => window.devicePixelRatio); + log(config, "debug", `Pixel density: ${pixelDensity}`); + + // Process each annotation + for (const annotation of annotations) { + try { + await renderAnnotation({ + config, + fabricCanvas, + annotation, + driver, + pixelDensity, + canvasWidth: width, + canvasHeight: height, + }); + } catch (error) { + log( + config, + "warn", + `Failed to render annotation: ${error.message}` + ); + return { + success: false, + error: `Annotation rendering failed: ${error.message}`, + }; + } + } + + // Render canvas to buffer + const buffer = nodeCanvas.toBuffer("image/png"); + + // Write buffer to file (overwriting original) + fs.writeFileSync(filePath, buffer); + + log( + config, + "debug", + `Successfully annotated screenshot with ${annotations.length} annotation(s)` + ); + + return { success: true }; + } catch (error) { + log(config, "error", `Annotation failed: ${error.message}`); + return { success: false, error: error.message }; + } +} + +async function renderAnnotation({ + config, + fabricCanvas, + annotation, + driver, + pixelDensity, + canvasWidth, + canvasHeight, +}) { + // Determine base position for annotation + let basePosition = { x: 0, y: 0 }; + + // If annotation has a 'find' field, locate the element + if (annotation.find) { + const findStep = { + find: annotation.find, + }; + + const findResult = await findElement({ + config, + step: findStep, + driver, + }); + + if (findResult.status === "FAIL") { + throw new Error(`Could not find element: ${findResult.description}`); + } + + const element = findResult.outputs?.rawElement; + if (!element) { + throw new Error("Element not found for annotation"); + } + + // Get element bounds and scale by pixel density + const rect = await driver.execute((el) => { + const bounds = el.getBoundingClientRect(); + return { + x: bounds.left, + y: bounds.top, + width: bounds.width, + height: bounds.height, + }; + }, element); + + // Scale coordinates by pixel density + basePosition.x = rect.x * pixelDensity; + basePosition.y = rect.y * pixelDensity; + basePosition.width = rect.width * pixelDensity; + basePosition.height = rect.height * pixelDensity; + + log(config, "debug", `Element position: ${JSON.stringify(basePosition)}`); + } + + // Apply position keyword if specified + if (annotation.position) { + if (typeof annotation.position === "string") { + basePosition = applyPositionKeyword( + annotation.position, + basePosition, + canvasWidth, + canvasHeight + ); + } else if ( + typeof annotation.position === "object" && + annotation.position.x !== undefined && + annotation.position.y !== undefined + ) { + // Absolute position + basePosition = { + x: annotation.position.x * pixelDensity, + y: annotation.position.y * pixelDensity, + }; + } + } + + // Render annotation based on type + if (annotation.arrow) { + renderArrow(fabricCanvas, annotation.arrow, basePosition, pixelDensity); + } else if (annotation.text) { + renderText(fabricCanvas, annotation.text, basePosition, pixelDensity); + } else if (annotation.rectangle) { + renderRectangle( + fabricCanvas, + annotation.rectangle, + basePosition, + pixelDensity + ); + } else if (annotation.circle) { + renderCircle(fabricCanvas, annotation.circle, basePosition, pixelDensity); + } else if (annotation.line) { + renderLine(fabricCanvas, annotation.line, basePosition, pixelDensity); + } else if (annotation.callout) { + renderCallout(fabricCanvas, annotation.callout, basePosition, pixelDensity); + } else if (annotation.highlight) { + renderHighlight( + fabricCanvas, + annotation.highlight, + basePosition, + pixelDensity + ); + } else if (annotation.blur) { + renderBlur(fabricCanvas, annotation.blur, basePosition, pixelDensity); + } +} + +function applyPositionKeyword( + keyword, + basePosition, + canvasWidth, + canvasHeight +) { + const hasElement = basePosition.width !== undefined; + + if (!hasElement) { + // Position within viewport + switch (keyword) { + case "top": + return { x: canvasWidth / 2, y: 50 }; + case "bottom": + return { x: canvasWidth / 2, y: canvasHeight - 50 }; + case "left": + return { x: 50, y: canvasHeight / 2 }; + case "right": + return { x: canvasWidth - 50, y: canvasHeight / 2 }; + case "center": + return { x: canvasWidth / 2, y: canvasHeight / 2 }; + case "top-left": + return { x: 50, y: 50 }; + case "top-right": + return { x: canvasWidth - 50, y: 50 }; + case "bottom-left": + return { x: 50, y: canvasHeight - 50 }; + case "bottom-right": + return { x: canvasWidth - 50, y: canvasHeight - 50 }; + default: + return { x: 0, y: 0 }; + } + } else { + // Position relative to element + const centerX = basePosition.x + basePosition.width / 2; + const centerY = basePosition.y + basePosition.height / 2; + + switch (keyword) { + case "top": + return { x: centerX, y: basePosition.y, ...basePosition }; + case "bottom": + return { + x: centerX, + y: basePosition.y + basePosition.height, + ...basePosition, + }; + case "left": + return { x: basePosition.x, y: centerY, ...basePosition }; + case "right": + return { + x: basePosition.x + basePosition.width, + y: centerY, + ...basePosition, + }; + case "center": + return { x: centerX, y: centerY, ...basePosition }; + case "top-left": + return { x: basePosition.x, y: basePosition.y, ...basePosition }; + case "top-right": + return { + x: basePosition.x + basePosition.width, + y: basePosition.y, + ...basePosition, + }; + case "bottom-left": + return { + x: basePosition.x, + y: basePosition.y + basePosition.height, + ...basePosition, + }; + case "bottom-right": + return { + x: basePosition.x + basePosition.width, + y: basePosition.y + basePosition.height, + ...basePosition, + }; + default: + return { x: centerX, y: centerY, ...basePosition }; + } + } +} + +function renderArrow(fabricCanvas, arrow, basePosition, pixelDensity) { + const defaults = { + color: "#FF0000", + strokeWidth: 3, + headSize: 15, + }; + + const config = { ...defaults, ...arrow }; + + // Calculate from/to positions + const fromX = basePosition.x + (arrow.from?.x || 0) * pixelDensity; + const fromY = basePosition.y + (arrow.from?.y || 0) * pixelDensity; + const toX = basePosition.x + (arrow.to?.x || 0) * pixelDensity; + const toY = basePosition.y + (arrow.to?.y || 0) * pixelDensity; + + // Calculate angle for arrowhead + const angle = Math.atan2(toY - fromY, toX - fromX); + + // Create arrow line + const line = new fabric.Line([fromX, fromY, toX, toY], { + stroke: config.color, + strokeWidth: config.strokeWidth, + selectable: false, + evented: false, + }); + + // Create arrowhead triangle + const headLength = config.headSize; + const headAngle = Math.PI / 6; // 30 degrees + + const arrowHead = new fabric.Triangle({ + left: toX, + top: toY, + originX: "center", + originY: "center", + width: headLength, + height: headLength, + fill: config.color, + angle: (angle * 180) / Math.PI + 90, + selectable: false, + evented: false, + }); + + fabricCanvas.add(line); + fabricCanvas.add(arrowHead); +} + +function renderText(fabricCanvas, text, basePosition, pixelDensity) { + const defaults = { + fontSize: 16, + fontFamily: "Arial", + color: "#000000", + backgroundColor: "#FFFFFF", + padding: 5, + opacity: 1, + }; + + const config = { ...defaults, ...text }; + + const textObj = new fabric.Textbox(config.content, { + left: basePosition.x, + top: basePosition.y, + fontSize: config.fontSize * pixelDensity, + fontFamily: config.fontFamily, + fill: config.color, + backgroundColor: config.backgroundColor, + padding: config.padding * pixelDensity, + width: config.maxWidth + ? config.maxWidth * pixelDensity + : 200 * pixelDensity, + opacity: config.opacity, + selectable: false, + evented: false, + }); + + fabricCanvas.add(textObj); +} + +function renderRectangle(fabricCanvas, rectangle, basePosition, pixelDensity) { + const defaults = { + fill: "transparent", + stroke: "#FF0000", + strokeWidth: 2, + opacity: 1, + rx: 0, + ry: 0, + }; + + const config = { ...defaults, ...rectangle }; + + const rect = new fabric.Rect({ + left: basePosition.x, + top: basePosition.y, + width: (config.width || basePosition.width || 100) * pixelDensity, + height: (config.height || basePosition.height || 100) * pixelDensity, + fill: config.fill, + stroke: config.stroke, + strokeWidth: config.strokeWidth * pixelDensity, + opacity: config.opacity, + rx: config.rx * pixelDensity, + ry: config.ry * pixelDensity, + selectable: false, + evented: false, + }); + + fabricCanvas.add(rect); +} + +function renderCircle(fabricCanvas, circle, basePosition, pixelDensity) { + const defaults = { + radius: 30, + fill: "transparent", + stroke: "#FF0000", + strokeWidth: 2, + opacity: 1, + }; + + const config = { ...defaults, ...circle }; + + const circleObj = new fabric.Circle({ + left: basePosition.x, + top: basePosition.y, + radius: config.radius * pixelDensity, + fill: config.fill, + stroke: config.stroke, + strokeWidth: config.strokeWidth * pixelDensity, + opacity: config.opacity, + originX: "center", + originY: "center", + selectable: false, + evented: false, + }); + + fabricCanvas.add(circleObj); +} + +function renderLine(fabricCanvas, line, basePosition, pixelDensity) { + const defaults = { + color: "#000000", + strokeWidth: 2, + }; + + const config = { ...defaults, ...line }; + + const fromX = basePosition.x + (line.from?.x || 0) * pixelDensity; + const fromY = basePosition.y + (line.from?.y || 0) * pixelDensity; + const toX = basePosition.x + (line.to?.x || 0) * pixelDensity; + const toY = basePosition.y + (line.to?.y || 0) * pixelDensity; + + const lineObj = new fabric.Line([fromX, fromY, toX, toY], { + stroke: config.color, + strokeWidth: config.strokeWidth * pixelDensity, + strokeDashArray: config.dashArray + ? config.dashArray.map((v) => v * pixelDensity) + : undefined, + selectable: false, + evented: false, + }); + + fabricCanvas.add(lineObj); +} + +function renderCallout(fabricCanvas, callout, basePosition, pixelDensity) { + const defaults = { + fontSize: 14, + color: "#000000", + backgroundColor: "#FFFFCC", + arrowColor: "#000000", + }; + + const config = { ...defaults, ...callout }; + + // Target position + const targetX = basePosition.x + (callout.target?.x || 0) * pixelDensity; + const targetY = basePosition.y + (callout.target?.y || 0) * pixelDensity; + + // Text position (auto-position if not specified) + let textX, textY; + if (callout.textPosition) { + textX = basePosition.x + callout.textPosition.x * pixelDensity; + textY = basePosition.y + callout.textPosition.y * pixelDensity; + } else { + // Auto-position above and to the left of target + textX = targetX - 100 * pixelDensity; + textY = targetY - 80 * pixelDensity; + } + + // Create text box + const textObj = new fabric.Textbox(config.content, { + left: textX, + top: textY, + fontSize: config.fontSize * pixelDensity, + fontFamily: "Arial", + fill: config.color, + backgroundColor: config.backgroundColor, + padding: 8 * pixelDensity, + width: config.maxWidth + ? config.maxWidth * pixelDensity + : 150 * pixelDensity, + selectable: false, + evented: false, + }); + + fabricCanvas.add(textObj); + + // Create arrow from text to target + const textCenterX = textX + textObj.width / 2; + const textCenterY = textY + textObj.height / 2; + + const angle = Math.atan2(targetY - textCenterY, targetX - textCenterX); + + const line = new fabric.Line([textCenterX, textCenterY, targetX, targetY], { + stroke: config.arrowColor, + strokeWidth: 2 * pixelDensity, + selectable: false, + evented: false, + }); + + const arrowHead = new fabric.Triangle({ + left: targetX, + top: targetY, + originX: "center", + originY: "center", + width: 10 * pixelDensity, + height: 10 * pixelDensity, + fill: config.arrowColor, + angle: (angle * 180) / Math.PI + 90, + selectable: false, + evented: false, + }); + + fabricCanvas.add(line); + fabricCanvas.add(arrowHead); +} + +function renderHighlight(fabricCanvas, highlight, basePosition, pixelDensity) { + const defaults = { + color: "#FFFF00", + opacity: 0.3, + }; + + const config = { ...defaults, ...highlight }; + + const rect = new fabric.Rect({ + left: basePosition.x, + top: basePosition.y, + width: basePosition.width || 100 * pixelDensity, + height: basePosition.height || 100 * pixelDensity, + fill: config.color, + opacity: config.opacity, + selectable: false, + evented: false, + }); + + fabricCanvas.add(rect); +} + +function renderBlur(fabricCanvas, blur, basePosition, pixelDensity) { + const defaults = { + intensity: 10, + }; + + const config = { ...defaults, ...blur }; + + // For blur, we use a semi-transparent overlay as a visual indicator + // True pixel blur would require Sharp preprocessing + const rect = new fabric.Rect({ + left: basePosition.x, + top: basePosition.y, + width: (config.width || basePosition.width || 100) * pixelDensity, + height: (config.height || basePosition.height || 100) * pixelDensity, + fill: "rgba(200, 200, 200, 0.8)", + selectable: false, + evented: false, + }); + + fabricCanvas.add(rect); +} diff --git a/core/src/tests/saveScreenshot.js b/core/src/tests/saveScreenshot.js index b339df6..ca2f163 100644 --- a/core/src/tests/saveScreenshot.js +++ b/core/src/tests/saveScreenshot.js @@ -283,6 +283,27 @@ async function saveScreenshot({ config, step, driver }) { } } + // Apply annotations if specified + if (step.screenshot.annotations && Array.isArray(step.screenshot.annotations)) { + const { annotateScreenshot } = require("./annotateScreenshot"); + const targetPath = existFilePath || filePath; + + const annotationResult = await annotateScreenshot({ + config, + filePath: targetPath, + annotations: step.screenshot.annotations, + driver, + }); + + if (!annotationResult.success) { + result.status = "FAIL"; + result.description = `Annotation failed: ${annotationResult.error}`; + return result; + } + + result.description += ` Added ${step.screenshot.annotations.length} annotation(s).`; + } + // If file already exists // If overwrite is true, replace old file with new file // If overwrite is aboveVariation, compare files and replace if variance is greater than threshold From d965072e90d7b9591e6a105bb7356535a3b39435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:28:43 +0000 Subject: [PATCH 3/9] Fix Fabric.js StaticCanvas usage and annotation targeting logic Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- core/src/tests/annotateScreenshot.js | 14 +- core/src/tests/saveScreenshot.js | 6 +- core/test/artifacts/annotations.spec.json | 225 ++++++++++++++++++++++ core/test/temp-dom-timeout-test.json | 17 ++ core/test/temp-element-timeout-test.json | 19 ++ core/test/temp-network-timeout-test.json | 17 ++ core/test/test-annotations.js | 44 +++++ 7 files changed, 334 insertions(+), 8 deletions(-) create mode 100644 core/test/artifacts/annotations.spec.json create mode 100644 core/test/temp-dom-timeout-test.json create mode 100644 core/test/temp-element-timeout-test.json create mode 100644 core/test/temp-network-timeout-test.json create mode 100644 core/test/test-annotations.js diff --git a/core/src/tests/annotateScreenshot.js b/core/src/tests/annotateScreenshot.js index 702a7fb..5241eda 100644 --- a/core/src/tests/annotateScreenshot.js +++ b/core/src/tests/annotateScreenshot.js @@ -20,10 +20,11 @@ async function annotateScreenshot({ config, filePath, annotations, driver }) { const ctx = nodeCanvas.getContext("2d"); ctx.drawImage(image, 0, 0); - // Create Fabric.js canvas using the node-canvas - const fabricCanvas = new fabric.Canvas(nodeCanvas); - fabricCanvas.setWidth(width); - fabricCanvas.setHeight(height); + // Create Fabric.js StaticCanvas for server-side rendering + const fabricCanvas = new fabric.StaticCanvas(nodeCanvas, { + width: width, + height: height, + }); // Get pixel density for scaling const pixelDensity = await driver.execute(() => window.devicePixelRatio); @@ -54,7 +55,10 @@ async function annotateScreenshot({ config, filePath, annotations, driver }) { } } - // Render canvas to buffer + // Render Fabric canvas back to node canvas + fabricCanvas.renderAll(); + + // Get buffer from node canvas const buffer = nodeCanvas.toBuffer("image/png"); // Write buffer to file (overwriting original) diff --git a/core/src/tests/saveScreenshot.js b/core/src/tests/saveScreenshot.js index ca2f163..9c08ae7 100644 --- a/core/src/tests/saveScreenshot.js +++ b/core/src/tests/saveScreenshot.js @@ -286,11 +286,11 @@ async function saveScreenshot({ config, step, driver }) { // Apply annotations if specified if (step.screenshot.annotations && Array.isArray(step.screenshot.annotations)) { const { annotateScreenshot } = require("./annotateScreenshot"); - const targetPath = existFilePath || filePath; - + + // Always annotate the newly captured screenshot (filePath) const annotationResult = await annotateScreenshot({ config, - filePath: targetPath, + filePath: filePath, annotations: step.screenshot.annotations, driver, }); diff --git a/core/test/artifacts/annotations.spec.json b/core/test/artifacts/annotations.spec.json new file mode 100644 index 0000000..21856cd --- /dev/null +++ b/core/test/artifacts/annotations.spec.json @@ -0,0 +1,225 @@ +{ + "specId": "screenshot-annotations", + "tests": [ + { + "testId": "test-annotations", + "description": "Test screenshot annotations with various types", + "steps": [ + { + "goTo": "http://localhost:8092/index.html" + }, + { + "stepId": "annotation-arrow", + "screenshot": { + "path": "annotation-arrow.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "selector": "#text-input" + }, + "position": "center", + "arrow": { + "from": { "x": 0, "y": -50 }, + "to": { "x": 0, "y": 0 }, + "color": "#FF0000", + "strokeWidth": 4, + "headSize": 15 + } + } + ] + } + }, + { + "stepId": "annotation-text", + "screenshot": { + "path": "annotation-text.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "position": "top-right", + "text": { + "content": "Important Notice", + "fontSize": 18, + "color": "#FFFFFF", + "backgroundColor": "#0000FF", + "padding": 10, + "maxWidth": 200, + "opacity": 0.9 + } + } + ] + } + }, + { + "stepId": "annotation-rectangle", + "screenshot": { + "path": "annotation-rectangle.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "selector": "#password-input" + }, + "rectangle": { + "stroke": "#00FF00", + "strokeWidth": 3, + "fill": "rgba(0, 255, 0, 0.2)", + "rx": 5, + "ry": 5 + } + } + ] + } + }, + { + "stepId": "annotation-circle", + "screenshot": { + "path": "annotation-circle.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "elementText": "Submit Button" + }, + "position": "center", + "circle": { + "radius": 40, + "stroke": "#FF00FF", + "strokeWidth": 3, + "fill": "transparent" + } + } + ] + } + }, + { + "stepId": "annotation-line", + "screenshot": { + "path": "annotation-line.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "position": { "x": 50, "y": 50 }, + "line": { + "from": { "x": 0, "y": 0 }, + "to": { "x": 100, "y": 100 }, + "color": "#0000FF", + "strokeWidth": 3, + "dashArray": [5, 5] + } + } + ] + } + }, + { + "stepId": "annotation-highlight", + "screenshot": { + "path": "annotation-highlight.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "selector": "h1" + }, + "highlight": { + "color": "#FFFF00", + "opacity": 0.4 + } + } + ] + } + }, + { + "stepId": "annotation-blur", + "screenshot": { + "path": "annotation-blur.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "selector": "#password-input" + }, + "blur": { + "intensity": 15 + } + } + ] + } + }, + { + "stepId": "annotation-callout", + "screenshot": { + "path": "annotation-callout.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "selector": "#text-input" + }, + "position": "center", + "callout": { + "content": "Enter your username here", + "target": { "x": 0, "y": 0 }, + "fontSize": 14, + "color": "#000000", + "backgroundColor": "#FFFFCC", + "arrowColor": "#000000", + "maxWidth": 150 + } + } + ] + } + }, + { + "stepId": "annotation-multiple", + "screenshot": { + "path": "annotation-multiple.png", + "directory": "test/artifacts/annotations", + "maxVariation": 0.1, + "annotations": [ + { + "find": { + "selector": "#text-input" + }, + "position": "center", + "arrow": { + "from": { "x": 0, "y": -50 }, + "to": { "x": 0, "y": 0 }, + "color": "#FF0000", + "strokeWidth": 3 + } + }, + { + "find": { + "selector": "#password-input" + }, + "rectangle": { + "stroke": "#00FF00", + "strokeWidth": 2 + } + }, + { + "position": "top-right", + "text": { + "content": "Test Page", + "fontSize": 16, + "color": "#000000", + "backgroundColor": "#FFFFFF" + } + } + ] + } + } + ] + } + ] +} diff --git a/core/test/temp-dom-timeout-test.json b/core/test/temp-dom-timeout-test.json new file mode 100644 index 0000000..6e2f7e2 --- /dev/null +++ b/core/test/temp-dom-timeout-test.json @@ -0,0 +1,17 @@ +{ + "tests": [ + { + "steps": [ + { + "goTo": { + "url": "http://localhost:8092/waitUntil-test-dom-mutations-forever.html", + "timeout": 5000, + "waitUntil": { + "domIdleTime": 500 + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/core/test/temp-element-timeout-test.json b/core/test/temp-element-timeout-test.json new file mode 100644 index 0000000..ec4c584 --- /dev/null +++ b/core/test/temp-element-timeout-test.json @@ -0,0 +1,19 @@ +{ + "tests": [ + { + "steps": [ + { + "goTo": { + "url": "http://localhost:8092/index.html", + "timeout": 5000, + "waitUntil": { + "find": { + "selector": ".nonexistent-element-that-will-never-appear" + } + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/core/test/temp-network-timeout-test.json b/core/test/temp-network-timeout-test.json new file mode 100644 index 0000000..75afdc6 --- /dev/null +++ b/core/test/temp-network-timeout-test.json @@ -0,0 +1,17 @@ +{ + "tests": [ + { + "steps": [ + { + "goTo": { + "url": "http://localhost:8092/waitUntil-test-network-forever.html", + "timeout": 5000, + "waitUntil": { + "networkIdleTime": 500 + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/core/test/test-annotations.js b/core/test/test-annotations.js new file mode 100644 index 0000000..0b6fcb3 --- /dev/null +++ b/core/test/test-annotations.js @@ -0,0 +1,44 @@ +const { runTests } = require("../src"); +const path = require("path"); + +async function testAnnotations() { + console.log("Testing annotations..."); + + const config = { + runTests: { + input: path.resolve(__dirname, "artifacts/annotations.spec.json"), + }, + logLevel: "info", + telemetry: { send: false } + }; + + try { + const result = await runTests(config); + console.log("\n=== Test Results ==="); + console.log("Specs:", result.summary.specs); + console.log("Tests:", result.summary.tests); + console.log("Steps:", result.summary.steps); + + if (result.summary.specs.fail > 0 || result.summary.tests.fail > 0) { + console.log("\n=== Failed Tests ==="); + result.specs.forEach((spec) => { + spec.tests.forEach((test) => { + test.steps.forEach((step) => { + if (step.status === "FAIL") { + console.log(`Step ${step.stepId}: ${step.description}`); + } + }); + }); + }); + process.exit(1); + } else { + console.log("\n✓ All annotation tests passed!"); + process.exit(0); + } + } catch (error) { + console.error("Error running tests:", error); + process.exit(1); + } +} + +testAnnotations(); From c2468c68e1eff9a3df5f925fef324bb431b79d08 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:29:00 +0000 Subject: [PATCH 4/9] Remove temp test files --- core/test/temp-dom-timeout-test.json | 17 ----------------- core/test/temp-element-timeout-test.json | 19 ------------------- core/test/temp-network-timeout-test.json | 17 ----------------- 3 files changed, 53 deletions(-) delete mode 100644 core/test/temp-dom-timeout-test.json delete mode 100644 core/test/temp-element-timeout-test.json delete mode 100644 core/test/temp-network-timeout-test.json diff --git a/core/test/temp-dom-timeout-test.json b/core/test/temp-dom-timeout-test.json deleted file mode 100644 index 6e2f7e2..0000000 --- a/core/test/temp-dom-timeout-test.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "tests": [ - { - "steps": [ - { - "goTo": { - "url": "http://localhost:8092/waitUntil-test-dom-mutations-forever.html", - "timeout": 5000, - "waitUntil": { - "domIdleTime": 500 - } - } - } - ] - } - ] -} \ No newline at end of file diff --git a/core/test/temp-element-timeout-test.json b/core/test/temp-element-timeout-test.json deleted file mode 100644 index ec4c584..0000000 --- a/core/test/temp-element-timeout-test.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "tests": [ - { - "steps": [ - { - "goTo": { - "url": "http://localhost:8092/index.html", - "timeout": 5000, - "waitUntil": { - "find": { - "selector": ".nonexistent-element-that-will-never-appear" - } - } - } - } - ] - } - ] -} \ No newline at end of file diff --git a/core/test/temp-network-timeout-test.json b/core/test/temp-network-timeout-test.json deleted file mode 100644 index 75afdc6..0000000 --- a/core/test/temp-network-timeout-test.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "tests": [ - { - "steps": [ - { - "goTo": { - "url": "http://localhost:8092/waitUntil-test-network-forever.html", - "timeout": 5000, - "waitUntil": { - "networkIdleTime": 500 - } - } - } - ] - } - ] -} \ No newline at end of file From 0b4aee5960007b97b93ac44e480b74baf246dc43 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:32:41 +0000 Subject: [PATCH 5/9] Replace Fabric.js with direct Canvas 2D API rendering for server-side compatibility Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- core/package.json | 1 - core/src/tests/annotateScreenshot.js | 446 ++++++++++++++++----------- core/test/test-canvas-output.png | Bin 0 -> 4532 bytes core/test/test-fabric-basic.js | 73 +++++ 4 files changed, 331 insertions(+), 189 deletions(-) create mode 100644 core/test/test-canvas-output.png create mode 100644 core/test/test-fabric-basic.js diff --git a/core/package.json b/core/package.json index 019f3e3..537d04a 100644 --- a/core/package.json +++ b/core/package.json @@ -40,7 +40,6 @@ "doc-detective-common": "^3.6.0", "doc-detective-resolver": "^3.6.1", "dotenv": "^17.2.3", - "fabric": "^6.0.0", "geckodriver": "^6.1.0", "jq-web": "^0.6.2", "json-schema-faker": "^0.5.9", diff --git a/core/src/tests/annotateScreenshot.js b/core/src/tests/annotateScreenshot.js index 5241eda..c9f9963 100644 --- a/core/src/tests/annotateScreenshot.js +++ b/core/src/tests/annotateScreenshot.js @@ -1,4 +1,3 @@ -const { fabric } = require("fabric"); const { createCanvas, loadImage } = require("canvas"); const { findElement } = require("./findElement"); const { log } = require("../utils"); @@ -15,17 +14,11 @@ async function annotateScreenshot({ config, filePath, annotations, driver }) { const width = image.width; const height = image.height; - // Create a node-canvas - const nodeCanvas = createCanvas(width, height); - const ctx = nodeCanvas.getContext("2d"); + // Create a canvas and draw the image + const canvas = createCanvas(width, height); + const ctx = canvas.getContext("2d"); ctx.drawImage(image, 0, 0); - // Create Fabric.js StaticCanvas for server-side rendering - const fabricCanvas = new fabric.StaticCanvas(nodeCanvas, { - width: width, - height: height, - }); - // Get pixel density for scaling const pixelDensity = await driver.execute(() => window.devicePixelRatio); log(config, "debug", `Pixel density: ${pixelDensity}`); @@ -35,7 +28,7 @@ async function annotateScreenshot({ config, filePath, annotations, driver }) { try { await renderAnnotation({ config, - fabricCanvas, + ctx, annotation, driver, pixelDensity, @@ -55,13 +48,8 @@ async function annotateScreenshot({ config, filePath, annotations, driver }) { } } - // Render Fabric canvas back to node canvas - fabricCanvas.renderAll(); - - // Get buffer from node canvas - const buffer = nodeCanvas.toBuffer("image/png"); - - // Write buffer to file (overwriting original) + // Save canvas to file + const buffer = canvas.toBuffer("image/png"); fs.writeFileSync(filePath, buffer); log( @@ -79,7 +67,7 @@ async function annotateScreenshot({ config, filePath, annotations, driver }) { async function renderAnnotation({ config, - fabricCanvas, + ctx, annotation, driver, pixelDensity, @@ -154,31 +142,21 @@ async function renderAnnotation({ // Render annotation based on type if (annotation.arrow) { - renderArrow(fabricCanvas, annotation.arrow, basePosition, pixelDensity); + renderArrow(ctx, annotation.arrow, basePosition, pixelDensity); } else if (annotation.text) { - renderText(fabricCanvas, annotation.text, basePosition, pixelDensity); + renderText(ctx, annotation.text, basePosition, pixelDensity); } else if (annotation.rectangle) { - renderRectangle( - fabricCanvas, - annotation.rectangle, - basePosition, - pixelDensity - ); + renderRectangle(ctx, annotation.rectangle, basePosition, pixelDensity); } else if (annotation.circle) { - renderCircle(fabricCanvas, annotation.circle, basePosition, pixelDensity); + renderCircle(ctx, annotation.circle, basePosition, pixelDensity); } else if (annotation.line) { - renderLine(fabricCanvas, annotation.line, basePosition, pixelDensity); + renderLine(ctx, annotation.line, basePosition, pixelDensity); } else if (annotation.callout) { - renderCallout(fabricCanvas, annotation.callout, basePosition, pixelDensity); + renderCallout(ctx, annotation.callout, basePosition, pixelDensity); } else if (annotation.highlight) { - renderHighlight( - fabricCanvas, - annotation.highlight, - basePosition, - pixelDensity - ); + renderHighlight(ctx, annotation.highlight, basePosition, pixelDensity); } else if (annotation.blur) { - renderBlur(fabricCanvas, annotation.blur, basePosition, pixelDensity); + renderBlur(ctx, annotation.blur, basePosition, pixelDensity); } } @@ -264,7 +242,7 @@ function applyPositionKeyword( } } -function renderArrow(fabricCanvas, arrow, basePosition, pixelDensity) { +function renderArrow(ctx, arrow, basePosition, pixelDensity) { const defaults = { color: "#FF0000", strokeWidth: 3, @@ -279,39 +257,32 @@ function renderArrow(fabricCanvas, arrow, basePosition, pixelDensity) { const toX = basePosition.x + (arrow.to?.x || 0) * pixelDensity; const toY = basePosition.y + (arrow.to?.y || 0) * pixelDensity; - // Calculate angle for arrowhead - const angle = Math.atan2(toY - fromY, toX - fromX); + // Draw line + ctx.strokeStyle = config.color; + ctx.lineWidth = config.strokeWidth; + ctx.beginPath(); + ctx.moveTo(fromX, fromY); + ctx.lineTo(toX, toY); + ctx.stroke(); - // Create arrow line - const line = new fabric.Line([fromX, fromY, toX, toY], { - stroke: config.color, - strokeWidth: config.strokeWidth, - selectable: false, - evented: false, - }); - - // Create arrowhead triangle + // Draw arrowhead + const angle = Math.atan2(toY - fromY, toX - fromX); const headLength = config.headSize; - const headAngle = Math.PI / 6; // 30 degrees - - const arrowHead = new fabric.Triangle({ - left: toX, - top: toY, - originX: "center", - originY: "center", - width: headLength, - height: headLength, - fill: config.color, - angle: (angle * 180) / Math.PI + 90, - selectable: false, - evented: false, - }); - fabricCanvas.add(line); - fabricCanvas.add(arrowHead); + ctx.save(); + ctx.translate(toX, toY); + ctx.rotate(angle); + ctx.fillStyle = config.color; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(-headLength, -headLength / 2); + ctx.lineTo(-headLength, headLength / 2); + ctx.closePath(); + ctx.fill(); + ctx.restore(); } -function renderText(fabricCanvas, text, basePosition, pixelDensity) { +function renderText(ctx, text, basePosition, pixelDensity) { const defaults = { fontSize: 16, fontFamily: "Arial", @@ -323,26 +294,76 @@ function renderText(fabricCanvas, text, basePosition, pixelDensity) { const config = { ...defaults, ...text }; - const textObj = new fabric.Textbox(config.content, { - left: basePosition.x, - top: basePosition.y, - fontSize: config.fontSize * pixelDensity, - fontFamily: config.fontFamily, - fill: config.color, - backgroundColor: config.backgroundColor, - padding: config.padding * pixelDensity, - width: config.maxWidth - ? config.maxWidth * pixelDensity - : 200 * pixelDensity, - opacity: config.opacity, - selectable: false, - evented: false, + ctx.save(); + ctx.font = `${config.fontSize * pixelDensity}px ${config.fontFamily}`; + ctx.fillStyle = config.color; + ctx.globalAlpha = config.opacity; + + // Measure text + const maxWidth = config.maxWidth + ? config.maxWidth * pixelDensity + : 200 * pixelDensity; + const lines = wrapText(ctx, config.content, maxWidth); + const lineHeight = config.fontSize * pixelDensity * 1.2; + const textHeight = lines.length * lineHeight; + const padding = config.padding * pixelDensity; + + // Calculate text box dimensions + let maxLineWidth = 0; + lines.forEach((line) => { + const metrics = ctx.measureText(line); + if (metrics.width > maxLineWidth) { + maxLineWidth = metrics.width; + } + }); + + // Draw background + ctx.fillStyle = config.backgroundColor; + ctx.fillRect( + basePosition.x - padding, + basePosition.y - padding, + maxLineWidth + padding * 2, + textHeight + padding * 2 + ); + + // Draw text + ctx.fillStyle = config.color; + lines.forEach((line, i) => { + ctx.fillText( + line, + basePosition.x, + basePosition.y + (i + 1) * lineHeight - lineHeight / 4 + ); }); - fabricCanvas.add(textObj); + ctx.restore(); } -function renderRectangle(fabricCanvas, rectangle, basePosition, pixelDensity) { +function wrapText(ctx, text, maxWidth) { + const words = text.split(" "); + const lines = []; + let currentLine = ""; + + words.forEach((word) => { + const testLine = currentLine + (currentLine ? " " : "") + word; + const metrics = ctx.measureText(testLine); + + if (metrics.width > maxWidth && currentLine) { + lines.push(currentLine); + currentLine = word; + } else { + currentLine = testLine; + } + }); + + if (currentLine) { + lines.push(currentLine); + } + + return lines.length > 0 ? lines : [text]; +} + +function renderRectangle(ctx, rectangle, basePosition, pixelDensity) { const defaults = { fill: "transparent", stroke: "#FF0000", @@ -354,25 +375,49 @@ function renderRectangle(fabricCanvas, rectangle, basePosition, pixelDensity) { const config = { ...defaults, ...rectangle }; - const rect = new fabric.Rect({ - left: basePosition.x, - top: basePosition.y, - width: (config.width || basePosition.width || 100) * pixelDensity, - height: (config.height || basePosition.height || 100) * pixelDensity, - fill: config.fill, - stroke: config.stroke, - strokeWidth: config.strokeWidth * pixelDensity, - opacity: config.opacity, - rx: config.rx * pixelDensity, - ry: config.ry * pixelDensity, - selectable: false, - evented: false, - }); + const x = basePosition.x; + const y = basePosition.y; + const width = (config.width || basePosition.width || 100) * pixelDensity; + const height = (config.height || basePosition.height || 100) * pixelDensity; + const rx = config.rx * pixelDensity; + const ry = config.ry * pixelDensity; + + ctx.save(); + ctx.globalAlpha = config.opacity; + + // Draw rounded rectangle + ctx.beginPath(); + if (rx > 0 || ry > 0) { + const r = Math.max(rx, ry); + ctx.moveTo(x + r, y); + ctx.lineTo(x + width - r, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + r); + ctx.lineTo(x + width, y + height - r); + ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height); + ctx.lineTo(x + r, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - r); + ctx.lineTo(x, y + r); + ctx.quadraticCurveTo(x, y, x + r, y); + } else { + ctx.rect(x, y, width, height); + } + ctx.closePath(); + + if (config.fill !== "transparent") { + ctx.fillStyle = config.fill; + ctx.fill(); + } - fabricCanvas.add(rect); + if (config.strokeWidth > 0) { + ctx.strokeStyle = config.stroke; + ctx.lineWidth = config.strokeWidth * pixelDensity; + ctx.stroke(); + } + + ctx.restore(); } -function renderCircle(fabricCanvas, circle, basePosition, pixelDensity) { +function renderCircle(ctx, circle, basePosition, pixelDensity) { const defaults = { radius: 30, fill: "transparent", @@ -383,24 +428,33 @@ function renderCircle(fabricCanvas, circle, basePosition, pixelDensity) { const config = { ...defaults, ...circle }; - const circleObj = new fabric.Circle({ - left: basePosition.x, - top: basePosition.y, - radius: config.radius * pixelDensity, - fill: config.fill, - stroke: config.stroke, - strokeWidth: config.strokeWidth * pixelDensity, - opacity: config.opacity, - originX: "center", - originY: "center", - selectable: false, - evented: false, - }); + ctx.save(); + ctx.globalAlpha = config.opacity; + + ctx.beginPath(); + ctx.arc( + basePosition.x, + basePosition.y, + config.radius * pixelDensity, + 0, + 2 * Math.PI + ); + + if (config.fill !== "transparent") { + ctx.fillStyle = config.fill; + ctx.fill(); + } - fabricCanvas.add(circleObj); + if (config.strokeWidth > 0) { + ctx.strokeStyle = config.stroke; + ctx.lineWidth = config.strokeWidth * pixelDensity; + ctx.stroke(); + } + + ctx.restore(); } -function renderLine(fabricCanvas, line, basePosition, pixelDensity) { +function renderLine(ctx, line, basePosition, pixelDensity) { const defaults = { color: "#000000", strokeWidth: 2, @@ -413,20 +467,23 @@ function renderLine(fabricCanvas, line, basePosition, pixelDensity) { const toX = basePosition.x + (line.to?.x || 0) * pixelDensity; const toY = basePosition.y + (line.to?.y || 0) * pixelDensity; - const lineObj = new fabric.Line([fromX, fromY, toX, toY], { - stroke: config.color, - strokeWidth: config.strokeWidth * pixelDensity, - strokeDashArray: config.dashArray - ? config.dashArray.map((v) => v * pixelDensity) - : undefined, - selectable: false, - evented: false, - }); + ctx.save(); + ctx.strokeStyle = config.color; + ctx.lineWidth = config.strokeWidth * pixelDensity; + + if (config.dashArray) { + ctx.setLineDash(config.dashArray.map((v) => v * pixelDensity)); + } + + ctx.beginPath(); + ctx.moveTo(fromX, fromY); + ctx.lineTo(toX, toY); + ctx.stroke(); - fabricCanvas.add(lineObj); + ctx.restore(); } -function renderCallout(fabricCanvas, callout, basePosition, pixelDensity) { +function renderCallout(ctx, callout, basePosition, pixelDensity) { const defaults = { fontSize: 14, color: "#000000", @@ -451,55 +508,72 @@ function renderCallout(fabricCanvas, callout, basePosition, pixelDensity) { textY = targetY - 80 * pixelDensity; } - // Create text box - const textObj = new fabric.Textbox(config.content, { - left: textX, - top: textY, - fontSize: config.fontSize * pixelDensity, - fontFamily: "Arial", - fill: config.color, - backgroundColor: config.backgroundColor, - padding: 8 * pixelDensity, - width: config.maxWidth - ? config.maxWidth * pixelDensity - : 150 * pixelDensity, - selectable: false, - evented: false, + // Draw text box + ctx.save(); + ctx.font = `${config.fontSize * pixelDensity}px Arial`; + + const maxWidth = config.maxWidth + ? config.maxWidth * pixelDensity + : 150 * pixelDensity; + const lines = wrapText(ctx, config.content, maxWidth); + const lineHeight = config.fontSize * pixelDensity * 1.2; + const textHeight = lines.length * lineHeight; + const padding = 8 * pixelDensity; + + let maxLineWidth = 0; + lines.forEach((line) => { + const metrics = ctx.measureText(line); + if (metrics.width > maxLineWidth) { + maxLineWidth = metrics.width; + } }); - fabricCanvas.add(textObj); - - // Create arrow from text to target - const textCenterX = textX + textObj.width / 2; - const textCenterY = textY + textObj.height / 2; + const boxWidth = maxLineWidth + padding * 2; + const boxHeight = textHeight + padding * 2; - const angle = Math.atan2(targetY - textCenterY, targetX - textCenterX); + // Draw background + ctx.fillStyle = config.backgroundColor; + ctx.fillRect(textX, textY, boxWidth, boxHeight); - const line = new fabric.Line([textCenterX, textCenterY, targetX, targetY], { - stroke: config.arrowColor, - strokeWidth: 2 * pixelDensity, - selectable: false, - evented: false, + // Draw text + ctx.fillStyle = config.color; + lines.forEach((line, i) => { + ctx.fillText( + line, + textX + padding, + textY + padding + (i + 1) * lineHeight - lineHeight / 4 + ); }); - const arrowHead = new fabric.Triangle({ - left: targetX, - top: targetY, - originX: "center", - originY: "center", - width: 10 * pixelDensity, - height: 10 * pixelDensity, - fill: config.arrowColor, - angle: (angle * 180) / Math.PI + 90, - selectable: false, - evented: false, - }); + // Draw arrow from text to target + const textCenterX = textX + boxWidth / 2; + const textCenterY = textY + boxHeight / 2; - fabricCanvas.add(line); - fabricCanvas.add(arrowHead); + ctx.strokeStyle = config.arrowColor; + ctx.lineWidth = 2 * pixelDensity; + ctx.beginPath(); + ctx.moveTo(textCenterX, textCenterY); + ctx.lineTo(targetX, targetY); + ctx.stroke(); + + // Draw arrowhead + const angle = Math.atan2(targetY - textCenterY, targetX - textCenterX); + const headLength = 10 * pixelDensity; + + ctx.translate(targetX, targetY); + ctx.rotate(angle); + ctx.fillStyle = config.arrowColor; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(-headLength, -headLength / 2); + ctx.lineTo(-headLength, headLength / 2); + ctx.closePath(); + ctx.fill(); + + ctx.restore(); } -function renderHighlight(fabricCanvas, highlight, basePosition, pixelDensity) { +function renderHighlight(ctx, highlight, basePosition, pixelDensity) { const defaults = { color: "#FFFF00", opacity: 0.3, @@ -507,21 +581,19 @@ function renderHighlight(fabricCanvas, highlight, basePosition, pixelDensity) { const config = { ...defaults, ...highlight }; - const rect = new fabric.Rect({ - left: basePosition.x, - top: basePosition.y, - width: basePosition.width || 100 * pixelDensity, - height: basePosition.height || 100 * pixelDensity, - fill: config.color, - opacity: config.opacity, - selectable: false, - evented: false, - }); - - fabricCanvas.add(rect); + ctx.save(); + ctx.fillStyle = config.color; + ctx.globalAlpha = config.opacity; + ctx.fillRect( + basePosition.x, + basePosition.y, + basePosition.width || 100 * pixelDensity, + basePosition.height || 100 * pixelDensity + ); + ctx.restore(); } -function renderBlur(fabricCanvas, blur, basePosition, pixelDensity) { +function renderBlur(ctx, blur, basePosition, pixelDensity) { const defaults = { intensity: 10, }; @@ -530,15 +602,13 @@ function renderBlur(fabricCanvas, blur, basePosition, pixelDensity) { // For blur, we use a semi-transparent overlay as a visual indicator // True pixel blur would require Sharp preprocessing - const rect = new fabric.Rect({ - left: basePosition.x, - top: basePosition.y, - width: (config.width || basePosition.width || 100) * pixelDensity, - height: (config.height || basePosition.height || 100) * pixelDensity, - fill: "rgba(200, 200, 200, 0.8)", - selectable: false, - evented: false, - }); - - fabricCanvas.add(rect); + ctx.save(); + ctx.fillStyle = "rgba(200, 200, 200, 0.8)"; + ctx.fillRect( + basePosition.x, + basePosition.y, + (config.width || basePosition.width || 100) * pixelDensity, + (config.height || basePosition.height || 100) * pixelDensity + ); + ctx.restore(); } diff --git a/core/test/test-canvas-output.png b/core/test/test-canvas-output.png new file mode 100644 index 0000000000000000000000000000000000000000..644b328cf246fc2de923ff6da61ea8309aba1656 GIT binary patch literal 4532 zcmdUzeK^zm|Hrp+#Oa8oQbapjtWM$7I^=e$v2`OwD9KLbt|<}CGOSalCT1Te);aL>n0o~YT~ZptFm*0SgM)X z+TY{=%epe328K(w$o ziJc`Is$(N%@}UN(XQ{6Nc#@#u1iN&JL>qhH`IPguBWb_#0u(%X6ez8>hSvu7x?Y&| z`%&Nqy{8YQB=GlvbpYuDJo|_2iC&e4Zd-mxCw|?k^mH>>l|A#T(!gRh)}Oz3ReD*h z#`^a}t;&rStFfkp0m>~ZXdZWT&324t!D-GasFZRuIA|CF6H&FD`8sWOfJM+O)__Bv zM?z}Aa7ec;cnSy$&!U6_h(6~0+8G1tL&DB&hlA=hi;aQnk2t?Ri~;Qh?}WiY5RYRR ziZ>GG2!lKCGPq~D9$Mg~gR|0y7Hk9ng%{>X^Yu(lPu+i!F2m~it3Z*0LK2v0x!-P78YOI?G6 zw<{T)G=ni=mI*;E1L<}c;WR=C$yqV|j?lH6*!2uzN(apV(L$@WT?>bsChQ+&V5c3| z_WcUeeNH%-p&>&Q>HcmrQ|H*j}{$J%;-i@}Lk7t~3 zuD_?%vuS6r$u;^R@{QX_m~I;h{>B*w(>;QrxB?Q$p{qGe_c#DEm)0U@ZbP0L3jrNxIuUU04yN9zX0e$ zc#i<=1c#l6L*{Q$>h?pyM|8B|5TISde@4_q1+i^d0}-B@Mk$mz^l(yJdpfjrt3l+{ zV`%awnd;OHEg0<6j`&ePp@HE-!o?|@q|KYc%)Q(Yj_*3P|1NPac_l)5L-Zd(XyQ=KWe z&~ulM>(;n%wvI&W+>IiwKRS{R$+tQK4=c6D-NtEuw*%kzRRQ_2NJ8nM!Vvm z^W^=?mJ3P=wTQk68u}CD;L8f*v|Uvx{nx)uFA)V>_QYJo9FaXV>*j0TGTmZtJ=%dn zWbFQcz2p_nig(h1hWa0xb_D-(=+~OhDnfE)(M0VQ;moqUK_D=+>ZbJ_y(mCz9*8l99KMhZnV(aQ%)Kl)V zJe_V6H-me%+%EjVa}DHa&v?`w+pF+RmNSCD$_8_8*xVPYA$}%@B+FP)BS+&#l211` zscrMfdq-Q037MjrqwE7~T*9ke=%w28MdtfcZ0zUWsLh51x;B`m2TjEJME(5e;`!_bY~|fvHKcibhV}Sc@?t zLG_txaQum-y{L{1*2*Z+X*+*s{Aip)kfRax(FK|lA$VEE3O&iriMS@-!&-^=542rg zpf-wAv+Qj~)l$CR`J!0$_m zk5W})eB#iy<$L+kN6B#0xZMGxZ0h;1 z3@b4~{o0iL`{6MF(B1R#ISOftzIrJTDX zZE~gE?GMQxbn{A72PSl=l_Zom@VkN6oIP2xF*I%>&lfS^aHh;#B=N!1>Xzh; z+j{hQQ3Q7JI~{S399b-Skz6+r%rGSt+sXf0E4fOR*D`{;Qlgh+jN^7Yc?Aa;>(CB# zlH>y}Brm(wE!QYa(1f#Udj2oz@rEgy4P4iFQ`qNAhzj40Q#aN~#*l8li8GH}l+Ewg zCD-*FXIy^0lc!cPDx2+i<~f+bpiJB|pNZ;-=Iqv4R-&mr!P_)$jK+8|_#3Z{!B}1r zPhVY`FJ)-yrPht5GAv*3;61cuG%xnzaxNQ%b!6c<8RLTIFz@_*P z0^BW2zpTQ7r-Kx#Dqq2Q3*SjIGXuQ}`w0Ky!b4JNSB~LS;T=hQX>LZVlk8NC|3rR% zCJ-~F8lguI$1u#@yEyCYo-8JKwo6BdBWhc}7_Z`1)8y!H6%3$a>c%q|{&5vjR&rnC zFU~!sr5hMlJ*E6O>+(OGR|prYRA6Ph4_tT4`l%%3#Z1<`$MU;@IPr81Q{Il3h*-}( z?nW!e8S5PP@pzAw@=Gtr`LDnJQ@Mo5vqjO-iXn2GY#L`jb8kW>;nWA_$6M1)9QN~i z-1!2ckfCg5sm(?bCUVL4a9&m7Ir|su8}Lg{?XG>kB+XpBZ&n{@)wr9UyQk>&%q;^+ z%|w2c<=LkFyi#;-e&ftPRYnIcwxwWuxnLm1wZK)ikG7 z5aSaw&|OFx$R+lrE_D$llKiD|0luGhZ3{)S_}BU&^YRDq*;j~&bz4y85t1^$7ya;U zg|daQ-cFRbDQ!hPbhVy)weJj+r4ADKc|597KCMBKx(n13UeEf_N6G@;-D=8y!ptRh z@vWGr8p-pMR4%zhT1`irey1l2J3~H)d)mv3(r0L$^+)#%s!EQ1;41`Y8_B}9CY>6lZoIX#IJAM%Bss$7J%+kF zrn92^m_tOosgIIpD{fLhZf-S&=BxbJ9of*tl{oI#xyF(4B_jiK;nL2H_~oc|A9QVm z-4%rSNm-^B#Cu>{Pi{5WA+2f`zD`6lN^eE0W?DwL2JV=xF{jvfoHkSs1oyswY-n*e zRwbgL6VBy!5?W29GW?3~j}KJ;Bf2zM3%-u++4^^{S32Tx3!VOIrbd@;Y;TQs&wI$) zJkgPqWn;A>j9Z){xs7Adcl+ZNv)sZOdF0$%Xrk(@C_ZjBTQ4(y?yZauv;JKEt*Uy~ zeb%Imya|E5MqZiw*LY=WsjO5IQmy<-!Y(46pw;6U%I2|D4q^YWSGEt9Kzx6PpISEA zuKMY^59g<1$+*1BUMZ}vTv%w8j!!?6W~xkx!q}~`e=dh99mP|N->mSakt&griwYJV z#RhZz(J*F3)Tn^>*kptiJ=Nkqn}b4b+Zgk$g5-HR?wOAw+@F&X<4`IOq%4LtP{Nrp zP8SpdA&6yJRa03Blkd+_5HHMqA)lUdQVHX=Lh^I<438wU>CvL&jCZLKbX};Mw+x|9G{Q8?jb`tBA z>2>@{_=@SS8w6Gvq4y~j)zvnUUw-;zqh7$=7h0k#e&L|gwxHP|YWgl4C#wP{-^;q& z;Stua6#}(cb8I9ViQe*E!clU<25Qv14hM*;90np=9hS30B<^E}ZVU5MB3}KP??-I= zl{AyJN4Ypike1{O6RQM1dlD0z3TG)Ab}KQ+o)Q@Vx zdX#M-H5v@0k0ai;(4H-AM5HTXyKG6cK#7ptp!`by)MwMo82dfsxF8c1=8^iwEK?XN zuEq*p&I{9&UvB;T{uvVaLUBV+h@XlQkd(zAKBP&VQdMFuHq?aZHxePxcwHc9g(`+_ z(}^S9B-qYzscDHD2f5*L&EaAN3!TrlNlXyEvKi?>*2fDG%B{D7p%JJ+r^K;dA3i$& zJjX(M^<2Dcv5GXBbPjFxFBKu_$8M|0TeCN)eR0f^xo?E181B7l{~Pjih5d`D%67fP z(~W8yR#J4^uS#~in@uNjW8T%{#p4`8D^u?4lznBg8wX7Ae4oRt@@-MPE_>`CS*q?A zC)ng~ZMbs2*)aekQ)jI)Z9}eKXPn`_erD3)Ui*08St)7z``hFEtu~gtbf2#im(iDj z8>wb$msQM(Jav;H-cKyGG!pFv+3ErP-Q!Om!9^N})70pXg(JVbNtB?1PbKzD&QBRT zE#6A#y{~cxP1*vhVcgMK%$*EteVY{r^%Z7_^BPS}UpK@Gp0oKx_&W$N^U)9eHH7~^3-15my@3DStF^6YG<*ts Wu7exi2W-QD4!a!3R37~Eum1+Pax8iP literal 0 HcmV?d00001 diff --git a/core/test/test-fabric-basic.js b/core/test/test-fabric-basic.js new file mode 100644 index 0000000..43a0931 --- /dev/null +++ b/core/test/test-fabric-basic.js @@ -0,0 +1,73 @@ +const { createCanvas, loadImage } = require("canvas"); +const fs = require("fs"); +const path = require("path"); + +async function testCanvasIntegration() { + try { + console.log("Testing node-canvas for annotations..."); + + // Create a simple canvas + const width = 400; + const height = 300; + const canvas = createCanvas(width, height); + const ctx = canvas.getContext("2d"); + + // Fill with white background + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, width, height); + + // Add a red rectangle + console.log("Adding rectangle..."); + ctx.strokeStyle = "red"; + ctx.lineWidth = 3; + ctx.strokeRect(100, 100, 200, 100); + + // Add an arrow (line + triangle) + console.log("Adding arrow..."); + ctx.strokeStyle = "blue"; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(50, 50); + ctx.lineTo(150, 150); + ctx.stroke(); + + // Arrow head + const angle = Math.atan2(150 - 50, 150 - 50); + ctx.save(); + ctx.translate(150, 150); + ctx.rotate(angle); + ctx.fillStyle = "blue"; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(-15, -7.5); + ctx.lineTo(-15, 7.5); + ctx.closePath(); + ctx.fill(); + ctx.restore(); + + // Add text + console.log("Adding text..."); + ctx.font = "20px Arial"; + ctx.fillStyle = "yellow"; + ctx.fillRect(48, 175, 205, 30); + ctx.fillStyle = "black"; + ctx.fillText("Test Annotation", 50, 195); + + // Save to file + const outputPath = path.join(__dirname, "test-canvas-output.png"); + const buffer = canvas.toBuffer("image/png"); + fs.writeFileSync(outputPath, buffer); + + console.log(`✓ Success! Output saved to: ${outputPath}`); + console.log(`File size: ${buffer.length} bytes`); + + return true; + } catch (error) { + console.error("✗ Error:", error); + return false; + } +} + +testCanvasIntegration().then((success) => { + process.exit(success ? 0 : 1); +}); From c8e923aa0ee38f529979699357da896f13e63cda Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:42:39 +0000 Subject: [PATCH 6/9] Add annotation_v3.schema.json to schema build process and rebuild schemas Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- common/dist/schemas/annotation_v3.schema.json | 1163 +++++++++++++++++ common/src/schemas/dereferenceSchemas.js | 1 + .../output_schemas/annotation_v3.schema.json | 1163 +++++++++++++++++ common/src/schemas/schemas.json | 1163 +++++++++++++++++ .../artifacts/annotations-simple.spec.json | 36 + core/test/artifacts/enhanced-modal-large.png | Bin 0 -> 6664 bytes core/test/artifacts/enhanced-modal.png | Bin 0 -> 1119 bytes 7 files changed, 3526 insertions(+) create mode 100644 common/dist/schemas/annotation_v3.schema.json create mode 100644 common/src/schemas/output_schemas/annotation_v3.schema.json create mode 100644 core/test/artifacts/annotations-simple.spec.json create mode 100644 core/test/artifacts/enhanced-modal-large.png create mode 100644 core/test/artifacts/enhanced-modal.png diff --git a/common/dist/schemas/annotation_v3.schema.json b/common/dist/schemas/annotation_v3.schema.json new file mode 100644 index 0000000..ecf576e --- /dev/null +++ b/common/dist/schemas/annotation_v3.schema.json @@ -0,0 +1,1163 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "annotation", + "type": "object", + "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", + "anyOf": [ + { + "required": [ + "arrow" + ], + "not": { + "required": [ + "text", + "rectangle", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "text" + ], + "not": { + "required": [ + "arrow", + "rectangle", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "rectangle" + ], + "not": { + "required": [ + "arrow", + "text", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "circle" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "line" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "callout" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "highlight" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "callout", + "blur" + ] + } + }, + { + "required": [ + "blur" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "callout", + "highlight" + ] + } + } + ], + "properties": { + "find": { + "type": "object", + "description": "Element on the page to annotate.", + "anyOf": [ + { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "additionalProperties": false, + "properties": { + "selector": { + "type": "string", + "description": "Selector of the element to annotate." + }, + "elementText": { + "type": "string", + "description": "Display text of the element to annotate." + }, + "elementTestId": { + "type": "string", + "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." + }, + "elementAttribute": { + "type": "object", + "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ] + } + }, + "elementAria": { + "type": "string", + "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + } + } + }, + "position": { + "anyOf": [ + { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + { + "type": "string", + "enum": [ + "top", + "bottom", + "left", + "right", + "center", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "description": "Position relative to the element (if `find` is provided) or to the viewport." + } + ] + }, + "arrow": { + "type": "object", + "description": "Configuration for arrow annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the arrow (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the arrow line in pixels.", + "minimum": 1, + "default": 3 + }, + "headSize": { + "type": "number", + "description": "Size of the arrowhead in pixels.", + "minimum": 1, + "default": 15 + } + } + }, + "text": { + "type": "object", + "description": "Configuration for text annotations.", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 16 + }, + "fontFamily": { + "type": "string", + "description": "Font family name.", + "default": "Arial" + }, + "color": { + "type": "string", + "description": "Text color (hex, rgb, or named color).", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFFF" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "description": "Padding in pixels on all sides.", + "minimum": 0 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + ], + "default": 5 + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box. Text will wrap.", + "minimum": 1 + }, + "opacity": { + "type": "number", + "description": "Opacity of the text and background (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "content" + ] + }, + "rectangle": { + "type": "object", + "description": "Configuration for rectangle annotations.", + "properties": { + "width": { + "type": "number", + "description": "Width of the rectangle in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the rectangle in pixels.", + "minimum": 1 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "rx": { + "type": "number", + "description": "Horizontal corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + }, + "ry": { + "type": "number", + "description": "Vertical corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + } + } + }, + "circle": { + "type": "object", + "description": "Configuration for circle annotations.", + "properties": { + "radius": { + "type": "number", + "description": "Radius of the circle in pixels.", + "minimum": 1, + "default": 30 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + } + }, + "line": { + "type": "object", + "description": "Configuration for line annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the line (hex, rgb, or named color).", + "default": "#000000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the line in pixels.", + "minimum": 1, + "default": 2 + }, + "dashArray": { + "type": "array", + "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", + "items": { + "type": "number", + "minimum": 0 + } + } + }, + "required": [ + "from", + "to" + ] + }, + "callout": { + "type": "object", + "description": "Configuration for callout annotations (text with arrow).", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "target": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "textPosition": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 14 + }, + "color": { + "type": "string", + "description": "Text color.", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFCC" + }, + "arrowColor": { + "type": "string", + "description": "Color of the arrow.", + "default": "#000000" + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box.", + "minimum": 1 + } + }, + "required": [ + "content", + "target" + ] + }, + "highlight": { + "type": "object", + "description": "Configuration for highlight annotations (semi-transparent overlay).", + "properties": { + "color": { + "type": "string", + "description": "Highlight color (hex, rgb, or named color).", + "default": "#FFFF00" + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + } + }, + "blur": { + "type": "object", + "description": "Configuration for blur annotations (for redacting sensitive information).", + "properties": { + "intensity": { + "type": "number", + "description": "Blur intensity level.", + "minimum": 1, + "default": 10 + }, + "width": { + "type": "number", + "description": "Width of the blur area in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the blur area in pixels.", + "minimum": 1 + } + } + } + }, + "components": { + "schemas": { + "arrow_properties": { + "type": "object", + "description": "Configuration for arrow annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the arrow (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the arrow line in pixels.", + "minimum": 1, + "default": 3 + }, + "headSize": { + "type": "number", + "description": "Size of the arrowhead in pixels.", + "minimum": 1, + "default": 15 + } + } + }, + "text_properties": { + "type": "object", + "description": "Configuration for text annotations.", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 16 + }, + "fontFamily": { + "type": "string", + "description": "Font family name.", + "default": "Arial" + }, + "color": { + "type": "string", + "description": "Text color (hex, rgb, or named color).", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFFF" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "description": "Padding in pixels on all sides.", + "minimum": 0 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + ], + "default": 5 + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box. Text will wrap.", + "minimum": 1 + }, + "opacity": { + "type": "number", + "description": "Opacity of the text and background (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "content" + ] + }, + "rectangle_properties": { + "type": "object", + "description": "Configuration for rectangle annotations.", + "properties": { + "width": { + "type": "number", + "description": "Width of the rectangle in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the rectangle in pixels.", + "minimum": 1 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "rx": { + "type": "number", + "description": "Horizontal corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + }, + "ry": { + "type": "number", + "description": "Vertical corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + } + } + }, + "circle_properties": { + "type": "object", + "description": "Configuration for circle annotations.", + "properties": { + "radius": { + "type": "number", + "description": "Radius of the circle in pixels.", + "minimum": 1, + "default": 30 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + } + }, + "line_properties": { + "type": "object", + "description": "Configuration for line annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the line (hex, rgb, or named color).", + "default": "#000000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the line in pixels.", + "minimum": 1, + "default": 2 + }, + "dashArray": { + "type": "array", + "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", + "items": { + "type": "number", + "minimum": 0 + } + } + }, + "required": [ + "from", + "to" + ] + }, + "callout_properties": { + "type": "object", + "description": "Configuration for callout annotations (text with arrow).", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "target": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "textPosition": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 14 + }, + "color": { + "type": "string", + "description": "Text color.", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFCC" + }, + "arrowColor": { + "type": "string", + "description": "Color of the arrow.", + "default": "#000000" + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box.", + "minimum": 1 + } + }, + "required": [ + "content", + "target" + ] + }, + "highlight_properties": { + "type": "object", + "description": "Configuration for highlight annotations (semi-transparent overlay).", + "properties": { + "color": { + "type": "string", + "description": "Highlight color (hex, rgb, or named color).", + "default": "#FFFF00" + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + } + }, + "blur_properties": { + "type": "object", + "description": "Configuration for blur annotations (for redacting sensitive information).", + "properties": { + "intensity": { + "type": "number", + "description": "Blur intensity level.", + "minimum": 1, + "default": 10 + }, + "width": { + "type": "number", + "description": "Width of the blur area in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the blur area in pixels.", + "minimum": 1 + } + } + }, + "point": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "padding": { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + } + }, + "examples": [ + { + "find": { + "selector": "#submit-button" + }, + "arrow": { + "from": { + "x": 0, + "y": -50 + }, + "to": { + "x": 0, + "y": 0 + }, + "color": "#00FF00", + "strokeWidth": 4, + "headSize": 20 + } + }, + { + "position": "top-right", + "text": { + "content": "Important Notice", + "fontSize": 18, + "color": "#FFFFFF", + "backgroundColor": "#0000FF", + "padding": 10, + "maxWidth": 200, + "opacity": 0.9 + } + }, + { + "find": { + "elementClass": [ + "sensitive-info", + "/^private-/" + ] + }, + "blur": { + "intensity": 15, + "width": 200, + "height": 50 + } + } + ] +} \ No newline at end of file diff --git a/common/src/schemas/dereferenceSchemas.js b/common/src/schemas/dereferenceSchemas.js index cd1d7c5..485d734 100644 --- a/common/src/schemas/dereferenceSchemas.js +++ b/common/src/schemas/dereferenceSchemas.js @@ -26,6 +26,7 @@ async function dereferenceSchemas() { // These files should be present in the input directory const files = [ // v3 schemas + "annotation_v3.schema.json", "checkLink_v3.schema.json", "click_v3.schema.json", "config_v3.schema.json", diff --git a/common/src/schemas/output_schemas/annotation_v3.schema.json b/common/src/schemas/output_schemas/annotation_v3.schema.json new file mode 100644 index 0000000..ecf576e --- /dev/null +++ b/common/src/schemas/output_schemas/annotation_v3.schema.json @@ -0,0 +1,1163 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "annotation", + "type": "object", + "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", + "anyOf": [ + { + "required": [ + "arrow" + ], + "not": { + "required": [ + "text", + "rectangle", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "text" + ], + "not": { + "required": [ + "arrow", + "rectangle", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "rectangle" + ], + "not": { + "required": [ + "arrow", + "text", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "circle" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "line" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "callout" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "highlight" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "callout", + "blur" + ] + } + }, + { + "required": [ + "blur" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "callout", + "highlight" + ] + } + } + ], + "properties": { + "find": { + "type": "object", + "description": "Element on the page to annotate.", + "anyOf": [ + { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "additionalProperties": false, + "properties": { + "selector": { + "type": "string", + "description": "Selector of the element to annotate." + }, + "elementText": { + "type": "string", + "description": "Display text of the element to annotate." + }, + "elementTestId": { + "type": "string", + "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." + }, + "elementAttribute": { + "type": "object", + "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ] + } + }, + "elementAria": { + "type": "string", + "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + } + } + }, + "position": { + "anyOf": [ + { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + { + "type": "string", + "enum": [ + "top", + "bottom", + "left", + "right", + "center", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "description": "Position relative to the element (if `find` is provided) or to the viewport." + } + ] + }, + "arrow": { + "type": "object", + "description": "Configuration for arrow annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the arrow (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the arrow line in pixels.", + "minimum": 1, + "default": 3 + }, + "headSize": { + "type": "number", + "description": "Size of the arrowhead in pixels.", + "minimum": 1, + "default": 15 + } + } + }, + "text": { + "type": "object", + "description": "Configuration for text annotations.", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 16 + }, + "fontFamily": { + "type": "string", + "description": "Font family name.", + "default": "Arial" + }, + "color": { + "type": "string", + "description": "Text color (hex, rgb, or named color).", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFFF" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "description": "Padding in pixels on all sides.", + "minimum": 0 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + ], + "default": 5 + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box. Text will wrap.", + "minimum": 1 + }, + "opacity": { + "type": "number", + "description": "Opacity of the text and background (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "content" + ] + }, + "rectangle": { + "type": "object", + "description": "Configuration for rectangle annotations.", + "properties": { + "width": { + "type": "number", + "description": "Width of the rectangle in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the rectangle in pixels.", + "minimum": 1 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "rx": { + "type": "number", + "description": "Horizontal corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + }, + "ry": { + "type": "number", + "description": "Vertical corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + } + } + }, + "circle": { + "type": "object", + "description": "Configuration for circle annotations.", + "properties": { + "radius": { + "type": "number", + "description": "Radius of the circle in pixels.", + "minimum": 1, + "default": 30 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + } + }, + "line": { + "type": "object", + "description": "Configuration for line annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the line (hex, rgb, or named color).", + "default": "#000000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the line in pixels.", + "minimum": 1, + "default": 2 + }, + "dashArray": { + "type": "array", + "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", + "items": { + "type": "number", + "minimum": 0 + } + } + }, + "required": [ + "from", + "to" + ] + }, + "callout": { + "type": "object", + "description": "Configuration for callout annotations (text with arrow).", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "target": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "textPosition": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 14 + }, + "color": { + "type": "string", + "description": "Text color.", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFCC" + }, + "arrowColor": { + "type": "string", + "description": "Color of the arrow.", + "default": "#000000" + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box.", + "minimum": 1 + } + }, + "required": [ + "content", + "target" + ] + }, + "highlight": { + "type": "object", + "description": "Configuration for highlight annotations (semi-transparent overlay).", + "properties": { + "color": { + "type": "string", + "description": "Highlight color (hex, rgb, or named color).", + "default": "#FFFF00" + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + } + }, + "blur": { + "type": "object", + "description": "Configuration for blur annotations (for redacting sensitive information).", + "properties": { + "intensity": { + "type": "number", + "description": "Blur intensity level.", + "minimum": 1, + "default": 10 + }, + "width": { + "type": "number", + "description": "Width of the blur area in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the blur area in pixels.", + "minimum": 1 + } + } + } + }, + "components": { + "schemas": { + "arrow_properties": { + "type": "object", + "description": "Configuration for arrow annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the arrow (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the arrow line in pixels.", + "minimum": 1, + "default": 3 + }, + "headSize": { + "type": "number", + "description": "Size of the arrowhead in pixels.", + "minimum": 1, + "default": 15 + } + } + }, + "text_properties": { + "type": "object", + "description": "Configuration for text annotations.", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 16 + }, + "fontFamily": { + "type": "string", + "description": "Font family name.", + "default": "Arial" + }, + "color": { + "type": "string", + "description": "Text color (hex, rgb, or named color).", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFFF" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "description": "Padding in pixels on all sides.", + "minimum": 0 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + ], + "default": 5 + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box. Text will wrap.", + "minimum": 1 + }, + "opacity": { + "type": "number", + "description": "Opacity of the text and background (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "content" + ] + }, + "rectangle_properties": { + "type": "object", + "description": "Configuration for rectangle annotations.", + "properties": { + "width": { + "type": "number", + "description": "Width of the rectangle in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the rectangle in pixels.", + "minimum": 1 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "rx": { + "type": "number", + "description": "Horizontal corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + }, + "ry": { + "type": "number", + "description": "Vertical corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + } + } + }, + "circle_properties": { + "type": "object", + "description": "Configuration for circle annotations.", + "properties": { + "radius": { + "type": "number", + "description": "Radius of the circle in pixels.", + "minimum": 1, + "default": 30 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + } + }, + "line_properties": { + "type": "object", + "description": "Configuration for line annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the line (hex, rgb, or named color).", + "default": "#000000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the line in pixels.", + "minimum": 1, + "default": 2 + }, + "dashArray": { + "type": "array", + "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", + "items": { + "type": "number", + "minimum": 0 + } + } + }, + "required": [ + "from", + "to" + ] + }, + "callout_properties": { + "type": "object", + "description": "Configuration for callout annotations (text with arrow).", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "target": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "textPosition": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 14 + }, + "color": { + "type": "string", + "description": "Text color.", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFCC" + }, + "arrowColor": { + "type": "string", + "description": "Color of the arrow.", + "default": "#000000" + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box.", + "minimum": 1 + } + }, + "required": [ + "content", + "target" + ] + }, + "highlight_properties": { + "type": "object", + "description": "Configuration for highlight annotations (semi-transparent overlay).", + "properties": { + "color": { + "type": "string", + "description": "Highlight color (hex, rgb, or named color).", + "default": "#FFFF00" + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + } + }, + "blur_properties": { + "type": "object", + "description": "Configuration for blur annotations (for redacting sensitive information).", + "properties": { + "intensity": { + "type": "number", + "description": "Blur intensity level.", + "minimum": 1, + "default": 10 + }, + "width": { + "type": "number", + "description": "Width of the blur area in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the blur area in pixels.", + "minimum": 1 + } + } + }, + "point": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "padding": { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + } + }, + "examples": [ + { + "find": { + "selector": "#submit-button" + }, + "arrow": { + "from": { + "x": 0, + "y": -50 + }, + "to": { + "x": 0, + "y": 0 + }, + "color": "#00FF00", + "strokeWidth": 4, + "headSize": 20 + } + }, + { + "position": "top-right", + "text": { + "content": "Important Notice", + "fontSize": 18, + "color": "#FFFFFF", + "backgroundColor": "#0000FF", + "padding": 10, + "maxWidth": 200, + "opacity": 0.9 + } + }, + { + "find": { + "elementClass": [ + "sensitive-info", + "/^private-/" + ] + }, + "blur": { + "intensity": 15, + "width": 200, + "height": 50 + } + } + ] +} \ No newline at end of file diff --git a/common/src/schemas/schemas.json b/common/src/schemas/schemas.json index 5e6e338..ca62b00 100644 --- a/common/src/schemas/schemas.json +++ b/common/src/schemas/schemas.json @@ -1,4 +1,1167 @@ { + "annotation_v3": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "annotation", + "type": "object", + "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", + "anyOf": [ + { + "required": [ + "arrow" + ], + "not": { + "required": [ + "text", + "rectangle", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "text" + ], + "not": { + "required": [ + "arrow", + "rectangle", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "rectangle" + ], + "not": { + "required": [ + "arrow", + "text", + "circle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "circle" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "line", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "line" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "callout", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "callout" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "highlight", + "blur" + ] + } + }, + { + "required": [ + "highlight" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "callout", + "blur" + ] + } + }, + { + "required": [ + "blur" + ], + "not": { + "required": [ + "arrow", + "text", + "rectangle", + "circle", + "line", + "callout", + "highlight" + ] + } + } + ], + "properties": { + "find": { + "type": "object", + "description": "Element on the page to annotate.", + "anyOf": [ + { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "additionalProperties": false, + "properties": { + "selector": { + "type": "string", + "description": "Selector of the element to annotate." + }, + "elementText": { + "type": "string", + "description": "Display text of the element to annotate." + }, + "elementTestId": { + "type": "string", + "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." + }, + "elementAttribute": { + "type": "object", + "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ] + } + }, + "elementAria": { + "type": "string", + "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + } + } + }, + "position": { + "anyOf": [ + { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + { + "type": "string", + "enum": [ + "top", + "bottom", + "left", + "right", + "center", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "description": "Position relative to the element (if `find` is provided) or to the viewport." + } + ] + }, + "arrow": { + "type": "object", + "description": "Configuration for arrow annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the arrow (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the arrow line in pixels.", + "minimum": 1, + "default": 3 + }, + "headSize": { + "type": "number", + "description": "Size of the arrowhead in pixels.", + "minimum": 1, + "default": 15 + } + } + }, + "text": { + "type": "object", + "description": "Configuration for text annotations.", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 16 + }, + "fontFamily": { + "type": "string", + "description": "Font family name.", + "default": "Arial" + }, + "color": { + "type": "string", + "description": "Text color (hex, rgb, or named color).", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFFF" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "description": "Padding in pixels on all sides.", + "minimum": 0 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + ], + "default": 5 + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box. Text will wrap.", + "minimum": 1 + }, + "opacity": { + "type": "number", + "description": "Opacity of the text and background (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "content" + ] + }, + "rectangle": { + "type": "object", + "description": "Configuration for rectangle annotations.", + "properties": { + "width": { + "type": "number", + "description": "Width of the rectangle in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the rectangle in pixels.", + "minimum": 1 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "rx": { + "type": "number", + "description": "Horizontal corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + }, + "ry": { + "type": "number", + "description": "Vertical corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + } + } + }, + "circle": { + "type": "object", + "description": "Configuration for circle annotations.", + "properties": { + "radius": { + "type": "number", + "description": "Radius of the circle in pixels.", + "minimum": 1, + "default": 30 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + } + }, + "line": { + "type": "object", + "description": "Configuration for line annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the line (hex, rgb, or named color).", + "default": "#000000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the line in pixels.", + "minimum": 1, + "default": 2 + }, + "dashArray": { + "type": "array", + "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", + "items": { + "type": "number", + "minimum": 0 + } + } + }, + "required": [ + "from", + "to" + ] + }, + "callout": { + "type": "object", + "description": "Configuration for callout annotations (text with arrow).", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "target": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "textPosition": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 14 + }, + "color": { + "type": "string", + "description": "Text color.", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFCC" + }, + "arrowColor": { + "type": "string", + "description": "Color of the arrow.", + "default": "#000000" + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box.", + "minimum": 1 + } + }, + "required": [ + "content", + "target" + ] + }, + "highlight": { + "type": "object", + "description": "Configuration for highlight annotations (semi-transparent overlay).", + "properties": { + "color": { + "type": "string", + "description": "Highlight color (hex, rgb, or named color).", + "default": "#FFFF00" + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + } + }, + "blur": { + "type": "object", + "description": "Configuration for blur annotations (for redacting sensitive information).", + "properties": { + "intensity": { + "type": "number", + "description": "Blur intensity level.", + "minimum": 1, + "default": 10 + }, + "width": { + "type": "number", + "description": "Width of the blur area in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the blur area in pixels.", + "minimum": 1 + } + } + } + }, + "components": { + "schemas": { + "arrow_properties": { + "type": "object", + "description": "Configuration for arrow annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the arrow (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the arrow line in pixels.", + "minimum": 1, + "default": 3 + }, + "headSize": { + "type": "number", + "description": "Size of the arrowhead in pixels.", + "minimum": 1, + "default": 15 + } + } + }, + "text_properties": { + "type": "object", + "description": "Configuration for text annotations.", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 16 + }, + "fontFamily": { + "type": "string", + "description": "Font family name.", + "default": "Arial" + }, + "color": { + "type": "string", + "description": "Text color (hex, rgb, or named color).", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFFF" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "description": "Padding in pixels on all sides.", + "minimum": 0 + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + ], + "default": 5 + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box. Text will wrap.", + "minimum": 1 + }, + "opacity": { + "type": "number", + "description": "Opacity of the text and background (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "content" + ] + }, + "rectangle_properties": { + "type": "object", + "description": "Configuration for rectangle annotations.", + "properties": { + "width": { + "type": "number", + "description": "Width of the rectangle in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the rectangle in pixels.", + "minimum": 1 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "rx": { + "type": "number", + "description": "Horizontal corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + }, + "ry": { + "type": "number", + "description": "Vertical corner radius for rounded rectangles.", + "minimum": 0, + "default": 0 + } + } + }, + "circle_properties": { + "type": "object", + "description": "Configuration for circle annotations.", + "properties": { + "radius": { + "type": "number", + "description": "Radius of the circle in pixels.", + "minimum": 1, + "default": 30 + }, + "fill": { + "type": "string", + "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", + "default": "transparent" + }, + "stroke": { + "type": "string", + "description": "Border color (hex, rgb, or named color).", + "default": "#FF0000" + }, + "strokeWidth": { + "type": "number", + "description": "Border width in pixels.", + "minimum": 0, + "default": 2 + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 1 + } + } + }, + "line_properties": { + "type": "object", + "description": "Configuration for line annotations.", + "properties": { + "from": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "to": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "color": { + "type": "string", + "description": "Color of the line (hex, rgb, or named color).", + "default": "#000000" + }, + "strokeWidth": { + "type": "number", + "description": "Width of the line in pixels.", + "minimum": 1, + "default": 2 + }, + "dashArray": { + "type": "array", + "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", + "items": { + "type": "number", + "minimum": 0 + } + } + }, + "required": [ + "from", + "to" + ] + }, + "callout_properties": { + "type": "object", + "description": "Configuration for callout annotations (text with arrow).", + "properties": { + "content": { + "type": "string", + "description": "Text content to display." + }, + "target": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "textPosition": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "fontSize": { + "type": "number", + "description": "Font size in pixels.", + "minimum": 1, + "default": 14 + }, + "color": { + "type": "string", + "description": "Text color.", + "default": "#000000" + }, + "backgroundColor": { + "type": "string", + "description": "Background color for the text box.", + "default": "#FFFFCC" + }, + "arrowColor": { + "type": "string", + "description": "Color of the arrow.", + "default": "#000000" + }, + "maxWidth": { + "type": "number", + "description": "Maximum width of the text box.", + "minimum": 1 + } + }, + "required": [ + "content", + "target" + ] + }, + "highlight_properties": { + "type": "object", + "description": "Configuration for highlight annotations (semi-transparent overlay).", + "properties": { + "color": { + "type": "string", + "description": "Highlight color (hex, rgb, or named color).", + "default": "#FFFF00" + }, + "opacity": { + "type": "number", + "description": "Opacity (0-1).", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + } + }, + "blur_properties": { + "type": "object", + "description": "Configuration for blur annotations (for redacting sensitive information).", + "properties": { + "intensity": { + "type": "number", + "description": "Blur intensity level.", + "minimum": 1, + "default": 10 + }, + "width": { + "type": "number", + "description": "Width of the blur area in pixels.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the blur area in pixels.", + "minimum": 1 + } + } + }, + "point": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." + }, + "y": { + "type": "number", + "description": "Y coordinate in pixels." + } + }, + "required": [ + "x", + "y" + ] + }, + "padding": { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 + }, + "right": { + "type": "number", + "minimum": 0 + }, + "bottom": { + "type": "number", + "minimum": 0 + }, + "left": { + "type": "number", + "minimum": 0 + } + } + } + } + }, + "examples": [ + { + "find": { + "selector": "#submit-button" + }, + "arrow": { + "from": { + "x": 0, + "y": -50 + }, + "to": { + "x": 0, + "y": 0 + }, + "color": "#00FF00", + "strokeWidth": 4, + "headSize": 20 + } + }, + { + "position": "top-right", + "text": { + "content": "Important Notice", + "fontSize": 18, + "color": "#FFFFFF", + "backgroundColor": "#0000FF", + "padding": 10, + "maxWidth": 200, + "opacity": 0.9 + } + }, + { + "find": { + "elementClass": [ + "sensitive-info", + "/^private-/" + ] + }, + "blur": { + "intensity": 15, + "width": 200, + "height": 50 + } + } + ] + }, "checkLink_v3": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "checkLink", diff --git a/core/test/artifacts/annotations-simple.spec.json b/core/test/artifacts/annotations-simple.spec.json new file mode 100644 index 0000000..d95b7c5 --- /dev/null +++ b/core/test/artifacts/annotations-simple.spec.json @@ -0,0 +1,36 @@ +{ + "specId": "annotation-simple-test", + "tests": [ + { + "testId": "test-simple-annotation", + "description": "Test simple text annotation without element finding", + "steps": [ + { + "goTo": "http://localhost:8092/index.html" + }, + { + "stepId": "annotation-text-only", + "screenshot": { + "path": "annotation-text-simple.png", + "directory": "test/artifacts/annotations", + "overwrite": "true", + "annotations": [ + { + "position": { + "x": 50, + "y": 50 + }, + "text": { + "content": "Simple Test", + "fontSize": 20, + "color": "#FF0000", + "backgroundColor": "#FFFFFF" + } + } + ] + } + } + ] + } + ] +} diff --git a/core/test/artifacts/enhanced-modal-large.png b/core/test/artifacts/enhanced-modal-large.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ea351556d72a8a6870352e45b0a839a2d280a2 GIT binary patch literal 6664 zcmeHMc~nyGn-}*ivrRGAY%f!@TqBnOlYyUr6vhYrM z+vuAteHNq+6mYIjKm9r!$X^b&?=$7>HI2-QX4;$Q*M^4>dU7&{;Zs#i-h4~+7@S~s zmc5}_VjRSbjle^w>a2}-W&X<{XWPn#sCEk=TrtZ?NrY&;a2TX18n>Ot%ZNs)tt=2Q zSbqHf)1q|zPigVXl19vyf3Tk+mbnIe=rwYSTAiJb|b<8Q8EZc<_AcIbC{C4{(V|s}w@vILp!;R&!3Tr3RTd z;9y~<3CDwE402(A%4%6Jjc~TCCAzp7&ZA~4>iZ9U=t<>qnEAX#x|1K?7`etZ2pDaM zf-DU>&617_*Vx(1b{U7SrP5YrTyY1f62Mbm(WDTnfz81J6h0P2=W{4kOx$!~^6zDN zqwk)niim~C>8}MVn9b6P3WANc(Tu4<&V7EiYqqmbzf;X; ziRkLU=Ph+peB`;~k+fVj$&R`c_oaVr3jAgbu0Tc1eXn*`VYSmbo*w=5MY##lYe+hO zgo@!Wli`QAlVub%auVcKUryykGu9%zb?S3UDeHjPVnf2t;_K(@$VDy7Bih22$tRGh z7{{9~Qm&lw=)lC-z`+v7CI1C}iaD&F-p4r0j z7*`@D9_=-78rL8wh@zpx(j^gOzYlgzD^uBQ3Y%bo;&CTa25Lzj*%mf?+{-J;Dy;dY z*~;fR5WNI+$Fl5)2@JtPh~R%8x>gREuNk;OqeioPjR$}VX1giA@o!lgGCM|1j?Nvd zc4pNR%vWn-aKMwq(#pEUv9e1$N0SNq&7t*U;bk(Ha-|T&xUC=hj`=3C8TAz8(xjL5 z2vF%V!OBysjXuYg8z!I3Zem$4Q3b2ad|KtK9|NOP_r1_Y1_9i_t(Y_R9lP*2@IOCc zQ!9KDen_&q=ScTY923LD0u^5(!BD9n3U-y@W+C_}qvLn}~^_79G5UmyU<0C$sT;szfq&J*NFMC#xQ8B#5w|WPUpskHciTA*6e$^rnH_sDYVZBz_yTtsj zRsbpll-V_18lfeq{8VuVO#&j{1oEtnd1kG2R=c9+qSfqLX)5|~f zbx_?fM#H=1RSfoXOnE?SU`X0LQCJxQyMb5{HpDXO{_iSakq^F} zUX)$r(GrFBN-?V&;7@iuK6jLG9Bw|<3UEVxWf(xkQ|vZVvLQgyZ$$r5nsf*HjL3e^ zhoHVXDWbl41(Coa`8>3G4WKsE+Dd--h>s7Tc@F3; ze~iOoY;53td85yuaVrJ0!E3^=1y%z9fk0Yi5a)Di2MyM7u>gIq=R!}Rr}yO}eruwJ zMA;tj#{-xqqhGjsn5u_7ByQj z0Epcsie@LHjvU~_Xr$T0`%Jw@fa?E_P)VFdE`GD2<0TZ%16PG+g$-R9*qMANHGC|L zwAcq>)|j2*+*dF^vpV;|0eZV2K4i~CmTzTd0FJ-R698PS$ApD`vv#6jV+JOY_41Y} zC}9z{$3nP9Pjj+A3(OZLfG{|-Fkw`SMKHlR+qbfDhN5a3as%pve)0S0KTJNi)53o1 z-t#3)O(Va{yuJwRbEI&UQhYPr-KZBxvkxG~=TNI;%5MP>TQPm~wM`16CS?KA#y_>^ z<{~@8>&aOewIEAqK;y5X(tJJKTF6K^*`Iy%F^%6yh|wJjYL&Mmspwxn#q04le_o~7 z>0dW|i$3g~pX(~=P z;Q>y-oAo#I0xA%@-bQ3M3=c;YU zAW8~y@wEZ7nO&5u+qB=JM46!i8Uw<}s zaknyAr|vRuoP$kYUF%Q{{CVe#i030w2#q5*&Wwa~>#zl~$06)rdMML;NS?!`E67dty*9y8ut41W7~-FNN)y=*vWdHzqUKE$`Q1k`6<&oFSAOO^!Cs@ zy!eWHGWGWp2;(yo3L*SKnxy*{mh}#$YhCUUW6l(?qK9J(NrhGMzU!b55JccH0)UIm zl((fc^QE^A=s=)v>^e`OJ-zT?5D74QW1&5)AFc44o)8cWVG&m-tDw!q36WR^Oz=B> zu}iz^=bd-5dTv#Kv4Q{eDvJ#SWZL)GRHDV&H3sS~XDospW4!Sje~o65KjaZTU&K6x z_K>`>SvKKr z;BqwwP>bS^_hpK6!$%IFp2#)HUM-_-DNL%aR;hAc)GuA0&^QPhw}r)4#xnB&+gmW zYB8B1OWwI7iK!9Xwpm?i?)C=mb>&-fG*_y? z+0qals~6X0B4A*c0V5h#-es{>xyTNtB4@N|ONgYuqbXRhkb?SYc_gkDurg&HQl_Tg zI)|j7g2iGB;;J%d8;TM-V5c6}^xZ@1K9MzNi}{a|E3w*>D)kKv4`O!atWJP&8TH1} zh|OK?6#bl9M@dvQKOMJrGitt;G-Cx-br1R|CCWnWRgq8TZiRo2S1ue5z`MrZByJjT z(bu~=r+M_&`Qm~r8}?OvLN^5X;=!#~AnUo~z`9}0RJEQ*evG)g7px=tv0(h`E65-nU_WwQxI@-*cv4hSYK2Rbk${41%~|SPXipI z<*rvr);ibin}?J@G}J*VhBs5jUZ~I_Ph|&sC~!yUv}=j#FB2)@;W&LgkFsg6p0{9* zCeCJ!k(+r@v+Q8^Io-xL1HP^w17-uiGLDKC?E6ooOChdJJ~r-q5vG4*xg8AaAwy}@ zVBSljcJcsBm0fG9wu9Nyr5NXt%a?X3HQc@=6&ifiyJ)Zzxaz3u zm|@@Z%kf_xvzNn`RcqLfM6T5KD;fklB)(ZO3bxYaIzxs^V4v->nF?Y6;_(H(*sc~- zoqDId0lKn6K;^a8Usl_h@I)hQ&~YWBL#wH}` zbEwzG#>+ZJ;_pms5Eka0rdEe`=m$~pYL*>2A&&9jU_g}9s{Uy-e6n22Ok+)wr6FU_!I=rDV+*)!(5SKy zf=0TOO`lG-#hL6yc5?gH?aO(ZV*2x`RY;I>8R_&tN-;@Kja-x~U2Fn~_L^RbW3mBW z_V|W?4PQjIaA0q?-;rU;t6c95Kr$}G>B@6=n$SsAFhCXCfF&jikmq9}$7tG?d|`iF zT}eq<+t=>zMxOXswFdv{b|uqy582JEPwQ7QWCcL07rfqlnGayOCwc#=48?mF9-IIm zGI1<=zSdRaw936972on_0hsx^qNJ)A&X{rH$<1oIwSyNUZ&Ew(rMZBM-`)9i!lZ7- zTk?iz9mZY@xi2l>MR*_F;0yWTS{|Sp^C%oZbNEOnpp8?+8;BqdbDg~{B<2xkugf=gfX&#e zTL?jbbMlp=A6u0l`OBd`rxm!vw>F;kg{ z(0@}0EE?$mX5kSO711UBn^?Wn>$m4$x&>q=>U6T`%I{U+d&Ge=7o`6Mwu$_*q!29| zzZP-4MZsEfwz8IDUzHDvK>e?9kj)UsS_Pb;qcj)-mM^q++HEoT&dCNMVbdRHe7-7a zJ@@5tBQ%_8M~|<+7{zQ&)6huoU-$YVl=_*Wz;!XL9pbol6c2Jxt2P0_P4 zmbNydY5l%i?|hv4NQx+@LXekiQ(Ch6F~ZVYqd$I6Mav~ji<;;>E@>Tiif?V3k4Wv0 z(92y5t^iT~!8k=NzDP@WQsTV!IO-tUEkCD0I8O5=qVyLd8n<2?Ve~%)!5&0Mm}U2; z_u2boPCD_bW}Tww^J&s*Mk}#;;w`ds(i$FQN9N+7 zOB3pFm&5XTaWcT$sI9jb8| zZQ+L7y1|Ywa23pL=>#vQ5kBf7l$BmPufHwgA~Jj)NWF=0-hnhFs|Km8`+NIBXqCR$ zBPE*O2JXanb<#0JJczoXsN z@d@l$t8@=4d4o1)96a7QWNmc)*NE~?%<`~0_UV9Ll0{KnVZf#B z$i;=WSiREKLfgX(9rMoXYE0DbzZrbCO_Am79Dr-7a`~ck%|-IYzDKq`f?W^=?)7U) zaK>5sQiLyikk7e)KnHQjA9hLH{*H>D(Z_ASY2M5x!R2(PyF_e+W7O*F7=9GZs! zGcz=#!m?wG7cL1%w%98BGxSX3JK75#{4;DdL?Y!gy-ptSMkM5 zIsckm_uo-3K2+@w*@+G0{oO{9+xsV>v2lNq_R3TIj~MOG_}@S6870d#ApEy4NB;fQ fNsz-c0#zvXrH$AizTu0Bh#t;b+n=gD=^6KLf~9dk literal 0 HcmV?d00001 diff --git a/core/test/artifacts/enhanced-modal.png b/core/test/artifacts/enhanced-modal.png new file mode 100644 index 0000000000000000000000000000000000000000..558ee29c9e1f4b41e9251a2f5252340500c7f365 GIT binary patch literal 1119 zcmV-l1fctgP)~L_&aI1OfyTC7Nish};Y&Dj_@&-bjd% zsKF3IB2T>dBAgb=9Vxe#aw`zPC|D51P*9{$u%!^o{UR+QE!P^$rBF&+DE!Q1c60XZ z!tN5!3}h<;tdp$>FuHb35=@hw6exm( z2VjPQY(;=|vK0YF*N#boX|j_7MUe0S%xJM7XY7UivX%>SewqG8zx(AGvLeYq?v)Aa zkHYo4(C`q-s$p?4bf24ekOwT&q~5557t_7IFL$Z$|HjthL4IqACh*8r82dd8%z=^X zVZ$-VE_r@HzET6DzxDb~ROz~b94Cnd7vN-7beD*Anf+vtJ7mDxBXGMO>K?#PXQAhO z*WW)I4phLsMyRQWqDq$)+N8tW{c!D$`eolc%i@DP{{U<|&LIFR0LvxECu=NdH7;Gv`$kdkodzv_7j`P(u{qs zzvB!AF_tDTIp|7P(tYP}yD5C*a^ft)28pSI`OK_0Qr>o2_Mf;=ck+2-TT$_#;^hKEZ+Qh_YC_ivq2 zWgzl1c!elYx+#(pB|%Sm$Dzxry`rb`-Osi>8^{4iuX^&X*D|9)_7j`XwXjRb|3aD; zK?vkYKSSwNZwx!mB{|5wm+GV`!;n<3BsJa@N+w#N%MWs+hnu$3^n22^uY3)|*Q!R# z+2YSCfq(D8CwU5h3^)smpwCi&Ah(ar| z?Hrk2WnFYz_I-2QeODk3$dMKaa;(_IS_LP3xqe-)(Fy&R^IlD!Rj9cT|CZBwrAm5` z&3JxtknjM^Fp#YXuuirj!06gBNia=zQlJPD9)KAJvK0Z=$yNjyT{|WTrpZnU6hXoR lFvCE$BEUM?ihy`I_z(P^tqBqdeE$Fd002ovPDHLkV1lu(5F7vi literal 0 HcmV?d00001 From 9bc5c1cc8e778e8aefdadda668cb0020380e5b02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:45:32 +0000 Subject: [PATCH 7/9] Address code review feedback: remove fabric dependency and replace magic numbers with named constants Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- core/package-lock.json | 454 --------------------------- core/src/tests/annotateScreenshot.js | 21 +- 2 files changed, 13 insertions(+), 462 deletions(-) diff --git a/core/package-lock.json b/core/package-lock.json index ab1cf68..7f3ebc8 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -23,7 +23,6 @@ "doc-detective-common": "^3.6.0", "doc-detective-resolver": "^3.6.1", "dotenv": "^17.2.3", - "fabric": "^6.0.0", "geckodriver": "^6.1.0", "jq-web": "^0.6.2", "json-schema-faker": "^0.5.9", @@ -1405,16 +1404,6 @@ "text-hex": "1.0.x" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -1783,14 +1772,6 @@ "node": ">=18.0.0" } }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "license": "BSD-3-Clause", - "optional": true - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -1822,43 +1803,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "optional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "license": "MIT", - "optional": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -17840,33 +17784,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "license": "MIT", - "optional": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "license": "MIT", - "optional": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "license": "MIT", - "optional": true - }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", @@ -17876,31 +17793,6 @@ "node": ">= 14" } }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/data-urls/node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -17930,13 +17822,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "license": "MIT", - "optional": true - }, "node_modules/decompress-response": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", @@ -18269,20 +18154,6 @@ ], "license": "BSD-2-Clause" }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", - "license": "MIT", - "optional": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", @@ -18816,19 +18687,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/fabric": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/fabric/-/fabric-6.0.0.tgz", - "integrity": "sha512-Kc187rYtOuTAXCMs+RRP8UEr09pZgJx0rusKMfv0wWFcbVakv3WKNB7lBhuWXjJk/gfxQHp2h+7f7AF1FGIGcg==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - }, - "optionalDependencies": { - "canvas": "^2.11.2", - "jsdom": "^20.0.1" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -19584,32 +19442,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "license": "MIT", - "optional": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-encoding-sniffer/node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/htmlfy": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.8.1.tgz", @@ -19932,13 +19764,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "license": "MIT", - "optional": true - }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -20033,117 +19858,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/jsdom/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "license": "MIT", - "optional": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdom/node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/jsep": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", @@ -21220,13 +20934,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/nwsapi": { - "version": "2.2.23", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", - "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", - "license": "MIT", - "optional": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -21827,19 +21534,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "license": "MIT", - "optional": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -21850,16 +21544,6 @@ "once": "^1.3.1" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -21881,13 +21565,6 @@ "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", "license": "MIT" }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT", - "optional": true - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -22061,13 +21738,6 @@ "dev": true, "license": "MIT" }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT", - "optional": true - }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -22307,19 +21977,6 @@ "truncate-utf8-bytes": "^1.0.0" } }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "license": "ISC", - "optional": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -23038,13 +22695,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "license": "MIT", - "optional": true - }, "node_modules/tagged-tag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", @@ -23167,35 +22817,6 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "license": "MIT", - "optional": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -23273,16 +22894,6 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/unorm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", @@ -23301,17 +22912,6 @@ "node": ">= 0.8" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/urlpattern-polyfill": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", @@ -23371,19 +22971,6 @@ "node": ">= 0.8" } }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "license": "MIT", - "optional": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/wait-port": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz", @@ -23534,16 +23121,6 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -23565,20 +23142,6 @@ "node": ">=18" } }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/which": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", @@ -23859,16 +23422,6 @@ } } }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -23878,13 +23431,6 @@ "node": ">=8.0" } }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "license": "MIT", - "optional": true - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/core/src/tests/annotateScreenshot.js b/core/src/tests/annotateScreenshot.js index c9f9963..a556503 100644 --- a/core/src/tests/annotateScreenshot.js +++ b/core/src/tests/annotateScreenshot.js @@ -3,6 +3,11 @@ const { findElement } = require("./findElement"); const { log } = require("../utils"); const fs = require("fs"); +// Constants for default dimensions and positioning +const DEFAULT_SIZE = 100; +const DEFAULT_CALLOUT_OFFSET_X = 100; +const DEFAULT_CALLOUT_OFFSET_Y = 80; + exports.annotateScreenshot = annotateScreenshot; async function annotateScreenshot({ config, filePath, annotations, driver }) { @@ -377,8 +382,8 @@ function renderRectangle(ctx, rectangle, basePosition, pixelDensity) { const x = basePosition.x; const y = basePosition.y; - const width = (config.width || basePosition.width || 100) * pixelDensity; - const height = (config.height || basePosition.height || 100) * pixelDensity; + const width = (config.width || basePosition.width || DEFAULT_SIZE) * pixelDensity; + const height = (config.height || basePosition.height || DEFAULT_SIZE) * pixelDensity; const rx = config.rx * pixelDensity; const ry = config.ry * pixelDensity; @@ -504,8 +509,8 @@ function renderCallout(ctx, callout, basePosition, pixelDensity) { textY = basePosition.y + callout.textPosition.y * pixelDensity; } else { // Auto-position above and to the left of target - textX = targetX - 100 * pixelDensity; - textY = targetY - 80 * pixelDensity; + textX = targetX - DEFAULT_CALLOUT_OFFSET_X * pixelDensity; + textY = targetY - DEFAULT_CALLOUT_OFFSET_Y * pixelDensity; } // Draw text box @@ -587,8 +592,8 @@ function renderHighlight(ctx, highlight, basePosition, pixelDensity) { ctx.fillRect( basePosition.x, basePosition.y, - basePosition.width || 100 * pixelDensity, - basePosition.height || 100 * pixelDensity + basePosition.width || DEFAULT_SIZE * pixelDensity, + basePosition.height || DEFAULT_SIZE * pixelDensity ); ctx.restore(); } @@ -607,8 +612,8 @@ function renderBlur(ctx, blur, basePosition, pixelDensity) { ctx.fillRect( basePosition.x, basePosition.y, - (config.width || basePosition.width || 100) * pixelDensity, - (config.height || basePosition.height || 100) * pixelDensity + (config.width || basePosition.width || DEFAULT_SIZE) * pixelDensity, + (config.height || basePosition.height || DEFAULT_SIZE) * pixelDensity ); ctx.restore(); } From 670d15992eb32f45d2d0afa6c24ccd56842445cb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:05:57 +0000 Subject: [PATCH 8/9] Fix schema issues: add elementId, required arrays, remove components, improve descriptions Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- common/dist/schemas/annotation_v3.schema.json | 473 +- common/dist/schemas/checkLink_v3.schema.json | 64 - common/dist/schemas/click_v3.schema.json | 121 - common/dist/schemas/config_v3.schema.json | 9956 +-------- common/dist/schemas/context_v3.schema.json | 82 - .../dist/schemas/dragAndDrop_v3.schema.json | 216 - common/dist/schemas/find_v3.schema.json | 650 - common/dist/schemas/goTo_v3.schema.json | 173 - .../dist/schemas/httpRequest_v3.schema.json | 400 - common/dist/schemas/loadCookie_v3.schema.json | 101 - common/dist/schemas/openApi_v3.schema.json | 12 - common/dist/schemas/record_v3.schema.json | 42 - common/dist/schemas/report_v3.schema.json | 184 +- .../dist/schemas/resolvedTests_v3.schema.json | 368 +- common/dist/schemas/runCode_v3.schema.json | 92 - common/dist/schemas/runShell_v3.schema.json | 91 - common/dist/schemas/saveCookie_v3.schema.json | 107 - common/dist/schemas/screenshot_v3.schema.json | 1559 +- common/dist/schemas/spec_v3.schema.json | 184 +- common/dist/schemas/step_v3.schema.json | 203 +- common/dist/schemas/test_v3.schema.json | 370 +- common/dist/schemas/type_v3.schema.json | 108 - common/dist/schemas/wait_v3.schema.json | 12 - common/src/schemas/dereferenceSchemas.js | 17 + .../output_schemas/annotation_v3.schema.json | 473 +- .../output_schemas/checkLink_v3.schema.json | 64 - .../output_schemas/click_v3.schema.json | 121 - .../output_schemas/config_v3.schema.json | 9956 +-------- .../output_schemas/context_v3.schema.json | 82 - .../output_schemas/dragAndDrop_v3.schema.json | 216 - .../output_schemas/find_v3.schema.json | 650 - .../output_schemas/goTo_v3.schema.json | 173 - .../output_schemas/httpRequest_v3.schema.json | 400 - .../output_schemas/loadCookie_v3.schema.json | 101 - .../output_schemas/openApi_v3.schema.json | 12 - .../output_schemas/record_v3.schema.json | 42 - .../output_schemas/report_v3.schema.json | 184 +- .../resolvedTests_v3.schema.json | 368 +- .../output_schemas/runCode_v3.schema.json | 92 - .../output_schemas/runShell_v3.schema.json | 91 - .../output_schemas/saveCookie_v3.schema.json | 107 - .../output_schemas/screenshot_v3.schema.json | 1559 +- .../output_schemas/spec_v3.schema.json | 184 +- .../output_schemas/step_v3.schema.json | 203 +- .../output_schemas/test_v3.schema.json | 370 +- .../output_schemas/type_v3.schema.json | 108 - .../output_schemas/wait_v3.schema.json | 12 - common/src/schemas/schemas.json | 17370 ++-------------- .../src_schemas/annotation_v3.schema.json | 20 +- core/src/tests/annotateScreenshot.js | 12 +- 50 files changed, 4161 insertions(+), 44394 deletions(-) diff --git a/common/dist/schemas/annotation_v3.schema.json b/common/dist/schemas/annotation_v3.schema.json index ecf576e..1a69643 100644 --- a/common/dist/schemas/annotation_v3.schema.json +++ b/common/dist/schemas/annotation_v3.schema.json @@ -222,6 +222,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -402,6 +406,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -453,6 +461,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -628,8 +639,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -646,7 +667,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -667,454 +688,6 @@ } } }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, "examples": [ { "find": { diff --git a/common/dist/schemas/checkLink_v3.schema.json b/common/dist/schemas/checkLink_v3.schema.json index ba4b15d..e4aee34 100644 --- a/common/dist/schemas/checkLink_v3.schema.json +++ b/common/dist/schemas/checkLink_v3.schema.json @@ -63,70 +63,6 @@ } } ], - "components": { - "schemas": { - "string": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - } - }, "examples": [ "https://www.google.com", "/search", diff --git a/common/dist/schemas/click_v3.schema.json b/common/dist/schemas/click_v3.schema.json index 7c62e4f..eef79c3 100644 --- a/common/dist/schemas/click_v3.schema.json +++ b/common/dist/schemas/click_v3.schema.json @@ -115,127 +115,6 @@ "type": "boolean" } ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, "examples": [ true, "right", diff --git a/common/dist/schemas/config_v3.schema.json b/common/dist/schemas/config_v3.schema.json index f828ad5..6b10a7f 100644 --- a/common/dist/schemas/config_v3.schema.json +++ b/common/dist/schemas/config_v3.schema.json @@ -5812,6 +5812,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -5992,6 +5996,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6043,6 +6051,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6218,8 +6229,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6236,7 +6257,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6399,6 +6420,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6450,6 +6475,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6625,8 +6653,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6643,7 +6681,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7175,6 +7213,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7355,6 +7397,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7406,6 +7452,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7581,8 +7630,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7599,7 +7658,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7762,6 +7821,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7813,6 +7876,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7988,8 +8054,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8006,7 +8082,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -10960,9870 +11036,6 @@ "default": false } }, - "components": { - "schemas": { - "environment": { - "type": "object", - "description": "Environment information for the system running Doc Detective.", - "readOnly": true, - "additionalProperties": false, - "required": [ - "platform" - ], - "properties": { - "workingDirectory": { - "description": "The current working directory of the process running Doc Detective.", - "type": "string" - }, - "platform": { - "description": "The operating system type running Doc Detective.", - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - }, - "arch": { - "description": "The processor architecture of the system running Doc Detective.", - "type": "string", - "enum": [ - "arm32", - "arm64", - "x32", - "x64" - ] - } - }, - "title": "Environment details" - }, - "markupDefinition": { - "type": "object", - "properties": { - "name": { - "description": "Name of the markup definition", - "type": "string" - }, - "regex": { - "description": "Regular expressions to match the markup type.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "batchMatches": { - "description": "If `true`, all matches are combined into a single string.", - "type": "boolean", - "default": false - }, - "actions": { - "description": "Actions to perform when the markup type is detected.", - "anyOf": [ - { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "step", - "description": "A step in a test.", - "type": "object", - "components": { - "schemas": { - "common": { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - } - }, - "anyOf": [ - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "checkLink" - ], - "properties": { - "checkLink": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "checkLink", - "anyOf": [ - { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - ], - "components": { - "schemas": { - "string": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - } - }, - "examples": [ - "https://www.google.com", - "/search", - { - "url": "https://www.google.com", - "statusCodes": 200 - }, - { - "url": "/search", - "origin": "www.google.com", - "statusCodes": [ - 200 - ] - } - ] - } - }, - "title": "checkLink" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "click" - ], - "properties": { - "click": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - } - }, - "title": "click" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "find" - ], - "properties": { - "find": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "find", - "description": "Find an element based on display text or a selector, then optionally interact with it.", - "anyOf": [ - { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - ], - "components": { - "schemas": { - "string": { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "object": { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - } - }, - "examples": [ - "Find me!", - { - "selector": "[title=Search]" - }, - { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": "shorthair cat" - }, - { - "selector": "[title=Search]", - "click": { - "button": "right" - } - }, - { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": { - "keys": [ - "shorthair cat" - ], - "inputDelay": 100 - } - }, - { - "elementId": "/^user-[0-9]+$/", - "elementClass": [ - "admin", - "/^level-[1-5]$/" - ], - "elementAttribute": { - "data-active": true, - "data-score": "/^[0-9]+$/" - }, - "timeout": 8000, - "moveTo": false - } - ] - } - }, - "title": "find" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "goTo" - ], - "properties": { - "goTo": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "goTo", - "anyOf": [ - { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - } - }, - "examples": [ - "https://www.google.com", - "/search", - { - "url": "https://www.google.com" - }, - { - "url": "/search", - "origin": "https://www.google.com" - }, - { - "url": "https://www.example.com", - "waitUntil": { - "networkIdleTime": 500 - } - }, - { - "url": "https://www.example.com/dashboard", - "waitUntil": { - "find": { - "selector": "[data-testid='dashboard-loaded']" - } - } - }, - { - "url": "https://www.example.com/app", - "timeout": 60000, - "waitUntil": { - "networkIdleTime": 500, - "domIdleTime": 1000, - "find": { - "selector": ".main-content", - "elementText": "Dashboard" - } - } - }, - { - "url": "https://www.example.com/app", - "timeout": 60000, - "waitUntil": { - "networkIdleTime": null - } - }, - { - "url": "https://www.example.com/status", - "waitUntil": { - "find": { - "elementText": "System operational" - } - } - }, - { - "url": "http://localhost:8092", - "waitUntil": { - "find": { - "selector": "button", - "elementText": "Standard Button", - "elementTestId": "standard-btn", - "elementAria": "Sample Standard Button", - "elementId": "standard-btn", - "elementClass": [ - "btn" - ], - "elementAttribute": { - "type": "button", - "value": "Standard Button" - } - } - } - } - ] - } - }, - "title": "goTo" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "httpRequest" - ], - "properties": { - "httpRequest": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "httpRequest", - "description": "Perform a generic HTTP request, for example to an API.", - "anyOf": [ - { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - ], - "components": { - "schemas": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - } - }, - "examples": [ - "https://reqres.in/api/users", - { - "url": "https://reqres.in/api/users" - }, - { - "url": "https://reqres.in/api/users/2", - "method": "put", - "request": { - "body": { - "name": "morpheus", - "job": "zion resident" - } - } - }, - { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ] - }, - { - "url": "https://www.api-server.com", - "method": "post", - "timeout": 30000, - "request": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - }, - "parameters": { - "param": "value" - } - }, - "response": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - } - }, - "statusCodes": [ - 200 - ] - }, - { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ], - "path": "response.json", - "directory": "media", - "maxVariation": 0.05, - "overwrite": "aboveVariation" - }, - { - "openApi": "getUserById" - }, - { - "openApi": { - "name": "Reqres", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme" - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme", - "headers": { - "Authorization": "Bearer $TOKEN" - } - } - }, - { - "url": "https://www.api-server.com", - "method": "post", - "request": { - "headers": "Content-Type: application/json\\nAuthorization: Bearer token" - } - }, - { - "url": "https://api.example.com/users/123", - "response": { - "required": [ - "id", - "email", - "createdAt" - ] - } - }, - { - "url": "https://api.example.com/users/123", - "response": { - "required": [ - "user.profile.name", - "user.profile.avatar", - "user.settings.notifications" - ] - } - }, - { - "url": "https://api.example.com/orders", - "response": { - "required": [ - "orders[0].id", - "orders[0].total", - "orders[0].items[0].productId" - ] - } - }, - { - "url": "https://api.example.com/users", - "response": { - "required": [ - "sessionToken", - "expiresAt", - "user.id" - ], - "body": { - "status": "success", - "user": { - "role": "admin" - } - } - } - } - ] - } - }, - "title": "httpRequest" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "runShell" - ], - "properties": { - "runShell": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "runShell", - "description": "Perform a native shell command.", - "anyOf": [ - { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - } - }, - "examples": [ - "docker run hello-world", - { - "command": "echo", - "args": [ - "$USER" - ] - }, - { - "command": "echo", - "args": [ - "hello-world" - ] - }, - { - "command": "docker run hello-world", - "timeout": 20000, - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!" - }, - { - "command": "false", - "exitCodes": [ - 1 - ] - }, - { - "command": "echo", - "args": [ - "setup" - ], - "exitCodes": [ - 0 - ], - "stdio": "/.*?/" - }, - { - "command": "docker run hello-world", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!", - "path": "docker-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - ] - } - }, - "title": "runShell" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "runCode" - ], - "properties": { - "runCode": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "runCode", - "description": "Assemble and run code.", - "anyOf": [ - { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - ], - "components": { - "schemas": { - "object": { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - } - }, - "examples": [ - { - "language": "javascript", - "code": "console.log('Hello, ${process.env.USER}!');" - }, - { - "language": "bash", - "code": "docker run hello-world", - "timeout": 20000, - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!" - }, - { - "language": "javascript", - "code": "return false", - "exitCodes": [ - 1 - ] - }, - { - "language": "python", - "code": "print('Hello from Python')", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Python!", - "path": "python-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - ] - } - }, - "title": "runCode" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - } - }, - "title": "type" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "screenshot" - ], - "properties": { - "screenshot": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "screenshot", - "description": "Takes a screenshot in PNG format.", - "anyOf": [ - { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - { - "type": "boolean", - "title": "Capture screenshot", - "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." - } - ], - "components": { - "schemas": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - "crop_element": { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - } - }, - "examples": [ - true, - "image.png", - "static/images/image.png", - "/User/manny/projects/doc-detective/static/images/image.png", - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": "#elementToScreenshot" - }, - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - }, - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "padding": { - "top": 0, - "right": 0, - "bottom": 0, - "left": 0 - } - } - }, - { - "path": "image.png", - "annotations": [ - { - "find": { - "selector": "#usernameField" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#FF0000", - "strokeWidth": 4, - "headSize": 10 - } - }, - { - "find": { - "elementText": "Username", - "elementClass": [ - "input-field", - "/^user-/" - ] - }, - "text": { - "content": "Enter your username here", - "fontSize": 14, - "color": "#0000FF", - "backgroundColor": "#FFFFFF", - "padding": 5 - } - }, - { - "rectangle": { - "x": 100, - "y": 150, - "width": 200, - "height": 100, - "borderColor": "#00FF00", - "borderWidth": 3, - "fillColor": "rgba(0, 255, 0, 0.2)" - } - } - ] - } - ] - } - }, - "title": "screenshot" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "saveCookie" - ], - "properties": { - "saveCookie": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "saveCookie", - "description": "Save a specific browser cookie to a file or environment variable for later reuse.", - "anyOf": [ - { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - } - }, - "examples": [ - "session_token", - "test_env_cookie", - { - "name": "auth_cookie", - "path": "auth-cookie.txt" - }, - { - "name": "session_token", - "variable": "SESSION_TOKEN" - }, - { - "name": "test_cookie", - "path": "test-cookie.txt", - "overwrite": true - }, - { - "name": "user_session", - "path": "user-session.txt", - "directory": "./test-data", - "overwrite": true - }, - { - "name": "login_token", - "path": "login-token.txt", - "domain": "app.example.com" - } - ] - } - }, - "title": "saveCookie" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "record" - ], - "properties": { - "record": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "record", - "description": "Start recording the current browser viewport. Must be followed by a `stopRecord` step. Only runs in Chrome browsers when they are visible. Supported extensions: [ '.mp4', '.webm', '.gif' ]", - "anyOf": [ - { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - }, - { - "type": "boolean", - "title": "Record (boolean)", - "description": "If `true`, records the current browser viewport. If `false`, doesn't record the current browser viewport." - } - ], - "components": { - "schemas": { - "string": { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - } - } - }, - "examples": [ - true, - "results.mp4", - { - "path": "results.mp4", - "directory": "static/media", - "overwrite": "true" - } - ] - } - }, - "title": "record" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "stopRecord" - ], - "properties": { - "stopRecord": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "stopRecord", - "description": "Stop the current recording.", - "anyOf": [ - { - "type": "boolean", - "nullable": true - } - ], - "examples": [ - true - ] - } - }, - "title": "stopRecord" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "loadVariables", - "type": "object", - "required": [ - "loadVariables" - ], - "properties": { - "loadVariables": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "loadVariables", - "type": "string", - "description": "Load environment variables from the specified `.env` file.", - "examples": [ - ".env" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "dragAndDrop", - "type": "object", - "required": [ - "dragAndDrop" - ], - "properties": { - "dragAndDrop": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "dragAndDrop", - "description": "Drag and drop an element from source to target.", - "type": "object", - "required": [ - "source", - "target" - ], - "properties": { - "source": { - "description": "The element to drag.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "target": { - "description": "The target location to drop the element.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "duration": { - "type": "integer", - "description": "Duration of the drag operation in milliseconds.", - "default": 1000, - "minimum": 0 - } - }, - "components": { - "schemas": { - "elementSpecification": { - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "string": { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - "object": { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - } - }, - "examples": [ - { - "source": "Table", - "target": "#canvas" - }, - { - "source": ".draggable-block", - "target": ".drop-zone", - "duration": 2000 - }, - { - "source": { - "selector": ".widget", - "elementText": "Data Table" - }, - "target": { - "selector": "#design-canvas" - }, - "duration": 500 - }, - { - "source": { - "selector": ".draggable", - "timeout": 10000 - }, - "target": { - "elementText": "Drop Zone", - "timeout": 5000 - } - }, - { - "source": "/Widget Item.*/", - "target": "#canvas" - }, - { - "source": { - "selector": ".draggable", - "elementText": "/Button [0-9]+/" - }, - "target": { - "elementText": "/Drop Zone.*/" - } - } - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "loadCookie", - "type": "object", - "required": [ - "loadCookie" - ], - "properties": { - "loadCookie": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "loadCookie", - "description": "Load a specific cookie from a file or environment variable into the browser.", - "anyOf": [ - { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - } - }, - "examples": [ - "session_token", - "./test-data/auth-session.txt", - "test_env_cookie", - { - "name": "auth_cookie", - "variable": "AUTH_COOKIE" - }, - { - "name": "test_cookie", - "path": "test-cookie.txt" - }, - { - "name": "session_token", - "path": "session-token.txt", - "directory": "./test-data" - }, - { - "name": "user_session", - "path": "saved-cookies.txt", - "domain": "app.example.com" - } - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "wait", - "type": "object", - "required": [ - "wait" - ], - "properties": { - "wait": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "wait", - "description": "Pause (in milliseconds) before performing the next action.", - "default": 5000, - "anyOf": [ - { - "type": "number", - "title": "Wait (simple)" - }, - { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "boolean", - "title": "Wait (boolean)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - } - } - }, - "examples": [ - 5000, - "$WAIT_DURATION", - true - ] - } - } - } - ] - } - ], - "examples": [ - { - "stepId": "uuid", - "description": "Description of the step.", - "checkLink": "https://www.google.com", - "outputs": { - "outputKey": "outputValue" - }, - "variables": { - "variableKey": "variableValue" - } - }, - { - "checkLink": "https://www.google.com" - }, - { - "stepId": "path-only", - "checkLink": "/search" - }, - { - "stepId": "status-code", - "checkLink": { - "url": "https://www.google.com", - "statusCodes": [ - 200 - ] - } - }, - { - "goTo": { - "url": "https://www.google.com" - } - }, - { - "goTo": "https://www.google.com" - }, - { - "wait": 5000 - }, - { - "runCode": { - "language": "python", - "code": "print('Hello from Python')", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Python!", - "path": "python-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - }, - { - "stopRecord": true - }, - { - "screenshot": true - }, - { - "screenshot": "image.png" - }, - { - "screenshot": "static/images/image.png" - }, - { - "screenshot": "/User/manny/projects/doc-detective/static/images/image.png" - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": "#elementToScreenshot" - } - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "padding": { - "top": 0, - "right": 0, - "bottom": 0, - "left": 0 - } - } - } - }, - { - "record": true - }, - { - "record": "video.mp4" - }, - { - "record": "static/media/video.mp4" - }, - { - "record": "/User/manny/projects/doc-detective/static/media/video.mp4" - }, - { - "record": { - "path": "video.mp4", - "directory": "static/media", - "overwrite": true - } - }, - { - "loadVariables": "variables.env" - }, - { - "saveCookie": "session_token" - }, - { - "saveCookie": { - "name": "auth_cookie", - "path": "auth-session.txt", - "directory": "./test-data", - "overwrite": true - } - }, - { - "loadCookie": "session_token" - }, - { - "loadCookie": { - "name": "auth_cookie", - "path": "auth-session.txt", - "directory": "./test-data" - } - }, - { - "find": "Find me!" - }, - { - "find": { - "selector": "[title=Search]" - } - }, - { - "find": { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": "shorthair cat" - } - }, - { - "find": { - "selector": "[title=Search]", - "click": { - "button": "right" - } - } - }, - { - "find": { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": { - "keys": [ - "shorthair cat" - ], - "inputDelay": 100 - } - } - }, - { - "click": true - }, - { - "click": "right" - }, - { - "click": { - "button": "left", - "elementText": "Element text" - } - }, - { - "click": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - }, - { - "httpRequest": "https://reqres.in/api/users" - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users" - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users/2", - "method": "put", - "request": { - "body": { - "name": "morpheus", - "job": "zion resident" - } - } - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ] - } - }, - { - "httpRequest": { - "url": "https://www.api-server.com", - "method": "post", - "timeout": 30000, - "request": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - }, - "parameters": { - "param": "value" - } - }, - "response": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - } - }, - "statusCodes": [ - 200 - ] - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ], - "path": "response.json", - "directory": "media", - "maxVariation": 0.05, - "overwrite": "aboveVariation" - } - }, - { - "httpRequest": { - "openApi": "getUserById" - } - }, - { - "httpRequest": { - "openApi": { - "name": "Reqres", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme" - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme", - "headers": { - "Authorization": "Bearer $TOKEN" - } - } - } - }, - { - "stepId": "breakpoint-example", - "description": "Step with breakpoint enabled", - "goTo": "https://www.example.com", - "breakpoint": true - }, - { - "checkLink": "https://www.google.com", - "breakpoint": false - }, - { - "dragAndDrop": { - "source": { - "selector": "#sourceElement" - }, - "target": { - "selector": "#targetElement" - } - } - } - ] - } - ] - } - } - ] - } - }, - "title": "Markup definition" - }, - "markupActionString": { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - "inlineStatements": { - "description": "Statements to include tests and steps inside the content of the file, such as within Markdown.", - "type": "object", - "properties": { - "testStart": { - "description": "Regular expressions that indicate the start of a test. If capture groups are used, the first capture group is used for the statement. If no capture groups are used, the entire match is used for the statement.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "testEnd": { - "description": "Regular expressions that indicate that the current test is complete.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "ignoreStart": { - "description": "Regular expressions that indicates that the following content should be ignored for testing purposes.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "ignoreEnd": { - "description": "Regular expressions that indicate that the ignored section of content is complete.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "step": { - "description": "Regular expressions that indicate a step in a test.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - } - }, - "title": "Inline statement definition" - }, - "stringOrArray": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - } - }, "examples": [ {}, { diff --git a/common/dist/schemas/context_v3.schema.json b/common/dist/schemas/context_v3.schema.json index 3a080b5..88e2b3a 100644 --- a/common/dist/schemas/context_v3.schema.json +++ b/common/dist/schemas/context_v3.schema.json @@ -196,88 +196,6 @@ ] } }, - "components": { - "schemas": { - "platform": { - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - }, - "browserName": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "browser": { - "type": "object", - "description": "Browser configuration.", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "headless": { - "type": "boolean", - "description": "If `true`, runs the browser in headless mode.", - "default": true - }, - "window": { - "type": "object", - "description": "Browser dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the browser window in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the browser window in pixels." - } - }, - "title": "Browser Window" - }, - "viewport": { - "type": "object", - "description": "Viewport dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the viewport in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the viewport in pixels." - } - }, - "title": "Browser Viewport" - } - }, - "title": "Browser" - } - } - }, "examples": [ { "platforms": "linux", diff --git a/common/dist/schemas/dragAndDrop_v3.schema.json b/common/dist/schemas/dragAndDrop_v3.schema.json index ced06e3..295db77 100644 --- a/common/dist/schemas/dragAndDrop_v3.schema.json +++ b/common/dist/schemas/dragAndDrop_v3.schema.json @@ -233,222 +233,6 @@ "minimum": 0 } }, - "components": { - "schemas": { - "elementSpecification": { - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "string": { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - "object": { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - } - }, "examples": [ { "source": "Table", diff --git a/common/dist/schemas/find_v3.schema.json b/common/dist/schemas/find_v3.schema.json index 4f4aea6..abdfbb1 100644 --- a/common/dist/schemas/find_v3.schema.json +++ b/common/dist/schemas/find_v3.schema.json @@ -650,656 +650,6 @@ } } ], - "components": { - "schemas": { - "string": { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "object": { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - } - }, "examples": [ "Find me!", { diff --git a/common/dist/schemas/goTo_v3.schema.json b/common/dist/schemas/goTo_v3.schema.json index 4b3378c..efa7488 100644 --- a/common/dist/schemas/goTo_v3.schema.json +++ b/common/dist/schemas/goTo_v3.schema.json @@ -172,179 +172,6 @@ "title": "Go to URL (detailed)" } ], - "components": { - "schemas": { - "string": { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - } - }, "examples": [ "https://www.google.com", "/search", diff --git a/common/dist/schemas/httpRequest_v3.schema.json b/common/dist/schemas/httpRequest_v3.schema.json index 20ae01d..26e96fa 100644 --- a/common/dist/schemas/httpRequest_v3.schema.json +++ b/common/dist/schemas/httpRequest_v3.schema.json @@ -400,406 +400,6 @@ } } ], - "components": { - "schemas": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - } - }, "examples": [ "https://reqres.in/api/users", { diff --git a/common/dist/schemas/loadCookie_v3.schema.json b/common/dist/schemas/loadCookie_v3.schema.json index 98c6ae2..39a292a 100644 --- a/common/dist/schemas/loadCookie_v3.schema.json +++ b/common/dist/schemas/loadCookie_v3.schema.json @@ -101,107 +101,6 @@ "title": "Load cookie (detailed)" } ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - } - }, "examples": [ "session_token", "./test-data/auth-session.txt", diff --git a/common/dist/schemas/openApi_v3.schema.json b/common/dist/schemas/openApi_v3.schema.json index bf4f847..d2c7cf9 100644 --- a/common/dist/schemas/openApi_v3.schema.json +++ b/common/dist/schemas/openApi_v3.schema.json @@ -87,18 +87,6 @@ "title": "OpenAPI request headers" } }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, "examples": [ { "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" diff --git a/common/dist/schemas/record_v3.schema.json b/common/dist/schemas/record_v3.schema.json index 1026028..c00159e 100644 --- a/common/dist/schemas/record_v3.schema.json +++ b/common/dist/schemas/record_v3.schema.json @@ -47,48 +47,6 @@ "description": "If `true`, records the current browser viewport. If `false`, doesn't record the current browser viewport." } ], - "components": { - "schemas": { - "string": { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - } - } - }, "examples": [ true, "results.mp4", diff --git a/common/dist/schemas/report_v3.schema.json b/common/dist/schemas/report_v3.schema.json index 4d0f1ce..86137f0 100644 --- a/common/dist/schemas/report_v3.schema.json +++ b/common/dist/schemas/report_v3.schema.json @@ -6245,6 +6245,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6425,6 +6429,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6476,6 +6484,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6651,8 +6662,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6669,7 +6690,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6832,6 +6853,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6883,6 +6908,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7058,8 +7086,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7076,7 +7114,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7608,6 +7646,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7788,6 +7830,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7839,6 +7885,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8014,8 +8063,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8032,7 +8091,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -8195,6 +8254,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -8246,6 +8309,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8421,8 +8487,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8439,7 +8515,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16106,6 +16182,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -16286,6 +16366,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16337,6 +16421,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16512,8 +16599,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16530,7 +16627,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16693,6 +16790,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16744,6 +16845,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16919,8 +17023,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16937,7 +17051,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17469,6 +17583,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17649,6 +17767,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17700,6 +17822,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17875,8 +18000,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17893,7 +18028,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -18056,6 +18191,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -18107,6 +18246,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -18282,8 +18424,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -18300,7 +18452,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/dist/schemas/resolvedTests_v3.schema.json b/common/dist/schemas/resolvedTests_v3.schema.json index 7081445..8e1e1c3 100644 --- a/common/dist/schemas/resolvedTests_v3.schema.json +++ b/common/dist/schemas/resolvedTests_v3.schema.json @@ -5825,6 +5825,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6005,6 +6009,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6056,6 +6064,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6231,8 +6242,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6249,7 +6270,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6412,6 +6433,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6463,6 +6488,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6638,8 +6666,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6656,7 +6694,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7188,6 +7226,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7368,6 +7410,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7419,6 +7465,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7594,8 +7643,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7612,7 +7671,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7775,6 +7834,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7826,6 +7889,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8001,8 +8067,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8019,7 +8095,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16117,6 +16193,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -16297,6 +16377,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16348,6 +16432,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16523,8 +16610,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16541,7 +16638,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16704,6 +16801,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16755,6 +16856,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16930,8 +17034,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16948,7 +17062,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17480,6 +17594,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17660,6 +17778,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17711,6 +17833,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17886,8 +18011,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17904,7 +18039,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -18067,6 +18202,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -18118,6 +18257,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -18293,8 +18435,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -18311,7 +18463,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -27178,6 +27330,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -27358,6 +27514,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -27409,6 +27569,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -27584,8 +27747,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -27602,7 +27775,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -27765,6 +27938,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -27816,6 +27993,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -27991,8 +28171,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -28009,7 +28199,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -28541,6 +28731,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -28721,6 +28915,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -28772,6 +28970,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -28947,8 +29148,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -28965,7 +29176,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -29128,6 +29339,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -29179,6 +29394,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -29354,8 +29572,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -29372,7 +29600,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -37039,6 +37267,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -37219,6 +37451,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -37270,6 +37506,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -37445,8 +37684,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -37463,7 +37712,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -37626,6 +37875,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -37677,6 +37930,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -37852,8 +38108,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -37870,7 +38136,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -38402,6 +38668,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -38582,6 +38852,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -38633,6 +38907,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -38808,8 +39085,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -38826,7 +39113,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -38989,6 +39276,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -39040,6 +39331,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -39215,8 +39509,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -39233,7 +39537,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/dist/schemas/runCode_v3.schema.json b/common/dist/schemas/runCode_v3.schema.json index 23899a5..e3be439 100644 --- a/common/dist/schemas/runCode_v3.schema.json +++ b/common/dist/schemas/runCode_v3.schema.json @@ -92,98 +92,6 @@ "title": "Run code (detailed)" } ], - "components": { - "schemas": { - "object": { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - } - }, "examples": [ { "language": "javascript", diff --git a/common/dist/schemas/runShell_v3.schema.json b/common/dist/schemas/runShell_v3.schema.json index a65de4f..dc0465b 100644 --- a/common/dist/schemas/runShell_v3.schema.json +++ b/common/dist/schemas/runShell_v3.schema.json @@ -91,97 +91,6 @@ "title": "Run shell command (detailed)" } ], - "components": { - "schemas": { - "string": { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - } - }, "examples": [ "docker run hello-world", { diff --git a/common/dist/schemas/saveCookie_v3.schema.json b/common/dist/schemas/saveCookie_v3.schema.json index 96f8565..c4f112f 100644 --- a/common/dist/schemas/saveCookie_v3.schema.json +++ b/common/dist/schemas/saveCookie_v3.schema.json @@ -107,113 +107,6 @@ "title": "Save cookie (detailed)" } ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - } - }, "examples": [ "session_token", "test_env_cookie", diff --git a/common/dist/schemas/screenshot_v3.schema.json b/common/dist/schemas/screenshot_v3.schema.json index e9b641f..996a656 100644 --- a/common/dist/schemas/screenshot_v3.schema.json +++ b/common/dist/schemas/screenshot_v3.schema.json @@ -415,6 +415,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -595,6 +599,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -646,6 +654,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -821,8 +832,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -839,7 +860,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -1002,6 +1023,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -1053,6 +1078,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -1228,8 +1256,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -1246,7 +1284,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -1364,1519 +1402,6 @@ "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." } ], - "components": { - "schemas": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - "crop_element": { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - } - }, "examples": [ true, "image.png", diff --git a/common/dist/schemas/spec_v3.schema.json b/common/dist/schemas/spec_v3.schema.json index 3302ef8..1cd7367 100644 --- a/common/dist/schemas/spec_v3.schema.json +++ b/common/dist/schemas/spec_v3.schema.json @@ -6227,6 +6227,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6407,6 +6411,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6458,6 +6466,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6633,8 +6644,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6651,7 +6672,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6814,6 +6835,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6865,6 +6890,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7040,8 +7068,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7058,7 +7096,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7590,6 +7628,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7770,6 +7812,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7821,6 +7867,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7996,8 +8045,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8014,7 +8073,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -8177,6 +8236,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -8228,6 +8291,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8403,8 +8469,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8421,7 +8497,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16088,6 +16164,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -16268,6 +16348,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16319,6 +16403,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16494,8 +16581,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16512,7 +16609,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16675,6 +16772,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16726,6 +16827,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16901,8 +17005,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16919,7 +17033,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17451,6 +17565,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17631,6 +17749,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17682,6 +17804,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17857,8 +17982,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17875,7 +18010,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -18038,6 +18173,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -18089,6 +18228,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -18264,8 +18406,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -18282,7 +18434,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/dist/schemas/step_v3.schema.json b/common/dist/schemas/step_v3.schema.json index 7cb3291..da1f359 100644 --- a/common/dist/schemas/step_v3.schema.json +++ b/common/dist/schemas/step_v3.schema.json @@ -3,117 +3,6 @@ "title": "step", "description": "A step in a test.", "type": "object", - "components": { - "schemas": { - "common": { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - } - }, "anyOf": [ { "allOf": [ @@ -5027,6 +4916,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -5207,6 +5100,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -5258,6 +5155,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -5433,8 +5333,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -5451,7 +5361,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -5614,6 +5524,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -5665,6 +5579,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -5840,8 +5757,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -5858,7 +5785,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6390,6 +6317,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6570,6 +6501,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6621,6 +6556,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6796,8 +6734,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6814,7 +6762,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6977,6 +6925,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7028,6 +6980,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7203,8 +7158,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7221,7 +7186,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/dist/schemas/test_v3.schema.json b/common/dist/schemas/test_v3.schema.json index b7e04da..9e37067 100644 --- a/common/dist/schemas/test_v3.schema.json +++ b/common/dist/schemas/test_v3.schema.json @@ -5626,6 +5626,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -5806,6 +5810,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -5857,6 +5865,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6032,8 +6043,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6050,7 +6071,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6213,6 +6234,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6264,6 +6289,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6439,8 +6467,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6457,7 +6495,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6989,6 +7027,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7169,6 +7211,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7220,6 +7266,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7395,8 +7444,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7413,7 +7472,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7576,6 +7635,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7627,6 +7690,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7802,8 +7868,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7820,7 +7896,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -15487,6 +15563,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -15667,6 +15747,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -15718,6 +15802,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -15893,8 +15980,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -15911,7 +16008,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16074,6 +16171,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16125,6 +16226,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16300,8 +16404,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16318,7 +16432,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16850,6 +16964,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17030,6 +17148,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17081,6 +17203,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17256,8 +17381,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17274,7 +17409,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17437,6 +17572,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17488,6 +17627,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17663,8 +17805,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17681,7 +17833,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -20083,192 +20235,6 @@ } ], "additionalProperties": false, - "components": { - "schemas": { - "openApi": { - "type": "array", - "items": { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "not": { - "required": [ - "operationId" - ] - }, - "required": [ - "name", - "descriptionPath" - ], - "title": "OpenAPI description (test)" - } - ] - } - } - } - }, "examples": [ { "steps": [ diff --git a/common/dist/schemas/type_v3.schema.json b/common/dist/schemas/type_v3.schema.json index 566eda5..684a4bf 100644 --- a/common/dist/schemas/type_v3.schema.json +++ b/common/dist/schemas/type_v3.schema.json @@ -108,114 +108,6 @@ "additionalProperties": false } ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, "examples": [ "kittens", [ diff --git a/common/dist/schemas/wait_v3.schema.json b/common/dist/schemas/wait_v3.schema.json index 0374d01..014333a 100644 --- a/common/dist/schemas/wait_v3.schema.json +++ b/common/dist/schemas/wait_v3.schema.json @@ -21,18 +21,6 @@ "title": "Wait (boolean)" } ], - "components": { - "schemas": { - "string": { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - } - } - }, "examples": [ 5000, "$WAIT_DURATION", diff --git a/common/src/schemas/dereferenceSchemas.js b/common/src/schemas/dereferenceSchemas.js index 485d734..e530104 100644 --- a/common/src/schemas/dereferenceSchemas.js +++ b/common/src/schemas/dereferenceSchemas.js @@ -117,6 +117,8 @@ async function dereferenceSchemas() { schema = await parser.dereference(schema); // Delete $id attributes schema = deleteDollarIds(schema); + // Delete components section (no longer needed after dereferencing) + schema = deleteComponents(schema); // Write to file fs.writeFileSync(outputFilePath, JSON.stringify(schema, null, 2)); @@ -204,3 +206,18 @@ function deleteDollarIds(schema) { } return schema; } + +/** + * Removes the `components` property from a dereferenced JSON schema object. + * After dereferencing, the components section contains unreferenced definitions + * and can be safely removed to reduce schema size. + * + * @param {object} schema - The dereferenced JSON schema object to process. + * @returns {object} The schema object with the `components` property deleted. + */ +function deleteComponents(schema) { + if (schema && typeof schema === "object" && schema.components) { + delete schema.components; + } + return schema; +} diff --git a/common/src/schemas/output_schemas/annotation_v3.schema.json b/common/src/schemas/output_schemas/annotation_v3.schema.json index ecf576e..1a69643 100644 --- a/common/src/schemas/output_schemas/annotation_v3.schema.json +++ b/common/src/schemas/output_schemas/annotation_v3.schema.json @@ -222,6 +222,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -402,6 +406,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -453,6 +461,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -628,8 +639,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -646,7 +667,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -667,454 +688,6 @@ } } }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, "examples": [ { "find": { diff --git a/common/src/schemas/output_schemas/checkLink_v3.schema.json b/common/src/schemas/output_schemas/checkLink_v3.schema.json index ba4b15d..e4aee34 100644 --- a/common/src/schemas/output_schemas/checkLink_v3.schema.json +++ b/common/src/schemas/output_schemas/checkLink_v3.schema.json @@ -63,70 +63,6 @@ } } ], - "components": { - "schemas": { - "string": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - } - }, "examples": [ "https://www.google.com", "/search", diff --git a/common/src/schemas/output_schemas/click_v3.schema.json b/common/src/schemas/output_schemas/click_v3.schema.json index 7c62e4f..eef79c3 100644 --- a/common/src/schemas/output_schemas/click_v3.schema.json +++ b/common/src/schemas/output_schemas/click_v3.schema.json @@ -115,127 +115,6 @@ "type": "boolean" } ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, "examples": [ true, "right", diff --git a/common/src/schemas/output_schemas/config_v3.schema.json b/common/src/schemas/output_schemas/config_v3.schema.json index f828ad5..6b10a7f 100644 --- a/common/src/schemas/output_schemas/config_v3.schema.json +++ b/common/src/schemas/output_schemas/config_v3.schema.json @@ -5812,6 +5812,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -5992,6 +5996,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6043,6 +6051,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6218,8 +6229,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6236,7 +6257,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6399,6 +6420,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6450,6 +6475,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6625,8 +6653,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6643,7 +6681,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7175,6 +7213,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7355,6 +7397,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7406,6 +7452,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7581,8 +7630,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7599,7 +7658,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7762,6 +7821,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7813,6 +7876,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7988,8 +8054,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8006,7 +8082,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -10960,9870 +11036,6 @@ "default": false } }, - "components": { - "schemas": { - "environment": { - "type": "object", - "description": "Environment information for the system running Doc Detective.", - "readOnly": true, - "additionalProperties": false, - "required": [ - "platform" - ], - "properties": { - "workingDirectory": { - "description": "The current working directory of the process running Doc Detective.", - "type": "string" - }, - "platform": { - "description": "The operating system type running Doc Detective.", - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - }, - "arch": { - "description": "The processor architecture of the system running Doc Detective.", - "type": "string", - "enum": [ - "arm32", - "arm64", - "x32", - "x64" - ] - } - }, - "title": "Environment details" - }, - "markupDefinition": { - "type": "object", - "properties": { - "name": { - "description": "Name of the markup definition", - "type": "string" - }, - "regex": { - "description": "Regular expressions to match the markup type.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "batchMatches": { - "description": "If `true`, all matches are combined into a single string.", - "type": "boolean", - "default": false - }, - "actions": { - "description": "Actions to perform when the markup type is detected.", - "anyOf": [ - { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "step", - "description": "A step in a test.", - "type": "object", - "components": { - "schemas": { - "common": { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - } - }, - "anyOf": [ - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "checkLink" - ], - "properties": { - "checkLink": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "checkLink", - "anyOf": [ - { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - ], - "components": { - "schemas": { - "string": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - } - }, - "examples": [ - "https://www.google.com", - "/search", - { - "url": "https://www.google.com", - "statusCodes": 200 - }, - { - "url": "/search", - "origin": "www.google.com", - "statusCodes": [ - 200 - ] - } - ] - } - }, - "title": "checkLink" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "click" - ], - "properties": { - "click": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - } - }, - "title": "click" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "find" - ], - "properties": { - "find": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "find", - "description": "Find an element based on display text or a selector, then optionally interact with it.", - "anyOf": [ - { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - ], - "components": { - "schemas": { - "string": { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "object": { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - } - }, - "examples": [ - "Find me!", - { - "selector": "[title=Search]" - }, - { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": "shorthair cat" - }, - { - "selector": "[title=Search]", - "click": { - "button": "right" - } - }, - { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": { - "keys": [ - "shorthair cat" - ], - "inputDelay": 100 - } - }, - { - "elementId": "/^user-[0-9]+$/", - "elementClass": [ - "admin", - "/^level-[1-5]$/" - ], - "elementAttribute": { - "data-active": true, - "data-score": "/^[0-9]+$/" - }, - "timeout": 8000, - "moveTo": false - } - ] - } - }, - "title": "find" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "goTo" - ], - "properties": { - "goTo": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "goTo", - "anyOf": [ - { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - } - }, - "examples": [ - "https://www.google.com", - "/search", - { - "url": "https://www.google.com" - }, - { - "url": "/search", - "origin": "https://www.google.com" - }, - { - "url": "https://www.example.com", - "waitUntil": { - "networkIdleTime": 500 - } - }, - { - "url": "https://www.example.com/dashboard", - "waitUntil": { - "find": { - "selector": "[data-testid='dashboard-loaded']" - } - } - }, - { - "url": "https://www.example.com/app", - "timeout": 60000, - "waitUntil": { - "networkIdleTime": 500, - "domIdleTime": 1000, - "find": { - "selector": ".main-content", - "elementText": "Dashboard" - } - } - }, - { - "url": "https://www.example.com/app", - "timeout": 60000, - "waitUntil": { - "networkIdleTime": null - } - }, - { - "url": "https://www.example.com/status", - "waitUntil": { - "find": { - "elementText": "System operational" - } - } - }, - { - "url": "http://localhost:8092", - "waitUntil": { - "find": { - "selector": "button", - "elementText": "Standard Button", - "elementTestId": "standard-btn", - "elementAria": "Sample Standard Button", - "elementId": "standard-btn", - "elementClass": [ - "btn" - ], - "elementAttribute": { - "type": "button", - "value": "Standard Button" - } - } - } - } - ] - } - }, - "title": "goTo" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "httpRequest" - ], - "properties": { - "httpRequest": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "httpRequest", - "description": "Perform a generic HTTP request, for example to an API.", - "anyOf": [ - { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - ], - "components": { - "schemas": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - } - }, - "examples": [ - "https://reqres.in/api/users", - { - "url": "https://reqres.in/api/users" - }, - { - "url": "https://reqres.in/api/users/2", - "method": "put", - "request": { - "body": { - "name": "morpheus", - "job": "zion resident" - } - } - }, - { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ] - }, - { - "url": "https://www.api-server.com", - "method": "post", - "timeout": 30000, - "request": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - }, - "parameters": { - "param": "value" - } - }, - "response": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - } - }, - "statusCodes": [ - 200 - ] - }, - { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ], - "path": "response.json", - "directory": "media", - "maxVariation": 0.05, - "overwrite": "aboveVariation" - }, - { - "openApi": "getUserById" - }, - { - "openApi": { - "name": "Reqres", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme" - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme", - "headers": { - "Authorization": "Bearer $TOKEN" - } - } - }, - { - "url": "https://www.api-server.com", - "method": "post", - "request": { - "headers": "Content-Type: application/json\\nAuthorization: Bearer token" - } - }, - { - "url": "https://api.example.com/users/123", - "response": { - "required": [ - "id", - "email", - "createdAt" - ] - } - }, - { - "url": "https://api.example.com/users/123", - "response": { - "required": [ - "user.profile.name", - "user.profile.avatar", - "user.settings.notifications" - ] - } - }, - { - "url": "https://api.example.com/orders", - "response": { - "required": [ - "orders[0].id", - "orders[0].total", - "orders[0].items[0].productId" - ] - } - }, - { - "url": "https://api.example.com/users", - "response": { - "required": [ - "sessionToken", - "expiresAt", - "user.id" - ], - "body": { - "status": "success", - "user": { - "role": "admin" - } - } - } - } - ] - } - }, - "title": "httpRequest" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "runShell" - ], - "properties": { - "runShell": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "runShell", - "description": "Perform a native shell command.", - "anyOf": [ - { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - } - }, - "examples": [ - "docker run hello-world", - { - "command": "echo", - "args": [ - "$USER" - ] - }, - { - "command": "echo", - "args": [ - "hello-world" - ] - }, - { - "command": "docker run hello-world", - "timeout": 20000, - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!" - }, - { - "command": "false", - "exitCodes": [ - 1 - ] - }, - { - "command": "echo", - "args": [ - "setup" - ], - "exitCodes": [ - 0 - ], - "stdio": "/.*?/" - }, - { - "command": "docker run hello-world", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!", - "path": "docker-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - ] - } - }, - "title": "runShell" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "runCode" - ], - "properties": { - "runCode": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "runCode", - "description": "Assemble and run code.", - "anyOf": [ - { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - ], - "components": { - "schemas": { - "object": { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - } - }, - "examples": [ - { - "language": "javascript", - "code": "console.log('Hello, ${process.env.USER}!');" - }, - { - "language": "bash", - "code": "docker run hello-world", - "timeout": 20000, - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!" - }, - { - "language": "javascript", - "code": "return false", - "exitCodes": [ - 1 - ] - }, - { - "language": "python", - "code": "print('Hello from Python')", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Python!", - "path": "python-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - ] - } - }, - "title": "runCode" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - } - }, - "title": "type" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "screenshot" - ], - "properties": { - "screenshot": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "screenshot", - "description": "Takes a screenshot in PNG format.", - "anyOf": [ - { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - { - "type": "boolean", - "title": "Capture screenshot", - "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." - } - ], - "components": { - "schemas": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - "crop_element": { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - } - }, - "examples": [ - true, - "image.png", - "static/images/image.png", - "/User/manny/projects/doc-detective/static/images/image.png", - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": "#elementToScreenshot" - }, - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - }, - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "padding": { - "top": 0, - "right": 0, - "bottom": 0, - "left": 0 - } - } - }, - { - "path": "image.png", - "annotations": [ - { - "find": { - "selector": "#usernameField" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#FF0000", - "strokeWidth": 4, - "headSize": 10 - } - }, - { - "find": { - "elementText": "Username", - "elementClass": [ - "input-field", - "/^user-/" - ] - }, - "text": { - "content": "Enter your username here", - "fontSize": 14, - "color": "#0000FF", - "backgroundColor": "#FFFFFF", - "padding": 5 - } - }, - { - "rectangle": { - "x": 100, - "y": 150, - "width": 200, - "height": 100, - "borderColor": "#00FF00", - "borderWidth": 3, - "fillColor": "rgba(0, 255, 0, 0.2)" - } - } - ] - } - ] - } - }, - "title": "screenshot" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "saveCookie" - ], - "properties": { - "saveCookie": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "saveCookie", - "description": "Save a specific browser cookie to a file or environment variable for later reuse.", - "anyOf": [ - { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - } - }, - "examples": [ - "session_token", - "test_env_cookie", - { - "name": "auth_cookie", - "path": "auth-cookie.txt" - }, - { - "name": "session_token", - "variable": "SESSION_TOKEN" - }, - { - "name": "test_cookie", - "path": "test-cookie.txt", - "overwrite": true - }, - { - "name": "user_session", - "path": "user-session.txt", - "directory": "./test-data", - "overwrite": true - }, - { - "name": "login_token", - "path": "login-token.txt", - "domain": "app.example.com" - } - ] - } - }, - "title": "saveCookie" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "record" - ], - "properties": { - "record": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "record", - "description": "Start recording the current browser viewport. Must be followed by a `stopRecord` step. Only runs in Chrome browsers when they are visible. Supported extensions: [ '.mp4', '.webm', '.gif' ]", - "anyOf": [ - { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - }, - { - "type": "boolean", - "title": "Record (boolean)", - "description": "If `true`, records the current browser viewport. If `false`, doesn't record the current browser viewport." - } - ], - "components": { - "schemas": { - "string": { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - } - } - }, - "examples": [ - true, - "results.mp4", - { - "path": "results.mp4", - "directory": "static/media", - "overwrite": "true" - } - ] - } - }, - "title": "record" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "stopRecord" - ], - "properties": { - "stopRecord": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "stopRecord", - "description": "Stop the current recording.", - "anyOf": [ - { - "type": "boolean", - "nullable": true - } - ], - "examples": [ - true - ] - } - }, - "title": "stopRecord" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "loadVariables", - "type": "object", - "required": [ - "loadVariables" - ], - "properties": { - "loadVariables": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "loadVariables", - "type": "string", - "description": "Load environment variables from the specified `.env` file.", - "examples": [ - ".env" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "dragAndDrop", - "type": "object", - "required": [ - "dragAndDrop" - ], - "properties": { - "dragAndDrop": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "dragAndDrop", - "description": "Drag and drop an element from source to target.", - "type": "object", - "required": [ - "source", - "target" - ], - "properties": { - "source": { - "description": "The element to drag.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "target": { - "description": "The target location to drop the element.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "duration": { - "type": "integer", - "description": "Duration of the drag operation in milliseconds.", - "default": 1000, - "minimum": 0 - } - }, - "components": { - "schemas": { - "elementSpecification": { - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "string": { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - "object": { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - } - }, - "examples": [ - { - "source": "Table", - "target": "#canvas" - }, - { - "source": ".draggable-block", - "target": ".drop-zone", - "duration": 2000 - }, - { - "source": { - "selector": ".widget", - "elementText": "Data Table" - }, - "target": { - "selector": "#design-canvas" - }, - "duration": 500 - }, - { - "source": { - "selector": ".draggable", - "timeout": 10000 - }, - "target": { - "elementText": "Drop Zone", - "timeout": 5000 - } - }, - { - "source": "/Widget Item.*/", - "target": "#canvas" - }, - { - "source": { - "selector": ".draggable", - "elementText": "/Button [0-9]+/" - }, - "target": { - "elementText": "/Drop Zone.*/" - } - } - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "loadCookie", - "type": "object", - "required": [ - "loadCookie" - ], - "properties": { - "loadCookie": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "loadCookie", - "description": "Load a specific cookie from a file or environment variable into the browser.", - "anyOf": [ - { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - } - }, - "examples": [ - "session_token", - "./test-data/auth-session.txt", - "test_env_cookie", - { - "name": "auth_cookie", - "variable": "AUTH_COOKIE" - }, - { - "name": "test_cookie", - "path": "test-cookie.txt" - }, - { - "name": "session_token", - "path": "session-token.txt", - "directory": "./test-data" - }, - { - "name": "user_session", - "path": "saved-cookies.txt", - "domain": "app.example.com" - } - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "wait", - "type": "object", - "required": [ - "wait" - ], - "properties": { - "wait": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "wait", - "description": "Pause (in milliseconds) before performing the next action.", - "default": 5000, - "anyOf": [ - { - "type": "number", - "title": "Wait (simple)" - }, - { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "boolean", - "title": "Wait (boolean)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - } - } - }, - "examples": [ - 5000, - "$WAIT_DURATION", - true - ] - } - } - } - ] - } - ], - "examples": [ - { - "stepId": "uuid", - "description": "Description of the step.", - "checkLink": "https://www.google.com", - "outputs": { - "outputKey": "outputValue" - }, - "variables": { - "variableKey": "variableValue" - } - }, - { - "checkLink": "https://www.google.com" - }, - { - "stepId": "path-only", - "checkLink": "/search" - }, - { - "stepId": "status-code", - "checkLink": { - "url": "https://www.google.com", - "statusCodes": [ - 200 - ] - } - }, - { - "goTo": { - "url": "https://www.google.com" - } - }, - { - "goTo": "https://www.google.com" - }, - { - "wait": 5000 - }, - { - "runCode": { - "language": "python", - "code": "print('Hello from Python')", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Python!", - "path": "python-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - }, - { - "stopRecord": true - }, - { - "screenshot": true - }, - { - "screenshot": "image.png" - }, - { - "screenshot": "static/images/image.png" - }, - { - "screenshot": "/User/manny/projects/doc-detective/static/images/image.png" - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": "#elementToScreenshot" - } - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "padding": { - "top": 0, - "right": 0, - "bottom": 0, - "left": 0 - } - } - } - }, - { - "record": true - }, - { - "record": "video.mp4" - }, - { - "record": "static/media/video.mp4" - }, - { - "record": "/User/manny/projects/doc-detective/static/media/video.mp4" - }, - { - "record": { - "path": "video.mp4", - "directory": "static/media", - "overwrite": true - } - }, - { - "loadVariables": "variables.env" - }, - { - "saveCookie": "session_token" - }, - { - "saveCookie": { - "name": "auth_cookie", - "path": "auth-session.txt", - "directory": "./test-data", - "overwrite": true - } - }, - { - "loadCookie": "session_token" - }, - { - "loadCookie": { - "name": "auth_cookie", - "path": "auth-session.txt", - "directory": "./test-data" - } - }, - { - "find": "Find me!" - }, - { - "find": { - "selector": "[title=Search]" - } - }, - { - "find": { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": "shorthair cat" - } - }, - { - "find": { - "selector": "[title=Search]", - "click": { - "button": "right" - } - } - }, - { - "find": { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": { - "keys": [ - "shorthair cat" - ], - "inputDelay": 100 - } - } - }, - { - "click": true - }, - { - "click": "right" - }, - { - "click": { - "button": "left", - "elementText": "Element text" - } - }, - { - "click": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - }, - { - "httpRequest": "https://reqres.in/api/users" - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users" - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users/2", - "method": "put", - "request": { - "body": { - "name": "morpheus", - "job": "zion resident" - } - } - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ] - } - }, - { - "httpRequest": { - "url": "https://www.api-server.com", - "method": "post", - "timeout": 30000, - "request": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - }, - "parameters": { - "param": "value" - } - }, - "response": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - } - }, - "statusCodes": [ - 200 - ] - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ], - "path": "response.json", - "directory": "media", - "maxVariation": 0.05, - "overwrite": "aboveVariation" - } - }, - { - "httpRequest": { - "openApi": "getUserById" - } - }, - { - "httpRequest": { - "openApi": { - "name": "Reqres", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme" - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme", - "headers": { - "Authorization": "Bearer $TOKEN" - } - } - } - }, - { - "stepId": "breakpoint-example", - "description": "Step with breakpoint enabled", - "goTo": "https://www.example.com", - "breakpoint": true - }, - { - "checkLink": "https://www.google.com", - "breakpoint": false - }, - { - "dragAndDrop": { - "source": { - "selector": "#sourceElement" - }, - "target": { - "selector": "#targetElement" - } - } - } - ] - } - ] - } - } - ] - } - }, - "title": "Markup definition" - }, - "markupActionString": { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - "inlineStatements": { - "description": "Statements to include tests and steps inside the content of the file, such as within Markdown.", - "type": "object", - "properties": { - "testStart": { - "description": "Regular expressions that indicate the start of a test. If capture groups are used, the first capture group is used for the statement. If no capture groups are used, the entire match is used for the statement.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "testEnd": { - "description": "Regular expressions that indicate that the current test is complete.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "ignoreStart": { - "description": "Regular expressions that indicates that the following content should be ignored for testing purposes.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "ignoreEnd": { - "description": "Regular expressions that indicate that the ignored section of content is complete.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "step": { - "description": "Regular expressions that indicate a step in a test.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - } - }, - "title": "Inline statement definition" - }, - "stringOrArray": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - } - }, "examples": [ {}, { diff --git a/common/src/schemas/output_schemas/context_v3.schema.json b/common/src/schemas/output_schemas/context_v3.schema.json index 3a080b5..88e2b3a 100644 --- a/common/src/schemas/output_schemas/context_v3.schema.json +++ b/common/src/schemas/output_schemas/context_v3.schema.json @@ -196,88 +196,6 @@ ] } }, - "components": { - "schemas": { - "platform": { - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - }, - "browserName": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "browser": { - "type": "object", - "description": "Browser configuration.", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "headless": { - "type": "boolean", - "description": "If `true`, runs the browser in headless mode.", - "default": true - }, - "window": { - "type": "object", - "description": "Browser dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the browser window in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the browser window in pixels." - } - }, - "title": "Browser Window" - }, - "viewport": { - "type": "object", - "description": "Viewport dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the viewport in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the viewport in pixels." - } - }, - "title": "Browser Viewport" - } - }, - "title": "Browser" - } - } - }, "examples": [ { "platforms": "linux", diff --git a/common/src/schemas/output_schemas/dragAndDrop_v3.schema.json b/common/src/schemas/output_schemas/dragAndDrop_v3.schema.json index ced06e3..295db77 100644 --- a/common/src/schemas/output_schemas/dragAndDrop_v3.schema.json +++ b/common/src/schemas/output_schemas/dragAndDrop_v3.schema.json @@ -233,222 +233,6 @@ "minimum": 0 } }, - "components": { - "schemas": { - "elementSpecification": { - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "string": { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - "object": { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - } - }, "examples": [ { "source": "Table", diff --git a/common/src/schemas/output_schemas/find_v3.schema.json b/common/src/schemas/output_schemas/find_v3.schema.json index 4f4aea6..abdfbb1 100644 --- a/common/src/schemas/output_schemas/find_v3.schema.json +++ b/common/src/schemas/output_schemas/find_v3.schema.json @@ -650,656 +650,6 @@ } } ], - "components": { - "schemas": { - "string": { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "object": { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - } - }, "examples": [ "Find me!", { diff --git a/common/src/schemas/output_schemas/goTo_v3.schema.json b/common/src/schemas/output_schemas/goTo_v3.schema.json index 4b3378c..efa7488 100644 --- a/common/src/schemas/output_schemas/goTo_v3.schema.json +++ b/common/src/schemas/output_schemas/goTo_v3.schema.json @@ -172,179 +172,6 @@ "title": "Go to URL (detailed)" } ], - "components": { - "schemas": { - "string": { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - } - }, "examples": [ "https://www.google.com", "/search", diff --git a/common/src/schemas/output_schemas/httpRequest_v3.schema.json b/common/src/schemas/output_schemas/httpRequest_v3.schema.json index 20ae01d..26e96fa 100644 --- a/common/src/schemas/output_schemas/httpRequest_v3.schema.json +++ b/common/src/schemas/output_schemas/httpRequest_v3.schema.json @@ -400,406 +400,6 @@ } } ], - "components": { - "schemas": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - } - }, "examples": [ "https://reqres.in/api/users", { diff --git a/common/src/schemas/output_schemas/loadCookie_v3.schema.json b/common/src/schemas/output_schemas/loadCookie_v3.schema.json index 98c6ae2..39a292a 100644 --- a/common/src/schemas/output_schemas/loadCookie_v3.schema.json +++ b/common/src/schemas/output_schemas/loadCookie_v3.schema.json @@ -101,107 +101,6 @@ "title": "Load cookie (detailed)" } ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - } - }, "examples": [ "session_token", "./test-data/auth-session.txt", diff --git a/common/src/schemas/output_schemas/openApi_v3.schema.json b/common/src/schemas/output_schemas/openApi_v3.schema.json index bf4f847..d2c7cf9 100644 --- a/common/src/schemas/output_schemas/openApi_v3.schema.json +++ b/common/src/schemas/output_schemas/openApi_v3.schema.json @@ -87,18 +87,6 @@ "title": "OpenAPI request headers" } }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, "examples": [ { "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" diff --git a/common/src/schemas/output_schemas/record_v3.schema.json b/common/src/schemas/output_schemas/record_v3.schema.json index 1026028..c00159e 100644 --- a/common/src/schemas/output_schemas/record_v3.schema.json +++ b/common/src/schemas/output_schemas/record_v3.schema.json @@ -47,48 +47,6 @@ "description": "If `true`, records the current browser viewport. If `false`, doesn't record the current browser viewport." } ], - "components": { - "schemas": { - "string": { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - } - } - }, "examples": [ true, "results.mp4", diff --git a/common/src/schemas/output_schemas/report_v3.schema.json b/common/src/schemas/output_schemas/report_v3.schema.json index 4d0f1ce..86137f0 100644 --- a/common/src/schemas/output_schemas/report_v3.schema.json +++ b/common/src/schemas/output_schemas/report_v3.schema.json @@ -6245,6 +6245,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6425,6 +6429,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6476,6 +6484,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6651,8 +6662,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6669,7 +6690,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6832,6 +6853,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6883,6 +6908,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7058,8 +7086,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7076,7 +7114,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7608,6 +7646,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7788,6 +7830,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7839,6 +7885,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8014,8 +8063,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8032,7 +8091,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -8195,6 +8254,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -8246,6 +8309,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8421,8 +8487,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8439,7 +8515,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16106,6 +16182,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -16286,6 +16366,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16337,6 +16421,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16512,8 +16599,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16530,7 +16627,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16693,6 +16790,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16744,6 +16845,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16919,8 +17023,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16937,7 +17051,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17469,6 +17583,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17649,6 +17767,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17700,6 +17822,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17875,8 +18000,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17893,7 +18028,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -18056,6 +18191,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -18107,6 +18246,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -18282,8 +18424,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -18300,7 +18452,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/src/schemas/output_schemas/resolvedTests_v3.schema.json b/common/src/schemas/output_schemas/resolvedTests_v3.schema.json index 7081445..8e1e1c3 100644 --- a/common/src/schemas/output_schemas/resolvedTests_v3.schema.json +++ b/common/src/schemas/output_schemas/resolvedTests_v3.schema.json @@ -5825,6 +5825,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6005,6 +6009,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6056,6 +6064,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6231,8 +6242,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6249,7 +6270,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6412,6 +6433,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6463,6 +6488,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6638,8 +6666,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6656,7 +6694,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7188,6 +7226,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7368,6 +7410,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7419,6 +7465,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7594,8 +7643,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7612,7 +7671,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7775,6 +7834,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7826,6 +7889,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8001,8 +8067,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8019,7 +8095,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16117,6 +16193,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -16297,6 +16377,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16348,6 +16432,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16523,8 +16610,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16541,7 +16638,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16704,6 +16801,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16755,6 +16856,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16930,8 +17034,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16948,7 +17062,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17480,6 +17594,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17660,6 +17778,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17711,6 +17833,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17886,8 +18011,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17904,7 +18039,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -18067,6 +18202,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -18118,6 +18257,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -18293,8 +18435,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -18311,7 +18463,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -27178,6 +27330,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -27358,6 +27514,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -27409,6 +27569,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -27584,8 +27747,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -27602,7 +27775,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -27765,6 +27938,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -27816,6 +27993,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -27991,8 +28171,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -28009,7 +28199,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -28541,6 +28731,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -28721,6 +28915,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -28772,6 +28970,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -28947,8 +29148,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -28965,7 +29176,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -29128,6 +29339,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -29179,6 +29394,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -29354,8 +29572,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -29372,7 +29600,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -37039,6 +37267,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -37219,6 +37451,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -37270,6 +37506,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -37445,8 +37684,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -37463,7 +37712,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -37626,6 +37875,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -37677,6 +37930,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -37852,8 +38108,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -37870,7 +38136,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -38402,6 +38668,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -38582,6 +38852,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -38633,6 +38907,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -38808,8 +39085,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -38826,7 +39113,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -38989,6 +39276,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -39040,6 +39331,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -39215,8 +39509,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -39233,7 +39537,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/src/schemas/output_schemas/runCode_v3.schema.json b/common/src/schemas/output_schemas/runCode_v3.schema.json index 23899a5..e3be439 100644 --- a/common/src/schemas/output_schemas/runCode_v3.schema.json +++ b/common/src/schemas/output_schemas/runCode_v3.schema.json @@ -92,98 +92,6 @@ "title": "Run code (detailed)" } ], - "components": { - "schemas": { - "object": { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - } - }, "examples": [ { "language": "javascript", diff --git a/common/src/schemas/output_schemas/runShell_v3.schema.json b/common/src/schemas/output_schemas/runShell_v3.schema.json index a65de4f..dc0465b 100644 --- a/common/src/schemas/output_schemas/runShell_v3.schema.json +++ b/common/src/schemas/output_schemas/runShell_v3.schema.json @@ -91,97 +91,6 @@ "title": "Run shell command (detailed)" } ], - "components": { - "schemas": { - "string": { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - } - }, "examples": [ "docker run hello-world", { diff --git a/common/src/schemas/output_schemas/saveCookie_v3.schema.json b/common/src/schemas/output_schemas/saveCookie_v3.schema.json index 96f8565..c4f112f 100644 --- a/common/src/schemas/output_schemas/saveCookie_v3.schema.json +++ b/common/src/schemas/output_schemas/saveCookie_v3.schema.json @@ -107,113 +107,6 @@ "title": "Save cookie (detailed)" } ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - } - }, "examples": [ "session_token", "test_env_cookie", diff --git a/common/src/schemas/output_schemas/screenshot_v3.schema.json b/common/src/schemas/output_schemas/screenshot_v3.schema.json index e9b641f..996a656 100644 --- a/common/src/schemas/output_schemas/screenshot_v3.schema.json +++ b/common/src/schemas/output_schemas/screenshot_v3.schema.json @@ -415,6 +415,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -595,6 +599,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -646,6 +654,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -821,8 +832,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -839,7 +860,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -1002,6 +1023,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -1053,6 +1078,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -1228,8 +1256,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -1246,7 +1284,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -1364,1519 +1402,6 @@ "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." } ], - "components": { - "schemas": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - "crop_element": { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - } - }, "examples": [ true, "image.png", diff --git a/common/src/schemas/output_schemas/spec_v3.schema.json b/common/src/schemas/output_schemas/spec_v3.schema.json index 3302ef8..1cd7367 100644 --- a/common/src/schemas/output_schemas/spec_v3.schema.json +++ b/common/src/schemas/output_schemas/spec_v3.schema.json @@ -6227,6 +6227,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6407,6 +6411,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6458,6 +6466,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6633,8 +6644,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6651,7 +6672,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6814,6 +6835,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6865,6 +6890,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7040,8 +7068,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7058,7 +7096,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7590,6 +7628,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7770,6 +7812,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7821,6 +7867,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7996,8 +8045,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8014,7 +8073,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -8177,6 +8236,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -8228,6 +8291,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8403,8 +8469,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8421,7 +8497,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16088,6 +16164,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -16268,6 +16348,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16319,6 +16403,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16494,8 +16581,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16512,7 +16609,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16675,6 +16772,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16726,6 +16827,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16901,8 +17005,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16919,7 +17033,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17451,6 +17565,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17631,6 +17749,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17682,6 +17804,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17857,8 +17982,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17875,7 +18010,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -18038,6 +18173,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -18089,6 +18228,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -18264,8 +18406,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -18282,7 +18434,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/src/schemas/output_schemas/step_v3.schema.json b/common/src/schemas/output_schemas/step_v3.schema.json index 7cb3291..da1f359 100644 --- a/common/src/schemas/output_schemas/step_v3.schema.json +++ b/common/src/schemas/output_schemas/step_v3.schema.json @@ -3,117 +3,6 @@ "title": "step", "description": "A step in a test.", "type": "object", - "components": { - "schemas": { - "common": { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - } - }, "anyOf": [ { "allOf": [ @@ -5027,6 +4916,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -5207,6 +5100,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -5258,6 +5155,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -5433,8 +5333,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -5451,7 +5361,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -5614,6 +5524,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -5665,6 +5579,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -5840,8 +5757,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -5858,7 +5785,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6390,6 +6317,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -6570,6 +6501,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6621,6 +6556,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6796,8 +6734,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6814,7 +6762,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6977,6 +6925,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7028,6 +6980,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7203,8 +7158,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7221,7 +7186,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/common/src/schemas/output_schemas/test_v3.schema.json b/common/src/schemas/output_schemas/test_v3.schema.json index b7e04da..9e37067 100644 --- a/common/src/schemas/output_schemas/test_v3.schema.json +++ b/common/src/schemas/output_schemas/test_v3.schema.json @@ -5626,6 +5626,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -5806,6 +5810,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -5857,6 +5865,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6032,8 +6043,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6050,7 +6071,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6213,6 +6234,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -6264,6 +6289,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -6439,8 +6467,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -6457,7 +6495,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -6989,6 +7027,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7169,6 +7211,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7220,6 +7266,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7395,8 +7444,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7413,7 +7472,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7576,6 +7635,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7627,6 +7690,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7802,8 +7868,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7820,7 +7896,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -15487,6 +15563,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -15667,6 +15747,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -15718,6 +15802,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -15893,8 +15980,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -15911,7 +16008,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16074,6 +16171,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -16125,6 +16226,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -16300,8 +16404,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -16318,7 +16432,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -16850,6 +16964,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -17030,6 +17148,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17081,6 +17203,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17256,8 +17381,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17274,7 +17409,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -17437,6 +17572,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -17488,6 +17627,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -17663,8 +17805,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -17681,7 +17833,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -20083,192 +20235,6 @@ } ], "additionalProperties": false, - "components": { - "schemas": { - "openApi": { - "type": "array", - "items": { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "not": { - "required": [ - "operationId" - ] - }, - "required": [ - "name", - "descriptionPath" - ], - "title": "OpenAPI description (test)" - } - ] - } - } - } - }, "examples": [ { "steps": [ diff --git a/common/src/schemas/output_schemas/type_v3.schema.json b/common/src/schemas/output_schemas/type_v3.schema.json index 566eda5..684a4bf 100644 --- a/common/src/schemas/output_schemas/type_v3.schema.json +++ b/common/src/schemas/output_schemas/type_v3.schema.json @@ -108,114 +108,6 @@ "additionalProperties": false } ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, "examples": [ "kittens", [ diff --git a/common/src/schemas/output_schemas/wait_v3.schema.json b/common/src/schemas/output_schemas/wait_v3.schema.json index 0374d01..014333a 100644 --- a/common/src/schemas/output_schemas/wait_v3.schema.json +++ b/common/src/schemas/output_schemas/wait_v3.schema.json @@ -21,18 +21,6 @@ "title": "Wait (boolean)" } ], - "components": { - "schemas": { - "string": { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - } - } - }, "examples": [ 5000, "$WAIT_DURATION", diff --git a/common/src/schemas/schemas.json b/common/src/schemas/schemas.json index ca62b00..5d2d922 100644 --- a/common/src/schemas/schemas.json +++ b/common/src/schemas/schemas.json @@ -223,6 +223,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -403,6 +407,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -454,6 +462,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -629,8 +640,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -647,7 +668,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -668,454 +689,6 @@ } } }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, "examples": [ { "find": { @@ -1227,70 +800,6 @@ } } ], - "components": { - "schemas": { - "string": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - } - }, "examples": [ "https://www.google.com", "/search", @@ -1424,127 +933,6 @@ "type": "boolean" } ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, "examples": [ true, "right", @@ -7373,6 +6761,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -7553,6 +6945,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -7604,6 +7000,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -7779,8 +7178,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -7797,7 +7206,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -7960,6 +7369,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -8011,6 +7424,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -8186,8 +7602,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -8204,7 +7630,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -8736,6 +8162,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -8916,6 +8346,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -8967,6 +8401,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -9142,8 +8579,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -9160,7 +8607,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -9323,6 +8770,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -9374,6 +8825,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -9549,8 +9003,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -9567,7 +9031,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -12521,11020 +11985,858 @@ "default": false } }, - "components": { - "schemas": { - "environment": { - "type": "object", - "description": "Environment information for the system running Doc Detective.", - "readOnly": true, - "additionalProperties": false, - "required": [ - "platform" - ], - "properties": { - "workingDirectory": { - "description": "The current working directory of the process running Doc Detective.", - "type": "string" + "examples": [ + {}, + { + "input": ".", + "output": ".", + "recursive": true, + "loadVariables": ".env", + "fileTypes": [ + "markdown" + ] + }, + { + "fileTypes": [ + { + "extends": "markdown", + "extensions": [ + "md", + "markdown", + "mdx" + ], + "inlineStatements": { + "testStart": "", + "testEnd": "", + "ignoreStart": "", + "ignoreEnd": "", + "step": "" }, - "platform": { - "description": "The operating system type running Doc Detective.", + "markup": [ + { + "name": "onscreenText", + "regex": "\\*\\*.+?\\*\\*", + "actions": "find" + } + ] + } + ] + }, + { + "fileTypes": [ + { + "name": "Jupyter Notebooks", + "extensions": "ipynb", + "runShell": { + "command": "jupyter", + "args": [ + "nbconvert", + "--to", + "script", + "--execute", + "$1", + "--stdout" + ] + } + }, + { + "name": "JavaScript", + "extensions": "js", + "runShell": { + "command": "node $1" + } + }, + { + "name": "Python", + "extensions": "py", + "runShell": { + "command": "python $1" + } + } + ] + }, + { + "environment": { + "platform": "windows", + "arch": "x64" + } + }, + { + "concurrentRunners": 1 + }, + { + "concurrentRunners": true + }, + { + "concurrentRunners": 4 + }, + { + "debug": false + }, + { + "debug": true + }, + { + "debug": "stepThrough" + }, + { + "integrations": { + "docDetectiveApi": { + "apiKey": "your-api-key-here" + } + } + }, + { + "crawl": true + } + ] + }, + "context_v3": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "context", + "type": "object", + "description": "A context in which to perform tests. If no contexts are specified but a context is required by one or more tests, Doc Detective attempts to identify a supported context in the current environment and run tests against it. For example, if a browser isn't specified but is required by steps in the test, Doc Detective will search for and use a supported browser available in the current environment.", + "additionalProperties": false, + "dynamicDefaults": { + "contextId": "uuid" + }, + "properties": { + "$schema": { + "description": "JSON Schema for this object.", + "type": "string", + "enum": [ + "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/context_v3.schema.json" + ] + }, + "contextId": { + "type": "string", + "description": "Unique identifier for the context." + }, + "platforms": { + "description": "Platforms to run tests on.", + "anyOf": [ + { + "type": "string", + "enum": [ + "linux", + "mac", + "windows" + ] + }, + { + "type": "array", + "items": { "type": "string", "enum": [ "linux", "mac", "windows" ] - }, - "arch": { - "description": "The processor architecture of the system running Doc Detective.", - "type": "string", - "enum": [ - "arm32", - "arm64", - "x32", - "x64" - ] } + } + ] + }, + "browsers": { + "description": "Browsers to run tests on.", + "anyOf": [ + { + "type": "string", + "description": "Name of the browser.", + "enum": [ + "chrome", + "firefox", + "safari", + "webkit" + ], + "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." }, - "title": "Environment details" - }, - "markupDefinition": { - "type": "object", - "properties": { - "name": { - "description": "Name of the markup definition", - "type": "string" + { + "type": "object", + "description": "Browser configuration.", + "required": [ + "name" + ], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "Name of the browser.", + "enum": [ + "chrome", + "firefox", + "safari", + "webkit" + ], + "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." + }, + "headless": { + "type": "boolean", + "description": "If `true`, runs the browser in headless mode.", + "default": true + }, + "window": { + "type": "object", + "description": "Browser dimensions.", + "additionalProperties": false, + "properties": { + "width": { + "type": "integer", + "description": "Width of the browser window in pixels." + }, + "height": { + "type": "integer", + "description": "Height of the browser window in pixels." + } + }, + "title": "Browser Window" + }, + "viewport": { + "type": "object", + "description": "Viewport dimensions.", + "additionalProperties": false, + "properties": { + "width": { + "type": "integer", + "description": "Width of the viewport in pixels." + }, + "height": { + "type": "integer", + "description": "Height of the viewport in pixels." + } + }, + "title": "Browser Viewport" + } }, - "regex": { - "description": "Regular expressions to match the markup type.", + "title": "Browser" + }, + { + "type": "array", + "items": { "anyOf": [ { + "type": "string", + "description": "Name of the browser.", + "enum": [ + "chrome", + "firefox", + "safari", + "webkit" + ], + "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." + }, + { + "type": "object", + "description": "Browser configuration.", + "required": [ + "name" + ], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "Name of the browser.", + "enum": [ + "chrome", + "firefox", + "safari", + "webkit" + ], + "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." + }, + "headless": { + "type": "boolean", + "description": "If `true`, runs the browser in headless mode.", + "default": true + }, + "window": { + "type": "object", + "description": "Browser dimensions.", + "additionalProperties": false, + "properties": { + "width": { + "type": "integer", + "description": "Width of the browser window in pixels." + }, + "height": { + "type": "integer", + "description": "Height of the browser window in pixels." + } + }, + "title": "Browser Window" + }, + "viewport": { + "type": "object", + "description": "Viewport dimensions.", + "additionalProperties": false, + "properties": { + "width": { + "type": "integer", + "description": "Width of the viewport in pixels." + }, + "height": { + "type": "integer", + "description": "Height of the viewport in pixels." + } + }, + "title": "Browser Viewport" + } + }, + "title": "Browser" + } + ] + } + } + ] + } + }, + "examples": [ + { + "platforms": "linux", + "browsers": "chrome" + }, + { + "platforms": [ + "windows", + "mac", + "linux" + ], + "browsers": [ + "chrome", + "firefox", + "webkit" + ] + }, + { + "browsers": { + "name": "chrome", + "headless": true + } + }, + { + "browsers": [ + { + "name": "chrome", + "headless": true + }, + { + "name": "firefox" + } + ] + }, + { + "platforms": [ + "mac", + "linux" + ], + "browsers": { + "name": "chrome", + "headless": true + } + }, + { + "platforms": [ + "windows", + "mac", + "linux" + ], + "browsers": [ + { + "name": "chrome", + "headless": true, + "window": { + "width": 1920, + "height": 1080 + }, + "viewport": { + "width": 1600, + "height": 900 + } + }, + { + "name": "firefox", + "window": { + "width": 1366, + "height": 768 + } + }, + { + "name": "webkit", + "headless": false, + "viewport": { + "width": 1440, + "height": 900 + } + } + ] + }, + { + "platforms": "mac", + "browsers": [ + { + "name": "safari", + "window": { + "width": 1280, + "height": 800 + } + } + ] + } + ] + }, + "dragAndDrop_v3": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "dragAndDrop", + "description": "Drag and drop an element from source to target.", + "type": "object", + "required": [ + "source", + "target" + ], + "properties": { + "source": { + "description": "The element to drag.", + "anyOf": [ + { + "title": "Element (simple)", + "type": "string", + "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." + }, + { + "title": "Element (detailed)", + "type": "object", + "anyOf": [ + { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "properties": { + "elementText": { + "type": "string", + "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." + }, + "selector": { + "type": "string", + "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementTestId": { + "type": "string", + "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." + }, + "elementAttribute": { + "type": "object", + "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", + "additionalProperties": { "anyOf": [ { "type": "string" }, { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } + "type": "number" + }, + { + "type": "boolean" } ] } - ] - }, - "batchMatches": { - "description": "If `true`, all matches are combined into a single string.", - "type": "boolean", - "default": false - }, - "actions": { - "description": "Actions to perform when the markup type is detected.", + }, + "elementAria": { + "type": "string", + "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "timeout": { + "type": "integer", + "description": "Max duration in milliseconds to wait for the element to exist.", + "default": 5000 + } + } + } + ] + }, + "target": { + "description": "The target location to drop the element.", + "anyOf": [ + { + "title": "Element (simple)", + "type": "string", + "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." + }, + { + "title": "Element (detailed)", + "type": "object", + "anyOf": [ + { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "properties": { + "elementText": { + "type": "string", + "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." + }, + "selector": { + "type": "string", + "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementTestId": { + "type": "string", + "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." + }, + "elementAttribute": { + "type": "object", + "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ] + } + }, + "elementAria": { + "type": "string", + "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "timeout": { + "type": "integer", + "description": "Max duration in milliseconds to wait for the element to exist.", + "default": 5000 + } + } + } + ] + }, + "duration": { + "type": "integer", + "description": "Duration of the drag operation in milliseconds.", + "default": 1000, + "minimum": 0 + } + }, + "examples": [ + { + "source": "Table", + "target": "#canvas" + }, + { + "source": ".draggable-block", + "target": ".drop-zone", + "duration": 2000 + }, + { + "source": { + "selector": ".widget", + "elementText": "Data Table" + }, + "target": { + "selector": "#design-canvas" + }, + "duration": 500 + }, + { + "source": { + "selector": ".draggable", + "timeout": 10000 + }, + "target": { + "elementText": "Drop Zone", + "timeout": 5000 + } + }, + { + "source": "/Widget Item.*/", + "target": "#canvas" + }, + { + "source": { + "selector": ".draggable", + "elementText": "/Button [0-9]+/" + }, + "target": { + "elementText": "/Drop Zone.*/" + } + } + ] + }, + "find_v3": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "find", + "description": "Find an element based on display text or a selector, then optionally interact with it.", + "anyOf": [ + { + "title": "Find element (simple)", + "type": "string", + "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." + }, + { + "title": "Find element (detailed)", + "type": "object", + "anyOf": [ + { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "additionalProperties": false, + "properties": { + "elementText": { + "type": "string", + "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." + }, + "selector": { + "type": "string", + "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementTestId": { + "type": "string", + "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementClass": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." + }, + "elementAttribute": { + "type": "object", + "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", + "additionalProperties": { "anyOf": [ { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] + "type": "string" }, { - "type": "array", - "items": { + "type": "number" + }, + { + "type": "boolean" + } + ] + } + }, + "elementAria": { + "type": "string", + "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "timeout": { + "type": "integer", + "description": "Max duration in milliseconds to wait for the element to exist.", + "default": 5000 + }, + "moveTo": { + "description": "Move to the element. If the element isn't visible, it's scrolled into view.", + "type": "boolean", + "default": true + }, + "click": { + "description": "Click the element.", + "anyOf": [ + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "click", + "description": "Click or tap an element.", + "anyOf": [ + { + "title": "Click element (simple)", + "type": "string", + "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." + }, + { + "title": "Click element (detailed)", + "type": "object", "anyOf": [ { + "required": [ + "selector" + ] + }, + { + "required": [ + "elementText" + ] + }, + { + "required": [ + "elementId" + ] + }, + { + "required": [ + "elementTestId" + ] + }, + { + "required": [ + "elementClass" + ] + }, + { + "required": [ + "elementAttribute" + ] + }, + { + "required": [ + "elementAria" + ] + } + ], + "properties": { + "button": { + "description": "Kind of click to perform.", "type": "string", "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "step", - "description": "A step in a test.", - "type": "object", - "components": { - "schemas": { - "common": { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - } - }, - "anyOf": [ - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "checkLink" - ], - "properties": { - "checkLink": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "checkLink", - "anyOf": [ - { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - ], - "components": { - "schemas": { - "string": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "string", - "pattern": "(^(http://|https://|\\/).*|\\$[A-Za-z0-9_]+$)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "Check link (detailed)", - "description": "Check if an HTTP or HTTPS URL returns an acceptable status code from a GET request.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to check. Can be a full URL or a path. If a path is provided, `origin` must be specified.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - } - } - ], - "default": [ - 200, - 301, - 302, - 307, - 308 - ] - } - } - } - } - }, - "examples": [ - "https://www.google.com", - "/search", - { - "url": "https://www.google.com", - "statusCodes": 200 - }, - { - "url": "/search", - "origin": "www.google.com", - "statusCodes": [ - 200 - ] - } - ] - } - }, - "title": "checkLink" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "click" - ], - "properties": { - "click": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - } - }, - "title": "click" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "find" - ], - "properties": { - "find": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "find", - "description": "Find an element based on display text or a selector, then optionally interact with it.", - "anyOf": [ - { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - ], - "components": { - "schemas": { - "string": { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "object": { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - } - }, - "examples": [ - "Find me!", - { - "selector": "[title=Search]" - }, - { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": "shorthair cat" - }, - { - "selector": "[title=Search]", - "click": { - "button": "right" - } - }, - { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": { - "keys": [ - "shorthair cat" - ], - "inputDelay": 100 - } - }, - { - "elementId": "/^user-[0-9]+$/", - "elementClass": [ - "admin", - "/^level-[1-5]$/" - ], - "elementAttribute": { - "data-active": true, - "data-score": "/^[0-9]+$/" - }, - "timeout": 8000, - "moveTo": false - } - ] - } - }, - "title": "find" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "goTo" - ], - "properties": { - "goTo": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "goTo", - "anyOf": [ - { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - } - }, - "examples": [ - "https://www.google.com", - "/search", - { - "url": "https://www.google.com" - }, - { - "url": "/search", - "origin": "https://www.google.com" - }, - { - "url": "https://www.example.com", - "waitUntil": { - "networkIdleTime": 500 - } - }, - { - "url": "https://www.example.com/dashboard", - "waitUntil": { - "find": { - "selector": "[data-testid='dashboard-loaded']" - } - } - }, - { - "url": "https://www.example.com/app", - "timeout": 60000, - "waitUntil": { - "networkIdleTime": 500, - "domIdleTime": 1000, - "find": { - "selector": ".main-content", - "elementText": "Dashboard" - } - } - }, - { - "url": "https://www.example.com/app", - "timeout": 60000, - "waitUntil": { - "networkIdleTime": null - } - }, - { - "url": "https://www.example.com/status", - "waitUntil": { - "find": { - "elementText": "System operational" - } - } - }, - { - "url": "http://localhost:8092", - "waitUntil": { - "find": { - "selector": "button", - "elementText": "Standard Button", - "elementTestId": "standard-btn", - "elementAria": "Sample Standard Button", - "elementId": "standard-btn", - "elementClass": [ - "btn" - ], - "elementAttribute": { - "type": "button", - "value": "Standard Button" - } - } - } - } - ] - } - }, - "title": "goTo" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "httpRequest" - ], - "properties": { - "httpRequest": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "httpRequest", - "description": "Perform a generic HTTP request, for example to an API.", - "anyOf": [ - { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - ], - "components": { - "schemas": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - } - }, - "examples": [ - "https://reqres.in/api/users", - { - "url": "https://reqres.in/api/users" - }, - { - "url": "https://reqres.in/api/users/2", - "method": "put", - "request": { - "body": { - "name": "morpheus", - "job": "zion resident" - } - } - }, - { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ] - }, - { - "url": "https://www.api-server.com", - "method": "post", - "timeout": 30000, - "request": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - }, - "parameters": { - "param": "value" - } - }, - "response": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - } - }, - "statusCodes": [ - 200 - ] - }, - { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ], - "path": "response.json", - "directory": "media", - "maxVariation": 0.05, - "overwrite": "aboveVariation" - }, - { - "openApi": "getUserById" - }, - { - "openApi": { - "name": "Reqres", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme" - } - }, - { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme", - "headers": { - "Authorization": "Bearer $TOKEN" - } - } - }, - { - "url": "https://www.api-server.com", - "method": "post", - "request": { - "headers": "Content-Type: application/json\\nAuthorization: Bearer token" - } - }, - { - "url": "https://api.example.com/users/123", - "response": { - "required": [ - "id", - "email", - "createdAt" - ] - } - }, - { - "url": "https://api.example.com/users/123", - "response": { - "required": [ - "user.profile.name", - "user.profile.avatar", - "user.settings.notifications" - ] - } - }, - { - "url": "https://api.example.com/orders", - "response": { - "required": [ - "orders[0].id", - "orders[0].total", - "orders[0].items[0].productId" - ] - } - }, - { - "url": "https://api.example.com/users", - "response": { - "required": [ - "sessionToken", - "expiresAt", - "user.id" - ], - "body": { - "status": "success", - "user": { - "role": "admin" - } - } - } - } - ] - } - }, - "title": "httpRequest" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "runShell" - ], - "properties": { - "runShell": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "runShell", - "description": "Perform a native shell command.", - "anyOf": [ - { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - } - }, - "examples": [ - "docker run hello-world", - { - "command": "echo", - "args": [ - "$USER" - ] - }, - { - "command": "echo", - "args": [ - "hello-world" - ] - }, - { - "command": "docker run hello-world", - "timeout": 20000, - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!" - }, - { - "command": "false", - "exitCodes": [ - 1 - ] - }, - { - "command": "echo", - "args": [ - "setup" - ], - "exitCodes": [ - 0 - ], - "stdio": "/.*?/" - }, - { - "command": "docker run hello-world", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!", - "path": "docker-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - ] - } - }, - "title": "runShell" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "runCode" - ], - "properties": { - "runCode": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "runCode", - "description": "Assemble and run code.", - "anyOf": [ - { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - ], - "components": { - "schemas": { - "object": { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - } - }, - "examples": [ - { - "language": "javascript", - "code": "console.log('Hello, ${process.env.USER}!');" - }, - { - "language": "bash", - "code": "docker run hello-world", - "timeout": 20000, - "exitCodes": [ - 0 - ], - "stdio": "Hello from Docker!" - }, - { - "language": "javascript", - "code": "return false", - "exitCodes": [ - 1 - ] - }, - { - "language": "python", - "code": "print('Hello from Python')", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Python!", - "path": "python-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - ] - } - }, - "title": "runCode" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - } - }, - "title": "type" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "screenshot" - ], - "properties": { - "screenshot": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "screenshot", - "description": "Takes a screenshot in PNG format.", - "anyOf": [ - { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - { - "type": "boolean", - "title": "Capture screenshot", - "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." - } - ], - "components": { - "schemas": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - "crop_element": { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - } - }, - "examples": [ - true, - "image.png", - "static/images/image.png", - "/User/manny/projects/doc-detective/static/images/image.png", - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": "#elementToScreenshot" - }, - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - }, - { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "padding": { - "top": 0, - "right": 0, - "bottom": 0, - "left": 0 - } - } - }, - { - "path": "image.png", - "annotations": [ - { - "find": { - "selector": "#usernameField" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#FF0000", - "strokeWidth": 4, - "headSize": 10 - } - }, - { - "find": { - "elementText": "Username", - "elementClass": [ - "input-field", - "/^user-/" - ] - }, - "text": { - "content": "Enter your username here", - "fontSize": 14, - "color": "#0000FF", - "backgroundColor": "#FFFFFF", - "padding": 5 - } - }, - { - "rectangle": { - "x": 100, - "y": 150, - "width": 200, - "height": 100, - "borderColor": "#00FF00", - "borderWidth": 3, - "fillColor": "rgba(0, 255, 0, 0.2)" - } - } - ] - } - ] - } - }, - "title": "screenshot" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "saveCookie" - ], - "properties": { - "saveCookie": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "saveCookie", - "description": "Save a specific browser cookie to a file or environment variable for later reuse.", - "anyOf": [ - { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - } - }, - "examples": [ - "session_token", - "test_env_cookie", - { - "name": "auth_cookie", - "path": "auth-cookie.txt" - }, - { - "name": "session_token", - "variable": "SESSION_TOKEN" - }, - { - "name": "test_cookie", - "path": "test-cookie.txt", - "overwrite": true - }, - { - "name": "user_session", - "path": "user-session.txt", - "directory": "./test-data", - "overwrite": true - }, - { - "name": "login_token", - "path": "login-token.txt", - "domain": "app.example.com" - } - ] - } - }, - "title": "saveCookie" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "record" - ], - "properties": { - "record": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "record", - "description": "Start recording the current browser viewport. Must be followed by a `stopRecord` step. Only runs in Chrome browsers when they are visible. Supported extensions: [ '.mp4', '.webm', '.gif' ]", - "anyOf": [ - { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - }, - { - "type": "boolean", - "title": "Record (boolean)", - "description": "If `true`, records the current browser viewport. If `false`, doesn't record the current browser viewport." - } - ], - "components": { - "schemas": { - "string": { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - } - } - }, - "examples": [ - true, - "results.mp4", - { - "path": "results.mp4", - "directory": "static/media", - "overwrite": "true" - } - ] - } - }, - "title": "record" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "type": "object", - "required": [ - "stopRecord" - ], - "properties": { - "stopRecord": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "stopRecord", - "description": "Stop the current recording.", - "anyOf": [ - { - "type": "boolean", - "nullable": true - } - ], - "examples": [ - true - ] - } - }, - "title": "stopRecord" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "loadVariables", - "type": "object", - "required": [ - "loadVariables" - ], - "properties": { - "loadVariables": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "loadVariables", - "type": "string", - "description": "Load environment variables from the specified `.env` file.", - "examples": [ - ".env" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "dragAndDrop", - "type": "object", - "required": [ - "dragAndDrop" - ], - "properties": { - "dragAndDrop": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "dragAndDrop", - "description": "Drag and drop an element from source to target.", - "type": "object", - "required": [ - "source", - "target" - ], - "properties": { - "source": { - "description": "The element to drag.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "target": { - "description": "The target location to drop the element.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "duration": { - "type": "integer", - "description": "Duration of the drag operation in milliseconds.", - "default": 1000, - "minimum": 0 - } - }, - "components": { - "schemas": { - "elementSpecification": { - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "string": { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - "object": { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - } - }, - "examples": [ - { - "source": "Table", - "target": "#canvas" - }, - { - "source": ".draggable-block", - "target": ".drop-zone", - "duration": 2000 - }, - { - "source": { - "selector": ".widget", - "elementText": "Data Table" - }, - "target": { - "selector": "#design-canvas" - }, - "duration": 500 - }, - { - "source": { - "selector": ".draggable", - "timeout": 10000 - }, - "target": { - "elementText": "Drop Zone", - "timeout": 5000 - } - }, - { - "source": "/Widget Item.*/", - "target": "#canvas" - }, - { - "source": { - "selector": ".draggable", - "elementText": "/Button [0-9]+/" - }, - "target": { - "elementText": "/Drop Zone.*/" - } - } - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "loadCookie", - "type": "object", - "required": [ - "loadCookie" - ], - "properties": { - "loadCookie": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "loadCookie", - "description": "Load a specific cookie from a file or environment variable into the browser.", - "anyOf": [ - { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - } - }, - "examples": [ - "session_token", - "./test-data/auth-session.txt", - "test_env_cookie", - { - "name": "auth_cookie", - "variable": "AUTH_COOKIE" - }, - { - "name": "test_cookie", - "path": "test-cookie.txt" - }, - { - "name": "session_token", - "path": "session-token.txt", - "directory": "./test-data" - }, - { - "name": "user_session", - "path": "saved-cookies.txt", - "domain": "app.example.com" - } - ] - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - { - "title": "wait", - "type": "object", - "required": [ - "wait" - ], - "properties": { - "wait": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "wait", - "description": "Pause (in milliseconds) before performing the next action.", - "default": 5000, - "anyOf": [ - { - "type": "number", - "title": "Wait (simple)" - }, - { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - { - "type": "boolean", - "title": "Wait (boolean)" - } - ], - "components": { - "schemas": { - "string": { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - } - } - }, - "examples": [ - 5000, - "$WAIT_DURATION", - true - ] - } - } - } - ] - } - ], - "examples": [ - { - "stepId": "uuid", - "description": "Description of the step.", - "checkLink": "https://www.google.com", - "outputs": { - "outputKey": "outputValue" - }, - "variables": { - "variableKey": "variableValue" - } - }, - { - "checkLink": "https://www.google.com" - }, - { - "stepId": "path-only", - "checkLink": "/search" - }, - { - "stepId": "status-code", - "checkLink": { - "url": "https://www.google.com", - "statusCodes": [ - 200 - ] - } - }, - { - "goTo": { - "url": "https://www.google.com" - } - }, - { - "goTo": "https://www.google.com" - }, - { - "wait": 5000 - }, - { - "runCode": { - "language": "python", - "code": "print('Hello from Python')", - "workingDirectory": ".", - "exitCodes": [ - 0 - ], - "stdio": "Hello from Python!", - "path": "python-output.txt", - "directory": "output", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - }, - { - "stopRecord": true - }, - { - "screenshot": true - }, - { - "screenshot": "image.png" - }, - { - "screenshot": "static/images/image.png" - }, - { - "screenshot": "/User/manny/projects/doc-detective/static/images/image.png" - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": "#elementToScreenshot" - } - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation" - } - }, - { - "screenshot": { - "path": "image.png", - "directory": "static/images", - "maxVariation": 0.1, - "overwrite": "aboveVariation", - "crop": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "padding": { - "top": 0, - "right": 0, - "bottom": 0, - "left": 0 - } - } - } - }, - { - "record": true - }, - { - "record": "video.mp4" - }, - { - "record": "static/media/video.mp4" - }, - { - "record": "/User/manny/projects/doc-detective/static/media/video.mp4" - }, - { - "record": { - "path": "video.mp4", - "directory": "static/media", - "overwrite": true - } - }, - { - "loadVariables": "variables.env" - }, - { - "saveCookie": "session_token" - }, - { - "saveCookie": { - "name": "auth_cookie", - "path": "auth-session.txt", - "directory": "./test-data", - "overwrite": true - } - }, - { - "loadCookie": "session_token" - }, - { - "loadCookie": { - "name": "auth_cookie", - "path": "auth-session.txt", - "directory": "./test-data" - } - }, - { - "find": "Find me!" - }, - { - "find": { - "selector": "[title=Search]" - } - }, - { - "find": { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": "shorthair cat" - } - }, - { - "find": { - "selector": "[title=Search]", - "click": { - "button": "right" - } - } - }, - { - "find": { - "selector": "[title=Search]", - "timeout": 10000, - "elementText": "Search", - "moveTo": true, - "click": true, - "type": { - "keys": [ - "shorthair cat" - ], - "inputDelay": 100 - } - } - }, - { - "click": true - }, - { - "click": "right" - }, - { - "click": { - "button": "left", - "elementText": "Element text" - } - }, - { - "click": { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - }, - { - "httpRequest": "https://reqres.in/api/users" - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users" - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users/2", - "method": "put", - "request": { - "body": { - "name": "morpheus", - "job": "zion resident" - } - } - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ] - } - }, - { - "httpRequest": { - "url": "https://www.api-server.com", - "method": "post", - "timeout": 30000, - "request": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - }, - "parameters": { - "param": "value" - } - }, - "response": { - "body": { - "field": "value" - }, - "headers": { - "header": "value" - } - }, - "statusCodes": [ - 200 - ] - } - }, - { - "httpRequest": { - "url": "https://reqres.in/api/users", - "method": "post", - "request": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "response": { - "body": { - "name": "morpheus", - "job": "leader" - } - }, - "statusCodes": [ - 200, - 201 - ], - "path": "response.json", - "directory": "media", - "maxVariation": 0.05, - "overwrite": "aboveVariation" - } - }, - { - "httpRequest": { - "openApi": "getUserById" - } - }, - { - "httpRequest": { - "openApi": { - "name": "Reqres", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - "request": { - "parameters": { - "id": 123 - } - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme" - } - } - }, - { - "httpRequest": { - "openApi": { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "updateUser", - "useExample": "request", - "exampleKey": "acme", - "headers": { - "Authorization": "Bearer $TOKEN" - } - } - } - }, - { - "stepId": "breakpoint-example", - "description": "Step with breakpoint enabled", - "goTo": "https://www.example.com", - "breakpoint": true - }, - { - "checkLink": "https://www.google.com", - "breakpoint": false - }, - { - "dragAndDrop": { - "source": { - "selector": "#sourceElement" - }, - "target": { - "selector": "#targetElement" - } - } - } - ] - } - ] - } - } - ] - } - }, - "title": "Markup definition" - }, - "markupActionString": { - "type": "string", - "enum": [ - "checkLink", - "click", - "find", - "goTo", - "httpRequest", - "loadCookie", - "loadVariables", - "record", - "runCode", - "runShell", - "saveCookie", - "screenshot", - "stopRecord", - "type", - "wait" - ] - }, - "inlineStatements": { - "description": "Statements to include tests and steps inside the content of the file, such as within Markdown.", - "type": "object", - "properties": { - "testStart": { - "description": "Regular expressions that indicate the start of a test. If capture groups are used, the first capture group is used for the statement. If no capture groups are used, the entire match is used for the statement.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "testEnd": { - "description": "Regular expressions that indicate that the current test is complete.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "ignoreStart": { - "description": "Regular expressions that indicates that the following content should be ignored for testing purposes.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "ignoreEnd": { - "description": "Regular expressions that indicate that the ignored section of content is complete.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - }, - "step": { - "description": "Regular expressions that indicate a step in a test.", - "anyOf": [ - { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - ] - } - }, - "title": "Inline statement definition" - }, - "stringOrArray": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - } - } - }, - "examples": [ - {}, - { - "input": ".", - "output": ".", - "recursive": true, - "loadVariables": ".env", - "fileTypes": [ - "markdown" - ] - }, - { - "fileTypes": [ - { - "extends": "markdown", - "extensions": [ - "md", - "markdown", - "mdx" - ], - "inlineStatements": { - "testStart": "", - "testEnd": "", - "ignoreStart": "", - "ignoreEnd": "", - "step": "" - }, - "markup": [ - { - "name": "onscreenText", - "regex": "\\*\\*.+?\\*\\*", - "actions": "find" - } - ] - } - ] - }, - { - "fileTypes": [ - { - "name": "Jupyter Notebooks", - "extensions": "ipynb", - "runShell": { - "command": "jupyter", - "args": [ - "nbconvert", - "--to", - "script", - "--execute", - "$1", - "--stdout" - ] - } - }, - { - "name": "JavaScript", - "extensions": "js", - "runShell": { - "command": "node $1" - } - }, - { - "name": "Python", - "extensions": "py", - "runShell": { - "command": "python $1" - } - } - ] - }, - { - "environment": { - "platform": "windows", - "arch": "x64" - } - }, - { - "concurrentRunners": 1 - }, - { - "concurrentRunners": true - }, - { - "concurrentRunners": 4 - }, - { - "debug": false - }, - { - "debug": true - }, - { - "debug": "stepThrough" - }, - { - "integrations": { - "docDetectiveApi": { - "apiKey": "your-api-key-here" - } - } - }, - { - "crawl": true - } - ] - }, - "context_v3": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "context", - "type": "object", - "description": "A context in which to perform tests. If no contexts are specified but a context is required by one or more tests, Doc Detective attempts to identify a supported context in the current environment and run tests against it. For example, if a browser isn't specified but is required by steps in the test, Doc Detective will search for and use a supported browser available in the current environment.", - "additionalProperties": false, - "dynamicDefaults": { - "contextId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/context_v3.schema.json" - ] - }, - "contextId": { - "type": "string", - "description": "Unique identifier for the context." - }, - "platforms": { - "description": "Platforms to run tests on.", - "anyOf": [ - { - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - }, - { - "type": "array", - "items": { - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - } - } - ] - }, - "browsers": { - "description": "Browsers to run tests on.", - "anyOf": [ - { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - { - "type": "object", - "description": "Browser configuration.", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "headless": { - "type": "boolean", - "description": "If `true`, runs the browser in headless mode.", - "default": true - }, - "window": { - "type": "object", - "description": "Browser dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the browser window in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the browser window in pixels." - } - }, - "title": "Browser Window" - }, - "viewport": { - "type": "object", - "description": "Viewport dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the viewport in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the viewport in pixels." - } - }, - "title": "Browser Viewport" - } - }, - "title": "Browser" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - { - "type": "object", - "description": "Browser configuration.", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "headless": { - "type": "boolean", - "description": "If `true`, runs the browser in headless mode.", - "default": true - }, - "window": { - "type": "object", - "description": "Browser dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the browser window in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the browser window in pixels." - } - }, - "title": "Browser Window" - }, - "viewport": { - "type": "object", - "description": "Viewport dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the viewport in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the viewport in pixels." - } - }, - "title": "Browser Viewport" - } - }, - "title": "Browser" - } - ] - } - } - ] - } - }, - "components": { - "schemas": { - "platform": { - "type": "string", - "enum": [ - "linux", - "mac", - "windows" - ] - }, - "browserName": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "browser": { - "type": "object", - "description": "Browser configuration.", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the browser.", - "enum": [ - "chrome", - "firefox", - "safari", - "webkit" - ], - "$comment": "`safari` is just a shortcut for `webkit`. Included for visibility and to reduce questions." - }, - "headless": { - "type": "boolean", - "description": "If `true`, runs the browser in headless mode.", - "default": true - }, - "window": { - "type": "object", - "description": "Browser dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the browser window in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the browser window in pixels." - } - }, - "title": "Browser Window" - }, - "viewport": { - "type": "object", - "description": "Viewport dimensions.", - "additionalProperties": false, - "properties": { - "width": { - "type": "integer", - "description": "Width of the viewport in pixels." - }, - "height": { - "type": "integer", - "description": "Height of the viewport in pixels." - } - }, - "title": "Browser Viewport" - } - }, - "title": "Browser" - } - } - }, - "examples": [ - { - "platforms": "linux", - "browsers": "chrome" - }, - { - "platforms": [ - "windows", - "mac", - "linux" - ], - "browsers": [ - "chrome", - "firefox", - "webkit" - ] - }, - { - "browsers": { - "name": "chrome", - "headless": true - } - }, - { - "browsers": [ - { - "name": "chrome", - "headless": true - }, - { - "name": "firefox" - } - ] - }, - { - "platforms": [ - "mac", - "linux" - ], - "browsers": { - "name": "chrome", - "headless": true - } - }, - { - "platforms": [ - "windows", - "mac", - "linux" - ], - "browsers": [ - { - "name": "chrome", - "headless": true, - "window": { - "width": 1920, - "height": 1080 - }, - "viewport": { - "width": 1600, - "height": 900 - } - }, - { - "name": "firefox", - "window": { - "width": 1366, - "height": 768 - } - }, - { - "name": "webkit", - "headless": false, - "viewport": { - "width": 1440, - "height": 900 - } - } - ] - }, - { - "platforms": "mac", - "browsers": [ - { - "name": "safari", - "window": { - "width": 1280, - "height": 800 - } - } - ] - } - ] - }, - "dragAndDrop_v3": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "dragAndDrop", - "description": "Drag and drop an element from source to target.", - "type": "object", - "required": [ - "source", - "target" - ], - "properties": { - "source": { - "description": "The element to drag.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "target": { - "description": "The target location to drop the element.", - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "duration": { - "type": "integer", - "description": "Duration of the drag operation in milliseconds.", - "default": 1000, - "minimum": 0 - } - }, - "components": { - "schemas": { - "elementSpecification": { - "anyOf": [ - { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - ] - }, - "string": { - "title": "Element (simple)", - "type": "string", - "description": "Display text, selector, or regex pattern (enclosed in forward slashes) of the element." - }, - "object": { - "title": "Element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text or regex pattern (enclosed in forward slashes) of the element. If combined with `selector`, the element must match both the text and the selector." - }, - "selector": { - "type": "string", - "description": "Selector of the element. If combined with `elementText`, the element must match both the text and the selector." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - } - } - } - } - }, - "examples": [ - { - "source": "Table", - "target": "#canvas" - }, - { - "source": ".draggable-block", - "target": ".drop-zone", - "duration": 2000 - }, - { - "source": { - "selector": ".widget", - "elementText": "Data Table" - }, - "target": { - "selector": "#design-canvas" - }, - "duration": 500 - }, - { - "source": { - "selector": ".draggable", - "timeout": 10000 - }, - "target": { - "elementText": "Drop Zone", - "timeout": 5000 - } - }, - { - "source": "/Widget Item.*/", - "target": "#canvas" - }, - { - "source": { - "selector": ".draggable", - "elementText": "/Button [0-9]+/" - }, - "target": { - "elementText": "/Drop Zone.*/" - } - } - ] - }, - "find_v3": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "find", - "description": "Find an element based on display text or a selector, then optionally interact with it.", - "anyOf": [ - { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" + "left", + "right", + "middle" ] }, "elementText": { @@ -24013,656 +13315,6 @@ } } ], - "components": { - "schemas": { - "string": { - "title": "Find element (simple)", - "type": "string", - "description": "Identifier for the element to find. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "object": { - "title": "Find element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to find. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "timeout": { - "type": "integer", - "description": "Max duration in milliseconds to wait for the element to exist.", - "default": 5000 - }, - "moveTo": { - "description": "Move to the element. If the element isn't visible, it's scrolled into view.", - "type": "boolean", - "default": true - }, - "click": { - "description": "Click the element.", - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "click", - "description": "Click or tap an element.", - "anyOf": [ - { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - { - "type": "boolean" - } - ], - "components": { - "schemas": { - "string": { - "title": "Click element (simple)", - "type": "string", - "description": "Identifier for the element to click. Can be a selector, element text, ARIA name, ID, or test ID." - }, - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "object": { - "title": "Click element (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - }, - "elementText": { - "type": "string", - "description": "Display text of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "selector": { - "type": "string", - "description": "Selector of the element to click. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to click. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - }, - "examples": [ - true, - "right", - { - "button": "left", - "elementText": "Element text" - }, - { - "selector": "#elementToScreenshot", - "elementText": "Element text", - "button": "middle" - } - ] - }, - { - "type": "object", - "properties": { - "button": { - "description": "Kind of click to perform.", - "type": "string", - "enum": [ - "left", - "right", - "middle" - ] - } - }, - "title": "Find element and click" - } - ] - }, - "type": { - "description": "Type keys after finding the element. Either a string or an object with a `keys` field as defined in [`type`](type). To type in the element, make the element active with the `click` parameter.", - "allOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "typeKeys", - "description": "Type keys. To type special keys, begin and end the string with `$` and use the special key's keyword. For example, to type the Escape key, enter `$ESCAPE$`.", - "anyOf": [ - { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, - "examples": [ - "kittens", - [ - "$ENTER$" - ], - [ - "kittens", - "$ENTER$" - ], - { - "keys": "kittens" - }, - { - "keys": [ - "$ENTER$" - ] - }, - { - "keys": [ - "kittens", - "$ENTER$" - ], - "inputDelay": 500 - } - ] - }, - { - "not": { - "type": "object", - "required": [ - "selector", - "elementText", - "elementId", - "elementTestId", - "elementClass", - "elementAttribute", - "elementAria" - ], - "title": "Find element and type" - } - } - ] - } - } - } - } - }, "examples": [ "Find me!", { @@ -24884,179 +13536,6 @@ "title": "Go to URL (detailed)" } ], - "components": { - "schemas": { - "string": { - "title": "Go to URL (simple)", - "description": "Navigate to an HTTP or HTTPS URL. Can be a full URL or a path. If a path is provided, navigates relative to the current URL, if any.", - "type": "string", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "description": "Navigate to an HTTP or HTTPS URL.", - "type": "object", - "additionalProperties": false, - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "description": "URL to navigate to. Can be a full URL or a path. If a path is provided and `origin` is specified, prepends `origin` to `url`. If a path is provided but `origin` isn't specified, attempts to navigate relative to the current URL, if any.", - "pattern": "(^(http://|https://|/).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "origin": { - "type": "string", - "description": "Protocol and domain to navigate to. Prepended to `url`.", - "transform": [ - "trim" - ] - }, - "timeout": { - "type": "integer", - "description": "Maximum time in milliseconds to wait for the page to be ready. If exceeded, the goTo action fails.", - "default": 30000, - "minimum": 0 - }, - "waitUntil": { - "type": "object", - "description": "Configuration for waiting conditions after navigation.", - "additionalProperties": false, - "properties": { - "networkIdleTime": { - "description": "Wait for network activity to be idle (no new requests) for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 500 - }, - "domIdleTime": { - "description": "Wait for DOM mutations to stop for this duration in milliseconds. Set to `null` to skip this check.", - "anyOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "null" - } - ], - "default": 1000 - }, - "find": { - "type": "object", - "description": "Wait for a specific element to be present in the DOM. At least one of selector or elementText must be specified.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "selector": { - "type": "string", - "description": "CSS selector for the element to wait for." - }, - "elementText": { - "type": "string", - "description": "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - } - } - } - }, - "title": "Go to URL (detailed)" - } - } - }, "examples": [ "https://www.google.com", "/search", @@ -25232,107 +13711,6 @@ "title": "Load cookie (detailed)" } ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name or file path", - "description": "Name of the specific cookie to load from default location, or file path to cookie file.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to load.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name containing the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to cookie file, relative to directory. Supports Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory containing the cookie file.", - "transform": [ - "trim" - ] - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by when loading from multi-cookie file (optional).", - "transform": [ - "trim" - ] - } - }, - "title": "Load cookie (detailed)" - } - } - }, "examples": [ "session_token", "./test-data/auth-session.txt", @@ -25768,406 +14146,6 @@ } } ], - "components": { - "schemas": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "title": "HTTP request (detailed)", - "type": "object", - "anyOf": [ - { - "required": [ - "url" - ] - }, - { - "required": [ - "openApi" - ] - } - ], - "additionalProperties": false, - "properties": { - "url": { - "title": "HTTP request (simple)", - "type": "string", - "description": "URL for the HTTP request.", - "pattern": "(^(http://|https://).*|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "openApi": { - "anyOf": [ - { - "allOf": [ - { - "type": "string", - "description": "ID of the operation to use for the request." - }, - { - "title": "Operation ID", - "description": "Operation ID from the OpenAPI schema. Only valid if the OpenAPI description path is specified elsewhere and the operation ID is unique among all specified OpenAPI descriptions." - } - ] - }, - { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "required": [ - "operationId" - ], - "title": "OpenAPI definition (httpRequest)" - } - ] - } - ] - }, - "statusCodes": { - "description": "Accepted status codes. If the specified URL returns a code other than what is specified here, the action fails.", - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 200, - 201 - ] - }, - "method": { - "type": "string", - "description": "Method of the HTTP request", - "enum": [ - "get", - "put", - "post", - "patch", - "delete" - ], - "transform": [ - "trim", - "toEnumCase" - ], - "default": "get" - }, - "timeout": { - "type": "integer", - "description": "Timeout for the HTTP request, in milliseconds.", - "default": 60000 - }, - "request": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers to include in the HTTP request.", - "default": {}, - "anyOf": [ - { - "title": "Request headers (object)", - "description": "Headers to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request headers (string)", - "description": "Headers to include in the HTTP request, as return-separated values. For example, `Content-Type: application/json\nAuthorization: Bearer token`.", - "type": "string" - } - ] - }, - "parameters": { - "description": "URL parameters to include in the HTTP request, in key/value format.", - "type": "object", - "additionalProperties": true, - "default": {}, - "properties": {}, - "title": "Request parameters" - }, - "body": { - "description": "The body of the HTTP request.", - "anyOf": [ - { - "title": "Request body (object)", - "description": "JSON object to include as the body of the HTTP request.", - "type": "object", - "additionalProperties": true, - "properties": {} - }, - { - "title": "Request body (array)", - "description": "JSON array to include as the body of the HTTP request.", - "type": "array", - "items": {} - }, - { - "title": "Request body (string)", - "description": "String to include as the body of the HTTP request.", - "type": "string" - } - ], - "default": {} - } - }, - "title": "Request" - }, - "response": { - "type": "object", - "additionalProperties": false, - "properties": { - "headers": { - "description": "Headers expected in the response, in key/value format. If one or more `responseHeaders` entries aren't present in the response, the step fails.", - "type": "object", - "additionalProperties": true, - "properties": {}, - "default": {}, - "title": "Response headers" - }, - "body": { - "description": "JSON object expected in the response. If one or more key/value pairs aren't present in the response, the step fails.", - "anyOf": [ - { - "type": "object", - "additionalProperties": true, - "properties": {}, - "title": "Response body object", - "description": "JSON key/value pairs expected in the response." - }, - { - "title": "Response body array", - "description": "JSON array expected in the response.", - "type": "array", - "items": {} - }, - { - "title": "Response body string", - "description": "String expected in the response.", - "type": "string" - } - ], - "default": {} - }, - "required": { - "type": "array", - "description": "Array of field paths that must exist in the response body. Uses dot notation for nested fields (e.g., 'user.name') and bracket notation for array indices (e.g., 'items[0].id'). Fields must be present but may have any value including null.", - "items": { - "type": "string" - }, - "default": [] - } - }, - "title": "Response" - }, - "allowAdditionalFields": { - "type": "boolean", - "description": "If `false`, the step fails when the response data contains fields not specified in the response body.", - "default": true - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`. Specify a file extension that matches the expected response type, such as `.json` for JSON content or `.txt` for strings." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - } - } - } - } - }, "examples": [ "https://reqres.in/api/users", { @@ -26449,18 +14427,6 @@ "title": "OpenAPI request headers" } }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, "examples": [ { "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" @@ -26571,48 +14537,6 @@ "description": "If `true`, records the current browser viewport. If `false`, doesn't record the current browser viewport." } ], - "components": { - "schemas": { - "string": { - "title": "Record (simple)", - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path of the recording. Supports the `.mp4`, `.webm`, and `.gif` extensions. If not specified, the file name is the ID of the step, and the extension is `.mp4`.", - "pattern": "([A-Za-z0-9_-]*\\.(mp4|webm|gif)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing recording at `path` if it exists.", - "enum": [ - "true", - "false" - ] - } - }, - "title": "Record (detailed)" - } - } - }, "examples": [ true, "results.mp4", @@ -32450,6 +20374,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -32630,6 +20558,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -32681,6 +20613,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -32856,8 +20791,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -32874,7 +20819,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -33037,6 +20982,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -33088,6 +21037,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -33263,8 +21215,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -33281,7 +21243,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -33813,6 +21775,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -33993,6 +21959,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -34044,6 +22014,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -34219,8 +22192,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -34237,7 +22220,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -34400,6 +22383,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -34451,6 +22438,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -34626,8 +22616,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -34644,7 +22644,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -42742,6 +30742,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -42922,6 +30926,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -42973,6 +30981,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -43148,8 +31159,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -43166,7 +31187,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -43329,6 +31350,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -43380,6 +31405,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -43555,8 +31583,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -43573,7 +31611,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -44105,6 +32143,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -44285,6 +32327,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -44336,6 +32382,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -44511,8 +32560,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -44529,7 +32588,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -44692,6 +32751,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -44743,6 +32806,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -44918,8 +32984,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -44936,7 +33012,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -53803,6 +41879,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -53983,6 +42063,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -54034,6 +42118,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -54209,8 +42296,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -54227,7 +42324,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -54390,6 +42487,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -54441,6 +42542,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -54616,8 +42720,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -54634,7 +42748,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -55166,6 +43280,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -55346,6 +43464,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -55397,6 +43519,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -55572,8 +43697,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -55590,7 +43725,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -55753,6 +43888,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -55804,6 +43943,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -55979,8 +44121,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -55997,7 +44149,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -63664,6 +51816,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -63844,6 +52000,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -63895,6 +52055,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -64070,8 +52233,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -64088,7 +52261,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -64251,6 +52424,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -64302,6 +52479,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -64477,8 +52657,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -64495,7 +52685,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -65027,6 +53217,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -65207,6 +53401,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -65258,6 +53456,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -65433,8 +53634,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -65451,7 +53662,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -65614,6 +53825,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -65665,6 +53880,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -65840,8 +54058,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -65858,7 +54086,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -75235,6 +63463,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -75415,6 +63647,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -75466,6 +63702,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -75641,8 +63880,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -75659,7 +63908,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -75822,6 +64071,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -75873,6 +64126,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -76048,8 +64304,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -76066,7 +64332,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -76598,6 +64864,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -76778,6 +65048,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -76829,6 +65103,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -77004,8 +65281,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -77022,7 +65309,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -77185,6 +65472,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -77236,6 +65527,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -77411,8 +65705,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -77429,7 +65733,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -85096,6 +73400,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -85276,6 +73584,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -85327,6 +73639,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -85502,8 +73817,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -85520,7 +73845,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -85683,6 +74008,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -85734,6 +74063,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -85909,8 +74241,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -85927,7 +74269,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -86459,6 +74801,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -86639,6 +74985,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -86690,6 +75040,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -86865,8 +75218,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -86883,7 +75246,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -87046,6 +75409,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -87097,6 +75464,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -87272,8 +75642,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -87290,7 +75670,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -90480,98 +78860,6 @@ "title": "Run code (detailed)" } ], - "components": { - "schemas": { - "object": { - "type": "object", - "required": [ - "code", - "language" - ], - "properties": { - "language": { - "type": "string", - "description": "Language of the code to run.", - "enum": [ - "python", - "bash", - "javascript" - ] - }, - "code": { - "description": "Code to run.", - "type": "string" - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's output. If the expected content can't be found in the command's output (either stdout or stderr), the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run code (detailed)" - } - } - }, "examples": [ { "language": "javascript", @@ -90701,97 +78989,6 @@ "title": "Run shell command (detailed)" } ], - "components": { - "schemas": { - "string": { - "title": "Run shell command (simple)", - "description": "Command to perform in the machine's default shell.", - "type": "string", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "required": [ - "command" - ], - "additionalProperties": false, - "properties": { - "command": { - "type": "string", - "description": "Command to perform in the machine's default shell." - }, - "args": { - "type": "array", - "description": "Arguments for the command.", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - }, - "default": [] - }, - "workingDirectory": { - "type": "string", - "description": "Working directory for the command.", - "default": "." - }, - "exitCodes": { - "type": "array", - "description": "Expected exit codes of the command. If the command's actual exit code isn't in this list, the step fails.", - "items": { - "anyOf": [ - { - "type": "integer" - } - ] - }, - "default": [ - 0 - ] - }, - "stdio": { - "type": "string", - "description": "Content expected in the command's stdout or stderr. If the expected content can't be found in the command's stdout or stderr, the step fails. Supports strings and regular expressions. To use a regular expression, the string must start and end with a forward slash, like in `/^hello-world.*/`." - }, - "path": { - "type": "string", - "description": "File path to save the command's output, relative to `directory`." - }, - "directory": { - "type": "string", - "description": "Directory to save the command's output. If the directory doesn't exist, creates the directory. If not specified, the directory is your media directory." - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of text different between the current output and previously saved output. If the difference between the current output and the previous output is greater than `maxVariation`, the step fails. If output doesn't exist at `path`, this value is ignored.", - "default": 0, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing output at `path` if it exists.\nIf `aboveVariation`, overwrites the existing output at `path` if the difference between the new output and the existing output is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "timeout": { - "type": "integer", - "description": "Max time in milliseconds the command is allowed to run. If the command runs longer than this, the step fails.", - "default": 60000 - } - }, - "title": "Run shell command (detailed)" - } - } - }, "examples": [ "docker run hello-world", { @@ -90953,113 +79150,6 @@ "title": "Save cookie (detailed)" } ], - "components": { - "schemas": { - "string": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save. Will be saved to a default file path or environment variable.", - "pattern": "^[A-Za-z0-9_./\\-]+$", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "$schema": { - "description": "Optional self-describing schema URI for linters", - "type": "string", - "format": "uri-reference" - }, - "name": { - "type": "string", - "title": "Cookie name", - "description": "Name of the specific cookie to save.", - "pattern": "^[A-Za-z0-9_.-]+$", - "transform": [ - "trim" - ] - }, - "variable": { - "type": "string", - "title": "Environment variable name", - "description": "Environment variable name to store the cookie as JSON string.", - "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", - "transform": [ - "trim" - ] - }, - "path": { - "type": "string", - "title": "Cookie file path", - "description": "File path to save the cookie, relative to directory. Uses Netscape cookie format.", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "title": "Directory path", - "description": "Directory to save the cookie file. If not specified, uses output directory.", - "transform": [ - "trim" - ] - }, - "overwrite": { - "type": "boolean", - "title": "Overwrite existing file", - "description": "Whether to overwrite existing cookie file.", - "default": false - }, - "domain": { - "type": "string", - "title": "Cookie domain", - "description": "Specific domain to filter the cookie by (optional).", - "transform": [ - "trim" - ] - } - }, - "required": [ - "name" - ], - "anyOf": [ - { - "required": [ - "path" - ], - "not": { - "required": [ - "variable" - ] - } - }, - { - "required": [ - "variable" - ], - "not": { - "anyOf": [ - { - "required": [ - "path" - ] - }, - { - "required": [ - "directory" - ] - } - ] - } - } - ], - "title": "Save cookie (detailed)" - } - } - }, "examples": [ "session_token", "test_env_cookie", @@ -91506,6 +79596,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -91686,6 +79780,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -91737,6 +79835,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -91912,8 +80013,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -91930,7 +80041,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -92093,6 +80204,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -92144,962 +80259,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - } - }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } - }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } - }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } - }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] - }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } - } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - { - "type": "boolean", - "title": "Capture screenshot", - "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." - } - ], - "components": { - "schemas": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "object": { - "type": "object", - "additionalProperties": false, - "properties": { - "path": { - "title": "Screenshot (simple)", - "description": "File path of the PNG file. Accepts absolute paths. If not specified, the file name is the ID of the step.", - "type": "string", - "pattern": "([A-Za-z0-9_-]*\\.(png|PNG)$|\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - }, - "directory": { - "type": "string", - "description": "Directory of the PNG file. If the directory doesn't exist, creates the directory.", - "transform": [ - "trim" - ] - }, - "maxVariation": { - "type": "number", - "description": "Allowed variation in percentage of pixels between the new screenshot and the existing screenshot at `path`. If the difference between the new screenshot and the existing screenshot is greater than `maxVariation`, the step fails. If a screenshot doesn't exist at `path`, this value is ignored.", - "default": 0.05, - "minimum": 0, - "maximum": 1 - }, - "overwrite": { - "type": "string", - "description": "If `true`, overwrites the existing screenshot at `path` if it exists.\nIf `aboveVariation`, overwrites the existing screenshot at `path` if the difference between the new screenshot and the existing screenshot is greater than `maxVariation`.", - "enum": [ - "true", - "false", - "aboveVariation" - ], - "default": "aboveVariation" - }, - "crop": { - "anyOf": [ - { - "title": "Crop by element (simple)", - "type": "string", - "description": "Display text or selector of the element to screenshot." - }, - { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } - ] - } - } - } - ] - }, - "annotations": { - "type": "array", - "description": "Array of annotations to add to the screenshot.", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "annotation", - "type": "object", - "description": "A visual annotation to add to the screenshot. Annotations can point to elements on the page (via `find`) or be positioned freely within the viewport.", - "anyOf": [ - { - "required": [ - "arrow" - ], - "not": { - "required": [ - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "text" - ], - "not": { - "required": [ - "arrow", - "rectangle", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "rectangle" - ], - "not": { - "required": [ - "arrow", - "text", - "circle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "circle" + "radius" ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "line", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "line" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "callout", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "callout" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "highlight", - "blur" - ] - } - }, - { - "required": [ - "highlight" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "blur" - ] - } - }, - { - "required": [ - "blur" - ], - "not": { - "required": [ - "arrow", - "text", - "rectangle", - "circle", - "line", - "callout", - "highlight" - ] - } - } - ], - "properties": { - "find": { - "type": "object", - "description": "Element on the page to annotate.", - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "additionalProperties": false, - "properties": { - "selector": { - "type": "string", - "description": "Selector of the element to annotate." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to annotate." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - } - }, - "position": { - "anyOf": [ - { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - { - "type": "string", - "enum": [ - "top", - "bottom", - "left", - "right", - "center", - "top-left", - "top-right", - "bottom-left", - "bottom-right" - ], - "description": "Position relative to the element (if `find` is provided) or to the viewport." - } - ] - }, - "arrow": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } - }, - "required": [ - "content" - ] - }, - "rectangle": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle": { - "type": "object", - "description": "Configuration for circle annotations.", "properties": { "radius": { "type": "number", @@ -93132,7 +80294,7 @@ } } }, - "line": { + "line_properties": { "type": "object", "description": "Configuration for line annotations.", "properties": { @@ -93197,7 +80359,7 @@ "to" ] }, - "callout": { + "callout_properties": { "type": "object", "description": "Configuration for callout annotations (text with arrow).", "properties": { @@ -93273,10 +80435,20 @@ "target" ] }, - "highlight": { + "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -93291,9 +80463,9 @@ } } }, - "blur": { + "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -93312,662 +80484,105 @@ "minimum": 1 } } - } - }, - "components": { - "schemas": { - "arrow_properties": { - "type": "object", - "description": "Configuration for arrow annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the arrow (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the arrow line in pixels.", - "minimum": 1, - "default": 3 - }, - "headSize": { - "type": "number", - "description": "Size of the arrowhead in pixels.", - "minimum": 1, - "default": 15 - } - } - }, - "text_properties": { - "type": "object", - "description": "Configuration for text annotations.", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 16 - }, - "fontFamily": { - "type": "string", - "description": "Font family name.", - "default": "Arial" - }, - "color": { - "type": "string", - "description": "Text color (hex, rgb, or named color).", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFFF" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "description": "Padding in pixels on all sides.", - "minimum": 0 - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - } - } - ], - "default": 5 - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box. Text will wrap.", - "minimum": 1 - }, - "opacity": { - "type": "number", - "description": "Opacity of the text and background (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } + }, + "point": { + "type": "object", + "description": "A coordinate point (x, y).", + "properties": { + "x": { + "type": "number", + "description": "X coordinate in pixels." }, - "required": [ - "content" - ] - }, - "rectangle_properties": { - "type": "object", - "description": "Configuration for rectangle annotations.", - "properties": { - "width": { - "type": "number", - "description": "Width of the rectangle in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the rectangle in pixels.", - "minimum": 1 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - }, - "rx": { - "type": "number", - "description": "Horizontal corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - }, - "ry": { - "type": "number", - "description": "Vertical corner radius for rounded rectangles.", - "minimum": 0, - "default": 0 - } - } - }, - "circle_properties": { - "type": "object", - "description": "Configuration for circle annotations.", - "properties": { - "radius": { - "type": "number", - "description": "Radius of the circle in pixels.", - "minimum": 1, - "default": 30 - }, - "fill": { - "type": "string", - "description": "Fill color (hex, rgb, or named color). Use 'transparent' for no fill.", - "default": "transparent" - }, - "stroke": { - "type": "string", - "description": "Border color (hex, rgb, or named color).", - "default": "#FF0000" - }, - "strokeWidth": { - "type": "number", - "description": "Border width in pixels.", - "minimum": 0, - "default": 2 - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 1 - } + "y": { + "type": "number", + "description": "Y coordinate in pixels." } }, - "line_properties": { - "type": "object", - "description": "Configuration for line annotations.", - "properties": { - "from": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "to": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "color": { - "type": "string", - "description": "Color of the line (hex, rgb, or named color).", - "default": "#000000" - }, - "strokeWidth": { - "type": "number", - "description": "Width of the line in pixels.", - "minimum": 1, - "default": 2 - }, - "dashArray": { - "type": "array", - "description": "Dash pattern [dash, gap]. E.g., [5, 5] for dashed line.", - "items": { - "type": "number", - "minimum": 0 - } - } + "required": [ + "x", + "y" + ] + }, + "padding": { + "type": "object", + "additionalProperties": false, + "properties": { + "top": { + "type": "number", + "minimum": 0 }, - "required": [ - "from", - "to" - ] - }, - "callout_properties": { - "type": "object", - "description": "Configuration for callout annotations (text with arrow).", - "properties": { - "content": { - "type": "string", - "description": "Text content to display." - }, - "target": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "textPosition": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } - }, - "required": [ - "x", - "y" - ] - }, - "fontSize": { - "type": "number", - "description": "Font size in pixels.", - "minimum": 1, - "default": 14 - }, - "color": { - "type": "string", - "description": "Text color.", - "default": "#000000" - }, - "backgroundColor": { - "type": "string", - "description": "Background color for the text box.", - "default": "#FFFFCC" - }, - "arrowColor": { - "type": "string", - "description": "Color of the arrow.", - "default": "#000000" - }, - "maxWidth": { - "type": "number", - "description": "Maximum width of the text box.", - "minimum": 1 - } + "right": { + "type": "number", + "minimum": 0 }, - "required": [ - "content", - "target" - ] - }, - "highlight_properties": { - "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", - "properties": { - "color": { - "type": "string", - "description": "Highlight color (hex, rgb, or named color).", - "default": "#FFFF00" - }, - "opacity": { - "type": "number", - "description": "Opacity (0-1).", - "minimum": 0, - "maximum": 1, - "default": 0.3 - } - } - }, - "blur_properties": { - "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", - "properties": { - "intensity": { - "type": "number", - "description": "Blur intensity level.", - "minimum": 1, - "default": 10 - }, - "width": { - "type": "number", - "description": "Width of the blur area in pixels.", - "minimum": 1 - }, - "height": { - "type": "number", - "description": "Height of the blur area in pixels.", - "minimum": 1 - } - } - }, - "point": { - "type": "object", - "description": "A coordinate point (x, y).", - "properties": { - "x": { - "type": "number", - "description": "X coordinate in pixels." - }, - "y": { - "type": "number", - "description": "Y coordinate in pixels." - } + "bottom": { + "type": "number", + "minimum": 0 }, - "required": [ - "x", - "y" - ] - }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } + "left": { + "type": "number", + "minimum": 0 } } } - }, - "examples": [ - { - "find": { - "selector": "#submit-button" - }, - "arrow": { - "from": { - "x": 0, - "y": -50 - }, - "to": { - "x": 0, - "y": 0 - }, - "color": "#00FF00", - "strokeWidth": 4, - "headSize": 20 - } - }, - { - "position": "top-right", - "text": { - "content": "Important Notice", - "fontSize": 18, - "color": "#FFFFFF", - "backgroundColor": "#0000FF", - "padding": 10, - "maxWidth": 200, - "opacity": 0.9 - } + } + }, + "examples": [ + { + "find": { + "selector": "#submit-button" }, - { - "find": { - "elementClass": [ - "sensitive-info", - "/^private-/" - ] + "arrow": { + "from": { + "x": 0, + "y": -50 }, - "blur": { - "intensity": 15, - "width": 200, - "height": 50 - } + "to": { + "x": 0, + "y": 0 + }, + "color": "#00FF00", + "strokeWidth": 4, + "headSize": 20 } - ] - } - } - }, - "title": "Capture screenshot (detailed)" - }, - "crop_element": { - "title": "Crop by element (detailed)", - "type": "object", - "description": "Crop the screenshot to a specific element.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "selector" - ] - }, - { - "required": [ - "elementText" - ] - }, - { - "required": [ - "elementId" - ] - }, - { - "required": [ - "elementTestId" - ] - }, - { - "required": [ - "elementClass" - ] - }, - { - "required": [ - "elementAttribute" - ] - }, - { - "required": [ - "elementAria" - ] - } - ], - "properties": { - "elementText": { - "type": "string", - "description": "Display text of the element to screenshot." - }, - "selector": { - "type": "string", - "description": "Selector of the element to screenshot." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" }, { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" + "position": "top-right", + "text": { + "content": "Important Notice", + "fontSize": 18, + "color": "#FFFFFF", + "backgroundColor": "#0000FF", + "padding": 10, + "maxWidth": 200, + "opacity": 0.9 } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - }, - "padding": { - "anyOf": [ - { - "title": "Padding (simple)", - "type": "number", - "description": "Padding in pixels to add to the bounds of the element.", - "minimum": 0 }, { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } + "find": { + "elementClass": [ + "sensitive-info", + "/^private-/" + ] }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." + "blur": { + "intensity": 15, + "width": 200, + "height": 50 + } } ] } } }, - "padding": { - "type": "object", - "additionalProperties": false, - "properties": { - "top": { - "type": "number", - "minimum": 0 - }, - "right": { - "type": "number", - "minimum": 0 - }, - "bottom": { - "type": "number", - "minimum": 0 - }, - "left": { - "type": "number", - "minimum": 0 - } - }, - "title": "Padding (detailed)", - "description": "Padding in pixels to add to the bounds of the element." - } + "title": "Capture screenshot (detailed)" + }, + { + "type": "boolean", + "title": "Capture screenshot", + "description": "If `true`, captures a screenshot. If `false`, doesn't capture a screenshot." } - }, + ], "examples": [ true, "image.png", @@ -100283,6 +86898,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -100463,6 +87082,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -100514,6 +87137,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -100689,8 +87315,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -100707,7 +87343,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -100870,6 +87506,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -100921,6 +87561,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -101096,8 +87739,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -101114,7 +87767,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -101646,6 +88299,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -101826,6 +88483,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -101877,6 +88538,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -102052,8 +88716,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -102070,7 +88744,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -102233,6 +88907,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -102284,6 +88962,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -102459,8 +89140,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -102477,7 +89168,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -110144,6 +96835,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -110324,6 +97019,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -110375,6 +97074,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -110550,8 +97252,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -110568,7 +97280,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -110731,6 +97443,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -110782,6 +97498,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -110957,8 +97676,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -110975,7 +97704,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -111507,6 +98236,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -111687,6 +98420,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -111738,6 +98475,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -111913,8 +98653,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -111931,7 +98681,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -112094,6 +98844,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -112145,6 +98899,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -112320,8 +99077,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -112338,7 +99105,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -115261,117 +102028,6 @@ "title": "step", "description": "A step in a test.", "type": "object", - "components": { - "schemas": { - "common": { - "type": "object", - "dynamicDefaults": { - "stepId": "uuid" - }, - "properties": { - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - }, - "title": "Common" - }, - "$schema": { - "description": "JSON Schema for this object.", - "type": "string", - "enum": [ - "https://raw.githubusercontent.com/doc-detective/common/refs/heads/main/dist/schemas/step_v3.schema.json" - ] - }, - "stepId": { - "type": "string", - "description": "ID of the step." - }, - "description": { - "type": "string", - "description": "Description of the step." - }, - "unsafe": { - "type": "boolean", - "description": "Whether or not the step may be unsafe. Unsafe steps may perform actions that could modify the system or environment in unexpected ways. Unsafe steps are only performed within Docker containers or if unsafe steps are enabled with the `allowUnsafeSteps` config property or the `--allow-unsafe` flag.", - "default": false - }, - "outputs": { - "type": "object", - "description": "Outputs from step processes and user-defined expressions. Use the `outputs` object to reference outputs in subsequent steps. If a user-defined output matches the key for a step-defined output, the user-defined output takes precedence.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Outputs (step)" - }, - "variables": { - "type": "object", - "description": "Environment variables to set from user-defined expressions.", - "default": {}, - "patternProperties": { - "^[A-Za-z0-9_]+$": { - "type": "string", - "description": "Runtime expression for a user-defined output value." - } - }, - "title": "Variables (step)" - }, - "breakpoint": { - "type": "boolean", - "description": "Whether or not this step should act as a breakpoint when debugging is enabled. When `true`, execution will pause at this step when debug mode is enabled.", - "default": false - } - } - }, "anyOf": [ { "allOf": [ @@ -120285,6 +106941,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -120465,6 +107125,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -120516,6 +107180,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -120691,8 +107358,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -120709,7 +107386,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -120872,6 +107549,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -120923,6 +107604,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -121098,8 +107782,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -121116,7 +107810,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -121648,6 +108342,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -121828,6 +108526,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -121879,6 +108581,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -122054,8 +108759,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -122072,7 +108787,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -122235,6 +108950,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -122286,6 +109005,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -122461,8 +109183,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -122479,7 +109211,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -130501,6 +117233,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -130681,6 +117417,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -130732,6 +117472,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -130907,8 +117650,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -130925,7 +117678,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -131088,6 +117841,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -131139,6 +117896,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -131314,8 +118074,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -131332,7 +118102,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -131864,6 +118634,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -132044,6 +118818,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -132095,6 +118873,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -132270,8 +119051,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -132288,7 +119079,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -132451,6 +119242,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -132502,6 +119297,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -132677,8 +119475,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -132695,7 +119503,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -140362,6 +127170,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -140542,6 +127354,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -140593,6 +127409,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -140768,8 +127587,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -140786,7 +127615,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -140949,6 +127778,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -141000,6 +127833,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -141175,8 +128011,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -141193,7 +128039,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -141725,6 +128571,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -141905,6 +128755,10 @@ "rectangle": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -141956,6 +128810,9 @@ "circle": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -142131,8 +128988,18 @@ }, "highlight": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -142149,7 +129016,7 @@ }, "blur": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -142312,6 +129179,10 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": [ + "width", + "height" + ], "properties": { "width": { "type": "number", @@ -142363,6 +129234,9 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": [ + "radius" + ], "properties": { "radius": { "type": "number", @@ -142538,8 +129412,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -142556,7 +129440,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", @@ -144958,192 +131842,6 @@ } ], "additionalProperties": false, - "components": { - "schemas": { - "openApi": { - "type": "array", - "items": { - "allOf": [ - { - "version": "1.0.0", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "openApi", - "type": "object", - "description": "OpenAPI description and configuration.", - "additionalProperties": false, - "anyOf": [ - { - "required": [ - "descriptionPath" - ] - }, - { - "required": [ - "operationId" - ] - } - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the OpenAPI description, as defined in your configuration." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - }, - "definition": { - "type": "object", - "readOnly": true, - "description": "OpenAPI definition object loaded from the `descriptionPath`. This is a resolved version of the OpenAPI description and should not be user-defined.", - "additionalProperties": true, - "title": "OpenAPI definition" - }, - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "server": { - "type": "string", - "description": "Server to use for example requests. Only valid if `useExample` is `request` or `both`. If not specified but an example is used for the request, uses the first server defined in the OpenAPI description." - }, - "validateAgainstSchema": { - "type": "string", - "description": "Validates the request and/or response against the schema in the OpenAPI description. If the request or response doesn't match the schema, the step fails.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "both" - }, - "mockResponse": { - "type": "boolean", - "description": "If `true`, doesn't make the HTTP request, but instead uses the response example or schema from the OpenAPI description as the response data. Useful for creating tests when an API isn't fully implemented yet. If `statusCode` isn't specified, uses the first defined response code." - }, - "statusCode": { - "type": "integer", - "description": "Response code to use for validation, examples, and status code checking. If the response code doesn't match, the step fails. `statusCodes` overrides this value when specified." - }, - "useExample": { - "type": [ - "string" - ], - "description": "Uses the example from the OpenAPI description as the request and response data. If the request or response has multiple examples, specify `exampleKey`. If `statusCode` isn't specified, uses the first defined response code. `requestData`, `requestParams`, and `requestHeaders` override portions of request examples when specified. `responseData` overrides portions of response examples when specified.", - "enum": [ - "request", - "response", - "both", - "none" - ], - "default": "none" - }, - "exampleKey": { - "type": "string", - "description": "Key of the example to use from the `examples` property in the OpenAPI description. If an `examples` key isn't specified or isn't available for a given parameter or object, the `example` property value is used.", - "default": "" - }, - "headers": { - "type": "object", - "description": "Request headers to add to requests. For example, to set `Authorization` headers for all requests from the specified OpenAPI document. If specified in both a config and a step, the step value overrides the config value.", - "additionalProperties": { - "type": "string" - }, - "title": "OpenAPI request headers" - } - }, - "components": { - "schemas": { - "operationId": { - "type": "string", - "description": "ID of the operation to use for the request." - }, - "descriptionPath": { - "type": "string", - "description": "URL or local path to the OpenAPI description." - } - } - }, - "examples": [ - { - "descriptionPath": "https://petstore.swagger.io/v2/swagger.json" - }, - { - "name": "Reqres", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "getUserById" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201 - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none" - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true - }, - { - "descriptionPath": "https://api.example.com/openapi.json", - "operationId": "createUser", - "useExample": "both", - "exampleKey": "example1", - "statusCode": 201, - "validateAgainstSchema": "none", - "mockResponse": true, - "headers": { - "Authorization": "Bearer 12345" - } - } - ] - }, - { - "type": "object", - "not": { - "required": [ - "operationId" - ] - }, - "required": [ - "name", - "descriptionPath" - ], - "title": "OpenAPI description (test)" - } - ] - } - } - } - }, "examples": [ { "steps": [ @@ -145418,114 +132116,6 @@ "additionalProperties": false } ], - "components": { - "schemas": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "object": { - "title": "Type keys (detailed)", - "type": "object", - "properties": { - "keys": { - "title": "Type keys (simple)", - "description": "Sequence of keys to enter.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - } - ] - } - } - ] - }, - "inputDelay": { - "type": "number", - "description": "Delay in milliseconds between each key press during a recording", - "default": 100 - }, - "selector": { - "type": "string", - "description": "Selector for the element to type into. If not specified, the typing occurs in the active element." - }, - "elementText": { - "type": "string", - "description": "Display text of the element to type into. If combined with other element finding fields, the element must match all specified criteria." - }, - "elementId": { - "type": "string", - "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementTestId": { - "type": "string", - "description": "data-testid attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." - }, - "elementClass": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Class or array of classes that the element must have. Each class supports exact match or regex pattern using /pattern/ syntax. Element must have all specified classes." - }, - "elementAttribute": { - "type": "object", - "description": "Object of attribute key-value pairs that the element must have. Values can be strings (supporting /pattern/ regex), numbers, or booleans. Boolean true matches attribute presence, false matches absence.", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "elementAria": { - "type": "string", - "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - } - } - }, "examples": [ "kittens", [ @@ -145575,18 +132165,6 @@ "title": "Wait (boolean)" } ], - "components": { - "schemas": { - "string": { - "title": "Wait (environment variable)", - "type": "string", - "pattern": "(\\$[A-Za-z0-9_]+)", - "transform": [ - "trim" - ] - } - } - }, "examples": [ 5000, "$WAIT_DURATION", diff --git a/common/src/schemas/src_schemas/annotation_v3.schema.json b/common/src/schemas/src_schemas/annotation_v3.schema.json index 42a3f99..54145ab 100644 --- a/common/src/schemas/src_schemas/annotation_v3.schema.json +++ b/common/src/schemas/src_schemas/annotation_v3.schema.json @@ -128,6 +128,10 @@ "elementAria": { "type": "string", "description": "Computed accessible name of the element per ARIA specification. Supports exact match or regex pattern using /pattern/ syntax." + }, + "elementId": { + "type": "string", + "description": "ID attribute of the element to find. Supports exact match or regex pattern using /pattern/ syntax." } } }, @@ -271,6 +275,7 @@ "rectangle_properties": { "type": "object", "description": "Configuration for rectangle annotations.", + "required": ["width", "height"], "properties": { "width": { "type": "number", @@ -322,6 +327,7 @@ "circle_properties": { "type": "object", "description": "Configuration for circle annotations.", + "required": ["radius"], "properties": { "radius": { "type": "number", @@ -435,8 +441,18 @@ }, "highlight_properties": { "type": "object", - "description": "Configuration for highlight annotations (semi-transparent overlay).", + "description": "Configuration for highlight annotations (semi-transparent overlay). Requires either a 'find' element (uses element's bounding box) or explicit 'width' and 'height' properties with a 'position'.", "properties": { + "width": { + "type": "number", + "description": "Width of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, + "height": { + "type": "number", + "description": "Height of the highlight area in pixels. Optional if 'find' is specified.", + "minimum": 1 + }, "color": { "type": "string", "description": "Highlight color (hex, rgb, or named color).", @@ -453,7 +469,7 @@ }, "blur_properties": { "type": "object", - "description": "Configuration for blur annotations (for redacting sensitive information).", + "description": "Configuration for blur annotations (for redacting sensitive information). Note: Current implementation uses a semi-transparent overlay rather than true pixel blur. Requires 'width' and 'height' unless a 'find' element is specified (which provides dimensions automatically).", "properties": { "intensity": { "type": "number", diff --git a/core/src/tests/annotateScreenshot.js b/core/src/tests/annotateScreenshot.js index a556503..03daaff 100644 --- a/core/src/tests/annotateScreenshot.js +++ b/core/src/tests/annotateScreenshot.js @@ -382,8 +382,8 @@ function renderRectangle(ctx, rectangle, basePosition, pixelDensity) { const x = basePosition.x; const y = basePosition.y; - const width = (config.width || basePosition.width || DEFAULT_SIZE) * pixelDensity; - const height = (config.height || basePosition.height || DEFAULT_SIZE) * pixelDensity; + const width = (config.width ?? basePosition.width ?? DEFAULT_SIZE) * pixelDensity; + const height = (config.height ?? basePosition.height ?? DEFAULT_SIZE) * pixelDensity; const rx = config.rx * pixelDensity; const ry = config.ry * pixelDensity; @@ -592,8 +592,8 @@ function renderHighlight(ctx, highlight, basePosition, pixelDensity) { ctx.fillRect( basePosition.x, basePosition.y, - basePosition.width || DEFAULT_SIZE * pixelDensity, - basePosition.height || DEFAULT_SIZE * pixelDensity + basePosition.width ?? DEFAULT_SIZE * pixelDensity, + basePosition.height ?? DEFAULT_SIZE * pixelDensity ); ctx.restore(); } @@ -612,8 +612,8 @@ function renderBlur(ctx, blur, basePosition, pixelDensity) { ctx.fillRect( basePosition.x, basePosition.y, - (config.width || basePosition.width || DEFAULT_SIZE) * pixelDensity, - (config.height || basePosition.height || DEFAULT_SIZE) * pixelDensity + (config.width ?? basePosition.width ?? DEFAULT_SIZE) * pixelDensity, + (config.height ?? basePosition.height ?? DEFAULT_SIZE) * pixelDensity ); ctx.restore(); } From 5003c8da870b7da4c4a65b1eec19226571f88156 Mon Sep 17 00:00:00 2001 From: hawkeyexl Date: Mon, 15 Dec 2025 19:56:22 -0800 Subject: [PATCH 9/9] Refactor screenshot annotation process and update dependencies - Replace the canvas library with sharp for image processing. - Change the way annotations are rendered, now using SVG for better quality. - Remove unused functions related to canvas rendering. - Update package.json to use local file reference for doc-detective-common. - Add a new smoke test script to validate annotation functionality. - Create a temporary regression test configuration for screenshot comparison. - Add multiple test artifacts for annotation outputs. - Ensure pixel density is correctly handled during annotation rendering. --- common/dist/schemas/annotation_v3.schema.json | 10 +- common/dist/schemas/config_v3.schema.json | 40 +- common/dist/schemas/report_v3.schema.json | 80 +- .../dist/schemas/resolvedTests_v3.schema.json | 160 +- common/dist/schemas/screenshot_v3.schema.json | 20 +- common/dist/schemas/spec_v3.schema.json | 80 +- common/dist/schemas/step_v3.schema.json | 40 +- common/dist/schemas/test_v3.schema.json | 80 +- common/package-lock.json | 1 + .../output_schemas/annotation_v3.schema.json | 10 +- .../output_schemas/config_v3.schema.json | 40 +- .../output_schemas/report_v3.schema.json | 80 +- .../resolvedTests_v3.schema.json | 160 +- .../output_schemas/screenshot_v3.schema.json | 20 +- .../output_schemas/spec_v3.schema.json | 80 +- .../output_schemas/step_v3.schema.json | 40 +- .../output_schemas/test_v3.schema.json | 80 +- common/src/schemas/schemas.json | 510 ++---- .../src_schemas/annotation_v3.schema.json | 7 +- core/package-lock.json | 1397 ++--------------- core/package.json | 3 +- core/src/tests/annotateScreenshot.js | 755 ++------- core/src/tests/saveScreenshot.js | 2 +- ...-with-crop-elementTestId_1765828572849.png | Bin 0 -> 1160 bytes .../annotations/annotation-arrow.png | Bin 0 -> 7369 bytes .../annotation-arrow_1765852453886.png | Bin 0 -> 7369 bytes .../annotation-arrow_1765852858413.png | Bin 0 -> 7369 bytes .../annotation-arrow_1765856264741.png | Bin 0 -> 7369 bytes .../annotations/annotation-text-simple.png | Bin 0 -> 8729 bytes core/test/runAnnotateSmoke.js | 31 + .../test/temp-screenshot-regression-test.json | 18 + core/test/test-canvas-output.png | Bin 4532 -> 8747 bytes 32 files changed, 820 insertions(+), 2924 deletions(-) create mode 100644 core/test/artifacts/screenshot-with-crop-elementTestId_1765828572849.png create mode 100644 core/test/artifacts/test/artifacts/annotations/annotation-arrow.png create mode 100644 core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765852453886.png create mode 100644 core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765852858413.png create mode 100644 core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765856264741.png create mode 100644 core/test/artifacts/test/artifacts/annotations/annotation-text-simple.png create mode 100644 core/test/runAnnotateSmoke.js create mode 100644 core/test/temp-screenshot-regression-test.json diff --git a/common/dist/schemas/annotation_v3.schema.json b/common/dist/schemas/annotation_v3.schema.json index 1a69643..4064939 100644 --- a/common/dist/schemas/annotation_v3.schema.json +++ b/common/dist/schemas/annotation_v3.schema.json @@ -405,20 +405,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/config_v3.schema.json b/common/dist/schemas/config_v3.schema.json index 6b10a7f..69022d1 100644 --- a/common/dist/schemas/config_v3.schema.json +++ b/common/dist/schemas/config_v3.schema.json @@ -5995,20 +5995,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6419,20 +6415,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7396,20 +7388,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7820,20 +7808,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/report_v3.schema.json b/common/dist/schemas/report_v3.schema.json index 86137f0..2b51717 100644 --- a/common/dist/schemas/report_v3.schema.json +++ b/common/dist/schemas/report_v3.schema.json @@ -6428,20 +6428,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6852,20 +6848,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7829,20 +7821,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -8253,20 +8241,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16365,20 +16349,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16789,20 +16769,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17766,20 +17742,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -18190,20 +18162,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/resolvedTests_v3.schema.json b/common/dist/schemas/resolvedTests_v3.schema.json index 8e1e1c3..e224dae 100644 --- a/common/dist/schemas/resolvedTests_v3.schema.json +++ b/common/dist/schemas/resolvedTests_v3.schema.json @@ -6008,20 +6008,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6432,20 +6428,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7409,20 +7401,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7833,20 +7821,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16376,20 +16360,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16800,20 +16780,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17777,20 +17753,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -18201,20 +18173,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -27513,20 +27481,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -27937,20 +27901,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -28914,20 +28874,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -29338,20 +29294,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -37450,20 +37402,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -37874,20 +37822,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -38851,20 +38795,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -39275,20 +39215,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/screenshot_v3.schema.json b/common/dist/schemas/screenshot_v3.schema.json index 996a656..8e2c7b2 100644 --- a/common/dist/schemas/screenshot_v3.schema.json +++ b/common/dist/schemas/screenshot_v3.schema.json @@ -598,20 +598,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -1022,20 +1018,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/spec_v3.schema.json b/common/dist/schemas/spec_v3.schema.json index 1cd7367..4c83b74 100644 --- a/common/dist/schemas/spec_v3.schema.json +++ b/common/dist/schemas/spec_v3.schema.json @@ -6410,20 +6410,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6834,20 +6830,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7811,20 +7803,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -8235,20 +8223,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16347,20 +16331,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16771,20 +16751,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17748,20 +17724,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -18172,20 +18144,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/step_v3.schema.json b/common/dist/schemas/step_v3.schema.json index da1f359..a3ec4a5 100644 --- a/common/dist/schemas/step_v3.schema.json +++ b/common/dist/schemas/step_v3.schema.json @@ -5099,20 +5099,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -5523,20 +5519,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6500,20 +6492,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6924,20 +6912,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/dist/schemas/test_v3.schema.json b/common/dist/schemas/test_v3.schema.json index 9e37067..18c1c86 100644 --- a/common/dist/schemas/test_v3.schema.json +++ b/common/dist/schemas/test_v3.schema.json @@ -5809,20 +5809,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6233,20 +6229,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7210,20 +7202,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7634,20 +7622,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -15746,20 +15730,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16170,20 +16150,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17147,20 +17123,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17571,20 +17543,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/package-lock.json b/common/package-lock.json index 633aa5a..a3f9052 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -202,6 +202,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", diff --git a/common/src/schemas/output_schemas/annotation_v3.schema.json b/common/src/schemas/output_schemas/annotation_v3.schema.json index 1a69643..4064939 100644 --- a/common/src/schemas/output_schemas/annotation_v3.schema.json +++ b/common/src/schemas/output_schemas/annotation_v3.schema.json @@ -405,20 +405,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/config_v3.schema.json b/common/src/schemas/output_schemas/config_v3.schema.json index 6b10a7f..69022d1 100644 --- a/common/src/schemas/output_schemas/config_v3.schema.json +++ b/common/src/schemas/output_schemas/config_v3.schema.json @@ -5995,20 +5995,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6419,20 +6415,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7396,20 +7388,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7820,20 +7808,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/report_v3.schema.json b/common/src/schemas/output_schemas/report_v3.schema.json index 86137f0..2b51717 100644 --- a/common/src/schemas/output_schemas/report_v3.schema.json +++ b/common/src/schemas/output_schemas/report_v3.schema.json @@ -6428,20 +6428,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6852,20 +6848,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7829,20 +7821,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -8253,20 +8241,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16365,20 +16349,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16789,20 +16769,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17766,20 +17742,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -18190,20 +18162,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/resolvedTests_v3.schema.json b/common/src/schemas/output_schemas/resolvedTests_v3.schema.json index 8e1e1c3..e224dae 100644 --- a/common/src/schemas/output_schemas/resolvedTests_v3.schema.json +++ b/common/src/schemas/output_schemas/resolvedTests_v3.schema.json @@ -6008,20 +6008,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6432,20 +6428,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7409,20 +7401,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7833,20 +7821,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16376,20 +16360,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16800,20 +16780,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17777,20 +17753,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -18201,20 +18173,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -27513,20 +27481,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -27937,20 +27901,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -28914,20 +28874,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -29338,20 +29294,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -37450,20 +37402,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -37874,20 +37822,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -38851,20 +38795,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -39275,20 +39215,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/screenshot_v3.schema.json b/common/src/schemas/output_schemas/screenshot_v3.schema.json index 996a656..8e2c7b2 100644 --- a/common/src/schemas/output_schemas/screenshot_v3.schema.json +++ b/common/src/schemas/output_schemas/screenshot_v3.schema.json @@ -598,20 +598,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -1022,20 +1018,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/spec_v3.schema.json b/common/src/schemas/output_schemas/spec_v3.schema.json index 1cd7367..4c83b74 100644 --- a/common/src/schemas/output_schemas/spec_v3.schema.json +++ b/common/src/schemas/output_schemas/spec_v3.schema.json @@ -6410,20 +6410,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6834,20 +6830,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7811,20 +7803,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -8235,20 +8223,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16347,20 +16331,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16771,20 +16751,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17748,20 +17724,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -18172,20 +18144,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/step_v3.schema.json b/common/src/schemas/output_schemas/step_v3.schema.json index da1f359..a3ec4a5 100644 --- a/common/src/schemas/output_schemas/step_v3.schema.json +++ b/common/src/schemas/output_schemas/step_v3.schema.json @@ -5099,20 +5099,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -5523,20 +5519,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6500,20 +6492,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6924,20 +6912,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/output_schemas/test_v3.schema.json b/common/src/schemas/output_schemas/test_v3.schema.json index 9e37067..18c1c86 100644 --- a/common/src/schemas/output_schemas/test_v3.schema.json +++ b/common/src/schemas/output_schemas/test_v3.schema.json @@ -5809,20 +5809,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6233,20 +6229,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7210,20 +7202,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7634,20 +7622,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -15746,20 +15730,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -16170,20 +16150,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17147,20 +17123,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -17571,20 +17543,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/schemas.json b/common/src/schemas/schemas.json index 5d2d922..06fe4d7 100644 --- a/common/src/schemas/schemas.json +++ b/common/src/schemas/schemas.json @@ -406,20 +406,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -6944,20 +6940,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -7368,20 +7360,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -8345,20 +8333,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -8769,20 +8753,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -20557,20 +20537,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -20981,20 +20957,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -21958,20 +21930,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -22382,20 +22350,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -30925,20 +30889,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -31349,20 +31309,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -32326,20 +32282,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -32750,20 +32702,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -42062,20 +42010,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -42486,20 +42430,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -43463,20 +43403,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -43887,20 +43823,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -51999,20 +51931,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -52423,20 +52351,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -53400,20 +53324,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -53824,20 +53744,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -63646,20 +63562,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -64070,20 +63982,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -65047,20 +64955,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -65471,20 +65375,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -73583,20 +73483,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -74007,20 +73903,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -74984,20 +74876,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -75408,20 +75296,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -79779,20 +79663,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -80203,20 +80083,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -87081,20 +86957,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -87505,20 +87377,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -88482,20 +88350,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -88906,20 +88770,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -97018,20 +96878,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -97442,20 +97298,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -98419,20 +98271,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -98843,20 +98691,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -107124,20 +106968,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -107548,20 +107388,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -108525,20 +108361,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -108949,20 +108781,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -117416,20 +117244,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -117840,20 +117664,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -118817,20 +118637,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -119241,20 +119057,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -127353,20 +127165,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -127777,20 +127585,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -128754,20 +128558,16 @@ }, "rectangle": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { @@ -129178,20 +128978,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": [ - "width", - "height" - ], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/common/src/schemas/src_schemas/annotation_v3.schema.json b/common/src/schemas/src_schemas/annotation_v3.schema.json index 54145ab..9c3c423 100644 --- a/common/src/schemas/src_schemas/annotation_v3.schema.json +++ b/common/src/schemas/src_schemas/annotation_v3.schema.json @@ -274,17 +274,16 @@ }, "rectangle_properties": { "type": "object", - "description": "Configuration for rectangle annotations.", - "required": ["width", "height"], + "description": "Configuration for rectangle annotations. When used with 'find', width and height are derived from the element's bounding box. When positioning freely (using 'position'), width and height must be specified.", "properties": { "width": { "type": "number", - "description": "Width of the rectangle in pixels.", + "description": "Width of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "height": { "type": "number", - "description": "Height of the rectangle in pixels.", + "description": "Height of the rectangle in pixels. Optional if 'find' is specified (uses element's bounding box).", "minimum": 1 }, "fill": { diff --git a/core/package-lock.json b/core/package-lock.json index 7f3ebc8..499bf24 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -19,8 +19,7 @@ "appium-geckodriver": "^2.1.2", "appium-safari-driver": "^4.1.2", "axios": "^1.13.2", - "canvas": "^2.11.2", - "doc-detective-common": "^3.6.0", + "doc-detective-common": "file:../common", "doc-detective-resolver": "^3.6.1", "dotenv": "^17.2.3", "geckodriver": "^6.1.0", @@ -73,6 +72,25 @@ "@img/sharp-win32-x64": "^0.34.5" } }, + "../common": { + "name": "doc-detective-common", + "version": "3.6.0", + "license": "AGPL-3.0-only", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.1.3", + "ajv": "^8.17.1", + "ajv-errors": "^3.0.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0", + "axios": "^1.13.2", + "yaml": "^2.8.2" + }, + "devDependencies": { + "chai": "^6.2.1", + "mocha": "^11.7.5", + "sinon": "^21.0.0" + } + }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "15.1.3", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.1.3.tgz", @@ -1275,51 +1293,6 @@ "jsep": "^0.4.0||^1.0.0" } }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "license": "BSD-3-Clause", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1772,12 +1745,6 @@ "node": ">=18.0.0" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC" - }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1817,6 +1784,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -1828,15 +1796,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", - "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", - "license": "MIT", - "peerDependencies": { - "ajv": "^8.0.1" - } - }, "node_modules/ajv-formats": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", @@ -1854,18 +1813,6 @@ } } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", @@ -1899,6 +1846,7 @@ "integrity": "sha512-0XEpQ7kIAIMPHT4eZRuczfzZhh/X/n6+IGX7URSCSm67ppyPl0zZvS3ZzLHXdfBIPiQi4T00CT1Id/9Ni26wdQ==", "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@appium/base-driver": "^10.1.1", "@appium/base-plugin": "^3.0.4", @@ -6780,7 +6728,6 @@ "resolved": "https://registry.npmjs.org/@appium/base-driver/-/base-driver-10.1.1.tgz", "integrity": "sha512-7I6SxkqkUojD+LzasixT+G6HEZs1a4sRMbeqwkSPCwf7WlvV0WctFFWNmjDrk+XVVqctafXLrqrDWpfGouw4bQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/support": "^7.0.3", "@appium/types": "^1.1.1", @@ -6815,7 +6762,6 @@ "resolved": "https://registry.npmjs.org/@appium/base-plugin/-/base-plugin-3.0.4.tgz", "integrity": "sha512-qpIkPT99EadfKQ2Jr8kHaY4uWeaRR77UVEbzjPTti4W82/nG9GCAWYJv2ORt3AY6PIGl1/Cp95tsOq9eatDQVA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/base-driver": "^10.1.1", "@appium/support": "^7.0.3" @@ -6830,7 +6776,6 @@ "resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-2.1.2.tgz", "integrity": "sha512-zJYdL0wWZfgE7uoCgcYCHmhgopehGAA6WEMc5fj4Sj81YdbVJsR3sqD3xj832GmbtP5FEoaFWi2xiHoovreA9w==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/support": "^7.0.3", "chalk": "4.1.2", @@ -6860,7 +6805,6 @@ "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", "integrity": "sha512-JyvPp0koEi9WVCrUYK8Rqg4G8Vxs+eY8XMpIjxJyGyG50UTo+u6CAfaWxCr5WW+ZvpMM3Qs2AFSdkS7SamQy3g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -7034,7 +6978,6 @@ "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", "license": "MIT", - "peer": true, "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", @@ -7561,7 +7504,6 @@ "resolved": "https://registry.npmjs.org/@sidvind/better-ajv-errors/-/better-ajv-errors-4.0.0.tgz", "integrity": "sha512-rLZQkN6IfNwG6iqZZwqFMcs7DvQX3ZrLVhsHmSO1LUA4EZAz+VZLpTBCIOFsC5Qu3xuwzVfRMZ+1rtk/mCRRZw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "kleur": "^4.1.0" }, @@ -7577,7 +7519,6 @@ "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", "license": "MIT", - "peer": true, "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" @@ -7599,8 +7540,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/@xmldom/xmldom": { "version": "0.8.11", @@ -7628,7 +7568,6 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", - "peer": true, "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" @@ -7642,7 +7581,6 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", - "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -7688,7 +7626,6 @@ "integrity": "sha512-0XEpQ7kIAIMPHT4eZRuczfzZhh/X/n6+IGX7URSCSm67ppyPl0zZvS3ZzLHXdfBIPiQi4T00CT1Id/9Ni26wdQ==", "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/base-driver": "^10.1.1", "@appium/base-plugin": "^3.0.4", @@ -7755,7 +7692,6 @@ "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", "integrity": "sha512-JyvPp0koEi9WVCrUYK8Rqg4G8Vxs+eY8XMpIjxJyGyG50UTo+u6CAfaWxCr5WW+ZvpMM3Qs2AFSdkS7SamQy3g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -7888,8 +7824,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0", - "peer": true + "license": "Python-2.0" }, "node_modules/appium-geckodriver/node_modules/async": { "version": "3.2.6", @@ -7999,7 +7934,6 @@ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "5.1.2" }, @@ -8021,7 +7955,6 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", - "peer": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -8033,7 +7966,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8054,7 +7986,6 @@ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", - "peer": true, "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", @@ -8110,7 +8041,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -8136,7 +8066,6 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -8159,7 +8088,6 @@ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", - "peer": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" @@ -8204,7 +8132,6 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "license": "MIT", - "peer": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -8217,7 +8144,6 @@ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -8230,7 +8156,6 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", @@ -8245,7 +8170,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -8257,15 +8181,13 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/cliui/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -8283,7 +8205,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -8301,7 +8222,6 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.8" } @@ -8311,7 +8231,6 @@ "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", "license": "MIT", - "peer": true, "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" @@ -8343,7 +8262,6 @@ "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", "license": "MIT", - "peer": true, "dependencies": { "color-name": "^2.0.0" }, @@ -8356,7 +8274,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12.20" } @@ -8366,7 +8283,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", "license": "MIT", - "peer": true, "dependencies": { "color-name": "^2.0.0" }, @@ -8379,7 +8295,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12.20" } @@ -8401,7 +8316,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "license": "MIT", - "peer": true, "engines": { "node": ">= 6" } @@ -8427,7 +8341,6 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", "license": "MIT", - "peer": true, "engines": { "node": "^14.18.0 || >=16.10.0" } @@ -8443,7 +8356,6 @@ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -8457,7 +8369,6 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -8467,7 +8378,6 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -8477,7 +8387,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.6.0" } @@ -8553,7 +8462,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -8571,7 +8479,6 @@ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "license": "MIT", - "peer": true, "dependencies": { "clone": "^1.0.2" }, @@ -8593,7 +8500,6 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -8613,15 +8519,13 @@ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/diff": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.3.1" } @@ -8656,8 +8560,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/emoji-regex": { "version": "9.2.2", @@ -8669,15 +8572,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -8741,7 +8642,6 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -8750,15 +8650,13 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -8795,7 +8693,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", @@ -8868,7 +8765,6 @@ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 4.9.1" } @@ -8877,15 +8773,13 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", @@ -8922,8 +8816,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/follow-redirects": { "version": "1.15.11", @@ -9015,7 +8908,6 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -9025,7 +8917,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -9079,7 +8970,6 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", - "peer": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -9089,7 +8979,6 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -9207,8 +9096,7 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/has-flag": { "version": "4.0.0", @@ -9270,7 +9158,6 @@ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -9283,8 +9170,7 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/hpack.js/node_modules/readable-stream": { "version": "2.3.8", @@ -9292,7 +9178,6 @@ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -9309,7 +9194,6 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -9319,15 +9203,13 @@ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", - "peer": true, "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", @@ -9347,15 +9229,13 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -9403,7 +9283,6 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.10" } @@ -9443,7 +9322,6 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -9461,8 +9339,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/is-stream": { "version": "2.0.1", @@ -9577,7 +9454,6 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -9586,8 +9462,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/lazystream": { "version": "1.0.1", @@ -9636,7 +9511,6 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "license": "MIT", - "peer": true, "engines": { "node": ">=14" }, @@ -9707,7 +9581,6 @@ "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", @@ -9743,7 +9616,6 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -9753,7 +9625,6 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -9766,7 +9637,6 @@ "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", "license": "MIT", - "peer": true, "dependencies": { "debug": "3.1.0", "methods": "~1.1.2", @@ -9782,7 +9652,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "license": "MIT", - "peer": true, "dependencies": { "ms": "2.0.0" } @@ -9791,15 +9660,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -9809,7 +9676,6 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -9819,7 +9685,6 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", - "peer": true, "dependencies": { "mime-db": "^1.54.0" }, @@ -9836,7 +9701,6 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -9846,8 +9710,7 @@ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "license": "ISC", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/minipass": { "version": "7.1.2", @@ -9872,7 +9735,6 @@ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", "license": "MIT", - "peer": true, "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", @@ -9889,7 +9751,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", - "peer": true, "dependencies": { "ms": "2.0.0" } @@ -9898,15 +9759,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/morgan/node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "license": "MIT", - "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -9934,7 +9793,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -9974,7 +9832,6 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -9987,15 +9844,13 @@ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", - "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -10008,7 +9863,6 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -10027,7 +9881,6 @@ "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "license": "MIT", - "peer": true, "dependencies": { "fn.name": "1.x.x" } @@ -10037,7 +9890,6 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", - "peer": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -10053,7 +9905,6 @@ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "license": "MIT", - "peer": true, "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -10077,7 +9928,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -10087,7 +9937,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10130,7 +9979,6 @@ "resolved": "https://registry.npmjs.org/package-changed/-/package-changed-3.0.0.tgz", "integrity": "sha512-HSRbrO+Ab5AuqqYGSevtKJ1Yt96jW1VKV7wrp8K4SKj5tyDp/7D96uPCQyCPiNtWTEH/7nA3hZ4z2slbc9yFxg==", "license": "ISC", - "peer": true, "dependencies": { "commander": "^6.2.0" }, @@ -10175,7 +10023,6 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -10225,7 +10072,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" @@ -10321,7 +10167,6 @@ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", - "peer": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -10341,7 +10186,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "side-channel": "^1.1.0" }, @@ -10357,7 +10201,6 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -10367,7 +10210,6 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", - "peer": true, "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", @@ -10383,7 +10225,6 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -10533,7 +10374,6 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "license": "MIT", - "peer": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -10547,7 +10387,6 @@ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", @@ -10570,7 +10409,6 @@ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -10579,8 +10417,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/sanitize-filename": { "version": "1.6.3", @@ -10596,8 +10433,7 @@ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-geckodriver/node_modules/semver": { "version": "7.7.3", @@ -10616,7 +10452,6 @@ "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", @@ -10639,7 +10474,6 @@ "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.1.tgz", "integrity": "sha512-JndLBslCLA/ebr7rS3d+/EKkzTsTi1jI2T9l+vHfAaGJ7A7NhtDpSZ0lx81HCNWnnE0yHncG+SSnVf9IMxOwXQ==", "license": "MIT", - "peer": true, "dependencies": { "etag": "~1.8.1", "fresh": "~0.5.2", @@ -10656,7 +10490,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -10679,15 +10512,13 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/serve-static": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", - "peer": true, "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", @@ -10708,8 +10539,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-geckodriver/node_modules/sharp": { "version": "0.34.5", @@ -10794,7 +10624,6 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -10814,7 +10643,6 @@ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -10831,7 +10659,6 @@ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", - "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -10850,7 +10677,6 @@ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", - "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -10928,7 +10754,6 @@ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -10946,7 +10771,6 @@ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -10962,7 +10786,6 @@ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -10977,7 +10800,6 @@ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "license": "MIT", - "peer": true, "engines": { "node": "*" } @@ -10987,7 +10809,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -11226,8 +11047,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/through": { "version": "2.3.8", @@ -11240,7 +11060,6 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.6" } @@ -11250,7 +11069,6 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 14.0.0" } @@ -11291,7 +11109,6 @@ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", - "peer": true, "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", @@ -11315,7 +11132,6 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -11360,7 +11176,6 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -11371,7 +11186,6 @@ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -11381,7 +11195,6 @@ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "license": "MIT", - "peer": true, "dependencies": { "defaults": "^1.0.3" } @@ -11406,7 +11219,6 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.18.3.tgz", "integrity": "sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", @@ -11429,7 +11241,6 @@ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", "license": "MIT", - "peer": true, "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", @@ -11444,7 +11255,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11459,7 +11269,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11474,7 +11283,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11551,7 +11359,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -11560,15 +11367,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/wrap-ansi/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -11583,7 +11388,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11602,7 +11406,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -11633,7 +11436,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "license": "ISC", - "peer": true, "engines": { "node": ">=10" } @@ -11643,7 +11445,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "license": "ISC", - "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -11656,7 +11457,6 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "license": "MIT", - "peer": true, "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", @@ -11674,7 +11474,6 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "license": "ISC", - "peer": true, "engines": { "node": "^20.19.0 || ^22.12.0 || >=23" } @@ -11683,15 +11482,13 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-geckodriver/node_modules/yargs/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -11780,7 +11577,6 @@ "resolved": "https://registry.npmjs.org/@appium/base-driver/-/base-driver-10.1.1.tgz", "integrity": "sha512-7I6SxkqkUojD+LzasixT+G6HEZs1a4sRMbeqwkSPCwf7WlvV0WctFFWNmjDrk+XVVqctafXLrqrDWpfGouw4bQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/support": "^7.0.3", "@appium/types": "^1.1.1", @@ -11815,7 +11611,6 @@ "resolved": "https://registry.npmjs.org/@appium/base-plugin/-/base-plugin-3.0.4.tgz", "integrity": "sha512-qpIkPT99EadfKQ2Jr8kHaY4uWeaRR77UVEbzjPTti4W82/nG9GCAWYJv2ORt3AY6PIGl1/Cp95tsOq9eatDQVA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/base-driver": "^10.1.1", "@appium/support": "^7.0.3" @@ -11830,7 +11625,6 @@ "resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-2.1.2.tgz", "integrity": "sha512-zJYdL0wWZfgE7uoCgcYCHmhgopehGAA6WEMc5fj4Sj81YdbVJsR3sqD3xj832GmbtP5FEoaFWi2xiHoovreA9w==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/support": "^7.0.3", "chalk": "4.1.2", @@ -11860,7 +11654,6 @@ "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", "integrity": "sha512-JyvPp0koEi9WVCrUYK8Rqg4G8Vxs+eY8XMpIjxJyGyG50UTo+u6CAfaWxCr5WW+ZvpMM3Qs2AFSdkS7SamQy3g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -11893,7 +11686,6 @@ "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-1.0.0.tgz", "integrity": "sha512-eowz+sV6YxuHdsuRizEhG+AGeeMsUiS9ryWLkdFSqQlsNB+uDudehpYQiRkrrtaGOBzq7a3GDUB7zjc6eR80QA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "json-schema": "0.4.0", "source-map-support": "0.5.21" @@ -11908,7 +11700,6 @@ "resolved": "https://registry.npmjs.org/@appium/support/-/support-7.0.3.tgz", "integrity": "sha512-r4vHjR+wQxg4DND9StWUM2GZvNO3+6ePVplBMKFU+HfKgxw07qjxf08CYMXvJb/YUMwhAhhbVRqzmGudNAk+bg==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/logger": "^2.0.2", "@appium/tsconfig": "^1.1.0", @@ -11959,7 +11750,6 @@ "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", "integrity": "sha512-JyvPp0koEi9WVCrUYK8Rqg4G8Vxs+eY8XMpIjxJyGyG50UTo+u6CAfaWxCr5WW+ZvpMM3Qs2AFSdkS7SamQy3g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -11976,7 +11766,6 @@ "resolved": "https://registry.npmjs.org/@appium/tsconfig/-/tsconfig-1.1.0.tgz", "integrity": "sha512-4QO++yh9hMDiqAnPNHWQStxhTz1to6wG8hsPaviHjqOnlGQa34jrcS6gqciPZL6+xkd5qgIkZjmOTNNWNUFgqQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@tsconfig/node20": "20.1.6" }, @@ -11990,7 +11779,6 @@ "resolved": "https://registry.npmjs.org/@appium/types/-/types-1.1.1.tgz", "integrity": "sha512-zYuCH/QmDfh1F8S3+vz0GUjtAjvpKQdb6H41bhVuK+ZOQbhNWI8f+UdKXoCSOrtVK7dQ2R9uYm8hriJYLjadJw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/logger": "^2.0.2", "@appium/schema": "^1.0.0", @@ -12007,7 +11795,6 @@ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", @@ -12022,7 +11809,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -12032,7 +11818,6 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.1.90" } @@ -12042,7 +11827,6 @@ "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", "license": "MIT", - "peer": true, "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", @@ -12065,7 +11849,6 @@ "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=18" } @@ -12082,7 +11865,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -12105,7 +11887,6 @@ "os": [ "darwin" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -12136,7 +11917,6 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -12154,7 +11934,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12167,7 +11946,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -12186,7 +11964,6 @@ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=14" } @@ -12196,7 +11973,6 @@ "resolved": "https://registry.npmjs.org/@sidvind/better-ajv-errors/-/better-ajv-errors-4.0.0.tgz", "integrity": "sha512-rLZQkN6IfNwG6iqZZwqFMcs7DvQX3ZrLVhsHmSO1LUA4EZAz+VZLpTBCIOFsC5Qu3xuwzVfRMZ+1rtk/mCRRZw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "kleur": "^4.1.0" }, @@ -12212,7 +11988,6 @@ "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", "license": "MIT", - "peer": true, "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" @@ -12222,29 +11997,25 @@ "version": "20.1.6", "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.6.tgz", "integrity": "sha512-sz+Hqx9zwZDpZIV871WSbUzSqNIsXzghZydypnfgzPKLltVJfkINfUeTct31n/tTSa9ZE1ZOfKdRre1uHHquYQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/@types/triple-beam": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/@xmldom/xmldom": { "version": "0.8.11", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" } @@ -12254,7 +12025,6 @@ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", - "peer": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -12267,7 +12037,6 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", - "peer": true, "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" @@ -12281,7 +12050,6 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", - "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -12299,7 +12067,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12312,7 +12079,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -12329,7 +12095,6 @@ "integrity": "sha512-0XEpQ7kIAIMPHT4eZRuczfzZhh/X/n6+IGX7URSCSm67ppyPl0zZvS3ZzLHXdfBIPiQi4T00CT1Id/9Ni26wdQ==", "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@appium/base-driver": "^10.1.1", "@appium/base-plugin": "^3.0.4", @@ -12374,7 +12139,6 @@ "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", "integrity": "sha512-JyvPp0koEi9WVCrUYK8Rqg4G8Vxs+eY8XMpIjxJyGyG50UTo+u6CAfaWxCr5WW+ZvpMM3Qs2AFSdkS7SamQy3g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -12391,7 +12155,6 @@ "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", "license": "MIT", - "peer": true, "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", @@ -12410,7 +12173,6 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", "license": "MIT", - "peer": true, "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", @@ -12429,7 +12191,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -12439,7 +12200,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", - "peer": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -12460,7 +12220,6 @@ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -12475,15 +12234,13 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/archiver-utils/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -12499,7 +12256,6 @@ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -12515,22 +12271,19 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0", - "peer": true + "license": "Python-2.0" }, "node_modules/appium-safari-driver/node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/async-lock": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/asyncbox": { "version": "3.0.0", @@ -12550,15 +12303,13 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/axios": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", - "peer": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", @@ -12570,7 +12321,6 @@ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", "license": "Apache-2.0", - "peer": true, "peerDependencies": { "react-native-b4a": "*" }, @@ -12584,15 +12334,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/bare-events": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "license": "Apache-2.0", - "peer": true, "peerDependencies": { "bare-abort-controller": "*" }, @@ -12620,22 +12368,19 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/base64-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/base64-stream/-/base64-stream-1.0.0.tgz", "integrity": "sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "5.1.2" }, @@ -12648,7 +12393,6 @@ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "license": "Unlicense", - "peer": true, "engines": { "node": ">=0.6" } @@ -12658,7 +12402,6 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", - "peer": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -12670,7 +12413,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -12691,7 +12433,6 @@ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", - "peer": true, "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", @@ -12712,7 +12453,6 @@ "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.1.tgz", "integrity": "sha512-Ese7052fdWrxp/vqSJkydgx/1MdBnNOCV2XVfbmdGWD2H6EYza+Q4pyYSuVSnCUD22hfI/BFI4jHaC3NLXLlJQ==", "license": "MIT", - "peer": true, "dependencies": { "stream-buffers": "2.2.x" } @@ -12722,7 +12462,6 @@ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", "license": "MIT", - "peer": true, "dependencies": { "big-integer": "1.6.x" }, @@ -12749,7 +12488,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -12760,7 +12498,6 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", "license": "MIT", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -12776,7 +12513,6 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -12786,7 +12522,6 @@ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -12800,7 +12535,6 @@ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", - "peer": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" @@ -12817,7 +12551,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12834,7 +12567,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -12847,7 +12579,6 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "license": "MIT", - "peer": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -12860,7 +12591,6 @@ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -12873,7 +12603,6 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", @@ -12888,7 +12617,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12900,15 +12628,13 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/cliui/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -12926,7 +12652,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -12944,7 +12669,6 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.8" } @@ -12954,7 +12678,6 @@ "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", "license": "MIT", - "peer": true, "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" @@ -12968,7 +12691,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -12980,15 +12702,13 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/color-string": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", "license": "MIT", - "peer": true, "dependencies": { "color-name": "^2.0.0" }, @@ -13001,7 +12721,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12.20" } @@ -13011,7 +12730,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", "license": "MIT", - "peer": true, "dependencies": { "color-name": "^2.0.0" }, @@ -13024,7 +12742,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", - "peer": true, "engines": { "node": ">=12.20" } @@ -13034,7 +12751,6 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", - "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -13047,7 +12763,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "license": "MIT", - "peer": true, "engines": { "node": ">= 6" } @@ -13057,7 +12772,6 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "license": "MIT", - "peer": true, "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", @@ -13074,7 +12788,6 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", "license": "MIT", - "peer": true, "engines": { "node": "^14.18.0 || >=16.10.0" } @@ -13090,7 +12803,6 @@ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -13104,7 +12816,6 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -13114,7 +12825,6 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -13124,7 +12834,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.6.0" } @@ -13133,15 +12842,13 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "license": "Apache-2.0", - "peer": true, "bin": { "crc32": "bin/crc32.njs" }, @@ -13154,7 +12861,6 @@ "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", "license": "MIT", - "peer": true, "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" @@ -13168,7 +12874,6 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", - "peer": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -13182,15 +12887,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/cross-spawn/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", - "peer": true, "dependencies": { "isexe": "^2.0.0" }, @@ -13206,7 +12909,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -13224,7 +12926,6 @@ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "license": "MIT", - "peer": true, "dependencies": { "clone": "^1.0.2" }, @@ -13237,7 +12938,6 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.4.0" } @@ -13247,7 +12947,6 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -13258,7 +12957,6 @@ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -13268,15 +12966,13 @@ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/diff": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.3.1" } @@ -13286,7 +12982,6 @@ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", - "peer": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -13300,43 +12995,37 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -13346,7 +13035,6 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "license": "MIT", - "peer": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -13356,7 +13044,6 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" } @@ -13366,7 +13053,6 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" } @@ -13376,7 +13062,6 @@ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -13389,7 +13074,6 @@ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -13405,7 +13089,6 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -13414,15 +13097,13 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -13432,7 +13113,6 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -13442,7 +13122,6 @@ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.8.x" } @@ -13452,7 +13131,6 @@ "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bare-events": "^2.7.0" } @@ -13462,7 +13140,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", @@ -13511,8 +13188,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/fast-uri": { "version": "3.1.0", @@ -13536,7 +13212,6 @@ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 4.9.1" } @@ -13545,15 +13220,13 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", @@ -13575,7 +13248,6 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "license": "MIT", - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -13591,8 +13263,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/follow-redirects": { "version": "1.15.11", @@ -13605,7 +13276,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=4.0" }, @@ -13620,7 +13290,6 @@ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "license": "ISC", - "peer": true, "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" @@ -13637,7 +13306,6 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "license": "ISC", - "peer": true, "engines": { "node": ">=14" }, @@ -13650,7 +13318,6 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", - "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -13667,7 +13334,6 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -13677,7 +13343,6 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", - "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -13690,7 +13355,6 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -13700,7 +13364,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -13709,7 +13372,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ftp-response-parser/-/ftp-response-parser-1.0.1.tgz", "integrity": "sha512-++Ahlo2hs/IC7UVQzjcSAfeUpCwTTzs4uvG5XfGnsinIFkWUYF4xWwPd5qZuK8MJrmUIxFMuHcfqaosCDjvIWw==", - "peer": true, "dependencies": { "readable-stream": "^1.0.31" }, @@ -13721,15 +13383,13 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/ftp-response-parser/node_modules/readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "license": "MIT", - "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -13741,15 +13401,13 @@ "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13759,7 +13417,6 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", - "peer": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -13769,7 +13426,6 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -13782,7 +13438,6 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", - "peer": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -13807,7 +13462,6 @@ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", - "peer": true, "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -13821,7 +13475,6 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -13834,7 +13487,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "license": "ISC", - "peer": true, "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", @@ -13858,7 +13510,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "@isaacs/brace-expansion": "^5.0.0" }, @@ -13874,7 +13525,6 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -13886,23 +13536,20 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -13912,7 +13559,6 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -13925,7 +13571,6 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", - "peer": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -13941,7 +13586,6 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", - "peer": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -13953,8 +13597,7 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/hpack.js": { "version": "2.1.6", @@ -13962,7 +13605,6 @@ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -13975,8 +13617,7 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/hpack.js/node_modules/readable-stream": { "version": "2.3.8", @@ -13984,7 +13625,6 @@ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -14001,7 +13641,6 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -14011,15 +13650,13 @@ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", - "peer": true, "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", @@ -14039,15 +13676,13 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -14073,22 +13708,19 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/appium-safari-driver/node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.10" } @@ -14097,15 +13729,13 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", - "peer": true, "dependencies": { "hasown": "^2.0.2" }, @@ -14121,7 +13751,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14131,7 +13760,6 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14149,15 +13777,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" }, @@ -14170,7 +13796,6 @@ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -14192,7 +13817,6 @@ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -14207,15 +13831,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/jsftp": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/jsftp/-/jsftp-2.1.3.tgz", "integrity": "sha512-r79EVB8jaNAZbq8hvanL8e8JGu2ZNr2bXdHC4ZdQhRImpSPpnWwm5DYVzQ5QxJmtGtKhNNuvqGgbNaFl604fEQ==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^3.1.0", "ftp-response-parser": "^1.0.1", @@ -14233,7 +13855,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -14242,15 +13863,13 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)", - "peer": true + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/appium-safari-driver/node_modules/json-schema-traverse": { "version": "1.0.0", @@ -14264,7 +13883,6 @@ "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.1.0.tgz", "integrity": "sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw==", "license": "MIT", - "peer": true, "engines": { "node": ">=14.14.0" } @@ -14274,7 +13892,6 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -14283,15 +13900,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "license": "MIT", - "peer": true, "dependencies": { "readable-stream": "^2.0.5" }, @@ -14303,15 +13918,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/lazystream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", - "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -14327,7 +13940,6 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -14337,7 +13949,6 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "license": "MIT", - "peer": true, "engines": { "node": ">=14" }, @@ -14349,15 +13960,13 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "license": "MIT", - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -14373,7 +13982,6 @@ "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", "license": "ISC", - "peer": true, "dependencies": { "signal-exit": "^3.0.2" } @@ -14395,7 +14003,6 @@ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "license": "MIT", - "peer": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -14412,7 +14019,6 @@ "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", @@ -14439,7 +14045,6 @@ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" } @@ -14449,7 +14054,6 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -14459,7 +14063,6 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -14472,7 +14075,6 @@ "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", "license": "MIT", - "peer": true, "dependencies": { "debug": "3.1.0", "methods": "~1.1.2", @@ -14488,7 +14090,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "license": "MIT", - "peer": true, "dependencies": { "ms": "2.0.0" } @@ -14497,15 +14098,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -14515,7 +14114,6 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -14525,7 +14123,6 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", - "peer": true, "dependencies": { "mime-db": "^1.54.0" }, @@ -14542,7 +14139,6 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -14552,8 +14148,7 @@ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "license": "ISC", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/minipass": { "version": "7.1.2", @@ -14569,7 +14164,6 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "license": "MIT", - "peer": true, "engines": { "node": "*" } @@ -14579,7 +14173,6 @@ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", "license": "MIT", - "peer": true, "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", @@ -14596,7 +14189,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", - "peer": true, "dependencies": { "ms": "2.0.0" } @@ -14605,15 +14197,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/morgan/node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "license": "MIT", - "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -14625,15 +14215,13 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", "license": "MIT", - "peer": true, "bin": { "ncp": "bin/ncp" } @@ -14643,7 +14231,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -14690,7 +14277,6 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "license": "BSD-2-Clause", - "peer": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -14703,7 +14289,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver" } @@ -14713,7 +14298,6 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -14723,7 +14307,6 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -14736,15 +14319,13 @@ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", - "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -14757,7 +14338,6 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -14767,7 +14347,6 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", - "peer": true, "dependencies": { "wrappy": "1" } @@ -14777,7 +14356,6 @@ "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "license": "MIT", - "peer": true, "dependencies": { "fn.name": "1.x.x" } @@ -14787,7 +14365,6 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", - "peer": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -14803,7 +14380,6 @@ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "license": "MIT", - "peer": true, "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -14827,7 +14403,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14837,7 +14412,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -14850,7 +14424,6 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "license": "MIT", - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -14866,7 +14439,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "license": "MIT", - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -14882,7 +14454,6 @@ "resolved": "https://registry.npmjs.org/package-changed/-/package-changed-3.0.0.tgz", "integrity": "sha512-HSRbrO+Ab5AuqqYGSevtKJ1Yt96jW1VKV7wrp8K4SKj5tyDp/7D96uPCQyCPiNtWTEH/7nA3hZ4z2slbc9yFxg==", "license": "ISC", - "peer": true, "dependencies": { "commander": "^6.2.0" }, @@ -14901,7 +14472,6 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -14919,7 +14489,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/parse-listing/-/parse-listing-1.1.3.tgz", "integrity": "sha512-a1p1i+9Qyc8pJNwdrSvW1g5TPxRH0sywVi6OzVvYHRo6xwF9bDWBxtH0KkxeOOvhUE8vAMtiSfsYQFOuK901eA==", - "peer": true, "engines": { "node": ">=0.6.21" } @@ -14929,7 +14498,6 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -14939,7 +14507,6 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14949,7 +14516,6 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14958,8 +14524,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/path-scurry": { "version": "2.0.1", @@ -14982,7 +14547,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" @@ -14992,22 +14556,19 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/pkg-dir": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "license": "MIT", - "peer": true, "dependencies": { "find-up": "^5.0.0" }, @@ -15020,7 +14581,6 @@ "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "license": "MIT", - "peer": true, "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", @@ -15035,7 +14595,6 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -15068,7 +14627,6 @@ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6.0" } @@ -15077,15 +14635,13 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", - "peer": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -15098,15 +14654,13 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "side-channel": "^1.1.0" }, @@ -15122,7 +14676,6 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -15132,7 +14685,6 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", - "peer": true, "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", @@ -15148,7 +14700,6 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -15165,7 +14716,6 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "license": "MIT", - "peer": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -15181,7 +14731,6 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=8" } @@ -15191,7 +14740,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "license": "MIT", - "peer": true, "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -15222,7 +14770,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -15233,7 +14780,6 @@ "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "minimatch": "^5.1.0" } @@ -15243,7 +14789,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -15253,7 +14798,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -15276,7 +14820,6 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "license": "MIT", - "peer": true, "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", @@ -15297,7 +14840,6 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -15307,7 +14849,6 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "license": "MIT", - "peer": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -15372,7 +14913,6 @@ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", @@ -15388,15 +14928,13 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/safe-stable-stringify": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -15405,15 +14943,13 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/sanitize-filename": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "license": "WTFPL OR ISC", - "peer": true, "dependencies": { "truncate-utf8-bytes": "^1.0.0" } @@ -15423,8 +14959,7 @@ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/appium-safari-driver/node_modules/semver": { "version": "7.7.3", @@ -15443,7 +14978,6 @@ "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", @@ -15466,7 +15000,6 @@ "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.1.tgz", "integrity": "sha512-JndLBslCLA/ebr7rS3d+/EKkzTsTi1jI2T9l+vHfAaGJ7A7NhtDpSZ0lx81HCNWnnE0yHncG+SSnVf9IMxOwXQ==", "license": "MIT", - "peer": true, "dependencies": { "etag": "~1.8.1", "fresh": "~0.5.2", @@ -15483,7 +15016,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -15506,15 +15038,13 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/serve-static": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", - "peer": true, "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", @@ -15535,8 +15065,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/sharp": { "version": "0.34.5", @@ -15545,7 +15074,6 @@ "hasInstallScript": true, "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", @@ -15589,7 +15117,6 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", - "peer": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -15602,7 +15129,6 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -15624,7 +15150,6 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -15644,7 +15169,6 @@ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -15661,7 +15185,6 @@ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", - "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -15680,7 +15203,6 @@ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", - "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -15699,8 +15221,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/source-map": { "version": "0.6.1", @@ -15726,7 +15247,6 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -15736,15 +15256,13 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "license": "CC-BY-3.0", - "peer": true + "license": "CC-BY-3.0" }, "node_modules/appium-safari-driver/node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "license": "MIT", - "peer": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -15754,8 +15272,7 @@ "version": "3.0.22", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/appium-safari-driver/node_modules/spdy": { "version": "4.0.2", @@ -15763,7 +15280,6 @@ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -15781,7 +15297,6 @@ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -15797,7 +15312,6 @@ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -15812,7 +15326,6 @@ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "license": "MIT", - "peer": true, "engines": { "node": "*" } @@ -15822,7 +15335,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -15832,7 +15344,6 @@ "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", "license": "Unlicense", - "peer": true, "engines": { "node": ">= 0.10.0" } @@ -15842,7 +15353,6 @@ "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", "license": "MIT", - "peer": true, "dependencies": { "duplexer": "~0.1.1", "through": "~2.3.4" @@ -15853,7 +15363,6 @@ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", "license": "MIT", - "peer": true, "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", @@ -15865,7 +15374,6 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -15888,15 +15396,13 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "license": "MIT", - "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -15915,7 +15421,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -15930,7 +15435,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -15939,15 +15443,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -15960,7 +15462,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -15977,7 +15478,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -15990,7 +15490,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -16000,7 +15499,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -16016,7 +15514,6 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -16029,7 +15526,6 @@ "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", "license": "MIT", - "peer": true, "engines": { "node": ">=20" }, @@ -16042,7 +15538,6 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "license": "MIT", - "peer": true, "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -16070,7 +15565,6 @@ "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "b4a": "^1.6.4" } @@ -16079,22 +15573,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.6" } @@ -16104,7 +15595,6 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 14.0.0" } @@ -16114,7 +15604,6 @@ "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "license": "WTFPL", - "peer": true, "dependencies": { "utf8-byte-length": "^1.0.1" } @@ -16131,7 +15620,6 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.2.0.tgz", "integrity": "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA==", "license": "(MIT OR CC0-1.0)", - "peer": true, "dependencies": { "tagged-tag": "^1.0.0" }, @@ -16147,7 +15635,6 @@ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", - "peer": true, "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", @@ -16162,7 +15649,6 @@ "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", "license": "MIT or GPL-2.0", - "peer": true, "engines": { "node": ">= 0.4.0" } @@ -16172,7 +15658,6 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -16181,15 +15666,13 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "license": "(WTFPL OR MIT)", - "peer": true + "license": "(WTFPL OR MIT)" }, "node_modules/appium-safari-driver/node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/uuid": { "version": "13.0.0", @@ -16209,7 +15692,6 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "license": "Apache-2.0", - "peer": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -16220,7 +15702,6 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8" } @@ -16231,7 +15712,6 @@ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -16241,7 +15721,6 @@ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "license": "MIT", - "peer": true, "dependencies": { "defaults": "^1.0.3" } @@ -16251,7 +15730,6 @@ "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "license": "ISC", - "peer": true, "dependencies": { "isexe": "^3.1.1" }, @@ -16267,7 +15745,6 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.18.3.tgz", "integrity": "sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", @@ -16290,7 +15767,6 @@ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", "license": "MIT", - "peer": true, "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", @@ -16305,7 +15781,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -16320,7 +15795,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -16335,7 +15809,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -16354,7 +15827,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -16372,7 +15844,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -16381,15 +15852,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -16404,7 +15873,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -16417,7 +15885,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -16426,15 +15893,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/wrap-ansi/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -16449,7 +15914,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -16461,15 +15925,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/appium-safari-driver/node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -16491,7 +15953,6 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "license": "MIT", - "peer": true, "engines": { "node": ">=8.0" } @@ -16501,7 +15962,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "license": "ISC", - "peer": true, "engines": { "node": ">=10" } @@ -16511,7 +15971,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "license": "ISC", - "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -16524,7 +15983,6 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "license": "MIT", - "peer": true, "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", @@ -16542,7 +16000,6 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "license": "ISC", - "peer": true, "engines": { "node": "^20.19.0 || ^22.12.0 || >=23" } @@ -16551,15 +16008,13 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/appium-safari-driver/node_modules/yargs/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -16577,7 +16032,6 @@ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz", "integrity": "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==", "license": "MIT", - "peer": true, "dependencies": { "buffer-crc32": "~0.2.3", "pend": "~1.2.0" @@ -16591,7 +16045,6 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "license": "MIT", - "peer": true, "engines": { "node": "*" } @@ -16601,7 +16054,6 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -16614,7 +16066,6 @@ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", "license": "MIT", - "peer": true, "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", @@ -16624,12 +16075,6 @@ "node": ">= 14" } }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "license": "ISC" - }, "node_modules/archiver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", @@ -16738,34 +16183,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -17261,21 +16678,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/canvas": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", - "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.17.0", - "simple-get": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -17376,15 +16778,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -17525,15 +16918,6 @@ "node": ">=12.20" } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/color/node_modules/color-convert": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.2.tgz", @@ -17596,6 +16980,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, "license": "MIT" }, "node_modules/consola": { @@ -17822,18 +17207,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "license": "MIT", - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/deepmerge-ts": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", @@ -17878,12 +17251,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, "node_modules/depcheck": { "version": "1.4.7", "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz", @@ -18063,6 +17430,7 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" } @@ -18084,34 +17452,8 @@ } }, "node_modules/doc-detective-common": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/doc-detective-common/-/doc-detective-common-3.6.0.tgz", - "integrity": "sha512-rHZ3WNuw3Y51KduBh9GgnrYFzJdbCQHPP3xnkp+W8QyF+4bKhWFlVVmbotFh/XL3BupbV9+CP7YEBTsW02Hvuw==", - "license": "AGPL-3.0-only", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^15.1.3", - "ajv": "^8.17.1", - "ajv-errors": "^3.0.0", - "ajv-formats": "^3.0.1", - "ajv-keywords": "^5.1.0", - "axios": "^1.13.2", - "yaml": "^2.8.2" - } - }, - "node_modules/doc-detective-common/node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } + "resolved": "../common", + "link": true }, "node_modules/doc-detective-resolver": { "version": "3.6.1", @@ -18932,36 +18274,6 @@ "node": ">= 0.8" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, "node_modules/ftp-response-parser": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ftp-response-parser/-/ftp-response-parser-1.0.1.tgz", @@ -18976,96 +18288,28 @@ "node_modules/ftp-response-parser/node_modules/readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ftp-response-parser/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "license": "MIT" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/ftp-response-parser/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/geckodriver": { @@ -19342,12 +18586,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC" - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -19628,17 +18866,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -19863,6 +19090,7 @@ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", "license": "MIT", + "peer": true, "engines": { "node": ">= 10.16.0" } @@ -20301,30 +19529,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -20438,18 +19642,6 @@ "node": ">=6" } }, - "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -20482,49 +19674,12 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mocha": { "version": "11.7.5", "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", @@ -20770,12 +19925,6 @@ "node": "*" } }, - "node_modules/nan": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.24.0.tgz", - "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==", - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -20822,63 +19971,6 @@ "node": ">= 0.4.0" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -20909,19 +20001,6 @@ "node": ">=0.10.0" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -20934,15 +20013,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -21271,15 +20341,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -21830,65 +20891,6 @@ "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", "license": "MIT" }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -22282,37 +21284,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "license": "MIT", - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -22707,23 +21678,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/tar-fs": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", @@ -22749,15 +21703,6 @@ "streamx": "^2.15.0" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "engines": { - "node": ">=8" - } - }, "node_modules/teen_process": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-3.0.2.tgz", @@ -23157,56 +22102,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/winston": { "version": "3.18.3", "resolved": "https://registry.npmjs.org/winston/-/winston-3.18.3.tgz", @@ -23440,12 +22335,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/yaml": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", diff --git a/core/package.json b/core/package.json index 537d04a..b2cc3b9 100644 --- a/core/package.json +++ b/core/package.json @@ -36,8 +36,7 @@ "appium-geckodriver": "^2.1.2", "appium-safari-driver": "^4.1.2", "axios": "^1.13.2", - "canvas": "^2.11.2", - "doc-detective-common": "^3.6.0", + "doc-detective-common": "file:../common", "doc-detective-resolver": "^3.6.1", "dotenv": "^17.2.3", "geckodriver": "^6.1.0", diff --git a/core/src/tests/annotateScreenshot.js b/core/src/tests/annotateScreenshot.js index 03daaff..6887b8f 100644 --- a/core/src/tests/annotateScreenshot.js +++ b/core/src/tests/annotateScreenshot.js @@ -1,619 +1,190 @@ -const { createCanvas, loadImage } = require("canvas"); +const sharp = require("sharp"); +const fs = require("fs"); const { findElement } = require("./findElement"); const { log } = require("../utils"); -const fs = require("fs"); - -// Constants for default dimensions and positioning -const DEFAULT_SIZE = 100; -const DEFAULT_CALLOUT_OFFSET_X = 100; -const DEFAULT_CALLOUT_OFFSET_Y = 80; +// Export exports.annotateScreenshot = annotateScreenshot; -async function annotateScreenshot({ config, filePath, annotations, driver }) { - try { - log(config, "debug", `Starting annotation of screenshot: ${filePath}`); - - // Load the screenshot image - const image = await loadImage(filePath); - const width = image.width; - const height = image.height; - - // Create a canvas and draw the image - const canvas = createCanvas(width, height); - const ctx = canvas.getContext("2d"); - ctx.drawImage(image, 0, 0); - - // Get pixel density for scaling - const pixelDensity = await driver.execute(() => window.devicePixelRatio); - log(config, "debug", `Pixel density: ${pixelDensity}`); - - // Process each annotation - for (const annotation of annotations) { - try { - await renderAnnotation({ - config, - ctx, - annotation, - driver, - pixelDensity, - canvasWidth: width, - canvasHeight: height, - }); - } catch (error) { - log( - config, - "warn", - `Failed to render annotation: ${error.message}` - ); - return { - success: false, - error: `Annotation rendering failed: ${error.message}`, - }; - } - } - - // Save canvas to file - const buffer = canvas.toBuffer("image/png"); - fs.writeFileSync(filePath, buffer); - - log( - config, - "debug", - `Successfully annotated screenshot with ${annotations.length} annotation(s)` - ); - - return { success: true }; - } catch (error) { - log(config, "error", `Annotation failed: ${error.message}`); - return { success: false, error: error.message }; - } +// Helper to escape XML for SVG text +function escapeXml(str = "") { + return String(str).replace(/[<>&'\"]/g, (c) => + ({ "<": "<", ">": ">", "&": "&", "'": "'", '"': """ }[c]) + ); } -async function renderAnnotation({ - config, - ctx, - annotation, - driver, - pixelDensity, - canvasWidth, - canvasHeight, -}) { - // Determine base position for annotation - let basePosition = { x: 0, y: 0 }; - - // If annotation has a 'find' field, locate the element - if (annotation.find) { - const findStep = { - find: annotation.find, - }; - - const findResult = await findElement({ - config, - step: findStep, - driver, - }); - - if (findResult.status === "FAIL") { - throw new Error(`Could not find element: ${findResult.description}`); - } - - const element = findResult.outputs?.rawElement; - if (!element) { - throw new Error("Element not found for annotation"); - } - - // Get element bounds and scale by pixel density - const rect = await driver.execute((el) => { - const bounds = el.getBoundingClientRect(); - return { - x: bounds.left, - y: bounds.top, - width: bounds.width, - height: bounds.height, - }; - }, element); - - // Scale coordinates by pixel density - basePosition.x = rect.x * pixelDensity; - basePosition.y = rect.y * pixelDensity; - basePosition.width = rect.width * pixelDensity; - basePosition.height = rect.height * pixelDensity; - - log(config, "debug", `Element position: ${JSON.stringify(basePosition)}`); - } +async function annotateScreenshot({ config, filePath, annotations = [], driver }) { + try { + log(config, "debug", `Starting SVG-based annotation of screenshot: ${filePath}`); - // Apply position keyword if specified - if (annotation.position) { - if (typeof annotation.position === "string") { - basePosition = applyPositionKeyword( - annotation.position, - basePosition, - canvasWidth, - canvasHeight - ); - } else if ( - typeof annotation.position === "object" && - annotation.position.x !== undefined && - annotation.position.y !== undefined - ) { - // Absolute position - basePosition = { - x: annotation.position.x * pixelDensity, - y: annotation.position.y * pixelDensity, - }; + if (!Array.isArray(annotations) || annotations.length === 0) { + log(config, "debug", "No annotations provided, skipping."); + return { success: true }; } - } - // Render annotation based on type - if (annotation.arrow) { - renderArrow(ctx, annotation.arrow, basePosition, pixelDensity); - } else if (annotation.text) { - renderText(ctx, annotation.text, basePosition, pixelDensity); - } else if (annotation.rectangle) { - renderRectangle(ctx, annotation.rectangle, basePosition, pixelDensity); - } else if (annotation.circle) { - renderCircle(ctx, annotation.circle, basePosition, pixelDensity); - } else if (annotation.line) { - renderLine(ctx, annotation.line, basePosition, pixelDensity); - } else if (annotation.callout) { - renderCallout(ctx, annotation.callout, basePosition, pixelDensity); - } else if (annotation.highlight) { - renderHighlight(ctx, annotation.highlight, basePosition, pixelDensity); - } else if (annotation.blur) { - renderBlur(ctx, annotation.blur, basePosition, pixelDensity); - } -} - -function applyPositionKeyword( - keyword, - basePosition, - canvasWidth, - canvasHeight -) { - const hasElement = basePosition.width !== undefined; - - if (!hasElement) { - // Position within viewport - switch (keyword) { - case "top": - return { x: canvasWidth / 2, y: 50 }; - case "bottom": - return { x: canvasWidth / 2, y: canvasHeight - 50 }; - case "left": - return { x: 50, y: canvasHeight / 2 }; - case "right": - return { x: canvasWidth - 50, y: canvasHeight / 2 }; - case "center": - return { x: canvasWidth / 2, y: canvasHeight / 2 }; - case "top-left": - return { x: 50, y: 50 }; - case "top-right": - return { x: canvasWidth - 50, y: 50 }; - case "bottom-left": - return { x: 50, y: canvasHeight - 50 }; - case "bottom-right": - return { x: canvasWidth - 50, y: canvasHeight - 50 }; - default: - return { x: 0, y: 0 }; + // Read image metadata + const image = sharp(filePath); + const meta = await image.metadata(); + const width = meta.width || 0; + const height = meta.height || 0; + + // Get device pixel ratio from driver, default to 1 + let pixelDensity = 1; + try { + const pd = await driver.execute(() => window.devicePixelRatio).catch(() => undefined); + if (pd && typeof pd === "number") pixelDensity = pd; + } catch (e) { + /* ignore */ } - } else { - // Position relative to element - const centerX = basePosition.x + basePosition.width / 2; - const centerY = basePosition.y + basePosition.height / 2; + log(config, "debug", `Pixel density: ${pixelDensity}`); - switch (keyword) { - case "top": - return { x: centerX, y: basePosition.y, ...basePosition }; - case "bottom": - return { - x: centerX, - y: basePosition.y + basePosition.height, - ...basePosition, - }; - case "left": - return { x: basePosition.x, y: centerY, ...basePosition }; - case "right": - return { - x: basePosition.x + basePosition.width, - y: centerY, - ...basePosition, - }; - case "center": - return { x: centerX, y: centerY, ...basePosition }; - case "top-left": - return { x: basePosition.x, y: basePosition.y, ...basePosition }; - case "top-right": - return { - x: basePosition.x + basePosition.width, - y: basePosition.y, - ...basePosition, - }; - case "bottom-left": - return { - x: basePosition.x, - y: basePosition.y + basePosition.height, - ...basePosition, + // Resolve any `find` annotations to bounding rects + const resolved = []; + for (const ann of annotations) { + const a = { ...ann }; + a._rect = null; + if (a.find) { + const findStep = { find: a.find }; + const findResult = await findElement({ config, step: findStep, driver }); + if (findResult.status === "FAIL") { + throw new Error(`Could not find element for annotation: ${findResult.description}`); + } + const element = findResult.outputs?.rawElement; + if (!element) throw new Error("Element not found for annotation"); + + const rect = await driver.execute((el) => { + const b = el.getBoundingClientRect(); + return { x: b.left, y: b.top, width: b.width, height: b.height }; + }, element); + + a._rect = { + x: Math.round(rect.x * pixelDensity), + y: Math.round(rect.y * pixelDensity), + width: Math.round(rect.width * pixelDensity), + height: Math.round(rect.height * pixelDensity), }; - case "bottom-right": - return { - x: basePosition.x + basePosition.width, - y: basePosition.y + basePosition.height, - ...basePosition, - }; - default: - return { x: centerX, y: centerY, ...basePosition }; + } + resolved.push(a); } - } -} - -function renderArrow(ctx, arrow, basePosition, pixelDensity) { - const defaults = { - color: "#FF0000", - strokeWidth: 3, - headSize: 15, - }; - - const config = { ...defaults, ...arrow }; - - // Calculate from/to positions - const fromX = basePosition.x + (arrow.from?.x || 0) * pixelDensity; - const fromY = basePosition.y + (arrow.from?.y || 0) * pixelDensity; - const toX = basePosition.x + (arrow.to?.x || 0) * pixelDensity; - const toY = basePosition.y + (arrow.to?.y || 0) * pixelDensity; - - // Draw line - ctx.strokeStyle = config.color; - ctx.lineWidth = config.strokeWidth; - ctx.beginPath(); - ctx.moveTo(fromX, fromY); - ctx.lineTo(toX, toY); - ctx.stroke(); - // Draw arrowhead - const angle = Math.atan2(toY - fromY, toX - fromX); - const headLength = config.headSize; - - ctx.save(); - ctx.translate(toX, toY); - ctx.rotate(angle); - ctx.fillStyle = config.color; - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.lineTo(-headLength, -headLength / 2); - ctx.lineTo(-headLength, headLength / 2); - ctx.closePath(); - ctx.fill(); - ctx.restore(); -} + // Build SVG overlay (without blur regions) + const svgParts = []; + svgParts.push(``); + + for (const a of resolved) { + // Compute base x,y,width,height helpers + const baseX = (a.position && typeof a.position.x === 'number') ? Math.round(a.position.x * pixelDensity) : (a._rect ? a._rect.x : 0); + const baseY = (a.position && typeof a.position.y === 'number') ? Math.round(a.position.y * pixelDensity) : (a._rect ? a._rect.y : 0); + const baseW = (a.rectangle && a.rectangle.width) ? Math.round(a.rectangle.width * pixelDensity) : (a._rect ? a._rect.width : undefined); + const baseH = (a.rectangle && a.rectangle.height) ? Math.round(a.rectangle.height * pixelDensity) : (a._rect ? a._rect.height : undefined); + + if (a.rectangle) { + const rx = (a.rectangle.rx || 0) * pixelDensity; + const ry = (a.rectangle.ry || 0) * pixelDensity; + const stroke = a.rectangle.stroke || '#FF0000'; + const strokeW = (a.rectangle.strokeWidth || 2) * pixelDensity; + const fill = (a.rectangle.fill === 'transparent') ? 'none' : (a.rectangle.fill || 'none'); + const opacity = a.rectangle.opacity == null ? 1 : a.rectangle.opacity; + const w = baseW || (100 * pixelDensity); + const h = baseH || (100 * pixelDensity); + svgParts.push(``); + continue; + } -function renderText(ctx, text, basePosition, pixelDensity) { - const defaults = { - fontSize: 16, - fontFamily: "Arial", - color: "#000000", - backgroundColor: "#FFFFFF", - padding: 5, - opacity: 1, - }; + if (a.circle) { + const cx = baseX; + const cy = baseY; + const r = Math.round((a.circle.radius || 30) * pixelDensity); + const fill = (a.circle.fill === 'transparent') ? 'none' : (a.circle.fill || 'none'); + const stroke = a.circle.stroke || '#FF0000'; + const strokeW = (a.circle.strokeWidth || 2) * pixelDensity; + const opacity = a.circle.opacity == null ? 1 : a.circle.opacity; + svgParts.push(``); + continue; + } - const config = { ...defaults, ...text }; + if (a.line || a.arrow) { + const from = (a.line && a.line.from) || (a.arrow && a.arrow.from) || { x: 0, y: 0 }; + const to = (a.line && a.line.to) || (a.arrow && a.arrow.to) || { x: 10, y: 10 }; + const fx = baseX + Math.round((from.x || 0) * pixelDensity); + const fy = baseY + Math.round((from.y || 0) * pixelDensity); + const tx = baseX + Math.round((to.x || 0) * pixelDensity); + const ty = baseY + Math.round((to.y || 0) * pixelDensity); + const color = (a.line && a.line.color) || (a.arrow && a.arrow.color) || '#000000'; + const strokeW = ((a.line && a.line.strokeWidth) || (a.arrow && a.arrow.strokeWidth) || 2) * pixelDensity; + svgParts.push(``); + if (a.arrow) { + const head = (a.arrow.headSize || 15) * pixelDensity; + const angle = Math.atan2(ty - fy, tx - fx); + const hx = tx; + const hy = ty; + const leftX = hx - Math.cos(angle) * head + Math.sin(angle) * (head / 2); + const leftY = hy - Math.sin(angle) * head - Math.cos(angle) * (head / 2); + const rightX = hx - Math.cos(angle) * head - Math.sin(angle) * (head / 2); + const rightY = hy - Math.sin(angle) * head + Math.cos(angle) * (head / 2); + svgParts.push(``); + } + continue; + } - ctx.save(); - ctx.font = `${config.fontSize * pixelDensity}px ${config.fontFamily}`; - ctx.fillStyle = config.color; - ctx.globalAlpha = config.opacity; + if (a.text) { + const x = baseX; + const y = baseY; + const fontSize = ((a.text.fontSize || 16) * pixelDensity); + const color = a.text.color || '#000000'; + const opacity = a.text.opacity == null ? 1 : a.text.opacity; + const family = a.text.fontFamily || 'Arial, sans-serif'; + const content = escapeXml(a.text.content || ''); + svgParts.push(`${content}`); + continue; + } - // Measure text - const maxWidth = config.maxWidth - ? config.maxWidth * pixelDensity - : 200 * pixelDensity; - const lines = wrapText(ctx, config.content, maxWidth); - const lineHeight = config.fontSize * pixelDensity * 1.2; - const textHeight = lines.length * lineHeight; - const padding = config.padding * pixelDensity; + if (a.highlight) { + const x = baseX; + const y = baseY; + const w = baseW || (a.highlight.width ? Math.round(a.highlight.width * pixelDensity) : (a._rect ? a._rect.width : 100)); + const h = baseH || (a.highlight.height ? Math.round(a.highlight.height * pixelDensity) : (a._rect ? a._rect.height : 100)); + const color = a.highlight.color || '#FFFF00'; + const opacity = a.highlight.opacity == null ? 0.3 : a.highlight.opacity; + svgParts.push(``); + continue; + } - // Calculate text box dimensions - let maxLineWidth = 0; - lines.forEach((line) => { - const metrics = ctx.measureText(line); - if (metrics.width > maxLineWidth) { - maxLineWidth = metrics.width; + // blur handled after SVG compositing via sharp } - }); - - // Draw background - ctx.fillStyle = config.backgroundColor; - ctx.fillRect( - basePosition.x - padding, - basePosition.y - padding, - maxLineWidth + padding * 2, - textHeight + padding * 2 - ); - - // Draw text - ctx.fillStyle = config.color; - lines.forEach((line, i) => { - ctx.fillText( - line, - basePosition.x, - basePosition.y + (i + 1) * lineHeight - lineHeight / 4 - ); - }); - - ctx.restore(); -} -function wrapText(ctx, text, maxWidth) { - const words = text.split(" "); - const lines = []; - let currentLine = ""; - - words.forEach((word) => { - const testLine = currentLine + (currentLine ? " " : "") + word; - const metrics = ctx.measureText(testLine); - - if (metrics.width > maxWidth && currentLine) { - lines.push(currentLine); - currentLine = word; + svgParts.push(``); + const svg = svgParts.join('\n'); + + // Composite SVG overlay onto original image -> buffer + const baseBuffer = await image.composite([{ input: Buffer.from(svg), blend: 'over' }]).png().toBuffer(); + + // If there are blur annotations, apply them by extracting, blurring, and compositing + const blurAnns = resolved.filter((a) => a.blur); + if (blurAnns.length > 0) { + let working = sharp(baseBuffer); + for (const b of blurAnns) { + const bx = (b.position && typeof b.position.x === 'number') ? Math.round(b.position.x * pixelDensity) : (b._rect ? b._rect.x : 0); + const by = (b.position && typeof b.position.y === 'number') ? Math.round(b.position.y * pixelDensity) : (b._rect ? b._rect.y : 0); + const bw = (b.blur && b.blur.width) ? Math.round(b.blur.width * pixelDensity) : (b._rect ? b._rect.width : Math.round((b.blur && b.blur.width) || 100)); + const bh = (b.blur && b.blur.height) ? Math.round(b.blur.height * pixelDensity) : (b._rect ? b._rect.height : Math.round((b.blur && b.blur.height) || 50)); + try { + const extracted = await sharp(baseBuffer).extract({ left: bx, top: by, width: bw, height: bh }).blur(b.blur.intensity || 10).toBuffer(); + working = working.composite([{ input: extracted, left: bx, top: by }]); + } catch (err) { + log(config, 'warn', `Couldn't apply blur for annotation: ${err.message}`); + } + } + await working.png().toFile(filePath); } else { - currentLine = testLine; + // No blur; write composed buffer directly + fs.writeFileSync(filePath, baseBuffer); } - }); - if (currentLine) { - lines.push(currentLine); - } - - return lines.length > 0 ? lines : [text]; -} - -function renderRectangle(ctx, rectangle, basePosition, pixelDensity) { - const defaults = { - fill: "transparent", - stroke: "#FF0000", - strokeWidth: 2, - opacity: 1, - rx: 0, - ry: 0, - }; - - const config = { ...defaults, ...rectangle }; - - const x = basePosition.x; - const y = basePosition.y; - const width = (config.width ?? basePosition.width ?? DEFAULT_SIZE) * pixelDensity; - const height = (config.height ?? basePosition.height ?? DEFAULT_SIZE) * pixelDensity; - const rx = config.rx * pixelDensity; - const ry = config.ry * pixelDensity; - - ctx.save(); - ctx.globalAlpha = config.opacity; - - // Draw rounded rectangle - ctx.beginPath(); - if (rx > 0 || ry > 0) { - const r = Math.max(rx, ry); - ctx.moveTo(x + r, y); - ctx.lineTo(x + width - r, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + r); - ctx.lineTo(x + width, y + height - r); - ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height); - ctx.lineTo(x + r, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - r); - ctx.lineTo(x, y + r); - ctx.quadraticCurveTo(x, y, x + r, y); - } else { - ctx.rect(x, y, width, height); - } - ctx.closePath(); - - if (config.fill !== "transparent") { - ctx.fillStyle = config.fill; - ctx.fill(); - } - - if (config.strokeWidth > 0) { - ctx.strokeStyle = config.stroke; - ctx.lineWidth = config.strokeWidth * pixelDensity; - ctx.stroke(); - } - - ctx.restore(); -} - -function renderCircle(ctx, circle, basePosition, pixelDensity) { - const defaults = { - radius: 30, - fill: "transparent", - stroke: "#FF0000", - strokeWidth: 2, - opacity: 1, - }; - - const config = { ...defaults, ...circle }; - - ctx.save(); - ctx.globalAlpha = config.opacity; - - ctx.beginPath(); - ctx.arc( - basePosition.x, - basePosition.y, - config.radius * pixelDensity, - 0, - 2 * Math.PI - ); - - if (config.fill !== "transparent") { - ctx.fillStyle = config.fill; - ctx.fill(); - } - - if (config.strokeWidth > 0) { - ctx.strokeStyle = config.stroke; - ctx.lineWidth = config.strokeWidth * pixelDensity; - ctx.stroke(); - } - - ctx.restore(); -} - -function renderLine(ctx, line, basePosition, pixelDensity) { - const defaults = { - color: "#000000", - strokeWidth: 2, - }; - - const config = { ...defaults, ...line }; - - const fromX = basePosition.x + (line.from?.x || 0) * pixelDensity; - const fromY = basePosition.y + (line.from?.y || 0) * pixelDensity; - const toX = basePosition.x + (line.to?.x || 0) * pixelDensity; - const toY = basePosition.y + (line.to?.y || 0) * pixelDensity; - - ctx.save(); - ctx.strokeStyle = config.color; - ctx.lineWidth = config.strokeWidth * pixelDensity; - - if (config.dashArray) { - ctx.setLineDash(config.dashArray.map((v) => v * pixelDensity)); - } - - ctx.beginPath(); - ctx.moveTo(fromX, fromY); - ctx.lineTo(toX, toY); - ctx.stroke(); - - ctx.restore(); -} - -function renderCallout(ctx, callout, basePosition, pixelDensity) { - const defaults = { - fontSize: 14, - color: "#000000", - backgroundColor: "#FFFFCC", - arrowColor: "#000000", - }; - - const config = { ...defaults, ...callout }; - - // Target position - const targetX = basePosition.x + (callout.target?.x || 0) * pixelDensity; - const targetY = basePosition.y + (callout.target?.y || 0) * pixelDensity; - - // Text position (auto-position if not specified) - let textX, textY; - if (callout.textPosition) { - textX = basePosition.x + callout.textPosition.x * pixelDensity; - textY = basePosition.y + callout.textPosition.y * pixelDensity; - } else { - // Auto-position above and to the left of target - textX = targetX - DEFAULT_CALLOUT_OFFSET_X * pixelDensity; - textY = targetY - DEFAULT_CALLOUT_OFFSET_Y * pixelDensity; + log(config, 'debug', `Successfully annotated screenshot with ${annotations.length} annotation(s)`); + return { success: true }; + } catch (error) { + log(config, 'error', `Annotation failed: ${error.message}`); + return { success: false, error: error.message }; } - - // Draw text box - ctx.save(); - ctx.font = `${config.fontSize * pixelDensity}px Arial`; - - const maxWidth = config.maxWidth - ? config.maxWidth * pixelDensity - : 150 * pixelDensity; - const lines = wrapText(ctx, config.content, maxWidth); - const lineHeight = config.fontSize * pixelDensity * 1.2; - const textHeight = lines.length * lineHeight; - const padding = 8 * pixelDensity; - - let maxLineWidth = 0; - lines.forEach((line) => { - const metrics = ctx.measureText(line); - if (metrics.width > maxLineWidth) { - maxLineWidth = metrics.width; - } - }); - - const boxWidth = maxLineWidth + padding * 2; - const boxHeight = textHeight + padding * 2; - - // Draw background - ctx.fillStyle = config.backgroundColor; - ctx.fillRect(textX, textY, boxWidth, boxHeight); - - // Draw text - ctx.fillStyle = config.color; - lines.forEach((line, i) => { - ctx.fillText( - line, - textX + padding, - textY + padding + (i + 1) * lineHeight - lineHeight / 4 - ); - }); - - // Draw arrow from text to target - const textCenterX = textX + boxWidth / 2; - const textCenterY = textY + boxHeight / 2; - - ctx.strokeStyle = config.arrowColor; - ctx.lineWidth = 2 * pixelDensity; - ctx.beginPath(); - ctx.moveTo(textCenterX, textCenterY); - ctx.lineTo(targetX, targetY); - ctx.stroke(); - - // Draw arrowhead - const angle = Math.atan2(targetY - textCenterY, targetX - textCenterX); - const headLength = 10 * pixelDensity; - - ctx.translate(targetX, targetY); - ctx.rotate(angle); - ctx.fillStyle = config.arrowColor; - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.lineTo(-headLength, -headLength / 2); - ctx.lineTo(-headLength, headLength / 2); - ctx.closePath(); - ctx.fill(); - - ctx.restore(); -} - -function renderHighlight(ctx, highlight, basePosition, pixelDensity) { - const defaults = { - color: "#FFFF00", - opacity: 0.3, - }; - - const config = { ...defaults, ...highlight }; - - ctx.save(); - ctx.fillStyle = config.color; - ctx.globalAlpha = config.opacity; - ctx.fillRect( - basePosition.x, - basePosition.y, - basePosition.width ?? DEFAULT_SIZE * pixelDensity, - basePosition.height ?? DEFAULT_SIZE * pixelDensity - ); - ctx.restore(); -} - -function renderBlur(ctx, blur, basePosition, pixelDensity) { - const defaults = { - intensity: 10, - }; - - const config = { ...defaults, ...blur }; - - // For blur, we use a semi-transparent overlay as a visual indicator - // True pixel blur would require Sharp preprocessing - ctx.save(); - ctx.fillStyle = "rgba(200, 200, 200, 0.8)"; - ctx.fillRect( - basePosition.x, - basePosition.y, - (config.width ?? basePosition.width ?? DEFAULT_SIZE) * pixelDensity, - (config.height ?? basePosition.height ?? DEFAULT_SIZE) * pixelDensity - ); - ctx.restore(); } diff --git a/core/src/tests/saveScreenshot.js b/core/src/tests/saveScreenshot.js index 9c08ae7..879e797 100644 --- a/core/src/tests/saveScreenshot.js +++ b/core/src/tests/saveScreenshot.js @@ -88,7 +88,7 @@ async function saveScreenshot({ config, step, driver }) { result.description = `File already exists: ${filePath}`; return result; } else { - // Set temp file path + await sharp(filePath) existFilePath = filePath; filePath = path.join(dir, `${step.stepId}_${Date.now()}.png`); } diff --git a/core/test/artifacts/screenshot-with-crop-elementTestId_1765828572849.png b/core/test/artifacts/screenshot-with-crop-elementTestId_1765828572849.png new file mode 100644 index 0000000000000000000000000000000000000000..19b83f1ddc975511b1f754fbc4b2ab9530986b1a GIT binary patch literal 1160 zcmV;31b6$1P)@?E!Hi@E%w1BM&tURiOY-2gK^gf zUu~i>8WRs7f?%N=>1K;nsx)07OPdhrHORnf5V-?xI8;vpT&Y0@ zR)feLaKoW`65vV=GO!v%?tmK()sp~MYLJ1|AaV!XaHyUH{4bUIN+tZ-IsR0-;1?)e zKeqqfegK|Xbc%dARUbI96c#r?XFm)LLq{*n-WVO!cUJT7mH)%YwKH?fPhIDK=uk%u z;N5d!;3&-9WNZhB>u~L8D1?5{(uO~wl z@O6Jc&td55hmu-2C)d_a3rt<@2jReB3&!(HLxmOAz@9_4x2g#)`6xBiFSbJSK6t7k zajkkgy!TxqRGpo>7IySN|54b`4)@Pb-1pW>*x3VpL$IvT&X0%s_9|%E5Bmn}oR=%p z6zZjg7M$b&q=I^JfqnF(Z{h4*xT+X7cEHRHw*J6;gLYAYJzqBkuKd{U^VUKA9=N>7 z_Et8*@@=W1svRiMD}D=qzj2zqUlk=DYECsYbi(yh;jA2ZtqKke!L=o}{$z#0yyp{3 zJXN7%eJ-&3*Nh{L$EPZ zpMK$lYGwD$gW=-_cr>U>8%@cB$3p*96{ge~+<2%`){Dy$&yZTBXx)EV4`rJZ*S~K~ zU4G@0E+t9YL6vHB-8*k=P_wJ8{Kc=|GQ-ZeFyEeUEwv!3#43=n-;e)oDsDSyCdj=< z;IhKhP<6kg!Bnn5?;U`frjLZGan0@SrxJKEG?=j%Ob z2UVt_LqpP7puWBwe(z3Pf4tn_B=3{TR<*#wt@gaTZ)AVWN@4L(ANdS+^}?%F*30!< zGE^nVOG!#qTX=JY-B;AZoTP93x;ca@pxgGsgvs`NUS66*ePW^Ym*QGe-MM+zi*B1a z5~@J$AA~o)vEk&3B3R#UWl`(eck^_+SMQoyX9JO*3x0$xyG?0&)|7qMoRdS8nP#GK<4x#GrSIy!3l?-VORrc@#Skr1H zQ-D<_71(5`vFW#FhxJaC(W07gpty6kDZhKrl)17c99EPBAFQ>>Sbb9Kg*7LK8dH)= zZ>;|&LlsDsXq~BVsNHEpQSzC3w_t1fRg%S^YM}e6&5}n7*B~h6rZrSIqKknCpYfM~ zkvrgqL-i!Ul^SGVHHh2+Hyo-b0j|^_1FJ#g4!Ge^Jqd871{qilB6q+Ihw4dyD>cZx aYVZ$d+(<6)GEc++0000|6t%(3JZiTA6dX&BC-xOeMM^}n)Ut9Y%StOP zD>K9yQ5-1Eyp>80fP!1EnN|pRNC8EGyE&Z?_uF}T&i!`z^sZ;^XFY4Jcm4mr{qD7s zj(ED7&RQ}H27{Tp9XfCn1~Wv#Uh4-a*UG4zE?c9=CzDl;ic1MLYgcxGTaB#Wbj3}C`xlXOM|%e- z+NRGkOGL`_*W@BUpvX2m_Wm#?eM&W4#Eybyg285Yuc}|KYd9bDHq^x#Gika2TM-1; zh2^UX40JI*{)8@ENGsN@88&wwYML(Y`*ZN2zZlF-dg);Yc0M>ibPv2_=GfJjks1DO zT{S;|TAM|dR!s^u;6mRsucYrb6p2wjA-6RZY*GAt&o7(UQ{SX&W#5RjZc>VuF!)j@ zW8J*-X)7*s|B-u;_&J*zt88;c5F0L=5#qwyTr4C`T9WWnijTQl7jl76TY_cTzGFx^EBN4IVL3T~cBE|yvqpyq+k@h1s5hT7JNzRo2 zf|PfH&>BIi!va?XCDK0ej(_xNsxXUC*9|>724-OK-OyGR)r;aErkB2+=Uz??_?{8% zPy1)l;M2SuWUr+Hph%M88~#=rXKeLl=mDu$q14`)nRM>do9kaQFt~ha&1mcJ!Rw3K zYUMmEn49V-kU+at7h{CKW`$K~$m_i|;{&N6$4T2`#o5v@JFGPP>1~wA`d;u&d{=Q0 zyEgnxA5}}S$16cnz_kvo=l3N{Q4$xREW88bq+O>{!_u<`SOY2cte;aIO34Gsc9^st zs#aY+ea@~NB-&hB`hL^!P&QQ~?Z1qW{+fCESycCA^L9>;fo}qfwO}d}C_J5>Emz$} z`&ZR6KMw9Sw(Rsro0mC;K0H74)rvYLTj;_b|9DNBmmQ1C_Q4qtU*tc-QByg+eP*$&-EdD>`n#SCe|qHsRT7#V}!b!oD8Y*s#5ISFZ54++>yToik9N>6T3l-U$$F zn>{J5CR}TDwIm)V@q9vwBQ>L*CN#MFhF;Xh2a)Y=!mSSC;szF-*~`)$(j0s72OG#h zAS5GRy=Y@ubGue5%O4Hs!v?7yUADrxTXa@sp1itFFgpD~y8rURL9?A;WJgqwh{70w z2a~^BUgKtDO54ny3TJkmyvDeIiX(1;d+~iET6QupL5z!mE|uY}yFW*A94G%tYJ{W5 z8u}sQ@lS>jlG`wZF^DvT8-@PZ_3yYl#OMGD*JFFjjxeFKIbjPN@PbT)ua;B*$I@-N zK7D?BD=kpNcD&%w{I~DX{^tjoByG`5QyP5F@ZFlRc6T*rWTLEi&j(q)+Xpz>x5VR$ zr{lyYHDx4$i^1nu$MCU)T7{1s3rxh#;toPulA;1A@}2!;NOR0}?T?;2M@y?dM=d4P zoFzL*$~&SUN5$Cn#f&nVp#4YJh+fbtC^YAqH%ox>5o}NbTu@>4rzmdjZ4d>{r`aY) zzczO*5A^Ox%Z~ZxMw*f}k&F>BXH01FKFHVI{@DJ4k3k*|3hTuH*mg7y4-)xdH;Vny z9rxJm;8;j+z>PAd*>snhSDmj#p7xSXNg2mcQaZ-EUsqSAcx15#z!IX%>dGqAz43|M z%%k+Amdq`d{PB9xc#0Q=s!o~p1j#6ppDU~y!j&-a%_p>*A*$^+xkLPgEK2lCb@+A& z>zJctz3S9-PKebCO#3566={B1T&o+h@GeHi;+0CEY-KZ_UHb3ieQLcNpmXAQ-gIXa z5P~Wwc;5=V2!|v+JZJZ(w3%~g16khcZ|^q?Zw2SeksDU|$H*EbvLl_bv7;?^VcCa0 z1~!#7Z==qjX_KD9*3aN?&7av4$BXl5z`2Ms4b)Sk9ASiQ6~>OMQoj~K@)X$AjM1PX}l}le6#++_q9p;d}1z&|!EpPE}&y1AY+|#d9;G=}GTdk(5iOJAa#B0#W#Y zNhXqU-*1C2we@Cz5+Zzb7X%6 z62yC`NVzW^z}hXNDV4JqqKx;f*>6e{64(^xhkYiD)1kWe*xfGEbp)+=366OFyi27|=mSPpMC)!LI1D6n+4E5D9w&IAH4r+&kgb?C0H^-_ z?^n!!7Az?xMwHB&&~1E6$&#bqA@$r_IF}Ds-|Bi^QjLS;PU4&Hn@%6gv|as2nK4D0 z`(t&+-zrk{gMYB9(6>0PCF6;wF?&8s;*N%SPq ulSEGvJxO%85I_23Lr+gVJ^w%GsY2wPyZ&h!HLFGE6E_#n1BLqnFa8IB+-}qW literal 0 HcmV?d00001 diff --git a/core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765852453886.png b/core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765852453886.png new file mode 100644 index 0000000000000000000000000000000000000000..ac82900abbfd42180ba0dbf83ae1c2d13fa561db GIT binary patch literal 7369 zcmeI1X;@O*8pp|wTA7&@*`!pbY_!>|6t%(3JZiTA6dX&BC-xOeMM^}n)Ut9Y%StOP zD>K9yQ5-1Eyp>80fP!1EnN|pRNC8EGyE&Z?_uF}T&i!`z^sZ;^XFY4Jcm4mr{qD7s zj(ED7&RQ}H27{Tp9XfCn1~Wv#Uh4-a*UG4zE?c9=CzDl;ic1MLYgcxGTaB#Wbj3}C`xlXOM|%e- z+NRGkOGL`_*W@BUpvX2m_Wm#?eM&W4#Eybyg285Yuc}|KYd9bDHq^x#Gika2TM-1; zh2^UX40JI*{)8@ENGsN@88&wwYML(Y`*ZN2zZlF-dg);Yc0M>ibPv2_=GfJjks1DO zT{S;|TAM|dR!s^u;6mRsucYrb6p2wjA-6RZY*GAt&o7(UQ{SX&W#5RjZc>VuF!)j@ zW8J*-X)7*s|B-u;_&J*zt88;c5F0L=5#qwyTr4C`T9WWnijTQl7jl76TY_cTzGFx^EBN4IVL3T~cBE|yvqpyq+k@h1s5hT7JNzRo2 zf|PfH&>BIi!va?XCDK0ej(_xNsxXUC*9|>724-OK-OyGR)r;aErkB2+=Uz??_?{8% zPy1)l;M2SuWUr+Hph%M88~#=rXKeLl=mDu$q14`)nRM>do9kaQFt~ha&1mcJ!Rw3K zYUMmEn49V-kU+at7h{CKW`$K~$m_i|;{&N6$4T2`#o5v@JFGPP>1~wA`d;u&d{=Q0 zyEgnxA5}}S$16cnz_kvo=l3N{Q4$xREW88bq+O>{!_u<`SOY2cte;aIO34Gsc9^st zs#aY+ea@~NB-&hB`hL^!P&QQ~?Z1qW{+fCESycCA^L9>;fo}qfwO}d}C_J5>Emz$} z`&ZR6KMw9Sw(Rsro0mC;K0H74)rvYLTj;_b|9DNBmmQ1C_Q4qtU*tc-QByg+eP*$&-EdD>`n#SCe|qHsRT7#V}!b!oD8Y*s#5ISFZ54++>yToik9N>6T3l-U$$F zn>{J5CR}TDwIm)V@q9vwBQ>L*CN#MFhF;Xh2a)Y=!mSSC;szF-*~`)$(j0s72OG#h zAS5GRy=Y@ubGue5%O4Hs!v?7yUADrxTXa@sp1itFFgpD~y8rURL9?A;WJgqwh{70w z2a~^BUgKtDO54ny3TJkmyvDeIiX(1;d+~iET6QupL5z!mE|uY}yFW*A94G%tYJ{W5 z8u}sQ@lS>jlG`wZF^DvT8-@PZ_3yYl#OMGD*JFFjjxeFKIbjPN@PbT)ua;B*$I@-N zK7D?BD=kpNcD&%w{I~DX{^tjoByG`5QyP5F@ZFlRc6T*rWTLEi&j(q)+Xpz>x5VR$ zr{lyYHDx4$i^1nu$MCU)T7{1s3rxh#;toPulA;1A@}2!;NOR0}?T?;2M@y?dM=d4P zoFzL*$~&SUN5$Cn#f&nVp#4YJh+fbtC^YAqH%ox>5o}NbTu@>4rzmdjZ4d>{r`aY) zzczO*5A^Ox%Z~ZxMw*f}k&F>BXH01FKFHVI{@DJ4k3k*|3hTuH*mg7y4-)xdH;Vny z9rxJm;8;j+z>PAd*>snhSDmj#p7xSXNg2mcQaZ-EUsqSAcx15#z!IX%>dGqAz43|M z%%k+Amdq`d{PB9xc#0Q=s!o~p1j#6ppDU~y!j&-a%_p>*A*$^+xkLPgEK2lCb@+A& z>zJctz3S9-PKebCO#3566={B1T&o+h@GeHi;+0CEY-KZ_UHb3ieQLcNpmXAQ-gIXa z5P~Wwc;5=V2!|v+JZJZ(w3%~g16khcZ|^q?Zw2SeksDU|$H*EbvLl_bv7;?^VcCa0 z1~!#7Z==qjX_KD9*3aN?&7av4$BXl5z`2Ms4b)Sk9ASiQ6~>OMQoj~K@)X$AjM1PX}l}le6#++_q9p;d}1z&|!EpPE}&y1AY+|#d9;G=}GTdk(5iOJAa#B0#W#Y zNhXqU-*1C2we@Cz5+Zzb7X%6 z62yC`NVzW^z}hXNDV4JqqKx;f*>6e{64(^xhkYiD)1kWe*xfGEbp)+=366OFyi27|=mSPpMC)!LI1D6n+4E5D9w&IAH4r+&kgb?C0H^-_ z?^n!!7Az?xMwHB&&~1E6$&#bqA@$r_IF}Ds-|Bi^QjLS;PU4&Hn@%6gv|as2nK4D0 z`(t&+-zrk{gMYB9(6>0PCF6;wF?&8s;*N%SPq ulSEGvJxO%85I_23Lr+gVJ^w%GsY2wPyZ&h!HLFGE6E_#n1BLqnFa8IB+-}qW literal 0 HcmV?d00001 diff --git a/core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765852858413.png b/core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765852858413.png new file mode 100644 index 0000000000000000000000000000000000000000..ac82900abbfd42180ba0dbf83ae1c2d13fa561db GIT binary patch literal 7369 zcmeI1X;@O*8pp|wTA7&@*`!pbY_!>|6t%(3JZiTA6dX&BC-xOeMM^}n)Ut9Y%StOP zD>K9yQ5-1Eyp>80fP!1EnN|pRNC8EGyE&Z?_uF}T&i!`z^sZ;^XFY4Jcm4mr{qD7s zj(ED7&RQ}H27{Tp9XfCn1~Wv#Uh4-a*UG4zE?c9=CzDl;ic1MLYgcxGTaB#Wbj3}C`xlXOM|%e- z+NRGkOGL`_*W@BUpvX2m_Wm#?eM&W4#Eybyg285Yuc}|KYd9bDHq^x#Gika2TM-1; zh2^UX40JI*{)8@ENGsN@88&wwYML(Y`*ZN2zZlF-dg);Yc0M>ibPv2_=GfJjks1DO zT{S;|TAM|dR!s^u;6mRsucYrb6p2wjA-6RZY*GAt&o7(UQ{SX&W#5RjZc>VuF!)j@ zW8J*-X)7*s|B-u;_&J*zt88;c5F0L=5#qwyTr4C`T9WWnijTQl7jl76TY_cTzGFx^EBN4IVL3T~cBE|yvqpyq+k@h1s5hT7JNzRo2 zf|PfH&>BIi!va?XCDK0ej(_xNsxXUC*9|>724-OK-OyGR)r;aErkB2+=Uz??_?{8% zPy1)l;M2SuWUr+Hph%M88~#=rXKeLl=mDu$q14`)nRM>do9kaQFt~ha&1mcJ!Rw3K zYUMmEn49V-kU+at7h{CKW`$K~$m_i|;{&N6$4T2`#o5v@JFGPP>1~wA`d;u&d{=Q0 zyEgnxA5}}S$16cnz_kvo=l3N{Q4$xREW88bq+O>{!_u<`SOY2cte;aIO34Gsc9^st zs#aY+ea@~NB-&hB`hL^!P&QQ~?Z1qW{+fCESycCA^L9>;fo}qfwO}d}C_J5>Emz$} z`&ZR6KMw9Sw(Rsro0mC;K0H74)rvYLTj;_b|9DNBmmQ1C_Q4qtU*tc-QByg+eP*$&-EdD>`n#SCe|qHsRT7#V}!b!oD8Y*s#5ISFZ54++>yToik9N>6T3l-U$$F zn>{J5CR}TDwIm)V@q9vwBQ>L*CN#MFhF;Xh2a)Y=!mSSC;szF-*~`)$(j0s72OG#h zAS5GRy=Y@ubGue5%O4Hs!v?7yUADrxTXa@sp1itFFgpD~y8rURL9?A;WJgqwh{70w z2a~^BUgKtDO54ny3TJkmyvDeIiX(1;d+~iET6QupL5z!mE|uY}yFW*A94G%tYJ{W5 z8u}sQ@lS>jlG`wZF^DvT8-@PZ_3yYl#OMGD*JFFjjxeFKIbjPN@PbT)ua;B*$I@-N zK7D?BD=kpNcD&%w{I~DX{^tjoByG`5QyP5F@ZFlRc6T*rWTLEi&j(q)+Xpz>x5VR$ zr{lyYHDx4$i^1nu$MCU)T7{1s3rxh#;toPulA;1A@}2!;NOR0}?T?;2M@y?dM=d4P zoFzL*$~&SUN5$Cn#f&nVp#4YJh+fbtC^YAqH%ox>5o}NbTu@>4rzmdjZ4d>{r`aY) zzczO*5A^Ox%Z~ZxMw*f}k&F>BXH01FKFHVI{@DJ4k3k*|3hTuH*mg7y4-)xdH;Vny z9rxJm;8;j+z>PAd*>snhSDmj#p7xSXNg2mcQaZ-EUsqSAcx15#z!IX%>dGqAz43|M z%%k+Amdq`d{PB9xc#0Q=s!o~p1j#6ppDU~y!j&-a%_p>*A*$^+xkLPgEK2lCb@+A& z>zJctz3S9-PKebCO#3566={B1T&o+h@GeHi;+0CEY-KZ_UHb3ieQLcNpmXAQ-gIXa z5P~Wwc;5=V2!|v+JZJZ(w3%~g16khcZ|^q?Zw2SeksDU|$H*EbvLl_bv7;?^VcCa0 z1~!#7Z==qjX_KD9*3aN?&7av4$BXl5z`2Ms4b)Sk9ASiQ6~>OMQoj~K@)X$AjM1PX}l}le6#++_q9p;d}1z&|!EpPE}&y1AY+|#d9;G=}GTdk(5iOJAa#B0#W#Y zNhXqU-*1C2we@Cz5+Zzb7X%6 z62yC`NVzW^z}hXNDV4JqqKx;f*>6e{64(^xhkYiD)1kWe*xfGEbp)+=366OFyi27|=mSPpMC)!LI1D6n+4E5D9w&IAH4r+&kgb?C0H^-_ z?^n!!7Az?xMwHB&&~1E6$&#bqA@$r_IF}Ds-|Bi^QjLS;PU4&Hn@%6gv|as2nK4D0 z`(t&+-zrk{gMYB9(6>0PCF6;wF?&8s;*N%SPq ulSEGvJxO%85I_23Lr+gVJ^w%GsY2wPyZ&h!HLFGE6E_#n1BLqnFa8IB+-}qW literal 0 HcmV?d00001 diff --git a/core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765856264741.png b/core/test/artifacts/test/artifacts/annotations/annotation-arrow_1765856264741.png new file mode 100644 index 0000000000000000000000000000000000000000..ac82900abbfd42180ba0dbf83ae1c2d13fa561db GIT binary patch literal 7369 zcmeI1X;@O*8pp|wTA7&@*`!pbY_!>|6t%(3JZiTA6dX&BC-xOeMM^}n)Ut9Y%StOP zD>K9yQ5-1Eyp>80fP!1EnN|pRNC8EGyE&Z?_uF}T&i!`z^sZ;^XFY4Jcm4mr{qD7s zj(ED7&RQ}H27{Tp9XfCn1~Wv#Uh4-a*UG4zE?c9=CzDl;ic1MLYgcxGTaB#Wbj3}C`xlXOM|%e- z+NRGkOGL`_*W@BUpvX2m_Wm#?eM&W4#Eybyg285Yuc}|KYd9bDHq^x#Gika2TM-1; zh2^UX40JI*{)8@ENGsN@88&wwYML(Y`*ZN2zZlF-dg);Yc0M>ibPv2_=GfJjks1DO zT{S;|TAM|dR!s^u;6mRsucYrb6p2wjA-6RZY*GAt&o7(UQ{SX&W#5RjZc>VuF!)j@ zW8J*-X)7*s|B-u;_&J*zt88;c5F0L=5#qwyTr4C`T9WWnijTQl7jl76TY_cTzGFx^EBN4IVL3T~cBE|yvqpyq+k@h1s5hT7JNzRo2 zf|PfH&>BIi!va?XCDK0ej(_xNsxXUC*9|>724-OK-OyGR)r;aErkB2+=Uz??_?{8% zPy1)l;M2SuWUr+Hph%M88~#=rXKeLl=mDu$q14`)nRM>do9kaQFt~ha&1mcJ!Rw3K zYUMmEn49V-kU+at7h{CKW`$K~$m_i|;{&N6$4T2`#o5v@JFGPP>1~wA`d;u&d{=Q0 zyEgnxA5}}S$16cnz_kvo=l3N{Q4$xREW88bq+O>{!_u<`SOY2cte;aIO34Gsc9^st zs#aY+ea@~NB-&hB`hL^!P&QQ~?Z1qW{+fCESycCA^L9>;fo}qfwO}d}C_J5>Emz$} z`&ZR6KMw9Sw(Rsro0mC;K0H74)rvYLTj;_b|9DNBmmQ1C_Q4qtU*tc-QByg+eP*$&-EdD>`n#SCe|qHsRT7#V}!b!oD8Y*s#5ISFZ54++>yToik9N>6T3l-U$$F zn>{J5CR}TDwIm)V@q9vwBQ>L*CN#MFhF;Xh2a)Y=!mSSC;szF-*~`)$(j0s72OG#h zAS5GRy=Y@ubGue5%O4Hs!v?7yUADrxTXa@sp1itFFgpD~y8rURL9?A;WJgqwh{70w z2a~^BUgKtDO54ny3TJkmyvDeIiX(1;d+~iET6QupL5z!mE|uY}yFW*A94G%tYJ{W5 z8u}sQ@lS>jlG`wZF^DvT8-@PZ_3yYl#OMGD*JFFjjxeFKIbjPN@PbT)ua;B*$I@-N zK7D?BD=kpNcD&%w{I~DX{^tjoByG`5QyP5F@ZFlRc6T*rWTLEi&j(q)+Xpz>x5VR$ zr{lyYHDx4$i^1nu$MCU)T7{1s3rxh#;toPulA;1A@}2!;NOR0}?T?;2M@y?dM=d4P zoFzL*$~&SUN5$Cn#f&nVp#4YJh+fbtC^YAqH%ox>5o}NbTu@>4rzmdjZ4d>{r`aY) zzczO*5A^Ox%Z~ZxMw*f}k&F>BXH01FKFHVI{@DJ4k3k*|3hTuH*mg7y4-)xdH;Vny z9rxJm;8;j+z>PAd*>snhSDmj#p7xSXNg2mcQaZ-EUsqSAcx15#z!IX%>dGqAz43|M z%%k+Amdq`d{PB9xc#0Q=s!o~p1j#6ppDU~y!j&-a%_p>*A*$^+xkLPgEK2lCb@+A& z>zJctz3S9-PKebCO#3566={B1T&o+h@GeHi;+0CEY-KZ_UHb3ieQLcNpmXAQ-gIXa z5P~Wwc;5=V2!|v+JZJZ(w3%~g16khcZ|^q?Zw2SeksDU|$H*EbvLl_bv7;?^VcCa0 z1~!#7Z==qjX_KD9*3aN?&7av4$BXl5z`2Ms4b)Sk9ASiQ6~>OMQoj~K@)X$AjM1PX}l}le6#++_q9p;d}1z&|!EpPE}&y1AY+|#d9;G=}GTdk(5iOJAa#B0#W#Y zNhXqU-*1C2we@Cz5+Zzb7X%6 z62yC`NVzW^z}hXNDV4JqqKx;f*>6e{64(^xhkYiD)1kWe*xfGEbp)+=366OFyi27|=mSPpMC)!LI1D6n+4E5D9w&IAH4r+&kgb?C0H^-_ z?^n!!7Az?xMwHB&&~1E6$&#bqA@$r_IF}Ds-|Bi^QjLS;PU4&Hn@%6gv|as2nK4D0 z`(t&+-zrk{gMYB9(6>0PCF6;wF?&8s;*N%SPq ulSEGvJxO%85I_23Lr+gVJ^w%GsY2wPyZ&h!HLFGE6E_#n1BLqnFa8IB+-}qW literal 0 HcmV?d00001 diff --git a/core/test/artifacts/test/artifacts/annotations/annotation-text-simple.png b/core/test/artifacts/test/artifacts/annotations/annotation-text-simple.png new file mode 100644 index 0000000000000000000000000000000000000000..92d5fdd4f3204ccd7059a08511ff322f82e5a16b GIT binary patch literal 8729 zcmeHNeN>X!)+c-WvN5KaWtN&YQ%#d*=1gX3>hvWwea&PdK}6=H2_YGRCIZc*V_#~` zG}dTHjg=`NI0_gDnAB()m?@wjkXl+GQYoM!@Pe-O{(INGbML$EAO7*I%{uGZ=hJ<-tGVZz+>0W?FRsWSzrLbt#a;c=SZ7$mfb1lo!WT_3joaj)b-2& z6yID704xLS+P>vr=FLI%nRiuKTT|LK;uCyh=ke>WJCDs>xV84eAH{z@s?EPk4fpm= z{NYZ;@PK1 zgjITBk=1V8MAc)1o;z&-0M4(uf?nYIahBz>7Vz;W;2AEtwK2dYzS#+x<&tyf(Od%X zS%RlaEL%Z$bIF{XIF~qk-7@72_nCHI7j6+f6Y2It;qObptP(CcKXT6 zzCM5Q#CrovyugPus3929UWZR@A=Ko_4%zlT{i5XL=aXw&Cv4OK$)jSauZv*H`t^YejYhJA06TVJrE=52&33z0>)=$xmUC9e-uq}i%`q_$t-`iO zhP?|27LN8dSlw^LA5Pn0bPQ0*QQ;(FQe)0M14osL!WK_C55r>d%t{oOI`L{%S(R07 zBq=s%vxhk&FLrZr3OJXN_Sce`dTFGko71wEU%Q_?-Y#gnjpJL(3Zs;;__Dyj*`;`8 z3i?tI=MB-!(^vV74j#V_m-{>(~cEyy+^9OH_- zT$%er#MsmLtdQ*2zs0AnD$P7bFv;Qx`hA;TU*jl_5IhFUqxf2qRWfp3hRN>pK~r$@ zl$Idw;Rx$sP4Z|-$0nIcpobfgC8@lWlJzMEU}=v%RY20aa|zZB$6Q!Do8}3oX7*k< za;n}s#0S9sEuR?P`^i;lqV|ey;>&@f@c5lzh z>xaLJ#nOdx%ka}cX01sMV-hWVt$`Tb)<(2 z)}ag$e{bpL2kKK|540>U-hd9PNx)Hw=9K->wsg$5x#Rh|QKqS6WM*3a$C{LKiZZQf zsbc;k+`i=^AM6zFQX7$yyU@0w_f7uPilyMqhC(QV#dF%}LARQ@BDIeoe7&z3!*%Ep z4y7E5VrU$mGf?S?S}`!XTgCZFGngau-Z3^zbz~nMdGl=`qXV{KJsrIGNJ6e>7Sp6a zkPC8U-aqmm&i47}vM;5J6|S^=jaJrbuFVb>jJ#lBjd?Qf3TRIav&z)x?-*^c77yL} z3Hi9|Qm`=d9`kl1GIvDiPGd8dRV+;agXpC= z`5}QrzrjSS;vrx9j;HksZ?-z)&RSOG6G$&G**cn~Sywunjpb3X zJsdl8F7z|*5tC|=Zxo6-(J#-=%o4>%OQlc6w16le@q8B~f$h%(Mvgq!T>B(+>Gr+f zue&xGehqaciR_qf3PPK75!x~7k+}@mvzEN5k=yw3x8<#1$WqiJWaLH~v)|n|m>lf` zKZ$mc3$UK~<;Jh*()aNEDSn@6 z-5q#_nr->rJvT9b_Ru533V4NHJ^e}smkL;hmw|MEr`QX z!Ra^GC2YlrOb$5=6B(;*-5aLv;5aokz8u6vub1lcOKZM5bvf%+$DLijX0^{c_@=7u z7EXPaL}ijpw3*g16O*hi;j@LULMK^Y4$sPnNx;==e@GG|4dwS{-hT%N*17WA*)SsH zxSW!utC$(G#I@4J{yDM-CqKM;;*6IRtaY7htU>>8%8{m@DebLD10^?NTcg2-kMw_*%4{ZBamau|#>CI>?+*pdw>!~HTSzptQ2 zg*deZHGj=>Wrpx;jMQ>FkJsnStk@(nSF2H`@+A}c_e}%O(p-hd(WtNNjk?eB(r=%Z zgu<*ZuJhV%tt#zQY6x7;^R0{^-U$@hKK#<`7~78u>wc~j0}HjTyr~Y^(DlkRk7gpq zce;wKvuVieTp5iyj6_q3yti&T zY_OpkR3h~6Oop5YkluUx!uH+7ew*c76FqDB(WmwyMrYg>GF_( z9KXz?UaR#rICyJR#DG|bu)k0aL@AU6t%@?>upu%$mPeWnW-Opi{9vJUXnCc@tMG4d z!PVQtj@8*6Z}$%mPud+;_udmsHrK3O=69;$=tj!bwtfganIhkyu4SKFfJFB`l1IJ2 zAO|A^s-Zi-@^00&#i&1+6viT_AJ0)my2{k9ggo3Zf2cM#V;_nhl1XBEf>E`GAwIC6 z%GT(`tN3V~J6z5+iog(tz6ys+&GXm5+y89ga7KF>aMIXIJTR(LSxLjkuI_l?n{@(Z zJhMMc&{zcHm`BTE2EKcqBZ9=zr)%Wj<4^}rQb4J8eu?zGTi>^Tn}iz{BBKJnB$ zr1)pq#e0|5ypSlMKyg4}r2O$;j~AiPBHL^bCCYLbMWeq^{<3=k$R!zFS!0 z=^xl3=h^3WwKeKim#4RUvDcea@CBY=1(e1hE zJ;Da%`Sk^d=Fysb+k-@}et8>>op`V2wXD@^;$JZ=q4|y9;fULq-%lmZsCD*6q?Tx5 z_?mM4;@llNYB1M6S?qflh$AXlJg{i7lR9|6z3`hQfJdv0QVO0E2jIJ<=@jLSbZ0d|wXSI^INA{t3Yr?BE-6A_QLz$xHxMByURZ6JPcE7_} zDPhoz6_cg?*|COE5885dW+I9@e$Z>a)^2{dF&qqmC*;1hR1cJ@IotfB;sSmtSmdPS zj;jIZwk&w7U|@pJ`SAtgc7*~3fx2U-w*-S($}{5klzqYT{cAej;rtyFeY zoKwx6>?WSg>8G-kib9$VrW{Cu*q$Zd(}H$1-!3}@`dK!|?~Mk-g@1yq(*twk62q0fp^&W&CU#HE(d))*|ppNUZ%33Ta5G?-h(ZOmM5z+LaO`2 zDXIjVMP051Ne+dluXxkU8h;w7-uXN(9*unlNie-U2cmwxA#LonIw}C-^?y#7N85%$ z`!D&}T6!kwR7nY@)S7_1x`Wq7*(MtS*v{;2%F2|1qFw~i&g=n&n>$m7IyWr@>wS@9 zJ$d^bzdMm-sOy6gCf+~Hi&9jaRnuSYacd z?eT0&grq)nl$l@IDIKlws zTv-ZexN*Mv!9icrtE<&q+G;nu&G_JSrOW5*nE6IlIP>yHlNfBM`!R;N%?qZBKEk&rP)xw@}F#bU0VN*Dg8g$>QAqE8YKU4KWG{x(;%4! z$-jG-bvml1qiQ;;rlacbpVv$?$uyHpGs!fQOf!j-3IFNS?!U>N<;{{30APm5br--n z)xUb?{x_}o|M;?9v^3%i=ZC&o+!4)A>I8-?27I%8>H@;&)l-`k7p86)?407`?UQH1 wfMuUdT}QY&bvxnwqX5@pzgh8Lq#8PBH9HUR { + const filePath = path.resolve(__dirname, 'test-canvas-output.png'); + console.log('Using file:', filePath); + + // Simple driver stub with execute returning devicePixelRatio + const driver = { + execute: async (fn, ...args) => { + // If fn is a function (from WDIO's execute), call it in node context where window isn't defined + // We'll handle only window.devicePixelRatio case + try { + if (typeof fn === 'function') { + const code = fn.toString(); + if (code.includes('window.devicePixelRatio')) return 1; + } + } catch (e) {} + return undefined; + }, + }; + + const annotations = [ + { text: { content: 'Smoke test', fontSize: 24, color: '#00AA00' }, position: { x: 20, y: 20 } }, + { rectangle: { stroke: '#FF0000', strokeWidth: 4 }, position: { x: 50, y: 50 } }, + { circle: { radius: 30, stroke: '#0000FF', strokeWidth: 3 }, position: { x: 200, y: 80 } }, + ]; + + const res = await annotateScreenshot({ config: { logLevel: 'silent' }, filePath, annotations, driver }); + console.log('Result:', res); +})(); \ No newline at end of file diff --git a/core/test/temp-screenshot-regression-test.json b/core/test/temp-screenshot-regression-test.json new file mode 100644 index 0000000..6ff985b --- /dev/null +++ b/core/test/temp-screenshot-regression-test.json @@ -0,0 +1,18 @@ +{ + "tests": [ + { + "steps": [ + { + "goTo": "http://localhost:8092/drag-drop-test.html" + }, + { + "screenshot": { + "path": "/home/hawkeyexl/Workspaces/.github/core/test/temp-regression-screenshot.png", + "maxVariation": 0.05, + "overwrite": "aboveVariation" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/core/test/test-canvas-output.png b/core/test/test-canvas-output.png index 644b328cf246fc2de923ff6da61ea8309aba1656..73846200e181fb9646e85ca85cfc5fcbbe277f6c 100644 GIT binary patch literal 8747 zcmeHtXHZjJ+wM-Nf>7q2Lkq*+N1*C}}y{OaxfnXzoG?5}z=}nL#NcTaJ zE<%795KwxLKuCa)aH2l%Ip_2Lne+YlGP5T$t6X>8*L~00>xrqc?lBe~761T_>Fa5k z0RSkG_DC=@(ni)B<~wMANABp^_yYhd$FBzjWMrKN04SiZb=4vyYkl%a9j|3}*Cx2* z7B7P?QS!SyGyQ#fh}QArxEJpg6=zX-@i7v@Vh`UOje2l&_T$k@N0XE9UQF)k`9XhF z=HcmE%t@BA58vo9+qfK4wqeGl9cDSEjM`6DO@~dA0)r=QDU>X85ya?Dnb&eyq&;cu zH5WGkunDC(f&ml&0u%*d0AS1v0Z<%Zdf@xR|JOsypFRzo@gd9%ZPvMd;AzNb1sKM* z0EBO+f6#|og|Be_y%;{y#O&JcG{2uCWfHy~?H}oGo@V&gC{zAL!kDj}*Uvpi)$=mxB4IrEc&d3vb zUdj9Iwb)G^zLxXr#28oDa~x|TG(M|BX- zb%U#T*-o~lq@_G(2j#i8snBV`1=MoR01Rx2X;WdP7JIH$DxTNXy9K7G4_X_jt-~!Z z{QB#p)eq)(d$r-`)e%IIP0QX5^Pq+g8>$i;UyY4IZ$Cpijd9Ij)#P`aiIZJzUVc@` z=85-8exDIR-wAX+Y0W{^35FDO_SSn*dE#EReI+WCHSzei?#GFcd2{%<>xA9$90loj zSEhUcCSvAFcs@v{oHrLQG$h97hYq@A_>x6xCCq8ndKYu3IFLa|QX5PVu5@WwL zcP^;gkL^j-LfxSzKmQ5GD;oasX>5TuewjnFPzVDAO;*n zC>4c9N|xvPg>QUnsuzH{x$C1!o_O{t*FP1{-4LtIDbc{<%ks$k0&Tt&5n_YM;6WXd zfEAFmT**HbA0uM_5AU5pP|%VeTO8S%kRi6_$>ES=8cInfg%48~lG>}KClAj}_|61v zws7FpWhxI=k0fTE`gU?~I;?ln0D_K*%zgc&cRUeJ1^EA>ux7u zt1NAmYHvyO=qzNpVjERFptK)U5o5{evGPv?|5I^|)|~Z_h##$7GZ2FZBG>qK%XoLj z0|)J}UZ`)x8K2EKP$-@OFI8flrlH?ge#;77L^w1TP?3vRCoq{*krkK9%B?t3E8hg| zj~Z`!VF#Prgf8UVpjs^VI`!v%dcH6ij&xNqfoqK}-umQqc_#BrK;@MEp|3{-&tq99 zkh>R3!shMSwoBbpcMFSz11n8zE_J3>IZmzP%Q_4q7pn^sEL-ZACbbK(BjFb7-=}%M z6%Mx^l=jUc99s@!<)-}(SZ8Okqb|>Lt}SZ9R4eK$N92Xdl5#(|Rmk$rB3x~H zUe&>o5_;kmM_!1){t2k(Fy=sbLp4uGrL5{ZTSkPb$J79;U;HBFL;j)Zc58rfz}s|H zX?kYVw@*1*YtOQlotX@EX9A6j}F*L1s3 zyju1kAZuqkJ~_Cek@6M-1zJu&sWdQZD0KL_%OL+VCyLW4FX|D_cuf|jCO2y?hfRr> zEZs3W^b^>d*p*{|i>*Icsub0kp1}~Q9#zJxC!l3_I9>M-3D_d6UGzQ^VLt*xjKw>Y z$rZwNJs+=LL#^G#@)s_=*_aadsWGp0P?B1#B_ZqUOq!G$*Gl`=k{Sd`5uC#G%z(7O z?L5~kygHRKtZ*Copo$F=$U-^^^*moL0;{LY*Kf9vr{A?ttn1@L%(^X^^pqU5lQTYe zUU!R>KN*(MwiE5QBMPf;_a`?^Uo$cnT~FRO3<$Ok;@){-w@Kiv51n0!A<^hRgd$Oa zS0%Q-JArAKwPNUIOAcBxdtr60>vch&3!PR~X`|lN0#aol=d+Dy-+cR)dv_DeTW1ZL zSQBNx)FrgG!h;*wR;`@YF)}1RbEO>5m5DbVnjYL>dYDwh=E_8y*qf=P%JY^EbQ}C% zYJlsDtqZglZqTdJZ~k#g;TzM=8+=gDh2yWy)mPa{R!C#pZNtiMG76i4A?x&aCT>^P z)v|S#9|JpaE>-Vo<>?C%(4QEW+jyz);ZU)q?`xbZ6PmHtW2&)TyWI zCA29{f$!QYzYSc(nMvb{J)X>J&kto8_w8U-gTZ%XjUmYg~MIb`W+NVDukQ{i6oapM8_lKYFK!MLXnuC5N15D08FYop0Z zWI4xR|E7F%2qe=_BM=T_+3e2+s9GQ6cyghzb02A}Wj z-$5r5z>N}JIe=qqLl8^;K#m3s&ZkXdKgNNnnq!< z59YzS9pzA{vq{1*)~jj0Y06ar$QC9|gn$4ip?@1DSTv*FNtwOyqu^?%2e|tTuI5GQ zlcD9f0fo%TJDQi451l`qt&+4$mtaK!J?-};_vcD)_w}DQy41WRR2xM%P(Rf~wI8n8 z=c81Py$S?ncTb;isA>_{E4m4GnboP~zTE#=ZNj^GJtKIf9`|YOxq1J2!;7}qjLdyN zde5@M-ZYAgJgV}>GX)o?kg?ttHkjFjb#U$Ca|_yNbmg+UDIefYQzD}nTW4sp`qepM zu9c7j8``_xLC!0qFFvGvQs}21bTK5&?sb!6W>anZgT7S<-Bu5IgPTtifuF;VM!4TK z5{G9P<@(Bdr{i8lk2#Qxm0!g1bh<%0t-b<+S_g^(h!?8OLGx{^m9B6H58^lffv~E* z?Saa7LN>uWWWJzuT-KF=FzNRqk6078KbL29rs%aT=1g^sT~Yxh)_g!LQu#&XDx+P6~3CEAWz2RN+`r~W%40h=H>Z9UgDlr z4gw7KExLi@8Xv2+hYWatbRYTgTd@TXCZa)+pWXPZ@lHty_7JkU8cs;@9UUMd zcE5U$X5XC^V^8wkWY8Fq`B#SY1Nz!o71<0G*)%&d#LmZ?nh#6z!CK76+du2(6GAdR zuuE4_(Zc;>i`&>Fa(M9Ab=?$_X8r<#z@~w@`!C3Gp5<)5v+0Y932is(y1gfS`pB0< z1Ey^0Ws8LA{$QyR9@?rFT(p0ylOFB6`*VxB)>4aG8AbRVH*JqU2BAe=NuYJec^EUg zQEL(=U^3j>mE$6CJQ8E{X9?S%C6hw}p2Odp1Kx&SymfuaWTA-sb}`3^xcu^R;BSva zqLxg$ipszFG~BX7x>RWd;R;(KlSLL=wP8r+M0H`U1GYp#&EE2s6)|yM)n@U@cIn6~ z_}8EnO_U2Q(2Qt)n>;tW!gB8gfd^ZiEr@vvCfi2bYL2!a&zvas5FH7+bobVL?kmZ% zs}I~iX;?ES^3Z$*p6g)kE63!?0#KI}v`zz9@qW&OAh`gD%~K!o-f(bRj6 zO=8F1i8oCKOXI7kXQjSh1{bhB)QbRJx@~~4q`jGsg4e3&DcMSLG($plP$N$uJtDAA zPerR%RvjBUlozwMsPTN6q%lBM7{&ub*Qvt@-X#H+O=rrNKC8F4w1<8?@(c6oL%lG% zx&74-)DPE@+)0&4rf?mUB2+7MU+Xv&c@+gcOOF=TC}=i0X=IJO%5h3V14RG{nyqqZ zi-bCUc@m!pfg-ig7Lj@H;u@si#c>G=!ZJ`0k3pCQrMfT=Gp*zV71X$jl070goTK}q z!p`GSXTBkX2VC%kIcZGAaP#E@rCFyKOi>ESJRyiFTo)y4(-p193ZBc0RdSZ-E=)@$ zZ8NENhk2o+Qvq;6r;?P`jgwHE zYlVHVoNetV7Uvz$TKk|^dn`W$VdF3JH43yrH4&{i{;=opus%tv)1fQA!~|Cl$0!H{ z>N6}OIGhKRM%0l}AXhK!4Z%t^S=ck(cfwlqdS?Q)&~+DKBi@AzO94;#o7X$2%|Aj7V>jLzkQNu!2g71fpCHgH7Xr|Aim-sE z@rrpZ`ybfZYX@Ny;d4pzl+!Bjpo;>0kANP1C(VLRkdXgE`pzmmf;H|tTbxct@kEsy zav(dCbP5zF3=3yXx|%RiR9+=>Mop!^R0(#2pe7ujn}f(4kf-)LF0|tVjh&+npEg{X zq$W9Lq>|+saH5p8pm(Mlg{DSSv<|q?^)^5(t?*lg0#5>wL+`(Qni)8Mh%%4+EDUI-Zug? zsGN2Rn7XBpA!jf)Oxh-2x7^9!8pPi{0XAtOpA5j+8@BVV|4?un6(OpK| z_8MpF;&)a656t=-9_w_ZZD7S}!u7p74VLvERM--b{ime*!}`GakRL1`mFdxL3}@Mr zRu(D}HO@u@N$0NhGqP2Ldrh8ic2Anu5lm{GSM;q{>Rua#Z%-86JPvgbf~iPA@A_Mn zH0&;%gf2Tzo2b6sT9-35iLTFPcN}rQ7k6=x?ZimH{<3RdT7#c5%Oha(1Zc(sbR;NC zFCHYMDoc+}V@?EE^h^b3uA>NJbr!12 z_&DCM3fz^&^z6up6H*z3$N`KOu3g{E%Tw3fMpp>dGN*e)+WOIG4ETg0IwV|8-d8qL z=EK@r?Z7?>e}$Rn1%Whfa;4L|sJkWMX zDd0BXn~bCX^zy1Jmt$5%e$s-p;xBx^-}n{a86=uMR4pJdPe$0hI3tcbSyuDk=BVp@ zl?S(Eth_L+<)rcN)oI|FK=jG^@b}U*lRBh-XqUd>k$_G;*1P_h=|BS&B6@Jb;WcGCE${%Sz^DL~5#GsAQ|5a%D6Na-`h-mK~%8?l& z{m8K+*33z+5jA(}zbaC3>SUswM!|(ex(Gpd7hZsK*mpaVx1tRG zxR;+ZaZ2Ot8UBpQ#v&BWQ=28>FD3r$s|63+qbqF8x%o4Q6IH(_E5f12fBSLX2~^4{ z6o#MNNrcNfbN)&b{#14dl=`y{HNui~!@QI`7P!ikl3>h5g@2@lk)JE^t=9l?vSASr zmHT%?T7vPZKWHAH(v6FFkC@Er-@!NO(=BHGoe^7aP_ifZ3kRfr1zSZz017+!VFU7z zRWTT_re{`qNz>;Kehw!j?xNpW6@%#ZUjg6zzcsaK`MTz&ewp0w#tfP3|F8uDe-y~! zN(}u_a50LlJ;Xsx$?{K1!WasQFN*flM1jQwvd%#)aERzqGo zHM*ThMw;>x(hU0^y?Ha=Pygh0U%L!}((H|j$fzk%QDh8fr1>@qc(o;nQre(RRnp$L zrD9QWd`I_38Rqr>vv^DDsUcF8k;~z<%}H${0mFNZ*6z_LhJ^!~X7|iOW5-ZeU@{|S zWz1GMQ@Npfdavrxpx&cTQaJ1fL%aBw6melPHZsn8?;a_z{{;swT_$DQx9v)ebc9UJ zV(wt1fU+|SgcdBAx{;0kt8^u~nm(!Wte|f)rCE`L{NBBM9l3T>-*2aJ zd#Yut=33hMKI*Lc`E3)mD>dv97i-v&7itD08y(!tN(qB4=(wS96f*=`UCJtVjHga+Jhm<&o< zZ*aVqQXd+Kcya8^vuR2%T*$WWLQOk$)kVF2TCFBOK4z_ryj59&%=(WXr@?b^3eOD8 zI0r1@+Qi61E?oP;wR;S2*6WidBO?(wuPURlyTkfPllQK<98#u}klUI1wHVRjvwbSm z5EoielOV18=?0P4TS;yu!wqoD9u0qV2;fYxA&h3KL97UNUrVJkwB6)Gr5yx>1Tw3)5 z@=5E>elC5f=lUr7*d!!%yQe9Tw=Tg8t5c8gH@ogvt?jayli5PVAM)b_qtEtH2M?c< z;O+UqSm;iq+><~qC=1H~rb##6P~)JY_8DSDTAu_@u6KmXE3v7QZCu*P_Aawsy2Kys zy2L2<=MUm(EaD&Nf(j=!_bB)TF1aqY6U@wh@CI2Uaw=6Udfdb%jMOO}E+RSU;j`Gm zhRHE&j#RN5lIq^pTeV~DgK9lN%PSX}E81+lY%HG-s@d+1bGy+FJFHFj;#68|dZaQR ze|yS3fBUUp*+?z?3~r&!t5S5(9A=^5)Ov8w#c@}oW@8P%`p&(z>}%~d=dDpBbQH8T z6Wh}kv6YSWZ!yh}bxgtE@=Mcp?>X2=^fRk(v0QND{ZEdQ z2hSPNN|UR{AUhm{Q_y|5dbxDrSdbWGq+rY(wRE}!j7|Au67h`SwG`rECh+tcszBkS z%I;09&oE-hYsGGmvHQ3#1iHiIjG{F~G@`!8o``icSy+Cn)BdEa))vmr1J84n3>+>p zvfp9U8%In{a3+rL+wwu1u9X#wL+p`+Ackke@{tucQ=pL^{V66Om?1B5)N3VJ5XN(O zl*xAP$iKJ{qb7=F!=tk7_Wj_g@Y*&F#ami6zLQ2HdZ>bRa&dO*f$wX5BVCpf*{mC! z&}GHv-qw~1JGYhp@nS%47-Li>aj6vKlP%CCI$z5oRD92_`6+VyHZkvstbDQiK$H?;qnAX^tB&akJ zhI<3wiopUF)08Gg=`E0p*q=XoYQ_gw?uz5?iY#U&_h+g$tC&o@bS`m~d_+5)*GXPj z-YClfyYxJpBf7+qOWIhkIR};r)|&6 zP^YOv?A8wAfHJKcgfZ$_Zz%g|;ZYi={+f4mp^7vN)wIw4=5K;sAKImt%#T8;`ZV0X z#z$(3ElmME3z99*)trR|9F_Ie#OIT+&Q>)Kh_c37?U5^`Nwi*kI7{}n!6lR6x66tv z#?m{pOH!qE(wfdbvZu{f6$xMFLL4Fxdo1~5ijcr?uc;(mouJvcp1WAf%!Oq;7g8)B z2unUNc&!{+9OqJx?>tO%2PhE7PX# zo^4{m48<7?7^qofl7^=GYMHRlxVfSi^i{lbDA$c(;UT%xrbg~Jtnj5U^K=XKjYq## z(_mue=t2zwM%M0p;D-jO2KBRQbf7%;KYhfn)`0iH7uv|5qWPchVeRtEUd6iQbm#uO z3oi(lTVSX;`}7xzjO)~+T2UtSXa#17*d4K-#^j@Od;qW zJTTz^-X8&hfjb%~0LY>>bbtu$ThRXu{l^o(ZY|WY!~Yxm#eefq2xcyWE|paTXg_^z LW35V!oA>`0vB+fh literal 4532 zcmdUzeK^zm|Hrp+#Oa8oQbapjtWM$7I^=e$v2`OwD9KLbt|<}CGOSalCT1Te);aL>n0o~YT~ZptFm*0SgM)X z+TY{=%epe328K(w$o ziJc`Is$(N%@}UN(XQ{6Nc#@#u1iN&JL>qhH`IPguBWb_#0u(%X6ez8>hSvu7x?Y&| z`%&Nqy{8YQB=GlvbpYuDJo|_2iC&e4Zd-mxCw|?k^mH>>l|A#T(!gRh)}Oz3ReD*h z#`^a}t;&rStFfkp0m>~ZXdZWT&324t!D-GasFZRuIA|CF6H&FD`8sWOfJM+O)__Bv zM?z}Aa7ec;cnSy$&!U6_h(6~0+8G1tL&DB&hlA=hi;aQnk2t?Ri~;Qh?}WiY5RYRR ziZ>GG2!lKCGPq~D9$Mg~gR|0y7Hk9ng%{>X^Yu(lPu+i!F2m~it3Z*0LK2v0x!-P78YOI?G6 zw<{T)G=ni=mI*;E1L<}c;WR=C$yqV|j?lH6*!2uzN(apV(L$@WT?>bsChQ+&V5c3| z_WcUeeNH%-p&>&Q>HcmrQ|H*j}{$J%;-i@}Lk7t~3 zuD_?%vuS6r$u;^R@{QX_m~I;h{>B*w(>;QrxB?Q$p{qGe_c#DEm)0U@ZbP0L3jrNxIuUU04yN9zX0e$ zc#i<=1c#l6L*{Q$>h?pyM|8B|5TISde@4_q1+i^d0}-B@Mk$mz^l(yJdpfjrt3l+{ zV`%awnd;OHEg0<6j`&ePp@HE-!o?|@q|KYc%)Q(Yj_*3P|1NPac_l)5L-Zd(XyQ=KWe z&~ulM>(;n%wvI&W+>IiwKRS{R$+tQK4=c6D-NtEuw*%kzRRQ_2NJ8nM!Vvm z^W^=?mJ3P=wTQk68u}CD;L8f*v|Uvx{nx)uFA)V>_QYJo9FaXV>*j0TGTmZtJ=%dn zWbFQcz2p_nig(h1hWa0xb_D-(=+~OhDnfE)(M0VQ;moqUK_D=+>ZbJ_y(mCz9*8l99KMhZnV(aQ%)Kl)V zJe_V6H-me%+%EjVa}DHa&v?`w+pF+RmNSCD$_8_8*xVPYA$}%@B+FP)BS+&#l211` zscrMfdq-Q037MjrqwE7~T*9ke=%w28MdtfcZ0zUWsLh51x;B`m2TjEJME(5e;`!_bY~|fvHKcibhV}Sc@?t zLG_txaQum-y{L{1*2*Z+X*+*s{Aip)kfRax(FK|lA$VEE3O&iriMS@-!&-^=542rg zpf-wAv+Qj~)l$CR`J!0$_m zk5W})eB#iy<$L+kN6B#0xZMGxZ0h;1 z3@b4~{o0iL`{6MF(B1R#ISOftzIrJTDX zZE~gE?GMQxbn{A72PSl=l_Zom@VkN6oIP2xF*I%>&lfS^aHh;#B=N!1>Xzh; z+j{hQQ3Q7JI~{S399b-Skz6+r%rGSt+sXf0E4fOR*D`{;Qlgh+jN^7Yc?Aa;>(CB# zlH>y}Brm(wE!QYa(1f#Udj2oz@rEgy4P4iFQ`qNAhzj40Q#aN~#*l8li8GH}l+Ewg zCD-*FXIy^0lc!cPDx2+i<~f+bpiJB|pNZ;-=Iqv4R-&mr!P_)$jK+8|_#3Z{!B}1r zPhVY`FJ)-yrPht5GAv*3;61cuG%xnzaxNQ%b!6c<8RLTIFz@_*P z0^BW2zpTQ7r-Kx#Dqq2Q3*SjIGXuQ}`w0Ky!b4JNSB~LS;T=hQX>LZVlk8NC|3rR% zCJ-~F8lguI$1u#@yEyCYo-8JKwo6BdBWhc}7_Z`1)8y!H6%3$a>c%q|{&5vjR&rnC zFU~!sr5hMlJ*E6O>+(OGR|prYRA6Ph4_tT4`l%%3#Z1<`$MU;@IPr81Q{Il3h*-}( z?nW!e8S5PP@pzAw@=Gtr`LDnJQ@Mo5vqjO-iXn2GY#L`jb8kW>;nWA_$6M1)9QN~i z-1!2ckfCg5sm(?bCUVL4a9&m7Ir|su8}Lg{?XG>kB+XpBZ&n{@)wr9UyQk>&%q;^+ z%|w2c<=LkFyi#;-e&ftPRYnIcwxwWuxnLm1wZK)ikG7 z5aSaw&|OFx$R+lrE_D$llKiD|0luGhZ3{)S_}BU&^YRDq*;j~&bz4y85t1^$7ya;U zg|daQ-cFRbDQ!hPbhVy)weJj+r4ADKc|597KCMBKx(n13UeEf_N6G@;-D=8y!ptRh z@vWGr8p-pMR4%zhT1`irey1l2J3~H)d)mv3(r0L$^+)#%s!EQ1;41`Y8_B}9CY>6lZoIX#IJAM%Bss$7J%+kF zrn92^m_tOosgIIpD{fLhZf-S&=BxbJ9of*tl{oI#xyF(4B_jiK;nL2H_~oc|A9QVm z-4%rSNm-^B#Cu>{Pi{5WA+2f`zD`6lN^eE0W?DwL2JV=xF{jvfoHkSs1oyswY-n*e zRwbgL6VBy!5?W29GW?3~j}KJ;Bf2zM3%-u++4^^{S32Tx3!VOIrbd@;Y;TQs&wI$) zJkgPqWn;A>j9Z){xs7Adcl+ZNv)sZOdF0$%Xrk(@C_ZjBTQ4(y?yZauv;JKEt*Uy~ zeb%Imya|E5MqZiw*LY=WsjO5IQmy<-!Y(46pw;6U%I2|D4q^YWSGEt9Kzx6PpISEA zuKMY^59g<1$+*1BUMZ}vTv%w8j!!?6W~xkx!q}~`e=dh99mP|N->mSakt&griwYJV z#RhZz(J*F3)Tn^>*kptiJ=Nkqn}b4b+Zgk$g5-HR?wOAw+@F&X<4`IOq%4LtP{Nrp zP8SpdA&6yJRa03Blkd+_5HHMqA)lUdQVHX=Lh^I<438wU>CvL&jCZLKbX};Mw+x|9G{Q8?jb`tBA z>2>@{_=@SS8w6Gvq4y~j)zvnUUw-;zqh7$=7h0k#e&L|gwxHP|YWgl4C#wP{-^;q& z;Stua6#}(cb8I9ViQe*E!clU<25Qv14hM*;90np=9hS30B<^E}ZVU5MB3}KP??-I= zl{AyJN4Ypike1{O6RQM1dlD0z3TG)Ab}KQ+o)Q@Vx zdX#M-H5v@0k0ai;(4H-AM5HTXyKG6cK#7ptp!`by)MwMo82dfsxF8c1=8^iwEK?XN zuEq*p&I{9&UvB;T{uvVaLUBV+h@XlQkd(zAKBP&VQdMFuHq?aZHxePxcwHc9g(`+_ z(}^S9B-qYzscDHD2f5*L&EaAN3!TrlNlXyEvKi?>*2fDG%B{D7p%JJ+r^K;dA3i$& zJjX(M^<2Dcv5GXBbPjFxFBKu_$8M|0TeCN)eR0f^xo?E181B7l{~Pjih5d`D%67fP z(~W8yR#J4^uS#~in@uNjW8T%{#p4`8D^u?4lznBg8wX7Ae4oRt@@-MPE_>`CS*q?A zC)ng~ZMbs2*)aekQ)jI)Z9}eKXPn`_erD3)Ui*08St)7z``hFEtu~gtbf2#im(iDj z8>wb$msQM(Jav;H-cKyGG!pFv+3ErP-Q!Om!9^N})70pXg(JVbNtB?1PbKzD&QBRT zE#6A#y{~cxP1*vhVcgMK%$*EteVY{r^%Z7_^BPS}UpK@Gp0oKx_&W$N^U)9eHH7~^3-15my@3DStF^6YG<*ts Wu7exi2W-QD4!a!3R37~Eum1+Pax8iP