@copado/agentia-cli 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -1
- package/README.md +2299 -1615
- package/dist/commands/auth/get.js +21 -1
- package/dist/commands/auth/set.js +13 -0
- package/dist/commands/auth/unset.js +37 -0
- package/dist/commands/cicd/cloud/commit.js +6 -5
- package/dist/commands/cicd/cloud/promote.js +44 -8
- package/dist/commands/cicd/credential/auth/status.js +2 -2
- package/dist/commands/cicd/credential/auth/web/login.js +2 -2
- package/dist/commands/cicd/credential/create.js +2 -2
- package/dist/commands/cicd/credential/list.js +4 -3
- package/dist/commands/cicd/credential/open.js +2 -2
- package/dist/commands/cicd/credential/update.js +2 -2
- package/dist/commands/cicd/data/commit/create.js +2 -2
- package/dist/commands/cicd/data/commit/list.js +2 -2
- package/dist/commands/cicd/data/dataset-file/content.js +2 -2
- package/dist/commands/cicd/data/dataset-file/list.js +2 -2
- package/dist/commands/cicd/data/filter/add.js +2 -2
- package/dist/commands/cicd/data/filter/delete.js +2 -2
- package/dist/commands/cicd/data/filter/list.js +2 -2
- package/dist/commands/cicd/data/filter/update.js +2 -2
- package/dist/commands/cicd/data/formula/create.js +2 -2
- package/dist/commands/cicd/data/formula/list.js +2 -2
- package/dist/commands/cicd/data/formula/update.js +2 -2
- package/dist/commands/cicd/data/records/match.js +2 -2
- package/dist/commands/cicd/data/records/search.js +2 -2
- package/dist/commands/cicd/data/sobject/fields.js +2 -2
- package/dist/commands/cicd/data/sobject/relationships.js +2 -2
- package/dist/commands/cicd/data/sync/apply.js +2 -2
- package/dist/commands/cicd/data/sync/preview-updates.js +2 -2
- package/dist/commands/cicd/data/template/convert-old.js +2 -2
- package/dist/commands/cicd/data/template/create.js +2 -2
- package/dist/commands/cicd/data/template/delete.js +2 -2
- package/dist/commands/cicd/data/template/get-detail.js +2 -2
- package/dist/commands/cicd/data/template/get.js +2 -2
- package/dist/commands/cicd/data/template/list.js +2 -2
- package/dist/commands/cicd/data/template/open.js +2 -2
- package/dist/commands/cicd/data/template/save-detail.js +2 -2
- package/dist/commands/cicd/environment/auth/status.js +2 -2
- package/dist/commands/cicd/environment/auth/web/login.js +2 -2
- package/dist/commands/cicd/environment/create.js +2 -2
- package/dist/commands/cicd/environment/get.js +2 -2
- package/dist/commands/cicd/environment/list.js +4 -3
- package/dist/commands/cicd/environment/open.js +2 -2
- package/dist/commands/cicd/environment/update.js +2 -2
- package/dist/commands/cicd/extension/create.js +2 -2
- package/dist/commands/cicd/extension/install.js +2 -2
- package/dist/commands/cicd/extension/package.js +2 -2
- package/dist/commands/cicd/extension/publish.js +2 -2
- package/dist/commands/cicd/extension/uninstall.js +2 -2
- package/dist/commands/cicd/extension/validate.js +2 -2
- package/dist/commands/cicd/extension-configuration/get.js +2 -2
- package/dist/commands/cicd/extension-configuration/list.js +4 -3
- package/dist/commands/cicd/extension-configuration/open.js +2 -2
- package/dist/commands/cicd/function/defaults.js +2 -2
- package/dist/commands/cicd/function/delete.js +2 -2
- package/dist/commands/cicd/function/get.js +2 -2
- package/dist/commands/cicd/function/list.js +12 -15
- package/dist/commands/cicd/function/open.js +2 -2
- package/dist/commands/cicd/function/result/get.js +2 -2
- package/dist/commands/cicd/function/result/log/get.js +2 -2
- package/dist/commands/cicd/function/run-local.js +2 -2
- package/dist/commands/cicd/function/run.js +2 -2
- package/dist/commands/cicd/function/upsert.js +2 -2
- package/dist/commands/cicd/health-check.js +2 -2
- package/dist/commands/cicd/job/get.js +2 -2
- package/dist/commands/cicd/job/kill.js +2 -2
- package/dist/commands/cicd/job/list.js +4 -3
- package/dist/commands/cicd/job/log/get.js +2 -2
- package/dist/commands/cicd/job/open.js +2 -2
- package/dist/commands/cicd/job/pause.js +2 -2
- package/dist/commands/cicd/job/result-file/get.js +13 -8
- package/dist/commands/cicd/job/result-file/list.js +2 -2
- package/dist/commands/cicd/job/resume.js +2 -2
- package/dist/commands/cicd/job/run.js +2 -2
- package/dist/commands/cicd/metadata/content/compare.js +2 -2
- package/dist/commands/cicd/metadata/content/get.js +2 -2
- package/dist/commands/cicd/metadata/dependency/list.js +44 -21
- package/dist/commands/cicd/metadata/explore.js +2 -2
- package/dist/commands/cicd/metadata/index/compare.js +2 -2
- package/dist/commands/cicd/metadata/list.js +2 -2
- package/dist/commands/cicd/metadata/refresh/deleted.js +2 -2
- package/dist/commands/cicd/metadata/refresh/run.js +2 -2
- package/dist/commands/cicd/metadata/refresh/status.js +2 -2
- package/dist/commands/cicd/notification/configure.js +2 -2
- package/dist/commands/cicd/notification/get.js +2 -2
- package/dist/commands/cicd/pipeline/automation/activate.js +2 -2
- package/dist/commands/cicd/pipeline/automation/create.js +2 -2
- package/dist/commands/cicd/pipeline/automation/deactivate.js +2 -2
- package/dist/commands/cicd/pipeline/automation/delete.js +2 -2
- package/dist/commands/cicd/pipeline/automation/get.js +2 -2
- package/dist/commands/cicd/pipeline/automation/list.js +4 -3
- package/dist/commands/cicd/pipeline/automation/open.js +2 -2
- package/dist/commands/cicd/pipeline/automation/update.js +2 -2
- package/dist/commands/cicd/pipeline/connection/create.js +2 -2
- package/dist/commands/cicd/pipeline/connection/delete.js +2 -2
- package/dist/commands/cicd/pipeline/connection/list.js +2 -2
- package/dist/commands/cicd/pipeline/connection/open.js +2 -2
- package/dist/commands/cicd/pipeline/connection/update.js +2 -2
- package/dist/commands/cicd/pipeline/create.js +2 -2
- package/dist/commands/cicd/pipeline/get.js +2 -2
- package/dist/commands/cicd/pipeline/list.js +4 -3
- package/dist/commands/cicd/pipeline/open.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/activate.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/create.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/deactivate.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/delete.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/get.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/list.js +4 -3
- package/dist/commands/cicd/pipeline/quality-gate/open.js +2 -2
- package/dist/commands/cicd/pipeline/quality-gate/update.js +2 -2
- package/dist/commands/cicd/pipeline/stage-connection/create.js +2 -2
- package/dist/commands/cicd/pipeline/stage-connection/delete.js +2 -2
- package/dist/commands/cicd/pipeline/stage-connection/list.js +2 -2
- package/dist/commands/cicd/pipeline/stage-connection/open.js +2 -2
- package/dist/commands/cicd/pipeline/stage-connection/update.js +2 -2
- package/dist/commands/cicd/pipeline/update.js +2 -2
- package/dist/commands/cicd/project/create.js +2 -2
- package/dist/commands/cicd/project/default/get.js +2 -2
- package/dist/commands/cicd/project/default/set.js +2 -2
- package/dist/commands/cicd/project/default/unset.js +2 -2
- package/dist/commands/cicd/project/delete.js +2 -2
- package/dist/commands/cicd/project/get.js +2 -2
- package/dist/commands/cicd/project/list.js +4 -3
- package/dist/commands/cicd/project/open.js +2 -2
- package/dist/commands/cicd/project/update.js +2 -2
- package/dist/commands/cicd/promotion/conflict/get.js +2 -2
- package/dist/commands/cicd/promotion/conflict/list.js +2 -2
- package/dist/commands/cicd/promotion/conflict/resolve.js +2 -2
- package/dist/commands/cicd/promotion/conflict/unresolve.js +2 -2
- package/dist/commands/cicd/promotion/get.js +2 -2
- package/dist/commands/cicd/promotion/job-step/update.js +2 -2
- package/dist/commands/cicd/promotion/list.js +4 -3
- package/dist/commands/cicd/promotion/open.js +2 -2
- package/dist/commands/cicd/promotion/queue/list.js +28 -0
- package/dist/commands/cicd/promotion/queue/remove.js +37 -0
- package/dist/commands/cicd/promotion/run.js +2 -2
- package/dist/commands/cicd/promotion/status.js +29 -0
- package/dist/commands/cicd/repository/auth/https/configure.js +2 -2
- package/dist/commands/cicd/repository/auth/oauth/login.js +2 -2
- package/dist/commands/cicd/repository/auth/setup.js +2 -2
- package/dist/commands/cicd/repository/auth/ssh/configure.js +2 -2
- package/dist/commands/cicd/repository/create.js +2 -2
- package/dist/commands/cicd/repository/delete.js +2 -2
- package/dist/commands/cicd/repository/get.js +2 -2
- package/dist/commands/cicd/repository/list.js +7 -10
- package/dist/commands/cicd/repository/open.js +2 -2
- package/dist/commands/cicd/repository/reset.js +2 -2
- package/dist/commands/cicd/repository/update.js +2 -2
- package/dist/commands/cicd/repository/validate.js +2 -2
- package/dist/commands/cicd/stage/create.js +2 -2
- package/dist/commands/cicd/stage/delete.js +2 -2
- package/dist/commands/cicd/stage/get.js +2 -2
- package/dist/commands/cicd/stage/list.js +4 -3
- package/dist/commands/cicd/stage/open.js +2 -2
- package/dist/commands/cicd/stage/update.js +2 -2
- package/dist/commands/cicd/template/defaults.js +2 -2
- package/dist/commands/cicd/template/delete.js +2 -2
- package/dist/commands/cicd/template/get.js +2 -2
- package/dist/commands/cicd/template/list.js +11 -14
- package/dist/commands/cicd/template/upsert.js +2 -2
- package/dist/commands/cicd/user/get.js +2 -2
- package/dist/commands/cicd/work/ahead-behind.js +2 -2
- package/dist/commands/cicd/work/create.js +2 -2
- package/dist/commands/cicd/work/delete.js +4 -4
- package/dist/commands/cicd/work/deployment-step/create.js +2 -2
- package/dist/commands/cicd/work/deployment-step/delete.js +2 -2
- package/dist/commands/cicd/work/deployment-step/list.js +2 -2
- package/dist/commands/cicd/work/deployment-step/reorder.js +2 -2
- package/dist/commands/cicd/work/deployment-step/salesforce-flows.js +2 -2
- package/dist/commands/cicd/work/deployment-step/types.js +2 -2
- package/dist/commands/cicd/work/deployment-step/update.js +2 -2
- package/dist/commands/cicd/work/done.js +2 -2
- package/dist/commands/cicd/work/environment-sync.js +140 -64
- package/dist/commands/cicd/work/get.js +4 -4
- package/dist/commands/cicd/work/list.js +4 -3
- package/dist/commands/cicd/work/open.js +2 -2
- package/dist/commands/cicd/work/promote.js +2 -2
- package/dist/commands/cicd/work/publish.js +2 -2
- package/dist/commands/cicd/work/push.js +2 -2
- package/dist/commands/cicd/work/set.js +2 -2
- package/dist/commands/cicd/work/status.js +2 -2
- package/dist/commands/cicd/work/submit.js +2 -2
- package/dist/commands/cicd/work/test/apex.js +20 -35
- package/dist/commands/cicd/work/test.js +116 -11
- package/dist/commands/cicd/work/update.js +4 -4
- package/dist/commands/help-agent.js +15 -0
- package/dist/commands/help.js +38 -0
- package/dist/commands/history/clear.js +42 -0
- package/dist/commands/history/list.js +50 -0
- package/dist/commands/support.js +15 -0
- package/dist/commands/testing/browser/execute.js +49 -0
- package/dist/commands/testing/browser/history.js +49 -0
- package/dist/commands/testing/browser/inspect.js +35 -0
- package/dist/commands/testing/browser/recorder.js +52 -0
- package/dist/commands/testing/browser/screenshot.js +27 -0
- package/dist/commands/testing/browser/set-options.js +35 -0
- package/dist/commands/testing/browser/start.js +51 -0
- package/dist/commands/testing/browser/status.js +26 -0
- package/dist/commands/testing/browser/stop.js +34 -0
- package/dist/commands/testing/browser/view.js +35 -0
- package/dist/commands/testing/job/runs/abort.js +1 -1
- package/dist/commands/testing/job/runs/get.js +1 -1
- package/dist/commands/testing/job/runs/list.js +1 -1
- package/dist/commands/testing/job/runs/logs.js +1 -1
- package/dist/commands/testing/job/runs/search.js +1 -1
- package/dist/hooks/init/cicd-connection.js +59 -0
- package/dist/lib/agentia-command.js +69 -6
- package/dist/lib/cicd-command.js +3 -0
- package/dist/lib/cicd-connection.js +22 -0
- package/dist/lib/cicd-gateway.js +2 -1
- package/dist/lib/command-history-sanitization.js +9 -0
- package/dist/lib/command-history.js +11 -0
- package/dist/lib/command-output-buffer.js +6 -1
- package/dist/lib/defaults-store.js +5 -1
- package/dist/lib/dependency-from-changes.js +3 -1
- package/dist/lib/dependency-source-context.js +3 -0
- package/dist/lib/function-list.js +3 -0
- package/dist/lib/git-worktree.js +4 -1
- package/dist/lib/help-agent-command.js +3 -0
- package/dist/lib/help-agent-interaction-history.js +10 -0
- package/dist/lib/help-agent-session.js +3 -0
- package/dist/lib/job-get.js +2 -1
- package/dist/lib/job-types.js +2 -1
- package/dist/lib/list-pagination.js +6 -1
- package/dist/lib/local-quality-gates.js +4 -1
- package/dist/lib/mcp/result.js +41 -3
- package/dist/lib/mcp/server.js +3 -2
- package/dist/lib/mcp/testing-browser-tools.js +179 -0
- package/dist/lib/mcp/testing-tools.js +4 -3
- package/dist/lib/mcp/tool-annotations.js +31 -12
- package/dist/lib/mcp/tools.js +115 -59
- package/dist/lib/mcp/work-tools.js +100 -47
- package/dist/lib/promotion-queue.js +5 -0
- package/dist/lib/promotion-run.js +4 -1
- package/dist/lib/promotion-status.js +12 -0
- package/dist/lib/quality-gates.js +13 -0
- package/dist/lib/repository-list.js +3 -0
- package/dist/lib/runtime.js +1 -1
- package/dist/lib/stock-quality-gates.js +2 -1
- package/dist/lib/support-ai-context.js +11 -0
- package/dist/lib/support-ai-stream-parser.js +4 -0
- package/dist/lib/support-ai.js +9 -0
- package/dist/lib/template-list.js +3 -0
- package/dist/lib/testing-browser-command.js +6 -0
- package/dist/lib/testing-browser-operations.js +16 -0
- package/dist/lib/testing-browser-requests.js +11 -0
- package/dist/lib/testing-browser-robot.js +9 -0
- package/dist/lib/testing-browser-session.js +13 -0
- package/dist/lib/testing-browser-state.js +17 -0
- package/dist/lib/testing-browser-stream.js +7 -0
- package/dist/lib/testing-browser-types.js +3 -0
- package/dist/lib/testing-browser-viewer-key.js +7 -0
- package/dist/lib/testing-gateway.js +2 -1
- package/dist/lib/testing-operations.js +21 -1
- package/dist/lib/testing-sanitization.js +2 -1
- package/dist/lib/work-apex-test-failures.js +2 -1
- package/dist/lib/work-environment-sync-ready.js +7 -1
- package/dist/lib/work-environment-sync.js +8 -1
- package/dist/lib/work-local-run-tests.js +2 -1
- package/dist/lib/work-promote-deploy.js +3 -1
- package/dist/lib/work-promote.js +2 -1
- package/dist/lib/work-types.js +3 -1
- package/oclif.manifest.json +3544 -1828
- package/package.json +11 -4
- package/templates/skills/agentia-ai/SKILL.md +6 -2
- package/templates/skills/agentia-ai/references/ai-agents.md +19 -1
- package/templates/skills/agentia-cicd/SKILL.md +6 -5
- package/templates/skills/agentia-cicd/references/environments-and-credentials.md +16 -0
- package/templates/skills/agentia-cicd/references/jobs.md +3 -2
- package/templates/skills/agentia-cicd/references/promotions.md +26 -5
- package/templates/skills/agentia-cicd/references/work.md +25 -11
- package/templates/skills/agentia-metadata/SKILL.md +9 -3
- package/templates/skills/agentia-metadata/references/metadata-dependency.md +70 -0
- package/templates/skills/agentia-metadata/references/metadata-explore.md +8 -4
- package/templates/skills/agentia-testing/SKILL.md +9 -4
- package/templates/skills/agentia-testing/references/browser-testing.md +92 -0
- package/templates/skills/agentia-testing/references/flow-automation.md +112 -0
- package/templates/skills/agentia-testing/references/qforce.md +88 -0
- package/templates/skills/agentia-testing/references/qweb.md +103 -0
- package/templates/skills/agentia-testing/references/tests.md +17 -9
- package/vendor/java/var-replace-command.jar +0 -0
- package/dist/commands/testing/live/continue.js +0 -16
- package/dist/commands/testing/live/execute.js +0 -43
- package/dist/commands/testing/live/history.js +0 -40
- package/dist/commands/testing/live/inspect.js +0 -31
- package/dist/commands/testing/live/interrupt.js +0 -16
- package/dist/commands/testing/live/recorder.js +0 -42
- package/dist/commands/testing/live/reports.js +0 -31
- package/dist/commands/testing/live/screenshot.js +0 -25
- package/dist/commands/testing/live/set-options.js +0 -35
- package/dist/commands/testing/live/start.js +0 -58
- package/dist/commands/testing/live/status.js +0 -24
- package/dist/commands/testing/live/stop.js +0 -36
- package/dist/commands/testing/live/view.js +0 -36
- package/dist/lib/mcp/testing-live-tools.js +0 -226
- package/dist/lib/testing-live-command.js +0 -8
- package/dist/lib/testing-live-operations.js +0 -25
- package/dist/lib/testing-live-recorder.js +0 -11
- package/dist/lib/testing-live-robot.js +0 -9
- package/dist/lib/testing-live-state.js +0 -12
- package/dist/lib/testing-live-types.js +0 -3
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!-- Agentia managed skill file: agentia setup skills -->
|
|
2
|
+
|
|
3
|
+
# CRT Browser Testing Reference
|
|
4
|
+
|
|
5
|
+
Use `agentia testing browser` (and the matching `agentia_testing_browser_*` MCP tools) to drive an interactive Copado Robotic Testing browser session tied to a CRT Job and Project.
|
|
6
|
+
|
|
7
|
+
## Mental Model
|
|
8
|
+
|
|
9
|
+
- **One active session at a time**, stored in `.agentia/config.user.json` under `testingBrowserSession`. Always pass `--project <project-id>` (and optional `<job-id>` / `--session-id` guards).
|
|
10
|
+
- **In-memory Session Cookies**: Agentia exchanges your CRT PAK for `FL`, `XSRF-TOKEN`, and `sessionsToken` cookies via `/user/access-keys/tokens?toSign=all`. Cookies stay in memory (cached with a 60s expiry buffer in long-lived processes like MCP and `recorder`) and are never written to disk.
|
|
11
|
+
- **Browser Viewer**: Always pass `--no-open` to `testing browser view` by default (`agentia testing browser view --project <project-id> --no-open --json`) to print/return the interactive CRT browser session URL `https://<domain>/browser/session/<sessionId>?projectId=<projectId>&orgId=<orgId>` without launching a local browser window. Omit `--no-open` only when the user explicitly asks to open the browser. `testing browser stop` cleans up the session automatically.
|
|
12
|
+
- **Replayable Keyword History**: Every `testing browser execute` and `testing browser recorder` event appends to `~/.agentia/testing-live/<projectId>/<jobId>.jsonl` with full Robot Framework keyword lines (`TypeSecret` values and auth tokens redacted). Closing a session does not clear history.
|
|
13
|
+
|
|
14
|
+
## Canonical Workflow
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
# 1. Start the session (polls /api/status, loads QWeb/QForce/QMobile, sets QWeb config, opens Chrome)
|
|
18
|
+
agentia testing browser start <job-id> --project <project-id> --json
|
|
19
|
+
|
|
20
|
+
# 2. (Optional) Start the recorder in a background subagent before handing the viewer URL to a user
|
|
21
|
+
agentia testing browser recorder --project <project-id> --output flow.robot
|
|
22
|
+
|
|
23
|
+
# 3. Surface the viewer URL with --no-open by default (omit --no-open only if the user explicitly asks to open the browser)
|
|
24
|
+
agentia testing browser view --project <project-id> --no-open --json
|
|
25
|
+
|
|
26
|
+
# 4. Execute Robot Framework keywords (4+ spaces separate arguments)
|
|
27
|
+
agentia testing browser execute --project <project-id> \
|
|
28
|
+
--line "GoTo https://example.com" \
|
|
29
|
+
--line "VerifyText Example Domain" --json
|
|
30
|
+
|
|
31
|
+
# 5. Observe page state, DOM, and annotated screenshots
|
|
32
|
+
agentia testing browser inspect --project <project-id> --json
|
|
33
|
+
agentia testing browser inspect --project <project-id> --dom --json
|
|
34
|
+
agentia testing browser screenshot --project <project-id> --output /tmp/page.png --json
|
|
35
|
+
|
|
36
|
+
# 6. Export proven steps from Keyword History into a .robot script
|
|
37
|
+
agentia testing browser history <job-id> --project <project-id> --lines-only > flow.robot
|
|
38
|
+
|
|
39
|
+
# 7. Tear down the session (cleans up host, PACE, and local state)
|
|
40
|
+
agentia testing browser stop --project <project-id> --yes --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Subcommands & Flags
|
|
44
|
+
|
|
45
|
+
| Subcommand | Purpose & Key Flags |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `testing browser start <job-id>` | Create and bootstrap a session. Flags: `--project` (required), `--library QWeb\|QForce\|QMobile` (default `QWeb`), `--no-bootstrap`, `--no-browser`, `--screen WIDTHxHEIGHTxDEPTH`, `--viewport WIDTHxHEIGHT`, `--file`, `--timeout`. |
|
|
48
|
+
| `testing browser status [job-id]` | Check `env` (`isBrowserStarted`, `isWindowOpen`), `recorder` (`connected`), `server` (`ambleApiVersion`, `inShutdownState`, `inFatalErrorState`), and `session` (`currentIdleTime`, `sessionIdleTimeout`, `timeToExpire`, `isKeywordExecutionPending`). |
|
|
49
|
+
| `testing browser execute [job-id]` | Run keywords using `--line "..."` (repeatable), `--keyword <name> --arg <val>`, `--file <path>`, or `--stdin`. Pass `--raw` to skip `.robot` section parsing. |
|
|
50
|
+
| `testing browser inspect [job-id]` | Fetch `GET /api/system-state` (`url`, `timestamp`, `changeOrigin`, `systemState` interactive element annotations). Add `--dom` with `--output <file>` or `--json` to stream and reassemble `document.documentElement.outerHTML` over the terminal WebSocket. |
|
|
51
|
+
| `testing browser screenshot [job-id]` | Save the current viewport PNG (including teal detection bounding boxes) to `--output <path>`. |
|
|
52
|
+
| `testing browser set-options [job-id]` | Set the full recorder option block (`--[no-]enable`, `--[no-]scroll-text`, `--[no-]healing-context`, `--[no-]hover-text`, `--[no-]system-state`, `--[no-]verify-text`, `--[no-]table-keywords`). Unspecified options default to `false`. |
|
|
53
|
+
| `testing browser view` | Print (`--no-open`, default for agents) or open the CRT browser session URL. Always use `--no-open` unless the user explicitly asks to open the browser. |
|
|
54
|
+
| `testing browser recorder [job-id]` | Connect to the session WebSocket, enable backend recording, and stream captured interactions and executed keywords as Robot Framework lines (or JSON lines with `--json`). Flags: `--output <file.robot>`, `--no-enable`, `--force` (reclaim stale lock), `--debug`. |
|
|
55
|
+
| `testing browser history [job-id]` | Read per-job keyword history. Flags: `--job <id>`, `--limit <n>`, `--keyword <name>` (case-insensitive first token), `--lines-only` (flatten to raw `.robot` lines), `--include-failed` (failed executions are omitted by default), `--status completed\|failed\|recorded`. MCP `linesOnly: true` returns `count`, `jobId`, `lines`, and `projectId` without `executions`. |
|
|
56
|
+
| `testing browser stop [job-id]` | Stop the session on the session host and PACE, and clear local state. Requires `--yes` in `--json` / non-TTY mode (`confirm: true` in MCP). |
|
|
57
|
+
|
|
58
|
+
## Parallel Recorder & Idle Keepalive Patterns
|
|
59
|
+
|
|
60
|
+
### 1. Parallel Recorder via Background Subagent
|
|
61
|
+
When driving or co-piloting a browser session with a human:
|
|
62
|
+
1. Run `agentia testing browser start <job-id> --project <project-id> --json`.
|
|
63
|
+
2. Before handing the viewer URL to the user, start `agentia testing browser recorder --project <project-id> --output captured.robot` in a background shell/subagent. The recorder captures both browser interactions (`status: "recorded"`) and `testing browser execute` commands (`status: "completed"`) in execution order so `--output` produces a complete `.robot` file.
|
|
64
|
+
3. Run `agentia testing browser view --project <project-id> --no-open --json` (always pass `--no-open` by default unless the user explicitly asks to open the browser) and share the `url` with the user.
|
|
65
|
+
4. **Verify capture after the user's first action**:
|
|
66
|
+
```sh
|
|
67
|
+
agentia testing browser history --project <project-id> --status recorded --json
|
|
68
|
+
```
|
|
69
|
+
`recorder.connected: true` in `status` only proves the WebSocket is open, not that events are firing. If `count` remains `0` after the user clicks, drive the steps via `testing browser execute` instead.
|
|
70
|
+
5. **Clean shutdown**: Send `SIGINT` (`kill -INT <pid>`) to the recorder process before running `testing browser stop` so it cleanly posts `setoptions {recorder: {enabled: false}}`. Then export the unified script from history with `agentia testing browser history --project <project-id> --lines-only > captured.robot`.
|
|
71
|
+
|
|
72
|
+
### 2. Keeping Idle Sessions Warm (600s Timeout)
|
|
73
|
+
- `session.sessionIdleTimeout` defaults to **600 seconds (10 minutes)** and is reset **only by executed keywords**.
|
|
74
|
+
- The recorder's 3-second WebSocket heartbeat keeps the socket open but **does not reset the session idle timer**.
|
|
75
|
+
- When waiting on a human to log in (e.g., MFA/SSO) or inspect the viewer, run a lightweight keepalive loop that fires `GetTitle` every 4 minutes:
|
|
76
|
+
```sh
|
|
77
|
+
while true; do sleep 240; agentia testing browser execute --project <project-id> --line "GetTitle" --json || break; done &
|
|
78
|
+
```
|
|
79
|
+
Stop the keepalive loop before `testing browser stop`.
|
|
80
|
+
|
|
81
|
+
## Troubleshooting
|
|
82
|
+
|
|
83
|
+
- **`No active CRT browser session`**: Start a session with `agentia testing browser start <job-id> --project <project-id>`. If a session died from the 600s idle timeout (`404` / `410`), Agentia clears the stale local state automatically on `status` or `stop`.
|
|
84
|
+
- **`A CRT browser recorder is already running for session <id>`**: Another recorder holds the owner-scoped lock at `~/.agentia/testing-live/locks/<sessionId>.lock`. Stop the other process or pass `--force` if the prior process crashed.
|
|
85
|
+
- **Keyword fails (`CRT browser keyword execution failed`)**:
|
|
86
|
+
1. Do not retry blindly. Run `agentia testing browser inspect --project <project-id> --json`.
|
|
87
|
+
2. Check if the target element has `isCovered: true` (modal/sticky header blocking it) or different `readableTexts`.
|
|
88
|
+
3. Check `agentia testing browser status --project <project-id> --json` to confirm `env.isWindowOpen: true` and `server.inFatalErrorState: false`.
|
|
89
|
+
- **Browser window closed (`isWindowOpen: false`)**: Re-open Chrome with:
|
|
90
|
+
```sh
|
|
91
|
+
agentia testing browser execute --project <project-id> --line "Open Browser about:blank chrome" --json
|
|
92
|
+
```
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<!-- Agentia managed skill file: agentia setup skills -->
|
|
2
|
+
|
|
3
|
+
# Goal-Driven Flow Automation in CRT Browser Testing
|
|
4
|
+
|
|
5
|
+
Use this methodology when turning a natural-language goal ("create a lead", "add a product to the cart and verify checkout") into a verified sequence of Robot Framework keywords against an active `agentia testing browser` session.
|
|
6
|
+
|
|
7
|
+
Applies to `QWeb` (default), `--library QForce` (see [qforce.md](qforce.md) for Lightning-specific rules layered on top), and `--library QMobile`.
|
|
8
|
+
|
|
9
|
+
## The Core Loop
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Observe -> Act (one logical step) -> Verify expected state -> Recover if needed -> Continue
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Do **not** write an entire multi-page `.robot` script up front and fire it in one `testing browser execute --file` call. Every page transition is a hypothesis until confirmed against the browser session. Execute one logical step at a time, verify the transition, and then choose the next keyword. Batching is only appropriate for coupled inputs on the same verified view (such as `TypeText Username ...` + `TypeSecret Password ...`).
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
# 1. Act
|
|
19
|
+
agentia testing browser execute --project <project-id> --line "GoTo https://example.com" --json
|
|
20
|
+
|
|
21
|
+
# 2. Verify
|
|
22
|
+
agentia testing browser execute --project <project-id> --line "VerifyText Example Domain" --json
|
|
23
|
+
|
|
24
|
+
# 3. Observe interactive elements before the next decision
|
|
25
|
+
agentia testing browser inspect --project <project-id> --json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Choosing Locators (Priority Order)
|
|
29
|
+
|
|
30
|
+
Always prefer semantic locators over structural XPaths:
|
|
31
|
+
|
|
32
|
+
1. **Visible text** (`ClickText`, `TypeText`, `TypeSecret`, `VerifyText`, `DropDown`, `ClickCheckbox`). Disambiguate repeated text with `anchor=<nearby text>` before reaching for `index=<N>`.
|
|
33
|
+
2. **Unique attribute** (`alt`, `title`, `tooltip`, `data-icon`) when there is no visible text — use `ClickItem` / `VerifyItem`.
|
|
34
|
+
3. **XPath as a last resort** (`ClickElement`, `VerifyElement`) only when text and attribute locators cannot reach the element.
|
|
35
|
+
|
|
36
|
+
While exploring unfamiliar pages, pass a short bounded timeout (`timeout=3`) so a wrong locator fails in 3 seconds instead of 10 seconds:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
agentia testing browser execute --project <project-id> --line "ClickText Sign In timeout=3" --json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Drop the tight `timeout=3` override when curating the final exported `.robot` suite.
|
|
43
|
+
|
|
44
|
+
## Why "Completed" Execution Still Needs Verification
|
|
45
|
+
|
|
46
|
+
`testing browser execute` returning `status: "completed"` only proves the keyword ran without throwing an error—it does **not** prove that navigation succeeded, a form submitted, or a modal opened.
|
|
47
|
+
|
|
48
|
+
After any state-changing keyword (`GoTo`, `Click*`, `Type*`, `DropDown`, `PickList`, `ComboBox`, `PressKey`), run a `Verify*` keyword targeting content **unique to the new state**:
|
|
49
|
+
- After login -> verify dashboard heading or app navigation.
|
|
50
|
+
- After opening a modal -> verify a field label inside the modal before typing.
|
|
51
|
+
- After saving a record -> verify the saved state or record detail field.
|
|
52
|
+
|
|
53
|
+
Watch for missing workflow transitions:
|
|
54
|
+
- **Typed into a search box**: Append `\n` to the `TypeText` value to submit on Enter, or click the search button.
|
|
55
|
+
- **Filled form fields**: Click `Save` / `Submit` before asserting the outcome.
|
|
56
|
+
|
|
57
|
+
## Observing Page State: `inspect` + `screenshot` Overlay
|
|
58
|
+
|
|
59
|
+
| Question | Command |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| Which interactive elements are visible? | `agentia testing browser inspect --project <project-id> --json` |
|
|
62
|
+
| What does the viewport look like with detection boxes? | `agentia testing browser screenshot --project <project-id> --output /tmp/page.png --json` |
|
|
63
|
+
| What is the raw HTML (`outerHTML`)? | `agentia testing browser inspect --project <project-id> --dom --json` |
|
|
64
|
+
|
|
65
|
+
### Reading `inspect` and `screenshot` Together
|
|
66
|
+
The PNG saved by `testing browser screenshot` is not a plain screenshot: the CRT inspection engine draws colored bounding rectangles (teal by default from `SetConfig HighlightColor teal`) around every detected UI element. Each rectangle corresponds to an entry in the `systemState` array from `testing browser inspect`:
|
|
67
|
+
- `annotationIndex` — matches the numbered/boxed element in the detection pass.
|
|
68
|
+
- `readableTexts` (`ownText`, `ariaLabel`, `nearbyTexts`) — exact strings to pass to `ClickText` / `TypeText` and `anchor=`.
|
|
69
|
+
- `elementType` and `role` — distinguishes inputs, buttons, links, and `role="combobox"` lookups.
|
|
70
|
+
- `isVisible`, `isInteractive`, `isEnabled`, `isCovered` — if `isCovered: true`, a modal, toast, or sticky header is covering the element and must be closed or scrolled past first.
|
|
71
|
+
|
|
72
|
+
## Recovery Protocol
|
|
73
|
+
|
|
74
|
+
When an action or verification fails:
|
|
75
|
+
1. **Stop immediately.** Do not execute the next planned step.
|
|
76
|
+
2. **Inspect first** (`testing browser inspect` and `testing browser screenshot`) — never retry blindly.
|
|
77
|
+
3. **Compare expected vs. actual state**:
|
|
78
|
+
- *Still on the previous view?* A workflow transition (submit, save, menu click) didn't fire. Complete the transition rather than swapping locators.
|
|
79
|
+
- *On the expected view?* The locator was wrong. Pick up to 3 semantic alternatives directly from `systemState[].readableTexts` (`anchor=`, `ClickItem`, etc.).
|
|
80
|
+
4. **Wrong-but-successful action** (e.g., clicked the wrong `New` button):
|
|
81
|
+
- Inspect where you landed, restore the prior view (`Back` or re-navigate), verify restoration, and retry with `anchor=<nearby text>` or `SetConfig PartialMatch False`.
|
|
82
|
+
- Remember that successful wrong clicks land in `testing browser history` (`status: "completed"`) — strip them when curating the final `.robot` file.
|
|
83
|
+
|
|
84
|
+
## Tuning the Session for Agent-Driven Flows
|
|
85
|
+
|
|
86
|
+
- **Exact text matching**: Bootstrap sets `PartialMatch True`. On text-dense pages (especially Salesforce Lightning), switch to exact matching since you have exact `readableTexts` from `inspect`:
|
|
87
|
+
```sh
|
|
88
|
+
agentia testing browser execute --project <project-id> --line "SetConfig PartialMatch False" --json
|
|
89
|
+
```
|
|
90
|
+
- **XHR-heavy pages**: Raise timeouts with `SetConfig DefaultTimeout 20s` and `SetConfig XHRTimeout 30s` instead of adding `Sleep`.
|
|
91
|
+
|
|
92
|
+
## Exporting and Promoting the Proven Flow
|
|
93
|
+
|
|
94
|
+
Failed probes (`status: "failed"`) are automatically excluded by `testing browser history`:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
agentia testing browser history <job-id> --project <project-id> --lines-only > flow.robot
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Curate `flow.robot` by removing exploratory detours, temporary `timeout=3` overrides, and duplicate steps, then wrap it in a standard Robot Framework suite for `agentia testing job files upload` and `agentia testing job run`:
|
|
101
|
+
|
|
102
|
+
```robotframework
|
|
103
|
+
*** Settings ***
|
|
104
|
+
Library QWeb
|
|
105
|
+
Suite Setup Open Browser about:blank chrome
|
|
106
|
+
Suite Teardown Close All Browsers
|
|
107
|
+
|
|
108
|
+
*** Test Cases ***
|
|
109
|
+
Verified Flow
|
|
110
|
+
GoTo https://example.com
|
|
111
|
+
VerifyText Example Domain
|
|
112
|
+
```
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<!-- Agentia managed skill file: agentia setup skills -->
|
|
2
|
+
|
|
3
|
+
# QForce & Salesforce Lightning Reference for CRT
|
|
4
|
+
|
|
5
|
+
QForce is Copado Robotic Testing's Salesforce keyword library. It is a superset of [QWeb](qweb.md): all QWeb keywords (`ClickText`, `TypeText`, `VerifyText`, `UseTable`, etc.) work unchanged, and QForce adds Salesforce Lightning-aware locators and keywords on top.
|
|
6
|
+
|
|
7
|
+
To start a Salesforce browser session:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
agentia testing browser start <job-id> --project <project-id> --library QForce --json
|
|
11
|
+
agentia testing browser execute --project <project-id> --line "SetConfig PartialMatch False" --json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
When these Salesforce-specific rules conflict with generic QWeb text-first guidance, **the Salesforce rule wins**.
|
|
15
|
+
|
|
16
|
+
## Mandatory Salesforce Rules
|
|
17
|
+
|
|
18
|
+
1. **Always normalize app state with `LaunchApp`**:
|
|
19
|
+
Immediately after login—and before any app-specific click, tab navigation, or assertion—run:
|
|
20
|
+
```robotframework
|
|
21
|
+
LaunchApp Sales
|
|
22
|
+
```
|
|
23
|
+
`LaunchApp` is idempotent: it checks the active Lightning app and only opens the App Launcher when needed. Never skip it just because the right app appears open, and do not replace it with manual clicks on the App Launcher waffle icon.
|
|
24
|
+
2. **Verify Record Details with `VerifyField`, never `VerifyText`**:
|
|
25
|
+
Lightning record pages contain repeated labels in headers, related lists, and activity timelines, causing `VerifyText` to pass for the wrong reason.
|
|
26
|
+
3. **Three dropdown families require three distinct keywords**:
|
|
27
|
+
- Native HTML `<select>` -> `DropDown <label> <value>`
|
|
28
|
+
- Lightning custom picklist (button/div/listbox widget) -> `PickList <label> <value>`
|
|
29
|
+
- Lookup / searchable combobox (`input` with `role="combobox"`) -> `ComboBox <locator> <value> timeout=10`
|
|
30
|
+
4. **Lookups (`ComboBox`) only select existing records**:
|
|
31
|
+
Never finish a lookup field with `TypeText` (typed text is not a selected record). If the target record does not exist, use the nested `New <Object>` creation flow.
|
|
32
|
+
5. **Never hard-code org-specific Lightning URLs or record IDs**:
|
|
33
|
+
Navigate via `LaunchApp` and object tabs so tests survive sandbox refreshes. Store credentials in CRT Variables (`testing variable`) or User Parameters (`testing user-parameter`) and type secrets with `TypeSecret`.
|
|
34
|
+
|
|
35
|
+
## QForce Keyword Catalog
|
|
36
|
+
|
|
37
|
+
In `.robot` files and `testing browser execute`, always use `KeywordCase` (`LaunchApp`, `VerifyField`, `PickList`, `ComboBox`). Separate arguments with 4+ spaces.
|
|
38
|
+
|
|
39
|
+
| Keyword | Form | When to Use |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `LaunchApp` | `LaunchApp <Exact App Name>` | Open a Salesforce Lightning app via the App Launcher by exact name (`Sales`, `Service`). |
|
|
42
|
+
| `VerifyField` | `VerifyField <label> <expected>` | Assert a plain-text field value on a Record Details page (`VerifyField Phone 123456789`). |
|
|
43
|
+
| `VerifyField` (link) | `VerifyField <label> <expected> tag=a` | Assert a linked field value (lookup, owner, related record: `VerifyField Account Name Acme tag=a`). |
|
|
44
|
+
| `VerifyField` (indexed) | `VerifyField <label> <expected> <index> [tag=a]` | Disambiguate when the same field label appears multiple times on the Details page. Discover `<index>` with `GetFieldValue` first. |
|
|
45
|
+
| `GetFieldValue` | `GetFieldValue <label> [index]` | Read the value of the Nth field with `<label>` to discover which index to pass to `VerifyField`. |
|
|
46
|
+
| `PickList` | `PickList <label> <value> [index=1] [timeout=0]` | Select an option from a Lightning custom picklist (`PickList Stage Closed Won`). |
|
|
47
|
+
| `ComboBox` | `ComboBox <locator> <value> timeout=10` | Search and select an **existing** record in a Lightning lookup/combobox (`ComboBox Account Name Acme timeout=10` or `ComboBox Search Accounts... Acme timeout=10`). |
|
|
48
|
+
|
|
49
|
+
## Record Details Verification Ladder
|
|
50
|
+
|
|
51
|
+
On a Salesforce record's **Details** tab, follow this order:
|
|
52
|
+
|
|
53
|
+
1. **Plain field**: `VerifyField <label> <expected>`
|
|
54
|
+
2. **Linked field (lookup/owner)**: `VerifyField <label> <expected> tag=a`
|
|
55
|
+
3. **Duplicate field label on page**: Probe indexes with `GetFieldValue`, then assert with indexed `VerifyField`:
|
|
56
|
+
```robotframework
|
|
57
|
+
GetFieldValue Account Name 1
|
|
58
|
+
GetFieldValue Account Name 2
|
|
59
|
+
VerifyField Account Name Acme Corp 2 tag=a
|
|
60
|
+
```
|
|
61
|
+
4. **Never use `VerifyText` as the primary Details assertion**, and do not assert on ephemeral toast messages (toasts vanish quickly; verify the saved record's Details instead).
|
|
62
|
+
|
|
63
|
+
## Lookup Fields & Nested Record Creation
|
|
64
|
+
|
|
65
|
+
When filling a lookup field (such as `Account Name` on a Contact or Opportunity):
|
|
66
|
+
|
|
67
|
+
- **If the target record exists**:
|
|
68
|
+
```robotframework
|
|
69
|
+
ComboBox Account Name Acme Corp timeout=10
|
|
70
|
+
ClickText Save
|
|
71
|
+
ClickText Details
|
|
72
|
+
VerifyField Account Name Acme Corp tag=a
|
|
73
|
+
```
|
|
74
|
+
- **If `ComboBox` fails (`Could not find combobox ... with value ...`) or the record does not exist**:
|
|
75
|
+
Do not retry `ComboBox` in a loop and do not leave raw `TypeText` in the input. Trigger the nested `New <Object>` modal from the lookup instead:
|
|
76
|
+
```robotframework
|
|
77
|
+
ClickText Account Name
|
|
78
|
+
ClickText New Account
|
|
79
|
+
TypeText Account Name Acme Corp
|
|
80
|
+
ClickText Save
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Recognising Dropdown Types via `testing browser inspect`
|
|
84
|
+
|
|
85
|
+
When unsure whether a field uses `DropDown`, `PickList`, or `ComboBox`, run `agentia testing browser inspect --project <project-id> --json` and check the element in `systemState`:
|
|
86
|
+
- `elementType: "select"` -> `DropDown`
|
|
87
|
+
- Clickable button/div showing the current picklist value (not an `input`) -> `PickList`
|
|
88
|
+
- `elementType: "input"` with `role: "combobox"` or placeholder `Search ...` -> `ComboBox`
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<!-- Agentia managed skill file: agentia setup skills -->
|
|
2
|
+
|
|
3
|
+
# QWeb Keyword Reference for CRT
|
|
4
|
+
|
|
5
|
+
QWeb is the web-automation Robot Framework library used by Copado Robotic Testing in `.robot` suites (`agentia testing job run`) and browser sessions (`agentia testing browser start <job-id> --project <project-id>`).
|
|
6
|
+
|
|
7
|
+
For goal-driven exploration in a browser session, pair this reference with [flow-automation.md](flow-automation.md). For Salesforce Lightning, also load [qforce.md](qforce.md).
|
|
8
|
+
|
|
9
|
+
## Syntax & Formatting Rules
|
|
10
|
+
|
|
11
|
+
- **4+ space separator**: Separate the keyword name, positional arguments, and `key=value` named arguments with **at least 4 spaces** (`KeywordName arg1 arg2 anchor=Header`). Never use a single space—Robot Framework treats `ClickText Login` as a single nonexistent keyword name.
|
|
12
|
+
- **Prefer visible text over XPath**: `PartialMatch` is `True` by default in browser sessions (`SetConfig PartialMatch False` forces exact matches).
|
|
13
|
+
- **`anchor=<text>` for disambiguation**: When the same text appears multiple times, pass `anchor=<nearby text>` (`ClickText Edit anchor=Profile`). Use 1-based `index=<N>` only as a last resort.
|
|
14
|
+
- **Booleans**: Capitalize `True` and `False` (`clear=False`, `partial_match=False`).
|
|
15
|
+
- **Submitting on Enter**: Append `\n` to `TypeText` (`TypeText Search laptop\n`) or run `PressKey ${EMPTY} {ENTER}`.
|
|
16
|
+
- **XPath `=` escaping**: In browser testing (`testing browser execute`), Agentia automatically escapes `=` inside `//...` XPath tokens so Robot Framework does not misread `@id="x"` as a named parameter.
|
|
17
|
+
|
|
18
|
+
## Keyword Catalog
|
|
19
|
+
|
|
20
|
+
### Navigation
|
|
21
|
+
|
|
22
|
+
| Keyword | Form | Notes |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| `GoTo` | `GoTo https://example.com` | Navigate to a full URL (`https://...`). |
|
|
25
|
+
| `Back` / `Forward` | `Back` | Browser history navigation. |
|
|
26
|
+
| `RefreshPage` | `RefreshPage` | Reload the current page. |
|
|
27
|
+
| `Open Browser` | `Open Browser about:blank chrome` | Suite setup; already executed during `testing browser start` unless `--no-browser` is passed. |
|
|
28
|
+
| `Close All Browsers` | `Close All Browsers` | Suite teardown. Do not call during an active browser session; use `testing browser stop` instead. |
|
|
29
|
+
|
|
30
|
+
### Clicking
|
|
31
|
+
|
|
32
|
+
| Keyword | Form | When to Use |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `ClickText` | `ClickText <text> [anchor=<text>]` | Default choice for any button, link, or tab with visible text. |
|
|
35
|
+
| `ClickItem` | `ClickItem <alt_or_title> [anchor=<text>]` | Click by `alt`, `title`, `tooltip`, `data-tooltip`, or `data-icon` (ideal for icon-only buttons). |
|
|
36
|
+
| `ClickElement` | `ClickElement <xpath>` | Last resort when neither `ClickText` nor `ClickItem` can target the element. |
|
|
37
|
+
| `ClickCheckbox` | `ClickCheckbox <label> on\|off` | Idempotently set a checkbox to `on` or `off`. |
|
|
38
|
+
| `ClickList` | `ClickList <list_locator> <item_text>` | Click an item inside a list widget. |
|
|
39
|
+
| `ClickCell` | `ClickCell <row> <col>` | Click a cell inside the active table (requires `UseTable` first). |
|
|
40
|
+
|
|
41
|
+
### Typing & Form Inputs
|
|
42
|
+
|
|
43
|
+
| Keyword | Form | Notes |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `TypeText` | `TypeText <label> <value> [clear=False]` | Clears the field and types `<value>`. Append `\n` to submit. |
|
|
46
|
+
| `TypeSecret` | `TypeSecret <label> <value>` | Same as `TypeText`, but masks the value in logs and Agentia browser history. |
|
|
47
|
+
| `DropDown` | `DropDown <label> <option>` | Select an option from a native HTML `<select>` element. |
|
|
48
|
+
| `GetInputValue` | `GetInputValue <label>` | Read the current value of an input field. |
|
|
49
|
+
|
|
50
|
+
### Verification & Reading
|
|
51
|
+
|
|
52
|
+
| Keyword | Form | Notes |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| `VerifyText` | `VerifyText <text> [timeout=30]` | Assert visible text appears on the page (preferred over `Sleep` for waiting). |
|
|
55
|
+
| `VerifyNoText` | `VerifyNoText <text> [timeout=10]` | Assert text does not appear (or disappears). |
|
|
56
|
+
| `VerifyItem` | `VerifyItem <alt_or_title>` | Assert an element with the given `alt`/`title`/`tooltip` exists. |
|
|
57
|
+
| `VerifyElement` | `VerifyElement <xpath> [timeout=30]` | Assert an XPath exists in the DOM. |
|
|
58
|
+
| `VerifyValue` | `VerifyValue <label> <expected>` | Assert an input field holds `<expected>`. |
|
|
59
|
+
| `VerifyCheckboxValue` | `VerifyCheckboxValue <label> on\|off` | Assert a checkbox state. |
|
|
60
|
+
| `GetText` | `GetText <locator>` | Read visible text of an element. |
|
|
61
|
+
| `GetAttribute` | `GetAttribute <locator> <attribute>` | Read an attribute (e.g., `href`, `aria-expanded`, `outerHTML`). |
|
|
62
|
+
| `GetTitle` | `GetTitle` | Read the document title (also useful as a harmless keepalive keyword in browser sessions). |
|
|
63
|
+
|
|
64
|
+
### Hover, Scroll, Drag & Keyboard
|
|
65
|
+
|
|
66
|
+
| Keyword | Form | Notes |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| `HoverText` / `HoverElement` | `HoverText <text>` | Hover over an element to reveal menus or tooltips. |
|
|
69
|
+
| `Scroll` | `Scroll <locator> page_down\|page_up\|<px>` | Scroll an element or `//html` for the full page. |
|
|
70
|
+
| `ScrollTo` | `ScrollTo <text_locator>` | Scroll until `<text_locator>` is in view. |
|
|
71
|
+
| `DragDrop` | `DragDrop <source> <target>` | Drag one element onto another. |
|
|
72
|
+
| `PressKey` | `PressKey <locator> <key>` | Use `${EMPTY}` for global key press (`{ENTER}`, `{ESC}`, `{TAB}`). |
|
|
73
|
+
|
|
74
|
+
### Stateful Tables
|
|
75
|
+
|
|
76
|
+
Call `UseTable` once to bind the active table, then address cells by 1-based row/column (`r1`, `c2`) or header/row text:
|
|
77
|
+
|
|
78
|
+
```robotframework
|
|
79
|
+
UseTable Users
|
|
80
|
+
ClickCell r1 Email
|
|
81
|
+
VerifyTable r1 Status Active
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Configuration (`SetConfig`)
|
|
85
|
+
|
|
86
|
+
| Setting | Example | Purpose |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| `DefaultTimeout` | `SetConfig DefaultTimeout 20s` | Global auto-wait timeout for locators (default `10s`). |
|
|
89
|
+
| `XHRTimeout` | `SetConfig XHRTimeout 30s` | Wait for pending XHR/network activity before acting. |
|
|
90
|
+
| `PartialMatch` | `SetConfig PartialMatch False` | Require exact text matches instead of substring matches. |
|
|
91
|
+
| `CaseInsensitive` | `SetConfig CaseInsensitive True` | Enable case-insensitive text matching. |
|
|
92
|
+
| `ClickToFocus` | `SetConfig ClickToFocus True` | Click inputs before typing (enabled by default in browser sessions). |
|
|
93
|
+
|
|
94
|
+
## Decision Tree
|
|
95
|
+
|
|
96
|
+
1. **Open a URL** -> `GoTo https://...`
|
|
97
|
+
2. **Click readable text** -> `ClickText <text>` (add `anchor=<nearby>` if repeated)
|
|
98
|
+
3. **Click an icon/image with no text** -> `ClickItem <alt_or_title>`, else `ClickElement <xpath>`
|
|
99
|
+
4. **Type into a field** -> `TypeText <label> <value>` (or `TypeSecret` for passwords/tokens)
|
|
100
|
+
5. **Select from a native `<select>`** -> `DropDown <label> <option>`
|
|
101
|
+
6. **Toggle a checkbox** -> `ClickCheckbox <label> on`
|
|
102
|
+
7. **Wait for page readiness** -> `VerifyText <landmark> timeout=30` (avoid `Sleep`)
|
|
103
|
+
8. **Work with a table** -> `UseTable <table_name>` -> `VerifyTable` / `ClickCell`
|
|
@@ -46,7 +46,7 @@ agentia testing job runs logs <build-id> --project <project-id> --job <job-id> -
|
|
|
46
46
|
| Variables | `testing variable list|get|create|update|delete` |
|
|
47
47
|
| User parameters | `testing user-parameter list|get|create|update|delete` |
|
|
48
48
|
| Data tables | `testing data-table list|get|create|update|delete|export` |
|
|
49
|
-
|
|
|
49
|
+
| Browser testing | `testing browser start|stop|status|execute|inspect|screenshot|set-options|history|view|recorder` |
|
|
50
50
|
|
|
51
51
|
`testing job` is the single namespace for test definitions and their runs. Commands directly under `job` take a job ID; `job runs get|logs|abort` take a build/run ID plus `--job`. On `testing job create` and `testing job update`, `--[no-]show-video-params` (`showVideoParams` in the API/MCP) enables or disables Video Streaming and Recording capabilities when running the test job. The older `testing create|update|status|logs|run`, `testing test ...`, `testing build ...`, and `testing job files|upload|download` forms are deprecated aliases that still execute but warn when used: `create` maps to `job create`, `update` to `job files upload` (file operations, not `job update`), `status`, `build list`, and `build latest` to `job runs list`, `build get` to `job runs get`, and `build search|logs|abort` to `job runs search|logs|abort`.
|
|
52
52
|
|
|
@@ -65,19 +65,27 @@ Schedules support get, set with cron/timezone/record policy, and remove. Data ta
|
|
|
65
65
|
|
|
66
66
|
Data-table create/update/delete and existing-file overwrite are protected operations. Never overwrite or delete without user intent.
|
|
67
67
|
|
|
68
|
-
##
|
|
68
|
+
## Browser Testing
|
|
69
69
|
|
|
70
70
|
Use a regression-owned job:
|
|
71
71
|
|
|
72
72
|
```sh
|
|
73
|
-
agentia testing
|
|
74
|
-
agentia testing
|
|
75
|
-
agentia testing
|
|
76
|
-
agentia testing
|
|
77
|
-
agentia testing
|
|
73
|
+
agentia testing browser start <job-id> --project <project-id> --json
|
|
74
|
+
agentia testing browser status --project <project-id> --json
|
|
75
|
+
agentia testing browser view --project <project-id> --no-open --json
|
|
76
|
+
agentia testing browser execute --project <project-id> --line "GoTo https://example.com" --json
|
|
77
|
+
agentia testing browser inspect --project <project-id> --json
|
|
78
|
+
agentia testing browser history <job-id> --project <project-id> --lines-only
|
|
79
|
+
agentia testing browser stop --project <project-id> --yes --json
|
|
78
80
|
```
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
Always pass `--no-open` to `testing browser view` by default to print/return the interactive CRT browser session URL without launching a browser; omit `--no-open` only when the user explicitly asks to open the browser. Session cookies and XSRF values remain in-memory only. `recorder` is long-running and uses an owner-scoped local lock (`--force` reclaims a stale lock); neither `view` nor `recorder` is exposed through MCP. The older `testing live ...` commands remain available as deprecated aliases, except `continue` and `interrupt`, which were removed.
|
|
83
|
+
|
|
84
|
+
For deep browser-testing guidance, load:
|
|
85
|
+
- [browser-testing.md](browser-testing.md) — subcommands, flags, parallel recorder subagent pattern, 600s idle keepalive, and troubleshooting
|
|
86
|
+
- [flow-automation.md](flow-automation.md) — Observe -> Act -> Verify -> Recover loop and reading `screenshot` detection overlays with `inspect` `systemState`
|
|
87
|
+
- [qweb.md](qweb.md) — QWeb keyword catalog, 4+ space separator rule, and locator priority
|
|
88
|
+
- [qforce.md](qforce.md) — Salesforce Lightning rules (`--library QForce`, `LaunchApp`, `VerifyField`, `PickList`, `ComboBox`)
|
|
81
89
|
|
|
82
90
|
## Secret Inputs And Redaction
|
|
83
91
|
|
|
@@ -90,7 +98,7 @@ Live viewer secrets remain in the keychain. Session cookies and XSRF values are
|
|
|
90
98
|
|
|
91
99
|
Destructive or protected CLI actions prompt in an interactive TTY. JSON and non-TTY calls require `--yes`. Matching MCP tools require `confirm: true`, not a `yes` field.
|
|
92
100
|
|
|
93
|
-
This applies to resource deletion, build abort, schedule removal,
|
|
101
|
+
This applies to resource deletion, build abort, schedule removal, browser stop, protected data-table imports/deletion, and output overwrite.
|
|
94
102
|
|
|
95
103
|
## Gotchas
|
|
96
104
|
|
|
Binary file
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
2
|
-
import { runTestingLiveControlCommand, testingLiveCommonFlags, testingLiveOptionalJobArg, } from '../../../lib/testing-live-command.js';
|
|
3
|
-
export default class TestingLiveContinue extends AgentiaCommand {
|
|
4
|
-
static args = testingLiveOptionalJobArg;
|
|
5
|
-
static description = 'Continue paused Robot execution in the active CRT live session';
|
|
6
|
-
static examples = ['<%= config.bin %> <%= command.id %> --project <project-id>'];
|
|
7
|
-
static flags = testingLiveCommonFlags;
|
|
8
|
-
async run() {
|
|
9
|
-
const { args, flags } = await this.parse(TestingLiveContinue);
|
|
10
|
-
return runTestingLiveControlCommand('continue', args, flags, {
|
|
11
|
-
display: (fn) => this.display(fn),
|
|
12
|
-
log: (msg) => this.log(msg),
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=continue.js.map
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
3
|
-
import { testingLiveCommonFlags, testingLiveOptionalJobArg } from '../../../lib/testing-live-command.js';
|
|
4
|
-
import { executeTestingLive } from '../../../lib/testing-live-operations.js';
|
|
5
|
-
export default class TestingLiveExecute extends AgentiaCommand {
|
|
6
|
-
static args = testingLiveOptionalJobArg;
|
|
7
|
-
static description = 'Execute bounded Robot Framework keywords in an active CRT live session';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> --project <project-id> --keyword GoTo --arg https://example.com',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --file smoke.robot --section Login',
|
|
11
|
-
];
|
|
12
|
-
static flags = {
|
|
13
|
-
...testingLiveCommonFlags,
|
|
14
|
-
arg: Flags.string({ description: 'Keyword argument. Repeat to preserve argument boundaries.', multiple: true }),
|
|
15
|
-
file: Flags.string({ description: 'Robot Framework input file.' }),
|
|
16
|
-
keyword: Flags.string({ description: 'Robot Framework keyword name.' }),
|
|
17
|
-
line: Flags.string({ description: 'Raw Robot Framework keyword line. Repeat for multiple lines.', multiple: true }),
|
|
18
|
-
raw: Flags.boolean({ default: false, description: 'Treat file input as raw keyword lines.' }),
|
|
19
|
-
section: Flags.string({ description: 'Robot test/task name to execute.' }),
|
|
20
|
-
'section-index': Flags.integer({ description: 'One-based Robot test/task index to execute.', min: 1 }),
|
|
21
|
-
};
|
|
22
|
-
async run() {
|
|
23
|
-
const { args, flags } = await this.parse(TestingLiveExecute);
|
|
24
|
-
const supplied = [flags.keyword !== undefined, flags.file !== undefined, (flags.line?.length ?? 0) > 0].filter(Boolean);
|
|
25
|
-
if (supplied.length !== 1)
|
|
26
|
-
throw new Error('Use exactly one of --keyword, --line, or --file.');
|
|
27
|
-
const result = await this.withSpinner('Executing CRT live keyword', () => executeTestingLive({
|
|
28
|
-
args: flags.arg,
|
|
29
|
-
file: flags.file,
|
|
30
|
-
jobId: args['job-id'],
|
|
31
|
-
keyword: flags.keyword,
|
|
32
|
-
lines: flags.line,
|
|
33
|
-
projectId: flags.project,
|
|
34
|
-
raw: flags.raw,
|
|
35
|
-
section: flags.section,
|
|
36
|
-
sectionIndex: flags['section-index'],
|
|
37
|
-
sessionId: flags['session-id'],
|
|
38
|
-
}));
|
|
39
|
-
this.display(() => this.log(`Execution ${result.executionId}: ${result.status}`));
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=execute.js.map
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
3
|
-
import { testingLiveCommonFlags } from '../../../lib/testing-live-command.js';
|
|
4
|
-
import { getTestingLiveHistory } from '../../../lib/testing-live-operations.js';
|
|
5
|
-
import { readTestingLiveState } from '../../../lib/testing-live-state.js';
|
|
6
|
-
export default class TestingLiveHistory extends AgentiaCommand {
|
|
7
|
-
static args = {
|
|
8
|
-
'job-id': Args.integer({ description: 'CRT job ID; defaults to the active session.', required: false }),
|
|
9
|
-
};
|
|
10
|
-
static description = 'Read bounded sanitized local CRT live execution history';
|
|
11
|
-
static examples = ['<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --limit 20 --json'];
|
|
12
|
-
static flags = {
|
|
13
|
-
...testingLiveCommonFlags,
|
|
14
|
-
limit: Flags.integer({ default: 10, description: 'Maximum records to return.', max: 500, min: 1 }),
|
|
15
|
-
status: Flags.option({
|
|
16
|
-
description: 'Execution status filter.',
|
|
17
|
-
options: ['completed', 'failed', 'recorded'],
|
|
18
|
-
})(),
|
|
19
|
-
};
|
|
20
|
-
async run() {
|
|
21
|
-
const { args, flags } = await this.parse(TestingLiveHistory);
|
|
22
|
-
const active = args['job-id'] === undefined ? await readTestingLiveState() : undefined;
|
|
23
|
-
const jobId = args['job-id'] ?? active?.jobId;
|
|
24
|
-
if (jobId === undefined || (active !== undefined && active.projectId !== flags.project)) {
|
|
25
|
-
throw new Error('Provide a job ID or start a live session for this project.');
|
|
26
|
-
}
|
|
27
|
-
const result = getTestingLiveHistory({
|
|
28
|
-
jobId,
|
|
29
|
-
limit: flags.limit,
|
|
30
|
-
projectId: flags.project,
|
|
31
|
-
status: flags.status,
|
|
32
|
-
});
|
|
33
|
-
this.display(() => {
|
|
34
|
-
for (const execution of result.executions)
|
|
35
|
-
this.log(`${execution.startedAt} [${execution.status}] ${execution.lines.join(' | ')}`);
|
|
36
|
-
});
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=history.js.map
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
3
|
-
import { testingLiveCommonFlags, testingLiveOptionalJobArg } from '../../../lib/testing-live-command.js';
|
|
4
|
-
import { inspectTestingLive } from '../../../lib/testing-live-operations.js';
|
|
5
|
-
import { formatTestingRecord } from '../../../lib/testing-types.js';
|
|
6
|
-
export default class TestingLiveInspect extends AgentiaCommand {
|
|
7
|
-
static args = testingLiveOptionalJobArg;
|
|
8
|
-
static description = 'Inspect bounded, sanitized page state from an active CRT live session';
|
|
9
|
-
static examples = [
|
|
10
|
-
'<%= config.bin %> <%= command.id %> --project <project-id> --json',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> --project <project-id> --dom --output page.html',
|
|
12
|
-
];
|
|
13
|
-
static flags = {
|
|
14
|
-
...testingLiveCommonFlags,
|
|
15
|
-
dom: Flags.boolean({ default: false, description: 'Fetch raw page DOM; requires --output.' }),
|
|
16
|
-
output: Flags.string({ dependsOn: ['dom'], description: 'Explicit file path for raw DOM.' }),
|
|
17
|
-
};
|
|
18
|
-
async run() {
|
|
19
|
-
const { args, flags } = await this.parse(TestingLiveInspect);
|
|
20
|
-
const result = await this.withSpinner('Inspecting CRT live session', () => inspectTestingLive({
|
|
21
|
-
dom: flags.dom,
|
|
22
|
-
jobId: args['job-id'],
|
|
23
|
-
output: flags.output,
|
|
24
|
-
projectId: flags.project,
|
|
25
|
-
sessionId: flags['session-id'],
|
|
26
|
-
}));
|
|
27
|
-
this.display(() => this.log(flags.dom ? `DOM written to ${String(result.path)}.` : formatTestingRecord(result)));
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=inspect.js.map
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
2
|
-
import { runTestingLiveControlCommand, testingLiveCommonFlags, testingLiveOptionalJobArg, } from '../../../lib/testing-live-command.js';
|
|
3
|
-
export default class TestingLiveInterrupt extends AgentiaCommand {
|
|
4
|
-
static args = testingLiveOptionalJobArg;
|
|
5
|
-
static description = 'Interrupt Robot execution in the active CRT live session';
|
|
6
|
-
static examples = ['<%= config.bin %> <%= command.id %> --project <project-id>'];
|
|
7
|
-
static flags = testingLiveCommonFlags;
|
|
8
|
-
async run() {
|
|
9
|
-
const { args, flags } = await this.parse(TestingLiveInterrupt);
|
|
10
|
-
return runTestingLiveControlCommand('interrupt', args, flags, {
|
|
11
|
-
display: (fn) => this.display(fn),
|
|
12
|
-
log: (msg) => this.log(msg),
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=interrupt.js.map
|