fix(helpers): press_key supports keyboard shortcuts (suppress char + canonical code/vk)#297
fix(helpers): press_key supports keyboard shortcuts (suppress char + canonical code/vk)#297sauravpanda wants to merge 1 commit intomainfrom
Conversation
Two related issues that have shown up across recent PRs: 1. press_key always emitted a `char` event after every single-char keyDown, regardless of modifiers. With Ctrl/Cmd held, that `char` makes Chrome treat the press as printable text input (typing "a") instead of firing the shortcut (Cmd+A). PR #258 worked around this inside fill_input by dispatching the select-all directly via raw CDP calls, but every other shortcut was still broken. 2. The keyDown's `code` and `windowsVirtualKeyCode` for letters/digits came from a literal-key fallback (code="a", vk=ord("a")=97). CDP's shortcut handlers compare against canonical physical-key codes — "KeyA" / 65 for the A key, "Digit5" / 53 for the 5 key. Without that, e.code in JS is wrong and shortcut listeners that check `e.code === "KeyA"` (a common pattern) do not fire. Fix at source so every shortcut works for any caller: - Added _key_metadata(key) which returns the canonical (vk, code, text) for letters (Key{X}, ord(upper)), digits (Digit{N}, ord(N)), and the pre-existing special-key table. Punctuation/symbols fall back to ASCII vk + literal code. - press_key suppresses both `text` on keyDown and the entire `char` event when any of Alt/Ctrl/Meta is set (modifier bits 0b0111). Shift alone is still text input. - fill_input's clear path now just calls press_key("a", modifiers=...) instead of dispatching directly via cdp; the helper does the right thing now. 10 new tests in tests/unit/test_helpers.py cover: - canonical code/vk for letters (KeyA/65, KeyZ/90) and digits (Digit5/53) - Enter/Backspace/etc still use the _KEYS table - no-modifier press emits text + char - Ctrl / Meta / Alt each suppress text + char - Shift alone keeps text + char - Ctrl+Shift combo suppresses (modifier wins over Shift) - keyUp metadata is consistent Identified via codex review (P1). Full suite: 93 passed (83 -> 93).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e0dcdd6905
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| upper = key.upper() | ||
| if "A" <= upper <= "Z": | ||
| # vk for letters is the uppercase ASCII codepoint, regardless of case. | ||
| return (ord(upper), f"Key{upper}", key) |
There was a problem hiding this comment.
Handle multichar uppercase mappings in
_key_metadata
The new letter path crashes for some valid single-character inputs because key.upper() can return multiple code points (for example "ß" -> "SS"), and ord(upper) then raises TypeError. This is a regression from the previous implementation and breaks fill_input for international text, since it calls press_key for each character and will now fail at runtime on these inputs.
Useful? React with 👍 / 👎.
Summary
Fixes a P1 surfaced by a codex review of the repo. Lifts the workaround that PR #258 made inside
fill_inputup to thepress_keyhelper itself, so every keyboard shortcut — Cmd+S, Ctrl+Z, Ctrl+L, Cmd+Shift+P, etc. — now works for any caller, not just the select-all thatfill_inputdoes.The bugs
Two distinct problems in
helpers.press_key:charevent always fired after keyDown. Even with Ctrl/Cmd held, the helper unconditionally emitted anInput.dispatchKeyEvent type=charafter the keyDown. Chrome treatscharas printable text input, so the shortcut handler fires AND the literal letter gets typed. PR fix(helpers): add fill_input, wait_for_element, wait_for_network_idle #258 worked around this insidefill_inputby dispatching select-all via raw CDP calls; every other shortcut remained broken.codeandwindowsVirtualKeyCodewere wrong for letters/digits. The fallback computedcode=key(socode="a"for the A key) andvk=ord(key[0])(97for"a"). CDP's shortcut handlers compare against canonical physical-key codes —"KeyA"/65for the A key,"Digit5"/53for the 5 key. Without those,e.codein JS is wrong and shortcut listeners that checke.code === "KeyA"(a common pattern) don't fire.The fix
_key_metadata(key)returns the canonical(vk, code, text)for letters (KeyA/65,KeyZ/90), digits (Digit5/53), and the pre-existing special-key table (Enter/13/\r,Backspace/8, etc.). Punctuation/symbols fall back to ASCII vk + literal code (best-effort; Chrome may still recognise the shortcut from the modifier flags alone).press_keynow suppresses bothtexton the keyDown and the entirecharevent when any ofAlt|Ctrl|Meta(modifier bits0b0111) is set. Shift alone is still text input —Shift+Astill typesA.fill_input's clear-first path simplified back topress_key("a", modifiers=...). The raw-CDP workaround was 5 lines; it's now one call. The helper does the right thing.Tests
10 new in
tests/unit/test_helpers.py:test_press_key_letter_uses_canonical_code_and_vk— covers"a"→KeyA/65 and"Z"→KeyZ/90.test_press_key_digit_uses_canonical_code_and_vk—"5"→Digit5/53.test_press_key_special_key_uses_kkeys_table—Enterstill resolves via_KEYS.test_press_key_no_modifiers_emits_text_and_char_event— keyDown carriestext,charevent fires.test_press_key_with_ctrl_suppresses_text_and_char— keyDown has notext, nocharevent.test_press_key_with_meta_suppresses_text_and_char— same for Cmd.test_press_key_with_alt_suppresses_text_and_char— same for Alt.test_press_key_shift_alone_still_emits_text_and_char— Shift alone is text input.test_press_key_ctrl_shift_combo_still_suppresses—Ctrl+Shift+P(modifier wins over Shift).test_press_key_emits_keyup_with_consistent_metadata— keyUp carries the same code/vk/modifiers.uv run pytest tests/→ 93 passed (83 → 93).Test plan
press_key("z", modifiers=2 if not darwin else 4)in a textarea undoes the last edit (Ctrl/Cmd+Z).press_key("l", modifiers=2 if not darwin else 4)focuses the address bar (Ctrl/Cmd+L).fill_input(selector, "hello", clear_first=True)still clears on macOS (Cmd+A path goes through the newpress_key).Summary by cubic
Fixes keyboard shortcuts by updating press_key to suppress printable char events with Alt/Ctrl/Meta and to emit canonical code/vk for letters and digits. Shortcuts like Cmd+S, Ctrl+Z, and Cmd/Ctrl+A now work reliably, and fill_input uses press_key directly.
Written for commit e0dcdd6. Summary will update on new commits.