Прежде всего: вы должны узнать о концепции асинхронного программирования в целом, возможностях Promises, ECMAScript 2016 и ECMAScript 2017:
Кроме того, вы должны понимать интерфейс WebDriver.Вы можете взглянуть на код:
Сейчас ...
Функции стрелок и интерфейс Selenium
//Bugged code starts below.
Нет, он запускается на пару строк раньше.
driver.wait(()=>{
driver.findElement(By.xpath("//a[@value='view all']").isDisplayed());
});
Это неправильно в двух аспектах:
- Функция стрелки с блоком требует оператора возврата
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();