Проверить наличие элемента без падения теста в случае его отсутствия

Проблема в следующем : Есть некий фильтр по кейворду, который отфильтруете и выдает карточки с наличием данного кейворда в блоках с информацией. Используя этот фильтр я знаю что этот введенный текст может содержатся в “Блок информации А” или в “Блок информации С” либо же и там и там. Эти блоки как могут быть так и могут не быть - то есть может быть три варианта: есть оба блока, есть только “Блок информации А” , есть только “Блок информации С”.

Задача: убедится что хотя бы один из этих блоков содержит искомый кейворд. По сути если хоть в одном из элементов есть искомый кейворд то тест -ОК.

blockInfoX.shouldHave(text("чайка")).should(exist);

Хотелось бы проверить наличие “Блок информации А” и если он есть то проверить наличие в нем кейворда, если кейворда нет - то перейти к “Блок информации С” и проверить наличие кейворда в нем. И также если “Блок информации А” отсутствует сразу - то перейти к “Блок информации С” и проверить наличие кейворда в нем.

Как вы находите эти блоки?
У всех этих blockInfoA, blockInfoB, blockInfoC ведь есть какой-то общий селектор?
Допустим, все они имеют вид

<div class="card card-A"">Блок информации A</div>

Тогда проще всего решить вашу задачу одной строкой:
$$(".card").filterBy(text("чайка")).shouldHave(sizeGreaterThan(0));

1 лайк

в том то и дело что общего нет : условно это выглядит так

страница с элементами :

 public class CardPage {

        public SelenideElement blockInfoA = $x("//blockInfoA");
        public SelenideElement blockInfoB = $x("//blockInfoB");
        public SelenideElement blockInfoC = $x("//blockInfoC");
        public SelenideElement blockInfoD = $x("//blockInfoD");
        public SelenideElement blockInfoF = $x("//blockInfoF");
}

сам тест:

@Test
    public void keyWordExist() {
        // Применяем фильтр , вводим кейворд 
        // Получаем отфильтрованные карточки
        // Переходим в карточку в которой надо проверить что кейворд есть в блоке А или С
       CardPage cardPage = new CardPage();
      // и вот тут эта проверка должна быть 

      cardPage.blockInfoA.shouldHave(text("чайка")).should(exist);

     cardPage.blockInfoC.shouldHave(text("чайка")).should(exist);
      
    }

пытался что то такое на прямую сделать

$$x("//blockInfoA,//blockInfoС").filterBy(text("чайка")).should(exist);

image

если я использую СSS то отрабатывает.

$$("blockInfoA, blockInfoС").filterBy(text("чайка")).shouldHave(sizeGreaterThan(0));

я так понимаю что с Xpath есть нюансы - ругается на синтаксис коллекции в скобках

$$x("//blockInfoA, //blockInfoС").filterBy(text("чайка")).shouldHave(sizeGreaterThan(0));

и можно ли эту коллекцию определить через переменные blockInfoA и blockInfoC ?

 public SelenideElement blockInfoA = $x("//blockInfoA");
 public SelenideElement blockInfoC = $x("//blockInfoC");

Отлично, вот и используйте CSS!

Да, в xpath надо использовать немного другой формат. Наизусть не знаю, надо гуглить.

Нет, нельзя.

если xpath, то можно написать такой
//*[contains(local-name(), 'blockInfo')]

А есть возможность проверить единичный элемент что он есть а в случае его отсутствия чтобы проверка не падала?

Вот в этом вся проблема. Попросите фронендера подверстать и сделать общий класс на эти элементы.

@al-kalin попробуйте мой xpath применить, вы так найдёте все блоки, и уже к коллекции можно применять метод, типо если в коллекции есть хоть один элемент с текстом, то всё ок

чуть чуть не то - //blockInfoA и //blockInfoC это скорее абстрактные xpath для примера , по сути они вообще разные как //qwert и //asdfg

ну тогда реально попросите напедалить фронтендера какой-то метод, который будет генерировать кастомные атрибуты
либо сами к ним в репозиторий зайдите и в html пихните в код карточек этот банальный div с каким-то атрибутом (правда потом войдёте во вкус и сами везде начнёте ставить свои якоря)

1 лайк

Если я правильно понял функциональное требование, которое вы проверяете, то оно заключается в том, что:

“При любом сочетании блоков информации, хоть где-то должен быть ожидаемый keyword”

И кейсы получаются такие:

  • Кейс №1. Предусловие: Есть Блок А и Блок С. Ожидаемо: Keyword в одном из них.
  • Кейс №2. Предусловие: Есть только Блок А (или Блок C). Ожидаемо: Keyword в этом существующем блоке.

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

  • Кейс №1.
    $$("blockInfoA, blockInfoС").filterBy(text("keyword")).shouldHave(sizeGreaterThan(0))
    или, если разработчики добавили аттрибуты на эти блоки:
    $$("[test-id='block-info']").filterBy(text("keyword")).shouldHave(sizeGreaterThan(0))

  • Кейс №2. Предусловие: Есть только Блок А (или Блок C). Ожидаемо: Keyword в этом существующем блоке.
    $$("blockInfoA").filterBy(text("keyword")).shouldHave(sizeGreaterThan(0))

1 лайк

Ничего сложного вроде как.

boolean haveInfo(WebElement blockInfo){
  try{
  blockInfo.shouldHave(text("чайка")).should(exist);
  }
  catch (NoSuchElementException e) {
    return false;
}
  return true;
}

// Main code
if !(haveInfo(blockX) && haveInfo(blockY) && haveInfo(blockZ)) {
  throw (// exception with description what's gone wrong)
}
// Success code here
1 лайк