Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Driver input method cannot type '[' #2554

Open
SirJerric opened this issue Apr 20, 2024 · 6 comments
Open

Driver input method cannot type '[' #2554

SirJerric opened this issue Apr 20, 2024 · 6 comments
Assignees
Labels

Comments

@SirJerric
Copy link

Discovered while logging in with randomized passwords using karate 1.4.1 and 1.5.0-RC3 (OpenJDK 17). Reproduction testing with develop branch and OpenJDK 21.

Reproducing Error

The below code can be used with any locator for an element accepting input. (Minimal project attached at end.)
test.feature -- central logic

* input('#testinput','()[]{}')
* match value('#testinput') == '()[]{}'

Output log contains this unexpected match failure:

15:39:25.544 [main] ERROR com.intuit.karate - classpath:ui/test.feature:9
* match value('#testinput') == '()[]{}'
match failed: EQUALS
  $ | not equal (STRING:STRING)
  '()]{}'
  '()[]{}'

Root cause

Debug log contains these lines:

15:39:25.517 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":12,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"rawKeyDown","text":")","windowsVirtualKeyCode":522}}
15:39:25.518 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":12,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}
15:39:25.518 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":13,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"char","text":")","windowsVirtualKeyCode":522}}
15:39:25.519 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":13,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}
15:39:25.521 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":14,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"keyUp","text":")","windowsVirtualKeyCode":522}}
15:39:25.522 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":14,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}
15:39:25.522 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":15,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"rawKeyDown","windowsVirtualKeyCode":91}}
15:39:25.523 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":15,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}
15:39:25.523 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":16,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"rawKeyDown","text":"]","windowsVirtualKeyCode":93}}
15:39:25.523 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":16,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}
15:39:25.524 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":17,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"char","text":"]","windowsVirtualKeyCode":93}}
15:39:25.524 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":17,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}
15:39:25.525 [main] DEBUG c.intuit.karate.driver.DriverOptions - >> {"id":18,"sessionId":"284DC1AB2976E0A071838D59EEBD35E6","method":"Input.dispatchKeyEvent","params":{"modifiers":0,"type":"keyUp","text":"]","windowsVirtualKeyCode":93}}
15:39:25.527 [nioEventLoopGroup-5-1] DEBUG c.intuit.karate.driver.DriverOptions - << {"id":18,"result":{},"sessionId":"284DC1AB2976E0A071838D59EEBD35E6"}

Notice the departure from pattern at "id":15. Raw key down, no text, virtual key code 91.

com.intuit.karate.driver.DevToolsDriver - method input() - lines 637-663

        Input input = new Input(value);
        while (input.hasNext()) {
            char c = input.next();
            int modifiers = input.getModifierFlags();
            Integer keyCode = Keys.code(c);
            if (keyCode != null) {
                switch (keyCode) {
                    case Keys.CODE_SHIFT:
                    case Keys.CODE_CONTROL:
                    case Keys.CODE_ALT:
                    case Keys.CODE_META:
                        if (input.release) {
                            sendKey(null, modifiers, "keyUp", keyCode);
                        } else {
                            sendKey(null, modifiers, "rawKeyDown", keyCode);
                        }
                        break;
                    default:
                        sendKey(c, modifiers, "rawKeyDown", keyCode);
                        sendKey(c, modifiers, "char", keyCode);
                        sendKey(c, modifiers, "keyUp", keyCode);
                }
            } else {
                logger.warn("unknown character / key code: {}", c);
                sendKey(c, modifiers, "char", null);
            }
        }

