How to perform drag and drop inside svg element using selenium? - selenium

[below is the image of page element,i want to drag and drop inside svg element tried action class and robot class as well but not able to do.
resizeblockTwo']">
<div class="chartCanvas js-resizeblockOne drpm-resize__block-one">
<div class="titleBar layout-align-space-between-center layout-row">
<graph-canvas class="ng-scope">
<section class="chartContainer">
<div class="chartArea joint-theme-default paper" droppable="">
<svg id="v-2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="100%">
</div>
</section>
<div ng-transclude="">
</graph-canvas>
<div class="processflow-empty-message ng-scope" ng-if="emptyGraph" style="">
<div class="drpm-resize__grabber">
</div>

You should stick to cssSelector as selenium has the problem to handle svn tag with other locators. I have experienced the same.
Now pass the same element in selenium drag and drop by action class. You havn't specify the element we can't extract CssSelector for you, you can use chrome-> Inspect-> copy -> copy selector
In java it will be something like below :-
Actions act=new Actions(driver);
// find element which we need to drag
WebElement drag=driver.findElement(By.cssSelector("YOUR CSS Selector"))
// find element which we need to drop
WebElement drop=driver.findElement(By.cssSelector("YOUR CSS Selector"));
// this will drag element to destination
act.dragAndDrop(drag, drop).build().perform();
Hope it will help you :)

Related

How to locate a svg element present inside a Shadow DOM in Selenium

