We have one CRM product of our client and we are in process of automating it. In that, we have one orders section where user can place orders for either themselves or for the customers. In the orders flow, since the user is purchasing product of their choice which are customised niche products – we have a requirement for the user to accept the agreements, and also sign the agreement, before they can go ahead and make a payment for their purchase.
In theory, this sounds pretty straightforward to do as most of the applications have some agreements to accept inorder to make payment. However, while automating it – we encountered some dynamic elements.
It is always tricky to deal with dynamic elements. Dynamic elements are those elements in the UI whose properties/attributes change on every browser load. Therefore, when we have automate flows which include such elements - we have to deal with them in a different way.
Here we have a dynamic element ‘Scrollbar’ which is visible only when mouse is hovered onto it. The other thing we have here is canvas where we have to sign. Canvas is by default locked here and we need to unlock it. To sign agreement we need to read the whole agreement. After then only canvas for signature gets unlock. So for our use case we just scroll the scrollbar to the bottom of the agreement.
Scrolling dynamic scrollbar becomes tough when it comes to automation. When mouse is hovered using moveToElement(element) function of Actions class, it just focuses on that element but cursor is not actually moved to that element and this is the reason that scrollbar remains disappeared.
In the below snaps, we can see scrollbar appears only when mouse is hovered onto it:
-
Mouse Not Hovered
-
Mouse Hovered
Also we can see in the above snap to unlock canvas, scrollbar needs to be scroll to bottom.
In such cases, first we need to check the attribute of scrollbar i.e, what is the change that reflects in the attribute value when mouse is hovered onto the scrollbar.
In this example, the display value of style attribute of scrollbar is by default 'none' i.e,
"background: rgb(0, 0, 0); width: 7px; position: absolute; top: 0px; opacity: 0.4; display: none; border-radius: 7px; z-index: 99; right: 1px; height: 301.003px;"
When the mouse is hovered, the display value of style attribute is changed to 'block' i.e,
"background: rgb(0, 0, 0); width: 7px; position: absolute; top: 0px; opacity: 0.4; display: block; border-radius: 7px; z-index: 99; right: 1px; height: 301.003px;"
-
When attribute has display: none
-
When attribute has display: block
As we know, moveToElement(element) would not help here. So we need to change the attribute of this scrollbar. WebElement doesn't have any method to set attribute of an element as per the use case. Although we can get attribute of it.
JavaScriptExecutor comes into the picture now. Using JavaScriptExecutor we can do that.
JavascriptExecutor jsExecutor = (JavascriptExecutor) BaseClass.driver;
jsExecutor.executeScript("arguments[0].setAttribute('style', 'background: rgb(0, 0, 0); width: 7px; position: absolute; top: 0px; opacity: 0.4; display: block; border-radius: 7px; z-index: 99; right: 1px; height: 142.857px;')",element);
Using this code we can set attribute value to display: block.
Now as per the requirement i.e, to unlock canvas we need to scroll the scrollbar to the bottom. Using JavaScriptExecutor, scrollbar is visible now.
How to scroll the internal scrollbar of the screen?
To scroll the internal scrollbar, most commonly used function is scrollIntoView(). In scrollIntoView() function, we pass the last element of that area and internal scrollbar is scrolled down. But here we don't have any element in the agreement. There is only paragraphs in the agreement which keeps on changing as per the agreement.
Better Solution Is To Use dragAndDrop():
To scroll it to the bottom we can use dragAndDrop() function of Actions class.
Take the xpath of 'Print this agreement', drag the scrollbar, and drop it to the 'Print this agreement' element. Now this will take the scrollbar to the bottom of the agreement and the canvas will get unlock.
Actions builder=new Actions(driver);
Action drawAction = builder.moveToElement(element) //start points x axis and y axis.
.click()
.clickAndHold()
.dragAndDrop(element, element2)
.release()
.build();
drawAction.perform();
Signature in Canvas:
Now to sign in the canvas, take the xpath of a label which is above the canvas, take X-,Y- coordinates of start point and end point, and use moveToElement(element, startX, startY), and moveByOffset(endX, endY) of Actions class.
Actions builder = new Actions(driver);
Action drawAction = builder.moveToElement(element,30,80) //start points x axis and y axis.
.click()
.clickAndHold()
.moveByOffset(50, 100) // 2nd points (x1,y1)
.release()
.build();
drawAction.perform();
Below is the output: