0

I am trying to use selenium to take a screenshot of a website, which has an img tag inside a shadow root, therefore, I want to wait for this img to exist.

Regularly I do something like this:

await driver.wait(until.elementLocated(By.css('img')));

But since it's in a shadow root I can't do it.

Using this :

(await (await element.getShadowRoot()).findElement(By.css('img'))); //I prefer double await than chaining tasks to ShadowRootPromise.

working only sometimes, and sometimes it throws an error that it has not found. I guess it's because the img has not been added to DOM yet.

(Currently, I am talking only about the problem of waiting for the img element to be available, the problem of waiting for the image to actually load and appear is another problem that I already solved.)

How can I wait for it to be available and not only 'get' it?

Ajeet Verma
  • 2,938
  • 3
  • 13
  • 24
ATP
  • 2,939
  • 4
  • 13
  • 34

2 Answers2

1

Try this:

await driver.wait(async () => {
  const shadowRoot = await element.getShadowRoot();
  return shadowRoot.findElement(By.css('img'))
    .then(() => true)
    .catch(() => false);
});
adsy
  • 8,531
  • 2
  • 20
  • 31
  • if not found findElement throws error, doesn't return falsy value. – ATP Jun 17 '23 at 21:33
  • tested it anyway, (changed to non existing selector) and still I get NoSuchElementError: no such element: Unable to locate element: {"method":"css selector","selector":"sdadas"} instead of waiting to it. – ATP Jun 17 '23 at 21:34
  • @ATP I beleive if you return a promise, it waits instead for the promise to be resolved. If `findElement` errors, that would be a rejected promise, which will be detected as "its not there yet". For none promises, the truthiness is what matters but this does not utilise that. Why it doesn't work though...not sure. – adsy Jun 17 '23 at 21:42
  • Actually possibly the resolved value also has a truthiness aspect, try my edited one. – adsy Jun 17 '23 at 21:51
  • "Try this" isn't informative. It's better to add an explanation ;) – Agent 327 Jun 17 '23 at 21:54
  • Seems like the await was the error eventually , thanks for the help! – ATP Jun 17 '23 at 21:56
0

Eventually I took a look at selenium src and saw how it's done with regular until.elementLocate and came up with:

const selector = 'img';
const shadow = await element.getShadowRoot();
const image = await driver.wait(new WebElementCondition(
    'for element to be located img',
     function () {
        return shadow.findElements(By.css('img')).then(function (elements) {
            return elements[0]
        })
    }
))
ATP
  • 2,939
  • 4
  • 13
  • 34