I am able to locate elements other than svg using either JS Path OR by using the plugin created by sukgu (https://github.com/sukgu/shadow-automation-selenium)
The problem is with svg element present inside the Shadow root, I am not able to locate it.
Tried below methods:
While trying css selector to find the svg element, got below error:-
WebElement ele = (WebElement) js.executeScript("return document.querySelector(\"body > sn-component-va-web-client\").shadowRoot.querySelector(\"#Path\")"); ele.click();
Output -
org.openqa.selenium.ElementClickInterceptedException: element click
intercepted: Element
Using above mentioned plugin to find the svg - Using css selector
WebElement close = shadow.findElement("div > div.sn-cs-header > div.header-menu > div.menu-item.new-conversation-clicker > div.new-conversation-button > div > svg"); close.click();
Output -
org.openqa.selenium.ElementNotVisibleException: Element with CSS div >
div.sn-cs-header > div.header-menu >
div.menu-item.new-conversation-clicker > div.new-conversation-button >
div > svg is not present on screen
Using Xpath
WebElement close = shadow.findElementByXPath("//*[local-name()='svg']//g//g//g//path[#id='Path']"); close.click();
Output -
org.openqa.selenium.ElementNotVisibleException: Element with XPath
//*[local-name()='svg']//g//g//g//path[#id='Path'] is not present on
screen
Below is the HTML :-
<div class="conversation-container" style="display: block;">
<iframe title="Chat Support" id="myiFrame" class="chat-frame" scrolling="no" horizontalscrolling="no" verticalscrolling="no" frameborder="none" ng-src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no" src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no"></iframe>
</div>
<iframe title="Chat Support" id="myiFrame" class="chat-frame" scrolling="no" horizontalscrolling="no" verticalscrolling="no" frameborder="none" ng-src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no" src="/$sn-va-web-client-app.do?sysparm_nostack=true&sysparm_stack=no"></iframe>
#document
<html>
<head>
<body>
<sn-component-va-web-client component-id="cid1" now-id="cid1"></sn-component-va-web-client>
#shadow-root (open)
<div class="sn-cs-webclient fill-window text-direction-ltr">
<div class="sn-cs-accessibility-reader" aria-live="polite" aria-atomic="false"></div>
<div></div>
<div class="sn-cs-header" style="z-index: 500;">
<div class="chat-title">
<div class="header-circle">
<img class="header-icon " src="599c06dedbbe6c109005db184b961967.iix" alt="Header Icon">
</div>
</div>
<div class="header-menu">
<div class="menu-item new-conversation-clicker " aria-label="End conversation" aria-haspopup="menu" role="button" aria-describedby="new-conversation-tip" tabindex="0">
<div class="new-conversation-button">
<div class="new-convo-icon close-icon">
<svg viewBox="0 0 26 23" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g id="Symbols" stroke="none" stroke-width="1" fill="rgba(0,0,0,0)" fill-rule="evenodd">
<g id="header/New-header-la-no-name" transform="translate(-330.000000, -20.000000)" fill-rule="nonzero" stroke="#ffffff" stroke-width="2">
<g id="Group" transform="translate(329.000000, 20.000000)">
<path d="M13.55,1 C7.17042969,1
<!-- removed extra numbers --> 19.9295703,1 13.55,1 Z" id="Path">
</path>
</g>
</g>
</g>
</svg>
Please try the following:
WebElement root = driver.findElement(By.cssSelector("body > sn-component-va-web-client"));
WebElement shadow_root = expand_shadow_element(root);
WebElement path = shadow_root.findElement(By.cssSelector("g > g > path"));
path.click();
public static WebElement expand_shadow_element(WebElement element)
{
WebElement shadow_root = (WebElement)((JavascriptExecutor)driver).executeScript("return arguments[0].shadowRoot", element);
return shadow_root;
}
Credits to the author
I suppose the problem is the different namespace the svg elements are in.
Take a look here : https://www.inflectra.com/support/knowledgebase/kb503.aspx
So probably you need (if the g-elements are irrelevant):
//*[local-name()='svg']//*[local-name()='path' and #id='Path']
If the g-elements are relevant, you need:
//*[local-name()='svg']/*[local-name()='g']/*[local-name()='g']/*[local-name()='g']/*[local-name()='path' and #id='Path']
Or maybe even use the XPath id-function like this:
id('Path')
I was able to locate/click on the svg element with a workaround, instead of finding xpath of svg element, I tried locating the element prior to svg.
Steps:-
Identify and click on the non-svg element prior to svg element
Shadow shadow = new Shadow(driver); // Using sukgu plugin
WebElement x = shadow.findElementByXPath("xpath");
x.click();
Move focus to the svg element using actions class and click on it
Actions action = new Actions(driver);
action.sendKeys(Keys.TAB).build().perform();
action.sendKeys(Keys.SPACE).build().perform();
Any answer would be a hit & trial without actually looking into the DOM.
ShadowDOM'S are often tricky.
In case you usually struggle around these areas, I suggest you install and use the Selectorshub extension for chrome: https://chrome.google.com/webstore/detail/selectorshub/ndgimibanhlabgdgjcpbbndiehljcpfh?hl=en
Once install check out this link to understand how to right paths for shadow dom:
https://www.youtube.com/watch?v=SCOAS86rJ9E
It has many other features which will make you write paths quickly. pretty good extension imo for ui-automation purpose.

XPath failing to select element

Can someone give a better xpath of this div element, or help explain why I cannot seem to select the desired div?
This XPath does not work:
//div[starts-with(normalize-space(.),'Welcome to the Shipt Shopper') and #class='text']
Even though it gets highlighted in chrome developer tool, NoSuchElementException is thrown.
This is the case with all elements on the page
A snippet of the HTML from the page with the content that I am trying to target:
<div class="content-wrapper">
<div class="content" style="padding-top: 116px;">
<div class="media">
<div class="attachment" data-attachment="{"image":"https:\/\/images.typeform.com\/images\/29rsVwT3VF\/image\/default#.png","width":360,"height":137,"video_source":"","video_id":""}" style="width: 360px; height: 137px;">
<img src="https://images.typeform.com/images/29rsVwT3VF/image/default#.png" data-original="https://images.typeform.com/images/29rsVwT3VF/image/default#.png" style="width: 360px; height: 137px; display: inline;">
</div>
</div>
<div class="text" style="padding-top: 30px; margin-left: 0px;">
Welcome to the Shipt Shopper application! <br><br>Ready to get started?
</div>
<div class="button-wrapper" style="margin-top: 30px;">
<div class="button general full enabled hover-effect" style="">Begin</div>
<div class="button-text">press <strong>ENTER</strong></div>
</div>
</div>
</div>
The content that you are targeting is inside of an <iframe>.
I'm not familiar with how to configure Selenium, but it looks as if you may need to switch to that frame. Since it does not have an #id you may need to select by position:
driver.switchTo().frame(0)
and then execute the XPath.
When you are done, jump back to the containing HTML page:
driver.switchTo().defaultContent();
As per the HTML you have shared the xpath which you have used is a valid one and is correct. But NoSuchElementException will be thrown when you will try to interact with it through Selenium.
To interact with the element through Selenium you can use the following xpath :
//div[#class='content-wrapper']/div[#class='content']//div[#class='text' and contains(normalize-space(), 'Welcome to the Shipt Shopper application')]
But looking at the HTML it seems your have to induce WebDriverWait for the element to be visible as follows :
WebElement welcomeShiptShopper = new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[#class='content-wrapper']/div[#class='content']//div[#class='text' and contains(normalize-space(), 'Welcome to the Shipt Shopper application')]")));
The webpage doesn't opens at my end. As other's have indicated, the WebElement might be within <iframe> tag, in that case you have to switch to the appropiate iframe first using either of the following methods first :
Switch through Frame Name
driver.switchTo().frame("frame_name");
Switch through Frame ID
driver.switchTo().frame("frame_id");
Switch through Frame Index
driver.switchTo().frame(1);
Once you switch to the appropiate frame, now you can lookout for the WebElement with the suggested xpaths mentioned above.

Close youtube popup window by clicking 'x' is not working using Selenium WebDriver

Trying to close a Youtube popup window by clicking 'x' button present on the top right corner, but I'm getting the following error message:
Caused by: org.openqa.selenium.ElementNotVisibleException: Element is
not currently visible and so may not be interacted with
Tried the bellow code:
driver.findElement(By.className("close")).click();
driver.findElement(By.xpath("//button[#class='close']")).click();
driver.findElement(By.cssSelector("button[class='close']")).click();
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();",
driver.findElement(By.className("close")));
HTML:
<div id="videoModal" class="modal fade in" aria-hidden="true" aria-labelledby="videoModal" role="dialog" tabindex="-1" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<button class="close" aria-hidden="true" data-dismiss="modal" type="button">×</button>
<div>
<iframe width="100%" height="350" allowfullscreen="" src="https://www.youtube.com/embed/SQFKxxKMIxc?autoplay=1"/>
</div>
Screenshot:
https://i.stack.imgur.com/W3IXe.png
public Boolean closeVideoPopup(){
try{
driver.findElement(By.id("video-how-to")).click();
driver.waitForPageLoad();
driver.findElement(By.className("close")).click();
return true;
}
catch(Exception e) {
logger.info("Exception occurred: "+ e.getMessage().toString().substring(0, Integer.parseInt(TestConstants.ERRCHARCOUNT)));
}
return false;
}
This selector should work but will be more efficient if you replace it with your suited markup:
driver.findElement(By.xpath("//*[contains(#class, 'close')]"));
Or, since we know the sought element is a div:
driver.findElement(By.xpath("//div[contains(#class, 'close')]"));
Hope it will help you.
Maybe some other element is overlapping your pop-up. Thus, you can use explicit waiting for the element in order for it to become visible.
WebDriverWait wait=new WebDriverWait(driver, 90);
wait.untill(ExpectedConditions.visibilityOf(driver.findElement(By.className("close")));
... or find out the element which is overlapping and wait for the element to disappears.
Both ways you can try.
It works using the complete xpath now
driver.findElement(By.xpath(".//*[#id='videoModal']/div/div/div/button[#class='close']")).click();
Steps to do this using Sikuli:
Add Sikuli jar in your project or add as a dependency in pom.xml
<dependency>
<groupId>com.sikulix</groupId>
<artifactId>sikulixapi</artifactId>
<version>1.1.0</version>
</dependency>
Take the screenshot of element using Sikuli IDE.
Steps to install and use Sikuli IDE:
http://www.sikuli.org/downloadrc3.html
Write the below code:
Screen screen = new Screen();
Pattern image = new Pattern(filePath\\xbutton.png");
screen.click(image);
click method of Screen class will help to click on the element

Click on button without id

How click button in webdriver without any id, values. Class of button is changing dynamically.
Sample:
<div class="d-k-l d-y-r-c g-h-f-Ck b-Qb" role="button" style="-moz-user-select: none;" tabindex="0" aria-haspopup="true">
<div class="d-k-l d-y-r-c-ha">
Мои круги
</div>
<div class="d-k-l d-y-r-c-Qa"></div>
</div>
Thx.
Show more HTML please. So that we can find something useful in the context.
Currently the only possible way is to use XPath' text()
.//*[#role='button']/*[contains(text(), 'Мои круги')]
If you are sure relevant elements are div, you can use
.//div[#role='button']/div[contains(text(), 'Мои круги')]

how to click on a button when specific image is asscoiated with it

I am using selenium for testing my application.
In my application there are 5 buttons, each have a different image associated with it.
I want to click on button which have a specific image associated.
Currently i am using a while loop to get the node of image and then replacing this node into xpath of button to select it.
is there any way either with xpath or css to do this directly.
Providing more information-this is like submit button is there and then below this image is there. submit button and images are sibling element and need to click submit button when the next element is specific image
<div class="select">
<span class="sysTxtBtn submit xxs">
<span class="btnTagDummy">
</span>
<div class="specialRateMarking">
<img width="79" height="11" alt="Marking2" src="someimages"/>
</div>
<div class="select">
<span class="sysTxtBtn submit xxs">
<span class="btnTagDummy">
</span>
<div class="specialRateMarking">
<img width="79" height="11" alt="Marking1" src="someimages"/>
</div>
Could you include a snippet of your HTML? Below is an example of an image in a form and a few ways of locating it using Selenium, but these may not be relevant depending on your implementation:
<input id="submitForm" name="imgbtn" type="image" src="images/submit.png" />
id=submitForm
name=imgbtn
//input[#src='images/submit.png']
//input[contains(#src, 'submit.png')]
css=input[src='images/submit.png']
UPDATE:
Given the HTML:
<div class="select">
<span class="submit">
<div class="marking1"></div>
<div class="select">
<span class="submit">
<div class="marking2"></div>
You can locate the 'submit' span parent of the 'marking2' div using the following XPaths:
//div[#class='marking2']/..
//div[#class='marking2']/parent::*
//div[#class='marking2']/parent::span
UPDATE 2:
Based on the HTML now included in the question, you can locate the span with the class of submit related to the image many ways, a few examples follow:
//div[//img[#alt='Marking2']/span[contains(#class, 'select')]
//img[#alt='Marking2']/../../span
//div[img[#alt='Marking2']]/preceding-sibling::span
I hope this gives you some ideas. I'd certainly recommend XPath over CSS for locating these elements as it's much better at these sorts of relationships.