Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Почему selenide пропускает индексы при клике на элемент из коллекции?

webdriver
selenide
selenium
Теги: #<Tag:0x00007fedb9735d08> #<Tag:0x00007fedb9735a60> #<Tag:0x00007fedb9735920>

(Mike Yelnikov) #1

Всем привет! Строго не судите^^ :angel:

Имеется страница с ссылками(16 ссылок). Задача: поочередно кликнуть на каждую ссылку.

        String testElement = "a[class='node node__leaf']"; //css selector
        int numOfElements = $$(testElement).filter(Condition.visible).size(); //вычисляем сколько ссылок на странице(16)

        for (int i = 0; i < numOfElements; i++) {
            System.out.println(i + " - " + $$(testElement).filter(Condition.visible).get(i).getText()); //распечатываем i и кликаемую ссылку
            $$(testElement).filter(Condition.visible).get(i).click(); // собственно сам клик
            sleep(1); // Thread.sleep 1 сек для надежности
        }

На выходе получаю, что при клике - пропускается один элемент и кликается через одну ссылку.

Вот распечатка:

0 - #1
1 - #3
2 - #5
3 - #7
4 - #9
5 - #11
6 - #13
7 - #15

НО!

Если же закомментировать клик($$(testElement).filter(Condition.visible).get(i).click();) , то отрабатывает корректно:

0 - #1
1 - #2
2 - #3
3 - #4
4 - #5
5 - #6
6 - #7
7 - #8
8 - #9
9 - #10
10 - #11
11 - #12
12 - #13
13 - #14
14 - #15
15 - #16

Собственно вопрос, где мой косяк и как пофиксать ситуацию? Спасибо :slight_smile:


(Vasiliy Rakshin) #2

А что происходит после клика со страницей?
Возможно, фокус меняется, ваш слип вносит нестабильность.
Попробуйте тупо увеличить слип до 5 и посмотреть что будет, так не делали?


(Ruslan Semerenko) #3

Думаю, проблема в том, что у вас на каждом шагу заново ищутся элементы через $$(testElement).filter(Condition.visible), а после клика, возможно, часть из них становится невидимой. Может быть чем-то закрываются, или совсем пропадают из dom.


(Nikita) #4

Видимо не все ссылки видимые


(Sergei Chipiga) #6

А почему есть уверенность, что именно 16 находит, если судить по аутпуту то 8. Можно поставить System.out.println("links number " + numOfElements);, чтобы точно убедиться: 8 или 16.


(Mike Yelnikov) #7

После клика фокус меняется, вот пример страницы(всем известная allure) https://ci.qameta.io/job/allure2/job/master/Demo_Report/index.html#behaviors

Слип до 5 сек не помогает


(Mike Yelnikov) #8

Хороший вариант! Нужно заново искать элемент?


(Mike Yelnikov) #9

Потому что физически на моей странице 16 ссылок, что и загоняется в переменную(numOfElements = 16) (links number 16)
numOfElements по пути не меняется, оно служит выходом из цикла. По аутпуту 8, потому что при клике пропускается одна ссылка(вся суть проблемы). Как только selenide пытается кликнуть на 9ую ссылку - тест падает, потому что пропустились по одной ссылке(#2, #4, #6, #8)

Циклов = 16;
Элементов = 8; // потому что идет пропуск при клике

(Ruslan Semerenko) #10

Если мое предположение верно, то нужно разобраться почему элементы становятся невидимыми. Возможно, после клика всплывает какой-то тултип поверх соседнего линка и скрывает его. Может быть нужно кликнуть куда-то в пустое место, чтобы тултип пропал.


(Vasiliy Rakshin) #11

С таким локатором всё заработает - div.tree__content > a.node.node__leaf


(Mike Yelnikov) #12

Да, все заработало! Спасибо! Объясните почему?


(Vasiliy Rakshin) #13

Негибкий локатор. Вы задали очень точный класс для a -элемента, когда на него кликаете ему ещё прибавляется ещё один класс (расскрытый) и он уже не подходит к вашему локатору. По моему локатору находятся все элементы, раскрытые или ещё нет.


(asolntsev) #14

Привет!
Вижу, что вам уже ответили, но хочу и от себя добавить пару комментариев по коду.

  1. Такой селектор слишком длинный и точный: $("a[class='node node__leaf']").
    Так проще и надёжнее: $("a.node.node__leaf").

  2. Вы внутри цикла каждый раз заново загружаете и фильтруете список, что делает код медленным. Лучше загрузить их один раз ДО цикла:

ElementCollection as = $$(testElement).filter(Condition.visible);
for (SelenideElement a : as) {
  a.click();
  sleep(1);
}
  1. sleep(1); - это не одна секунда, а одна миллисекунда. :slight_smile:

(Mike Yelnikov) #15

Спасибо, великий отец Selenide :innocent: очень полезная информация!

sleep(1) - кастомный метод, поэтому и указал в комментарии, что именно 1 сек :slightly_smiling_face:


(asolntsev) #16

Ясно :slight_smile:

В Selenide тоже есть метод sleep, только с миллисекундами.
Вариант с секундами плох тем, что рано или поздно кто-то захочет подождать полсекунды - и дико обломится.