Skip to content

Commit 6aa5ff1

Browse files
committed
docs: add Robot Framework comparison PoC design spec
Formal spec for the dual-track PoC comparing agent-driven Selenium locator refresh vs. Playwright keyword port, recovering the Superpowers loop after partial implementation without spec/review gates.
1 parent d5debb6 commit 6aa5ff1

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Robot Framework Maintenance Comparison PoC Design
2+
3+
Status: Proposed
4+
Date: 2026-04-27
5+
Scope: Evidence-gathering PoC comparing two Robot Framework maintenance strategies for CumulusCI
6+
7+
## Context
8+
9+
CumulusCI ships a Robot Framework integration with ~37 Selenium keywords (`Salesforce.py`), a versioned locator dictionary (`locators_*.py`), a page object model, and a nascent Playwright library (`SalesforcePlaywright.py`, 8 keywords). The Selenium locators are tightly coupled to Salesforce Lightning's DOM structure, which changes every API version. Bryan's original architecture (copy-on-write locator files, `locator_manager` with dot-notation, parameterized format strings, multi-tier keyword libraries) was designed for periodic per-release maintenance. That maintenance stopped due to team capacity, not architectural failure.
10+
11+
Two questions now need evidence-backed answers:
12+
13+
1. With agent token budgets unblocked, is refreshing Selenium locators per API version a tractable ongoing cost?
14+
2. Is porting to Playwright cheaper to maintain per release, and does it justify the migration cost?
15+
16+
The parent v5 roadmap requires an ADR on this topic and explicitly mandates evidence before decision.
17+
18+
### Shadow DOM Finding (from WIP)
19+
20+
API v66 has migrated parts of Lightning Experience from Aura (light DOM) to LWC (shadow DOM). Selenium 3 XPath/CSS cannot pierce shadow DOM. Affected elements include the actions ribbon on filtered list views and the List View Controls button. This is a structural ceiling for Selenium that grows with each API version as Salesforce continues the Aura-to-LWC migration.
21+
22+
## Goals
23+
24+
- Measure agent token cost to refresh CCI's Selenium locators from API v57 to v66.
25+
- Measure agent token cost to port ~8 high-value Playwright keywords covering the same test surface.
26+
- Quantify locator durability: what fraction of Selenium locators reference Aura internals (fragile) vs. SLDS/Lightning-stable selectors?
27+
- Identify structural coverage ceilings (shadow DOM elements unreachable by Selenium 3).
28+
- Write ADR 0004 backed by the comparison evidence.
29+
- Draft a local "Robot Locator Refresh" skill spec codifying Bryan's best practices for agent-driven locator updates.
30+
31+
## Non-Goals
32+
33+
- Full Playwright feature parity with `Salesforce.py` (37 keywords). Track B ports ~8.
34+
- Upgrading Selenium 3 to 4 (that is in the dependency-modernization phase).
35+
- Fixing pre-existing `[Return]` deprecation warnings or `_tkinter` import noise.
36+
- Refactoring the `locator_manager` or page object architecture.
37+
- NPSP/EDA downstream migration planning (noted in ADR as future work).
38+
- Resolving the `form_handlers.py` Selenium coupling for Playwright (out of scope; Track B uses Playwright-native form filling).
39+
40+
## Decisions
41+
42+
1. **Two-track comparison against the same scratch org (API v66).**
43+
Track A: Selenium locator refresh. Track B: Playwright keyword port. Same test surface, same org, comparable evidence.
44+
45+
2. **Track A preserves Bryan's architecture.**
46+
`locators_66.py` deepcopies `locators_57` and overrides only changed locators. No structural changes to `locator_manager`, `Salesforce.py`, or the versioning system.
47+
48+
3. **Track B uses Playwright-native locators (not `locator_manager`).**
49+
`SalesforcePlaywright.py` already ignores the versioned locator system. Track B continues that pattern, using Playwright's accessibility-first selectors (`role=`, `text=`, CSS). This is a data point on whether `locator_manager` adds value for Playwright.
50+
51+
4. **Inline locators in page objects are in scope for Track A.**
52+
`BasePageObjects.py` and `ObjectManagerPageObject.py` contain hardcoded locators outside the versioning system. Track A fixes breakage in these files too, since they are part of the real maintenance cost.
53+
54+
5. **ADR format follows `docs/adrs/templates/template.md`.**
55+
Status starts as `Proposed`. Sections: Context and Problem Statement, Assumptions, Constraints, Decision, Considered Options, Decision Outcome, Consequences, References.
56+
57+
6. **Skill spec is local only.**
58+
Written to `~/.cursor/skills-cursor/robot-locator-refresh/SKILL.md`, not committed to the repo.
59+
60+
## Current-State Inputs (WIP Baseline)
61+
62+
The following work was completed in a prior session before the formal loop was established. It is preserved as evidence and starting state, not reverted.
63+
64+
### Completed
65+
66+
- Scratch org `robot-poc` created (API v66, expires ~May 4 2026).
67+
- `locators_66.py` created with 3 locator overrides:
68+
- `actions`: added `//div[contains(@class, 'slds-page-header')]` as OR branch.
69+
- `app_launcher.current_app`: broadened to `//*[contains(@class,'appName')][.//text()='{}']`.
70+
- `list_view_menu.button`: added `aria-label` CSS fallback (not yet verified against shadow DOM).
71+
- Test file adjustments for API v66 UI changes:
72+
- `TestLibraryA.py`: `breadcrumbDetail` class replaced with `//a[@role='tab'][.='{}']`.
73+
- `locators.robot` line 20: `text:Mobile Publisher` changed to `text:Object Manager`.
74+
- 86 of 88 Selenium tests pass across 10 suites.
75+
- `forms.robot` radiobutton test needs re-run after `list_view_menu.button` fix.
76+
77+
### Remaining
78+
79+
- Verify `forms.robot` fix or document as shadow DOM limitation.
80+
- Run full 11-suite battery for final confirmation.
81+
- Run 4 page object suites and fix inline locator breakage.
82+
- Locator durability audit.
83+
- Skill spec draft.
84+
- All of Track B (Playwright port + test).
85+
- Comparison analysis.
86+
- ADR 0004.
87+
- Parent roadmap update.
88+
89+
## Architecture
90+
91+
### Locator Version Resolution
92+
93+
```mermaid
94+
flowchart LR
95+
orgApi["Org API version (e.g. 66)"] --> resolver["get_locator_module_name(66)"]
96+
resolver --> check{"locators_66.py exists?"}
97+
check -- yes --> load["import locators_66"]
98+
check -- no --> fallback["use highest-numbered locators_*.py"]
99+
load --> update["lex_locators.update(module.lex_locators)"]
100+
fallback --> update
101+
update --> register["locator_manager.register_locators('sf', lex_locators)"]
102+
```
103+
104+
### Locator Inheritance Chain
105+
106+
```
107+
locators_56.py (base dict, ~87 lines, all locators)
108+
|
109+
v deepcopy
110+
locators_57.py (no changes, identity copy)
111+
|
112+
v deepcopy + 3 overrides
113+
locators_66.py (WIP: actions, app_launcher.current_app, list_view_menu.button)
114+
```
115+
116+
Versions 58-65 all fall back to 57 via the resolver's highest-numbered fallback.
117+
118+
### Inline Locator Inventory (Outside Versioning System)
119+
120+
| File | Locator Count | Risk |
121+
| ------------------------------------------------- | ------------- | -------------------------------------------- |
122+
| `BasePageObjects.py` (`ModalMixin`) | ~8 | `uiModal` class is Aura-internal |
123+
| `ObjectManagerPageObject.py` | 13 | Standalone dict, fully outside versioning |
124+
| `Salesforce.py` (modal-container, label strategy) | ~3 | Mixed Aura/SLDS |
125+
| `form_handlers.py` (combobox/lookup values) | ~2 | Lightning component selectors, moderate risk |
126+
127+
### Track B: SalesforcePlaywright.py
128+
129+
Currently 8 keywords, no connection to `lex_locators` or `locator_manager`. Hardcodes SLDS selectors inline. Track B adds ~8 keywords covering: app launcher navigation, form population, modal handling, related list interaction.
130+
131+
## Comparison Criteria
132+
133+
| Metric | How Measured |
134+
| ------------------------------- | -------------------------------------------------------------------------- |
135+
| Agent token cost | Approximate from conversation length per track |
136+
| Locator durability | Count Aura-internal refs vs. SLDS/Lightning-stable refs in final artifacts |
137+
| Shadow DOM ceiling | Count elements unreachable by Selenium 3 but accessible via Playwright |
138+
| Per-release maintenance posture | Estimated effort to repeat locator refresh for next API version |
139+
| Coverage gap | Keywords ported vs. total `Salesforce.py` surface (37 keywords) |
140+
| Downstream impact | Qualitative assessment of NPSP/EDA migration cost per path |
141+
142+
## Verification Strategy
143+
144+
- **Track A Selenium battery**: 11 suites run via `uv run cci task run robot --org robot-poc -o suites <list> -o vars BROWSER:headlesschrome`
145+
- **Track A page objects**: 4 suites under `cumulusci/robotframework/tests/salesforce/pageobjects/`
146+
- **Track B Playwright**: 1 end-to-end suite via `uv run cci task run robot --org robot-poc -o suites <path> -o vars BROWSER:headlesschrome`
147+
- **Unit tests**: `pytest cumulusci/robotframework/tests/test_salesforce_locators.py cumulusci/robotframework/tests/test_locator_manager.py`
148+
- **Known noise to ignore**: `_tkinter` Dialogs import error (cosmetic), `[Return]` deprecation warnings (pre-existing)
149+
150+
## Risks and Mitigations
151+
152+
- **Scratch org expiry (~May 4)**: all work must complete before expiry. Mitigation: org can be recreated if needed.
153+
- **Shadow DOM expansion**: more elements may be unreachable than currently identified. Mitigation: document all shadow DOM encounters as evidence for the ADR.
154+
- **Playwright `rfbrowser` installation**: requires `cci robot install_playwright`. Mitigation: already available in the dev environment.
155+
- **Token cost measurement is approximate**: conversation length is a proxy, not a precise metric. Mitigation: sufficient for directional comparison.
156+
157+
## Acceptance Criteria
158+
159+
- All 11 Selenium test suites pass (or failures documented as shadow DOM limitations).
160+
- All 4 page object suites pass (or failures documented with root cause).
161+
- Locator durability audit complete with counts.
162+
- At least 1 Playwright end-to-end test passes against the same org.
163+
- ADR 0004 written with evidence from both tracks.
164+
- Local skill spec drafted.
165+
- Parent roadmap updated per closeout obligations.
166+
167+
## Deliverables
168+
169+
1. `cumulusci/robotframework/locators_66.py` (committed to repo)
170+
2. Any keyword/page-object/test fixes (committed to repo)
171+
3. Expanded `SalesforcePlaywright.py` with ~8 ported keywords (committed to repo)
172+
4. 1 Playwright end-to-end `.robot` test (committed to repo)
173+
5. `docs/adrs/0004-robot-framework-selenium-vs-playwright.md` (committed to repo)
174+
6. `~/.cursor/skills-cursor/robot-locator-refresh/SKILL.md` (local only)
175+
7. Parent roadmap updates (local plan file)

0 commit comments

Comments
 (0)