webdriverio/webdriverio

[🐛 Bug]: Custom command fail for element that is not in the DOM

Open

#13.327 geöffnet am 6. Aug. 2024

Auf GitHub ansehen
 (2 Kommentare) (1 Reaktion) (0 zugewiesene Personen)JavaScript (6.029 Stars) (1.793 Forks)batch import
Bug 🐛help wanted

Beschreibung

Have you 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

Contributor Guide