Selenium WebDriver, Junit, Ant, Java
Не работает d’n’d при запуске тестов на сервере
На локальной машине удалось выполнить d’n’d. Код следующий (пример):
public class HTML5DD1 {
static WebDriver driver;
public static void main(String[] args) throws Exception {
FirefoxProfile ffProfile = new FirefoxProfile();
ffProfile.setEnableNativeEvents(true);
ffProfile.setPreference("permissions.default.image", 2);
driver = new FirefoxDriver(ffProfile);
driver = new FirefoxDriver();
Thread.sleep(3000);
driver.get("http://www.w3schools...draganddrop.htm");
driver.manage().window().maximize();
WebElement dragFrom = driver.findElement(By.id("drag1"));
WebElement dragTo = driver.findElement(By.id("div1")); dragAndDropElement(dragFrom, dragTo, 0, 90);
System.out.println("Done Dragging!");
dragAndDropElement2(dragFrom, dragTo, 0, 90);
System.out.println("Done Dragging! 2");
}
public static void dragAndDropElement(WebElement dragFrom, WebElement dragTo, int xOffset, int yOffset) throws Exception {
System.out.println("dragFrom ="+dragFrom + " dragTo = "+dragTo +"xOffset = "+xOffset +" yOffset ="+yOffset );
// Setup robot
Robot robot = new Robot();
robot.setAutoDelay(500);
// Get size of elements
Dimension fromSize = dragFrom.getSize();
Dimension toSize = dragTo.getSize();
//Get centre distance
int xCentreFrom = fromSize.width / 2;
int yCentreFrom = fromSize.height / 2;
int xCentreTo = toSize.width / 2;
int yCentreTo = toSize.height / 2;
Point toLocation = dragTo.getLocation();
Point fromLocation = dragFrom.getLocation();
System.out.println(fromLocation.toString());
//Make Mouse coordinate centre of element
toLocation.x += xOffset + xCentreTo;
toLocation.y += yOffset + yCentreTo;
fromLocation.x += xOffset + xCentreFrom;
fromLocation.y += yOffset + yCentreFrom;
System.out.println(fromLocation.toString());
//Move mouse to drag from location
robot.mouseMove(fromLocation.x, fromLocation.y);
//Click and drag
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseMove(((toLocation.x - fromLocation.x) / 2) + fromLocation.x, ((toLocation.y - fromLocation.y) / 2) + fromLocation.y);
//Move to final position
robot.mouseMove(toLocation.x, toLocation.y);
//Drop
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
Необходимо запустить на Jenkins. OS Debian.
Настройки браузера на Jenkins:
[junit] Caused an ERROR
[junit] headless environment
[junit] java.awt.AWTException: headless environment
[junit] at java.awt.Robot.<init>(Robot.java:94)
[junit] at WeekCalendar.dragAndDropElement(WeekCalendar.java:318)
[junit] at WeekCalendar.weekcalendar(WeekCalendar.java:203)
Технически, ему без разницы, web это или нет. Он умеет эмулировать работу мыши / клавы, но сугубо в рамках текущей JVM. Т.е. при его помощи можно спокойно взаимодействовать с ОС диалогами открытия / сохранения при file upload / download, чтобы ввести путь и кликнуть Enter, к примеру. Но это будет работать только локально. Чтобы запустить робота ремоутно, его нужно внедрить в клиент-серверную платформу и запускать на той тачке, где исполняются тесты. Ну т.е. теоретически, его можно прикрутить в selenium-standalone и дергать какой-то кастомный end-point. У того же Sikuli, его внедряли в серверную часть.
Попробуйте Sikuli. Я тут недавно постил тему с RESTful SikuliX. Эту клиент-серверную платформу можно использовать для вызова нативного сикулишного drag&drop (SikuliX API уже внедрены в серверную часть). Но придется дописать соответствующую обертку. Ну или можете внедрить того же робота в качестве доп. функционала. В любом случае вам придется поднимать доп. клиент-сервер или редактировать существующий для вызова кода на той тачке, где запускаются сами тесты. Кстати у нас на проекте мы как раз юзаем сикулишный d&d (тянем файл с десктопа в браузер).
П.С. А нативный селениумовский d&d не работает? Ну или можно JSовский попробовать - JS executor via RemoteWebDriver API.
Документации никакой нет. С вашим кодом в идеале надо модифицировать selenium-server-standalone, копаться в исходниках, искать серверный код и добавлять свои эндпоинты. При этом ваш код можно оформить в виде утилити класса. Сколько времени на это уйдет - не имею понятия, ибо надо хорошо знать структуру проекта.
А вот по структуре SikuliX клиент-сервера могу подсказать.
Собственно, как я уже выше намекнул, код нужно поместить в отдельный
утилити класс на сервере, по примеру одного из уже имеющихся (utils package).
WebDriver / WebElement вам не пригодятся, исходя из того, что вы оттуда тянете
лишь x,y координаты элемента. Плюс ко всему, нам не нужны лишние тяжеловесные
библиотеки в dependencies.
После создания утилити класса с необходимым нам методом, нужно
добавить end-point, с которым может взаимодействовать клиент. Примеры таких end-points можно найти в service package.
В самом примитивном случае можете создать POST обработчик с 4 query
param: x1, y1, x2, y2. Или создать 2 Point (не селениумовских) объекта и передавать их в качестве списка в post entity (клиентская часть).