Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Общие элементы для Popup и главной страницы


(Alex) #1

Здравствуйте, на данный момент столкнулся с проблемой работы с Popup окном. Ситуация такая, я тестирую админку в которой есть например кнопка “Создать” и у нее есть локатор обобщенный для всех страниц, включая Popup. Но когда открывается Popup я не знаю как на него правильно переключиться (он накладывается поверх основного, в нем можно открыть еще один P.S. подробнее на скриншоте) чтобы взаимодействовать с такой-же кнопкой.

Из ниже приведенного кода можно увидеть, что кнопка создать, на всех Popup и главной страницы, имеет один и тот же локатор ([ng-click='addRow(row)']), но когда накладывается Popup окно, я могу переключится на него только добавив локатор ([additional-view='0']).
Пожалуйста скажите мне, что есть другой способ сказать коду что я работаю с Popup окном. Если нужен какой-то дополнительный мой код я предоставлю, но пока я рассматриваю это в грубой форме, чтобы понять как оно должно работать.

public class A1{
  @Test
  
public void asd(){
	 
	 /*
		....................
		....................
		....................

	 */
	 
//	  
	 
	  driver.findElement(By.cssSelector("[name='row.__states.ContentAssets'] [ng-click='onAddRow()']")).click(); //нажимаем добавить на главной странице всплывает Popup окно
	  
	  driver.findElement("[additional-view='0'] [name='Аудио PID'] [ng-click='onAddRow()']")).click(); // В этом окне мы хотим добавить Аудио PID, накладывается еще одно Popup
	  
	  driver.findElement(By.cssSelector("[additional-view='1'] [ng-click='addRow(row)']")).click(); //Нажимаем кнопку создать в последнем Popup, оно закрывается и переходит к родительскому Popup
	  
	   driver.findElement(By.cssSelector("[additional-view='0'] [ng-click='addRow(row)']")).click(); //Нажимаем кнопку создать во 2 Popup и переходим на главную страницу

	   driver.findElement(By.cssSelector("[ng-click='addRow(row)']")).click(); //нажимаем кнопку создать на главной странице

	}


(Максим Малунов) #2
String parentHandle = driver.getWindowHandle(); // get the current window handle
driver.findElement(By.xpath("//*[@id='someXpath']")).click(); // click some link that opens a new window

for (String winHandle : driver.getWindowHandles()) {
    driver.switchTo().window(winHandle); // switch focus of WebDriver to the next found window handle (that's your newly opened window)
}

что-то такое поможет .
Может еще чего с Alert


(Александр Таранков) #3

WindowHandles надо использовать, если имеем дело с несколькими окнами браузера. Здесь же ситуация проще: popup-ы - это обычные div


(Александр Таранков) #4

Нет другого способа. В твоем случае popup - это div. Чтобы адресовать в нём элементы, необходимо указывать в xpath, что путь до них пролегает через этот div.

В чём тут сложность? Надо просто правильно организовать архитектуру своего фреймворка, чтобы основная страничка и popup на ней были отдельными классами. Все особенности взаимодействия с элементами интерфейса (xpath с учетом/без учета div) класс скрывает в себе, а из теста всё будет выглядеть прозрачно:

page.clickCreateButton();
popup.clickCreateButton();

(Alex) #5

Спасибо за ответы, в дополнение к решению вчера нашел тему очень близкую к этой по организации Framework (Заполнение однотипных форм)


(Alex) #6

Я хотел бы еще такую вещь уточнить. Когда я из теста обращаюсь к popup для редактирования поля, не будет ли хардкорностью писать следующее?:

popup.servicePopup("rules", "Номер по порядку", "10", "fields");

//servicePopup - Тип popup. Я бы мог сделать обобщенный метод для всех попапов, но не получится, так как поведение их бывает разное. Например в одном отобразятся сразу поля, а в другом, перед отображением появится меню.
//rules - popup к которому обращаемся
//Номер по порядку - поле которое будем редактировать
//10 - значение применяемое к полю
//fields - это значение определяет каким образом мы работаем с полем. В данном случае как с текстовым.


(Александр Таранков) #7

Если у тебя разные окна (с разным поведением), то вполне нормально работать с ними через разные классы. Это более правильно, чем пихать всю функциональность разных попапов в один класс


(Alex) #8

Ситуация складывается такая, попапов может быть вложенных бесконечное множество:

[additional-view='0'] [ng-click='addRow(row)'] //элемент на первом попапе
[additional-view='1'] [ng-click='addRow(row)'] //элемент на вложенном попапе
[additional-view='2'] [ng-click='addRow(row)'] //
[additional-view='3'] [ng-click='addRow(row)'] //
[additional-view='4'] [ng-click='addRow(row)'] //
итд.

Если даже описывать общий функционал Popups, то нужно реализовать какой нибудь метод типо стека, или сделать свой счетчик окон, верно?


(Alex) #9

Хотел бы поднять опять вопрос по popup. На popup решил выбрать элемент в list2list, но никак не получается это сделать вываливаются исключения (java)

Локатор в итоге получился следующий (проверял в firepath) //*[@additional-view][last()]//section[@name='row.__states.AvalabiltyOnVideoServers']//td[normalize-space(.)='Московский']/input[@ng-model='row.__selected']

Пробовал следующие способы кликнуть элемент в list2list:

  1. element.click(); выбрасывает исключение ElementNotVisibleException
  2. actions.moveToElement(element).click().perform(); выбрасывает исключение MoveTargetOutOfBoundsException
  3. Если попробовать взять координаты element.getLocation().getX() выдает “0
  4. Пытался кликнуть элемент через SeleniumIDE, кликает только через clickAt

Что происходит и как выполнить клик по элементу?


Поиск элемента через WebElement
(Максим Малунов) #10
  1. Если окно всплывающее то подождать его появления и возможно конца AJAx. (visibilityOfElementLocated )
  2. C кодировками все ок ? Попробуйте переписать локатор без русских букв .

(Alex) #11

Спасибо но проблема была в одно лишь точке при поиске локатора. Подробнее тут.


(Alex) #12

На странице и Popup встречается combobox, я не могу использовать библиотеку Select. Поэтому я написал следующий код во избежании дублирования кода:

public class Combobox{	
	
	private WebDriver driver;
	public Combobox(WebDriver driver){
		this.driver = driver;
		
	}
	
public void editCombobox(WebElement name, String value) {													
				name.click();
				driver.findElement(By.cssSelector("[id='select2-drop'] input")).sendKeys(value);										
				driver.findElement(By.xpath("//div/span[@class='select2-match'][normalize-space(text())='"+value+"']")).click();		
	}
}

То есть описывая страницу я пишу следующее:

public class Videomovies(){
         WebDriver driver;
         Combobox combobox;
@FindBy(css = "[id='s2id_row.contractor'] span")
 	 WebElement row_contractor;

public Videomovies(WebDriver driver){
this.driver = driver
PageFactory.initElements(driver, this);
combobox = new Combobox(driver)
}
public void setContactor(String text){
combobox.editCombobox(row_contractor, text);
}
}

Причем на сайте полно другого объемного функционала, например List2List и там уже больше 2 строчек кода будет. Скажите, такая практика применима при написании framework , или нужно прибегать к другим способам?