chromeflow 0.4.0 → 0.5.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/CLAUDE.md +36 -4
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -126,6 +126,17 @@ use `take_and_copy_screenshot()` — it saves a PNG to ~/Downloads and copies it
|
|
|
126
126
|
- `set_file_input` accepts CSS selectors as the hint (e.g. `#import-problem-file`,
|
|
127
127
|
`.upload-input`) in addition to label text. Use selectors when file inputs are hidden
|
|
128
128
|
behind custom UIs and have no visible label.
|
|
129
|
+
- **Replacing an already-uploaded file**: after `set_file_input` succeeds, the input
|
|
130
|
+
becomes invisible and a "Remove" span/button typically appears near the upload area.
|
|
131
|
+
To replace the file: `click_element("Remove", nth=N)` (the right `nth` if there are
|
|
132
|
+
multiple), then call `set_file_input(hint, newPath)` again — the same hidden input is
|
|
133
|
+
recycled and accepts the new file. Verify with `get_form_fields()` between the two
|
|
134
|
+
steps so you're sure the input has reappeared.
|
|
135
|
+
- **Forcing auto-save on idempotent text edits** (e.g. keep-alive loop on an
|
|
136
|
+
auto-saving DataAnnotation form): some auto-save logic diffs against the last-saved
|
|
137
|
+
value and skips no-op writes. To force a real save on each tick without changing
|
|
138
|
+
visible content, toggle a trailing space — add when absent, remove when present.
|
|
139
|
+
`fill_input` value comparison handles both directions transparently.
|
|
129
140
|
- After any radio/checkbox click that reveals new fields, call `get_form_fields()` again —
|
|
130
141
|
the inventory will include the new fields and warn if more hidden ones still exist.
|
|
131
142
|
- If a form has collapsible sections, expand them all before calling `get_form_fields()` so
|
|
@@ -144,6 +155,12 @@ use `take_and_copy_screenshot()` — it saves a PNG to ~/Downloads and copies it
|
|
|
144
155
|
- `switch_to_tab("1")` switches by tab number; `switch_to_tab("form")` matches by URL or title substring.
|
|
145
156
|
- Before navigating away from a partially-filled form, call `save_page_state()` so the form
|
|
146
157
|
can be restored if the tab reloads or the page loses its state on return.
|
|
158
|
+
- **In long-lived self-rescheduling loops**, the active tab can silently drift mid-session
|
|
159
|
+
(the user navigates manually while AFK, or another tab steals focus). At the start of
|
|
160
|
+
every loop iteration, call `list_tabs` and verify the active tab's URL matches your
|
|
161
|
+
expected target — if not, `switch_to_tab(<URL or title substring>)` before running
|
|
162
|
+
`execute_script` or any other tab-scoped tool. Without this guard, scripts run on the
|
|
163
|
+
wrong tab and fail with confusing "undefined" errors that look like page bugs.
|
|
147
164
|
|
|
148
165
|
## Error handling
|
|
149
166
|
|
|
@@ -270,10 +287,25 @@ document.body.style.zoom = '1';
|
|
|
270
287
|
1. Retry the exact same `execute_script` call
|
|
271
288
|
2. If still failing, use `find_and_highlight` to show the user a download button to click manually
|
|
272
289
|
|
|
273
|
-
**
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
290
|
+
**React-controlled native radios/checkboxes that don't update `checked`**: `click_element`
|
|
291
|
+
auto-handles this for native `<input type=radio>` and `<input type=checkbox>` inputs
|
|
292
|
+
(including labels that wrap or `for=` reference them). The flow:
|
|
293
|
+
- If a radio is already `checked=true`, `click_element` skips the click — re-clicking can
|
|
294
|
+
toggle it OFF on React forms whose `onChange` interprets the click as a deselect. The
|
|
295
|
+
response says `"X — radio already checked, click skipped"`.
|
|
296
|
+
- If the standard click fires but the input's `checked` state didn't change as expected
|
|
297
|
+
(radio still unchecked, or checkbox didn't toggle), `click_element` automatically
|
|
298
|
+
dispatches the full pointer-event chain (`pointerdown → mousedown → pointerup → mouseup
|
|
299
|
+
→ click`) on the input. The response says `"now checked (after pointer-chain fallback)"`.
|
|
300
|
+
|
|
301
|
+
You only need to drop into `execute_script` for the no-native-input case below.
|
|
302
|
+
|
|
303
|
+
**Shadow DOM `[role=radio]` / role-only custom radios silently no-op**: On sites like
|
|
304
|
+
Outlier where the radio is a `[role=radio]` div with no underlying `<input>`,
|
|
305
|
+
`click_element`'s native-input fallback can't help — the click target has no `.checked`
|
|
306
|
+
property to verify. Two things must be true: (a) the element must be scrolled into view
|
|
307
|
+
FIRST (`scrollIntoView({block:'center'})`), and (b) the full pointer-event chain must
|
|
308
|
+
fire — not just `click()`:
|
|
277
309
|
```js
|
|
278
310
|
['pointerdown','mousedown','pointerup','mouseup','click'].forEach(t =>
|
|
279
311
|
el.dispatchEvent(new MouseEvent(t, {bubbles: true, cancelable: true}))
|
package/package.json
CHANGED