📜 ⬆️ ⬇️

How we tested drag & drop in HTML5

Anyway, everyone was faced with situations when something unusual happened in a banal atmosphere. About such a case happened to us when testing a new application on a proven environment a hundred times. A surprise for us was the use of some HTML5 features in the work of the front-end, or rather the impossibility of using standard tools of Selenium WebDriver to automate the testing of drag & drop operations. We want to tell about this experience.



Imagine a project that is technologically very similar to the previous one (in our opinion, it had a slight negative effect from the point of view of correct understanding and analysis of the problem that appeared), but the Angular version between projects changed from 1.x to 5.x and the Selenide library was added for UI autotests .

The developed web application had a page with a certain set of entities that could be moved between each other. What was our surprise when the attempt to perform an autotest of checking the drag & drop function by means of Selenide did not succeed. It would seem that could go wrong? On the previous project on a similar test environment, everything worked fine.

First of all, we checked the operation of the drag & drop functions of Selenide and Selenium in the current browser using the example of another web application. Everything is working. Updated version, you never know ...
We decided to check whether we are dragging and there. And it’s pretty easy to make a mistake when choosing elements when using Angular. They sat down with the front-end developer and figured out that the drag and drop elements were selected correctly.

In general, the test environment is working, test methods are written correctly, drag & drop “hands” work, but the autotest does not work. And at first glance there are no reasons for this.

Finally, we put up with the fact of the problem and went to look for a solution on the Internet. What was our surprise when we found an open issue Chrome WebDriver # 3604 from 03/04/2016 . Just think, since the spring of 2016 there has officially been a problem with idle drag & drop in Chrome WebDriver, not to mention other browsers. No, it certainly works, but not when using HTML5. And as it turned out in the process of analyzing the problem, our application used the drag & drop implementation in HTML5.

What are the options for implementing drag & drop for testing in HTML5? On the Internet, two solutions were found:


Probably, we have slightly earned or dug in the problem, but at once I will make a reservation that the first chosen solution did not suit us :)

What can be said about the implementation on Robot:


But something about the implementation on JavaScript came up with something like this:


At first glance, the first solution was much more convenient and was tested.

//Setup robot Robot robot = new Robot(); robot.setAutoDelay(50); //Fullscreen page so selenium coordinates work robot.keyPress(KeyEvent.VK_F11); Thread.sleep(2000); //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; //Get x and y of WebElement to drag to Point toLocation = dragTo.getLocation(); Point fromLocation = dragFrom.getLocation(); //Make Mouse coordinate centre of element toLocation.x += xOffset + xCentreTo; toLocation.y += yCentreTo; fromLocation.x += xCentreFrom; fromLocation.y += yCentreFrom; //Move mouse to drag from location robot.mouseMove(fromLocation.x, fromLocation.y); //Click and drag robot.mousePress(InputEvent.BUTTON1_MASK); //Move to final position robot.mouseMove(toLocation.x, toLocation.y); //Drop robot.mouseRelease(InputEvent.BUTTON1_MASK); 

In general, the solution is working ... However, in the process of its study, its problem areas became clear.


As a result, all the same JavaScript implementation ...

I just want to say that the problem of using xpath locators was solved using the jQuery plugin jquery.xpath.js.

And the main tool for js drag & drop operations management is the library drag_and_drop_helper.js (the source is here ). There is not much sense in analyzing her work, but about how we finished it a little later.

Now directly on the implementation of the tests. At Selenide, everything is simple. Before using drag & drop, you need to load the used JS libraries:

 StringBuilder sb = new StringBuilder(); sb.append(readFile("jquery-3.3.1.min.js")); sb.append(readFile("jquery.xpath.min.js")); sb.append(readFile("drag_and_drop_helper.js")); executeJavaScript(sb.toString()); 

Naturally, jQuery needs to be loaded if it is not already in the application.

In the initial version of the library it is enough to register the following:

 executeJavaScript("$('" + source + "') .simulateDragDrop({ dropTarget: '" + target + "'});"); 

source and target are css-locators of drag and drop elements.

As mentioned above, we often use xpath-locators in the project, so after a little refinement the library began to accept them:

 executeJavaScript("$(document).xpath('" + source + "').simulateDragDrop({ dropTarget: '" + target + "'});"); 

Now, actually, about the drag_and_drop_helper.js library. In the simulateEvent code block, there are chunks responsible for certain mouse events. It makes no sense to list the possible events of drag & drop operations in HTML5, this information is easy to find.

For testing, we needed to implement a function that moves the element and holds the mouse on the target element. And this is not provided in the source library.

By analogy, add a dragenter event to the library (between dragstart and drop).

 /*Simulating dragenter*/ type = 'dragenter'; var dragenterEvent = this.createEvent(type, {}); dragenterEvent.dataTransfer = event.dataTransfer; this.dispatchEvent($(options.dropTarget)[0], type, dragenterEvent); 

However, this is not enough. After all, the hold event will be instantly over. Putting a fixed pause between dragEnter and drop events seemed not the most convenient option. After all, it is not initially known how long the application takes to process an event, the number and time of checks in the tests is unknown. The delay between these events should be at least controllable. Instead, we decided to split the testing of drag & drop into stages and not to emulate the full set of mouse events, that is, to add the ability to manage the list of involved events through a parameter.

And everything seems to be good, the new flaws did not manifest, and some of the old ones are no longer as such, and the main task is being fulfilled. It would seem that everything is perfect. However, modern development tools provide for the processing of more than two events and use different parameters of the moving element. Suppose we have this solution when performing drag & drop causes errors dragStartListener. But since it does not break anything, then we have nothing more and did not change. However, in some other application you will probably have to finish this moment as well.

We want to summarize the above. Surprisingly, but a fact! HTML5 was released in the distant 2013, browsers have been supporting it for a long time already, for the first time, applications sharpened for it are being developed, but webDriver, alas, is still not able to use its capabilities. And testing of drag & drop operations has to be implemented by third-party tools, complicate the architecture and go for all sorts of tricks. Yes, there are such means and “dancing with a tambourine” only makes us stronger, but I still want to have a working solution out of the box.

In our experience, we can say that such problems are not so common today, although drag & drop is used everywhere. It’s probably a matter of choosing a web application development technology. However, the percentage of applications using HTML5 is growing steadily, the frameworks are evolving, and it would be great if the developers of browsers and drivers for them also did not lag behind.

PS And finally, some lyrics. I would like to advise everyone if possible not to take into account the banality of the situation or the proximity of the test environment to some kind of pattern when analyzing problems. This can lead to incorrect conclusions or loss of time.

Source: https://habr.com/ru/post/437200/