Невозможно щелкнуть по элементам в цикле в транспортире

#loops #dictionary #filter #protractor

#циклы #словарь #Фильтр #транспортир

Вопрос:

У меня есть веб-сайт электронной коммерции, на котором есть список товаров, похожих на Amazon. я пытаюсь найти элемент и щелкнуть по нему. я пробовал с помощью filter и map, и оба они не работают для меня. Пожалуйста, помогите.

Ниже приведен код для каждого продукта:

 <b class="productNameHover pcursor word-break">product1</b>
<b class="productNameHover pcursor word-break">product2</b>
<b class="productNameHover pcursor word-break">product3</b>
<b class="productNameHover pcursor word-break">product4</b> 

допустим, у меня есть 4 элемента на моей странице. итак, я попытался подсчитать, и это сработало для меня.

var products = element.all(by.className(‘productNameHover’)) ; ожидать(products.count()).toBe(4);

когда я попытался фильтровать,

Решение A) не работает, сообщения об ошибке нет, но ничего не сделал

 var products = element.all(by.className('productNameHover'));

products.filter(function(elem) {
    return products.getText().then(function(text) {
        return text === 'product4';
    });
}).click();

browser.sleep(5000);
 

Решение B) не работает; индекс вне пределов; Попытка получить доступ к элементу с индексом: 0, но есть только 0 элементов, которые соответствуют локатору

 var products = element.all(by.className('productNameHover'));

products.filter(function(elem) {
    return products.getText().then(function(text) {
        return text === 'product4';
    });
}).first().click();

browser.sleep(5000);
 

Решение C) нет сообщения об ошибке, но ничего не сделал

 var products = element.all(by.className('productNameHover'));

products.filter(function(elem) {
    return products
            .element(by.xpath(
                "//div[@class='item text-center slide-image-content active']/img"
            ))
            .getText()
            .then(function(text) {
                expect(text).toContain(product4);
             })
            .then(function(filteredElements) {
                filteredElements.first().click();
            });
});

browser.sleep(5000);
 

Решение D) Это работает и дает мне все продукты; но мне нужно либо щелкнуть по одному продукту, либо выполнить цикл

 var products = element.all(by.className('productNameHover'));

products.map(function(item) {
    return item.getText();
}).then(function(txt) {
    console.log(txt);
    //expect(txt).toContain("product 4")
});
 

Решение E) не работает и нет сообщения об ошибке

 products.map(function(item) {
    return item.getText();
}).then(function(txt) {
    console.log(txt);
    if( txt== 'product4') {
        console.log(item);
        item.click();
        browser.sleep(5000);
    }
});
 

Решение F) Я попытался щелкнуть по всем элементам в цикле, но он нажимает на первый элемент, а не на второй; он выдает сбой: устаревшая ссылка на элемент: элемент не прикреплен к документу страницы.

 products.map(function(item) {
    browser.sleep(5000);
    item.click();
    browser.sleep(5000);
    var backButton = element.all(by.className('btn btn-outline btn-big mt-3 ml-0 ml-sm-2')).first() ;
    backButton.click();
    browser.sleep(5000);
})
 

Ответ №1:

Вы неправильно поняли API транспортира : each() / map() / filter() . Рекомендуем вам изучить JavaScript Array forEach() / map() / filter(), чтобы лучше понять, прежде чем использовать Protractor API.

Решение А)

  1. return products.getText() должно быть return elem.getText() .
  2. filter() возвращает массив элементов, поэтому вы не можете вызвать click() array.

Решение B)

  1. return products.getText() должно быть return elem.getText() .

Решение E) map() также возвращает массив.

 products.map(function(item) {
    return item.getText();
}).then(function(txt) {
    // txt = [ 'product1', 'product2', 'product3', 'product4']
    console.log(txt);

    if( txt == 'product4') { // this condition never be true
        console.log(item);
        item.click();
        browser.sleep(5000);
    }
});

// correct code example
products.map(function(item) {
    return item.getText();
}).then(function(txts) {
    // txts = [ 'product1', 'product2', 'product3', 'product4']
    console.log(txts);

    let index = txts.indexOf('product4');

    if( index > -1) {
        products.get(index).click();
        browser.sleep(5000);
    }
});
 

Комментарии:

1. Спасибо за четкое объяснение решения E. Теперь это дает лучшее понимание

Ответ №2:

Вы пробовали использовать функцию each () API транспортира?

  var products = element.all(by.className('productNameHover'));
 products.each(function(element) {
   return element.getText().then(function (text) {
           if(text === 'product4') {
               return element.click();
           }
    });
 })
 

Я бы посоветовал вам переключиться на новый async/await синтаксис написания js-кода.

  const products = element.all(by.className('productNameHover'));
 products.each(async function(element) {
    let text = await element.getText();
           if(text === 'product4') {
               await element.click();
           }
 });
 

Вы также можете использовать map() функцию —

 element.all(by.className('productNameHover')).map(function(element) {
         return element.getText(function(text) {
                 return text === 'product4'
           });
     }).then(function(elements) {
           for (var i = 0; i < elements.length; i  ) {
                  elements.get(i).click();
             }
     });
 

Ответ №3:

Похоже, у вас все получилось, и я могу неправильно понять, но если вы просто пытаетесь щелкнуть по определенному продукту в списке, вы можете использовать

 element(by.cssContainingText('.productNameHover', 'product4')).click();