Based on the Debug log snippet, default block is used for most characters, but [ has decided to sendKey "rawKeyDown" with keyCode 91.

com.intuit.karate.driver.Keys - lines 140, 195, and 240-242

    public static final int CODE_META = 91; // left command key on mac, right is 93
// ...
        put(META, CODE_META, "Meta");
// ...
        CODES.put('[', 91);
        CODES.put('\\', 92);
        CODES.put(']', 93);

(For context, method put() runs CODES.put(META, CODE_META) as well as VALUES.put(META, "Meta").)
After the above, CODES.get('[') == CODES.get(META) == 91. Since the switch checks for Keys.CODE_META and finds keyCode == 91, the break before default is executed and [ is never typed.

Thus, Driver.input() cannot type [ due to a duplicate numeric value in Keys.CODES map. Specifically due to the overlap with a modifier key code.

Project file

karate-input-open-bracket.zip
Run UiRunner.java as unit test to demonstrate. mvn test did not find UiRunner in my testing.
pom.xml is set to use karate version 1.6.0-SNAPSHOT due to testing with local develop branch. My IDE didn't want to compile master. Feel free to use other versions; the conflict was introduced in Feb 2022 per git history.

@SirJerric
Copy link
Author

While looking into this, I noticed that there are some other incomplete mappings in the codes.

16:52:11.588 [main] WARN  c.intuit.karate.driver.DriverOptions - unknown character / key code: ~
16:52:11.599 [main] WARN  c.intuit.karate.driver.DriverOptions - unknown character / key code: %
16:52:11.600 [main] WARN  c.intuit.karate.driver.DriverOptions - unknown character / key code: ^
16:52:11.623 [main] WARN  c.intuit.karate.driver.DriverOptions - unknown character / key code: |
16:52:11.643 [main] WARN  c.intuit.karate.driver.DriverOptions - unknown character / key code: ?
16:52:11.653 [main] ERROR com.intuit.karate - classpath:ui/test.feature:9
* match value('#testinput') == '`~!@#$%^&*()[]{}|\\;:\'",./<>?'
match failed: EQUALS
  $ | not equal (STRING:STRING)
  '`~!@#$%^&*()]{}|\;:'",./<>?'
  '`~!@#$%^&*()[]{}|\;:'",./<>?'

Despite falling into the else block, these "unknown" key codes are entered into the input successfully.

@ptrthomas
Copy link
Member

tagging as help wanted - PRs welcome

@SirJerric
Copy link
Author

Before submitting a Pull Request (PR), please make sure that you have had a discussion with the project-leads

Please proceed with a PR only after the project admins or owners are okay with your approach. We don't want you to spend time and effort working on something - only to find out later that it was not aligned with how the project developers were thinking about it !

I would be happy to contribute if I knew the meaning behind the numbering system, assuming the numbering system is the aligned solution path. It proved challenging to pin down. Possibly due to being assembled across at least three years.

I found one resource that came close to fitting. That resource came with a warning that all such mappings can be hardware-dependent. If these numbers have a specific function elsewhere in the code base I wouldn't want to break that.

My experiments with the develop branch and this lone test case determined that the numbers are arbitrary in the operation under test. Multiple reassignments of the [ key code resulted in a green test.

With multiple solution paths possible, what standard should I pursue? Changing the numbers in Keys.CODES is a simple solution, but is that the aligned approach?

@SirJerric
Copy link
Author

If PR #2555 is satisfactory, my employer has allowed access to 1.5.0-RC versions. I do not know what your release versioning policy is, but if we can get it into an easily accessed version, my coworkers and I would be much obliged.

@SirJerric
Copy link
Author

Upon further research, It turns out that the issue described in the opening post is not the only way to have an error involving the input method and [. I have not finished pinning down the cause(s), but it can be avoided by adding a \ to the [ before hand-off to WebDriver.input() creates the JSON for the request payload sent to the remote browser (SauceLabs, in my case). Comparing input string, modified input string, logged request payload, screenshot value of input, and expected value for matching the returned actual value, there were four variants of the test string. Most interesting was the evidence that some where in the input-to-request logic the / turned into \/, so someone else already made one escape-character insertion.

Minimal reproduction will be provided when time permits.

@ptrthomas
Copy link
Member

@SirJerric I'm really sorry for the delay even merging a PR, thanks for the contribution.
we can release a 1.5.0.RC5 shortly, let me know if you need it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants