Драйвер Selenium-Web не может прочитать свойство 'filter' из неопределенного - PullRequest
0 голосов
/ 16 декабря 2018

Я начал использовать Selenium.Когда я хочу дождаться загрузки элемента, он выдает эту ошибку:

    (node:8472) UnhandledPromiseRejectionWarning: NoSuchElementError: no such element: Unable to locate element: {"method":"xpath","selector":"//a[@value='view all']"}
  (Session info: chrome=70.0.3538.110)
  (Driver info: chromedriver=2.45.615291 (ec3682e3c9061c10f26ea9e5cdcf3c53f3f74387),platform=Windows NT 10.0.17134 x86_64)
    at Object.checkLegacyResponse (C:\Users\Ben Levy\Desktop\bot\node_modules\selenium-webdriver\lib\error.js:585:15)
    at parseHttpResponse (C:\Users\Ben Levy\Desktop\bot\node_modules\selenium-webdriver\lib\http.js:533:13)
    at Executor.execute (C:\Users\Ben Levy\Desktop\bot\node_modules\selenium-webdriver\lib\http.js:468:26)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:8472) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:8472) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Вот код, который я пытаюсь:

const {Builder, By, Key, until} = require('selenium-webdriver'),
  app = require('express'),
  express = app();

let driver = new Builder().forBrowser('chrome').build();

driver.get('https://supremenewyork.com');

driver.findElement(By.className('shop_link')).click();

driver.wait(()=>{
  driver.findElement(By.xpath("//a[@value='view all']").isDisplayed());
});
//Bugged code starts below.
let all = driver.findElement(By.xpath("//a[@value='view all']"));

driver.promise.filter(all, (element)=>{
  return element.isDisplayed();
}).then((element)=>{
  element.click();
});
//End of bugged code.

Пожалуйста, скажите мне, что я делаюнеправильный / лучший метод для ожидания, пока элемент не будет загружен.Спасибо!


Это исправленный код:

const {Builder, By, Key, until} = require('selenium-webdriver'),
  app = require('express'),
  express = app();
  driver = new Builder().forBrowser('chrome').build();

driver.get('https://supremenewyork.com');

driver.findElement(By.className('shop_link')).click();
async function main(){
  let all = await driver.findElements(By.xpath("//a[@value='view all']")),
  element,
  visible;

  for(element of elements){
    visible = await element.isDisplayed();
    if (visible) {
    element.click();
    }
  }
};

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Я понял это!Я использовал Selenium wait Docs

Код:

const { Builder, By, Key, until } = require('selenium-webdriver');

async function main() {
    let driver = new Builder().forBrowser('chrome').build();

    driver.get('https://supremenewyork.com');

    driver.findElement(By.className('shop_link')).click();
    let element =
      await driver.wait(until.elementLocated(By.xpath("//*[contains(@href,'http://www.supremenewyork.com/shop/all')]", 10000)));
    await element.click();
}

main();
0 голосов
/ 16 декабря 2018

Прежде всего: вы должны узнать о концепции асинхронного программирования в целом, возможностях Promises, ECMAScript 2016 и ECMAScript 2017:

Кроме того, вы должны понимать интерфейс WebDriver.Вы можете взглянуть на код:

Сейчас ...

Функции стрелок и интерфейс Selenium

//Bugged code starts below.

Нет, он запускается на пару строк раньше.

driver.wait(()=>{
  driver.findElement(By.xpath("//a[@value='view all']").isDisplayed());
});

Это неправильно в двух аспектах:

  1. Функция стрелки с блоком требует оператора возврата
  2. isDisplayed() - это функция в WebElementPromise, возвращаемая findElement().Вы вызывали его для объекта селектора.

Это правильно:

driver.wait(() => {
  return driver.findElement(By.xpath("//a[@value='view all']")).isDisplayed();
});

Асинхронные функции

Теперь wait() - это асинхронный код.Он возвращает Promise и, как таковой, он должен await редактироваться или обрабатываться с помощью then(), в противном случае следующие операторы выполняются сразу после бесконечного ожидания видимости элемента.

Лучше:

await driver.wait(() => {
  return driver.findElement(By.xpath("//a[@value='view all']")).isDisplayed();
});

Теперь await можно использовать только в асинхронной функции, поэтому вы должны обернуть весь свой код в асинхронную функцию, например:

async main() {
  // ...
  await driver.wait(...);
  // wait() condition fulfilled, code continues
  driver.findElement(...).click();
  // ...
}

main();

Интерфейс Seleniumи массив Обещаний

let all = driver.findElement(By.xpath("//a[@value='view all']"));

Из именования и селектора можно предположить, что вы ожидаете нескольких элементов.Хотя, как следует из названия, findElement() найдет только один элемент, первый.Используйте findElements().Это разрешится с помощью массива WebElements.

Нет driver.promise.

Чтобы сделать его коротким, последний блок может выглядеть следующим образом:

    // as with earlier examples, findElements() is async (returns a Prmomise),
    // thus you've to await the result
    let elements = await driver.findElements(By.xpath("//a[@value='view all']")),
        element,
        visible;

    for (element of elements) {
        // isDisplayed() is async (returns a Promise),
        // thus you've to await the result
        visible = await element.isDisplayed();

        if (visible) {
            element.click();
        }
    }

Это даст вам некоторое направление для изучения.

С помощью Chromium или Chrome вы можете отладить свой код Node.js

node --debug-brk --inspect bot.js

См. этот ответ и Google Developers за некоторые рекомендации.


Полный код

async function main() {
    const { Builder, By, Key, until } = require('selenium-webdriver');

    let driver = new Builder().forBrowser('chrome').build();

    driver.get('https://supremenewyork.com');

    driver.findElement(By.className('shop_link')).click();

    await driver.wait(() => {
       return driver.findElement(By.xpath("//a[@value='view all']")).isDisplayed();
    });

    let elements = await driver.findElements(By.xpath("//a[@value='view all']")),
        element,
        visible;

    for (element of elements) {
        visible = await element.isDisplayed();

        if (visible) {
            element.click();
        }
    }
}

main();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...