[🐛 Bug]: Custom command fail for element that is not in the DOM
#13.327 geöffnet am 6. Aug. 2024
Beschreibung
Have you read the Contributing Guidelines on issues?
- I have read the Contributing Guidelines on issues.
WebdriverIO Version
8.39.1
Node.js Version
18.20.4
Mode
WDIO Testrunner
What happened?
I was trying to add a custom command following the instructions and was stuck with a weird issue https://webdriver.io/docs/customcommands/#examples
A little bit of context
I'm working on test automation for an Android native app. It appeared that selector for the element that is outside visible screen area not exists until I scroll to it...
For that reason, I decided to extend basic wdio commands by adding:
scrollToElement(opts?: {direction: 'up' | 'down'}) :Promise<void>
The problem I face is that when the selector is not in the "DOM" my command doesn't want to work, and execution stops with error Can't call scrollToElement on element with selector "non-existing-selector" because element wasn't found
await driver.$("selector-for-visible-element").scrollToElement() // - working fine,
await driver.$("non-existing-selector").scrollToElement() // - fail with error
I tried to debug it, but my custom command wasn't even called for "non-existing-selector" case. It looks like the exception was thrown before getting inside the function. For the "selector-for-visible-element" case, I was able to go inside my custom command function with the debugger.
It's not the first custom command I have in my framework. I have others, and they work fine. But this is the first that deals with an element that may not exist.
On the other side, the built-in isDisplayed() function works fine whether selector is present in the "dom" or not.
What is your expected behavior?
No response
How to reproduce the bug.
I created a minimal reproducible example here https://github.com/vparlah/wdio-custom-command-issue
import { expect, browser } from "@wdio/globals";
browser.addCommand(
"myCommand",
async function () {
return 1;
},
true
);
describe("Custom command test", () => {
const existingSel = "#username";
const nonExistingSel = "#username123";
beforeEach(async () => {
await browser.url("https://the-internet.herokuapp.com/login");
await expect($(existingSel)).toBeExisting();
await expect($(nonExistingSel)).not.toBeExisting();
});
it("default command isDisplayed() should work", async () => {
const resultExistingSel = await $(existingSel).isDisplayed();
expect(resultExistingSel).toBe(true);
const resultNonExistingSel = await $(nonExistingSel).isDisplayed();
expect(resultNonExistingSel).toBe(false);
});
it("custom command myCommand() should work", async () => {
const resultExistingSel = await $(existingSel).myCommand();
expect(resultExistingSel).toBe(1);
// ERROR: Can't call myCommand on element with selector "#username123" because element wasn't found
const resultNonExistingSel = await $(nonExistingSel).myCommand();
expect(resultNonExistingSel).toBe(1);
});
});
Relevant log output
[0-0] 2024-08-06T15:37:21.871Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:22.356Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:22.357Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:22.357Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:22.367Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:22.856Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:22.856Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:22.857Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:22.862Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:23.356Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:23.357Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:23.357Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:23.365Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:23.855Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:23.856Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:23.856Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:23.860Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:24.355Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:24.355Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:24.355Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:24.360Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:24.855Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:24.856Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:24.856Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:24.861Z INFO webdriver: RESULT []
[0-0] 2024-08-06T15:37:25.355Z INFO webdriver: COMMAND findElements("css selector", "#username123")
[0-0] 2024-08-06T15:37:25.356Z INFO webdriver: [POST] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e/elements
[0-0] 2024-08-06T15:37:25.356Z INFO webdriver: DATA { using: 'css selector', value: '#username123' }
[0-0] 2024-08-06T15:37:25.360Z INFO webdriver: RESULT []
[0-0] Error in "Custom command test.custom command myCommand() should work"
Error: Can't call myCommand on element with selector "#username123" because element wasn't found
at async Context.<anonymous> (file:///Users/volodymyrparlah/Documents/investigation/wdio-custom-command-issue/test.e2e.js:34:34)
[0-0] 2024-08-06T15:37:25.858Z INFO webdriver: COMMAND deleteSession()
[0-0] 2024-08-06T15:37:25.859Z INFO webdriver: [DELETE] http://0.0.0.0:56244/session/845069fca93a91a7f589783ddb4da95e
[0-0] 2024-08-06T15:37:25.913Z INFO webdriver: RESULT null
[0-0] 2024-08-06T15:37:25.913Z INFO webdriver: Kill driver process with PID 37828
[0-0] FAILED in chrome - file:///test.e2e.js
2024-08-06T15:37:26.030Z INFO @wdio/cli:launcher: Run onWorkerEnd hook
2024-08-06T15:37:26.030Z INFO @wdio/cli:launcher: Run onComplete hook
"spec" Reporter:
------------------------------------------------------------------
[chrome 127.0.6533.89 mac #0-0] Running: chrome (v127.0.6533.89) on mac
[chrome 127.0.6533.89 mac #0-0] Session ID: 845069fca93a91a7f589783ddb4da95e
[chrome 127.0.6533.89 mac #0-0]
[chrome 127.0.6533.89 mac #0-0] » /test.e2e.js
[chrome 127.0.6533.89 mac #0-0] Custom command test
[chrome 127.0.6533.89 mac #0-0] ✓ default command isDisplayed() should work
[chrome 127.0.6533.89 mac #0-0] ✖ custom command myCommand() should work
[chrome 127.0.6533.89 mac #0-0]
[chrome 127.0.6533.89 mac #0-0] 1 passing (11.9s)
[chrome 127.0.6533.89 mac #0-0] 1 failing
[chrome 127.0.6533.89 mac #0-0]
[chrome 127.0.6533.89 mac #0-0] 1) Custom command test custom command myCommand() should work
[chrome 127.0.6533.89 mac #0-0] Can't call myCommand on element with selector "#username123" because element wasn't found
[chrome 127.0.6533.89 mac #0-0] Error: Can't call myCommand on element with selector "#username123" because element wasn't found
[chrome 127.0.6533.89 mac #0-0] at async Context.<anonymous> (file:///Users/volodymyrparlah/Documents/investigation/wdio-custom-command-issue/test.e2e.js:34:34)
Spec Files: 0 passed, 1 failed, 1 total (100% completed) in 00:00:15
2024-08-06T15:37:26.031Z INFO @wdio/local-runner: Shutting down spawned worker
2024-08-06T15:37:26.283Z INFO @wdio/local-runner: Waiting for 0 to shut down gracefully
2024-08-06T15:37:26.283Z INFO @wdio/local-runner: shutting down
Code of Conduct
- I agree to follow this project's Code of Conduct
Is there an existing issue for this?
- I have searched the existing issues