I want to test for checkbox checked or unchecked condition.
This is the html code for checkbox checked
<div classs="input-control checkbox">
<span class="check">
::before
</span>
</div>
::before is css selector.
when i hoverover to checkbox, it shows webelement as span.check::before
but
driver.FindElement(By.CssSelector("span.check::before"));
throws element not found exception.
Any help will be highly appreciated.
In my case, I have removed the pseudo-element ::before from the CSS selector as seen below and it works
Instead of:
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(By.cssSelector("span.check::before"))).build().perform();
I gave:
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(By.cssSelector("span.check"))).build().perform();
Using pseudo-elements in the selector is actually not supposed to work as mentioned here and here.
I'm not sure of your exact html as the comment mentions there is no ::after in your example html. Based on your description this seems similar to the below, but not sure if that is what your exact situation is.
I have utilized the mouse move and then wait for the element that displays the modified css/class. The mouse would move and hover to the first element and then wait for the second to appear on the screen. This works similarly for click and then wait for element to appear.
Hover code example - needs to match your code language and structure...
[Actions Instance goes here].MoveToElement([IWebElementGoesHere]).Perform();
you can also just do
[Actions Instance].Click([IWebElementGoesHere]).Perform();
Reference for this library: https://code.google.com/p/selenium/wiki/AdvancedUserInteractions
I have faced similar issue with pseudo css selectors (::before alike), I have overcome the issue using "Actions" class of selenium java.
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(By.cssSelector("button[id$='save-button']"))).build().perform();
Hope it helps.
Thanks,
Sampath
Related
I have got a problem with Selenium code to find a button which has only "Value" and "type", in inspection it looks like this:
<input type="sumbit" value="login" />
Image of inspection
I tried twice but neither line worked for me.
The lines:
1st solution:
driver.FindElement(By.XPath("//button[contains(text(),'Login')]")).Click();
2nd solution:
driver.FindElement(By.ClassName("submit")).Click();
Image with ERROR MESSAGE (second line error)
Can anybody help me, or at least point out what am I missing, because its getting pretty frustrating to find a solution for such common thing, I practiced this on tutorial pages and buttons were never a problem.
Please. (Sorry for my English)
P.s.: I checked the "similar questions and I haven't found the solution.
P.s.s: Guys, there is another one which I didnt try yet but I have 3 different lines of code, do you think one of them will work:
There is drop-down list and I want to select the last thing in the list...
driver.FindElement(By.XPath("//*[contains(., 'Process Data >>')]"));
driver.FindElement(By.Id("pdatasub")).Click();
driver.FindElement(By.XPath("//div[text()='Process Data >>']")).Click();
Inspection of the Drop-down list
Code for the opening of the last "button" in the drop-down list:
driver.FindElement(By.XPath("//div[text()='Final Values']")).Click();
enter link description here
Thanks guys for help !
You are using the wrong locator :
try this instead :
driver.FindElement(By.XPath("//input[#type='submit' and #value='Login']")).Click();
or
With ExplicitWaits
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//input[#type='submit' and #value='Login']"))).Click();
Your locator is wrong.
You can use this:
driver.FindElement(By.XPath("//button[#type='submit']")).Click();
or
driver.FindElement(By.XPath("//button[#value='login']")).Click();
or
driver.FindElement(By.XPath("//button[#value='login' and #type='submit']")).Click();
CSS Selector can be used as well similarly.
Also there are several possible issues:
You should add a wait before accessing that element. Otherwise you are trying to find an element while page is still not loaded. Expected conditions are the preferred way to do this with.
The element can be inside an iframe. If so you have to switch to that iframe in order to access elements inside it.
I am trying to create this simple test where you head to the URL, enter your login credentials and then click the button to sign in. It is doing everything, except for clicking the button. I am trying to doing it by calling up ClassName. Can anyone look at my test and see what I am doing wrong?
public void test_search()
{
var driver2 = new ChromeDriver(#"C:\Users\MyName\Desktop\NUnitTestProject1\NUnitTestProject1\bin\Debug\netcoreapp2.1");
driver2.Navigate().GoToUrl("https://portal.crushdata.com/");
driver2.FindElement(By.Name("Email")).SendKeys("email#email.com");
driver2.FindElement(By.Name("Password")).SendKeys("Password");
driver2.FindElement(By.ClassName("btn bg-teal btn-block btn-lg waves-effect")).Click();
}
This is my classname for my button.
Use CSS selector as shown below:
By.ClassName("btn.bg-teal.btn-block.btn-lg.waves-effect")
Each dot represents a class.
See this page for more info and here is an example from that page:
.name1.name2
Selects all elements with both name1 and name2 set within its class attribute
To click on the SIGN IN button you have to induce WebDriverWait for the desired ElementToBeClickable() and you can use either of the following Locator Strategies:
CssSelector:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("button.btn.bg-teal.btn-block.btn-lg.waves-effect"))).Click();
XPath:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//button[text()='SIGN IN']"))).Click();
Try making use of the button xpath.
Open the dev tools. Right click on the button you want to be clicked > Select Inspect >Then right click the html in the dev tools window and Copy Xpath from the Copy option.
Then in you code replace FindElement with FindElementByXPath:
driver2.FindElementByXPath("//*xpath/goes/here")).Click();
Given your shared html block, the following XPath will suffice.
//div[contains(#class = "text-center")]//button[contains(#class, 'btn bg-teal btn-block btn-lg waves-effect') and #type = 'submit']
If the driver is still unable to click you should consider the following:
Is the XPath unique? paste the xpath in chrome's devtools search box in the inspect element tab and make sure the provided xpath is targeting the element you are intending. If this is not the case then you should make the xpath more unique.
Is the element in an iframe? if the element is in an iframe the driver won't be able to locate it by default. In such cases you will need to first switch to the iframe and then attempt to locate and interact with the element.
Is the element clickable, visible and enabled? To check these properties first find the element and store in a separate variable and then check the said properties are true.
A temporary CSS element is obscuring the xpath element I want to click on.
Using Selenium in Visual Studio I am writing a testcase where an element is to be clicked. But when I run this testcase I get an error message telling me:
OpenQA.Selenium.ElementClickInterceptedException Element <a href="#/app/customer/handling/devices"> is not clickable at point (105,221) because another element <div class="showbox layout-align-center-center layout-row ng-star-inserted"> obscures it
The obscuring element seems to be a CSS element. But when I manually go to this page, inspect the code and search for this css element
<div class="showbox layout-align-center-center layout-row ng-star-inserted"> I get no results.
I am therefore assuming that this CSS element is temporary and can only be identified for a couple of seconds while the page is loadning. This assumption is confirmed by the fact that if I put a static wait method Task.Delay(4000).Wait();in this testcase I am able to complete this testcase.
But I'm not interested in a solution where I use a static wait method in my code. I want to be able to wait for the temporary css to disappear so I can click on my desired xpath element.
This is my code:
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
//Waiting for temporary CSS element to be visible
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
//Waiting for temporary CSS element to disappear
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div/div[2]/nav[2]/div/ul/li[1]/a"))).Click();
//Click on "Handle Tools" link
As you can read by the comments in my code I do three things here:
1. I wait for the temporary CSS to be loaded
2. I wait for it to disappear
3. I click on the xpath element.
When I do this I get an error telling me the CSS selector I'm trying to find is invalid.
If I skip the first step and just wait for the CSS to disappear/be "invisible" it will check this too fast and look before the CSS element have started loading.
So either I'm not writing the By.CssSelector format correctly. Or the CSS element is called something else than Visual Studio is calling it in the error message I quoted above.
So please tell me if I'm using an incorrect way to identify this CSS element here:
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
OR
Is there another way to dynamically wait out temporary CSS elements?
OR
Can I somehow confirm that the name of obscuring CSS element is actually called "div class='showbox layout-align-center-center layout-row ng-star-inserted'"?
So I am not 100% sure what you mean by a CSS element. But I am thinking it is just a misnomer you may have picked up. But CSS is cascading style sheets. It is markup that defines the appearance of a Document Object Model (DOM) element.
XPath is an approach to defining the location of an element for a driver to find it and interact with it. Css selectors are an alternative approach to finding elements in the xml or html of a DOM. So there is no such thing as a "Css element" or an "XPath element". They are just "elements".
As for fixing the issue you are seeing, you could try this:
//This is called an extension method. It adds methods to an existing class. This should go in a static class that is accessible to your driver.
private static void WaitUntil(this IWebDriver driver, Func<bool> Condition, float timeout)
{
float timer = timeout;
while (!Condition.Invoke() && timer > 0f)
{
System.Threading.Thread.Sleep(500);
timer -= 0.5f;
}
System.Threading.Thread.Sleep(500);
}
driver.WaitUntil(() => driver.FindElementsBy(By.CssSelector(".showbox.layout-align-center-center.layout-row.ng-star-inserted").length == 0);
Also of note, your CSS Selectors in your description are completely invalid. I suggest reading up on them in a tutorial like this one.
The problem in this case was that my CSS selector was indeed invalid. Removing the "div class=" in the beginning and adding a "." solved the problem.
Before:
"div class='showbox layout-align-center-center layout-row ng-star-inserted'"
After:
".showbox.layout-align-center-center.layout-row.ng-star-inserted"
Thanks to Asyranok for providing me with the correct format for my CSS selector.
I did not need the rest of your code in this case, instead I just copied the correct CSS format from your code into my solution and it worked. :)
I usually only use xpath when trying to identify an element so I'm not that used to CSS and what format to use.
Also thanks to JeffC for confirming my suspicion that I need to wait for the obscuring element to first load and then wait again for it to disappear.
I know there are existing questions on this topic, but none of them seems to help me with this:
I've got a lightbox with several elements.
I can find and access all of these elements, except ONE, using the XPath.
These are the items:
Text header: No problem
Text: No problem
Input field: No problem
Text: No problem
Text: No problem
Button (upload file): THIS IS SEEMINGLY IMPOSSIBLE FOR Selenium TO FIND
Button (cancel): No problem
Button (send): No problem
The XPaths for all the elements:
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[1] /content-placeholder/h1
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/ul[1]/li[1]/label/span
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/ul[1]/li[1]/div/div/input
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/label
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/span
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[5]/content-placeholder/button[1]
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[5]/content-placeholder/button[2]
The problematic element is this:
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input
As far as I can see, there's no reason why it should be different from the other elements (textfield, button, text)?
I'm accessing all these elements with an implicit wait, to check that they've all loaded before continuing.
GCDriver.WaitForVisible("//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input");
From the GCDriver (Selenium Driver) class:
public static void WaitForVisible (string xpath) {
var wait = new WebDriverWait(GCDriver.Instance,
TimeSpan.FromSeconds(10));
wait.Until(driver =>
driver.FindElement(By.XPath(xpath)).Displayed);
}
Now, as mentioned, this works for all the other elements, as well as accessing them directly. For this, the wait times out with WebDriverTimeoutEsception:
Result Message:
Test method Tests.Regression_tests.VerifyOverlays.Verify_Update_Ticket_OverlayContent threw exception:
OpenQA.Selenium.WebDriverTimeoutException: Timed out after 10 seconds
Also, of course, trying to ACCESS the button with .Click() also fails:
GCDriver.Instance.FindElement(By.XPath(".//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input")).Click();
Result Message:
Test method Tests.Regression_tests.VerifyOverlays.Verify_Update_Ticket_OverlayContent threw exception:
System.InvalidOperationException: unknown error: Element is not clickable at point (-208, 307)
Here's the html code for the element:
<a class="btn btn-grey file-input-container btn-small" data-bind="enable: !uploading() "
style="margin-top: 10px; padding: 7px 12px; "data-tooltipped=""
aria-describedby="tippy-tooltip-32"
data-original-title="Add Attachment">
<i class="fa fa-cloud-upload"/>
<span class="mq-for-small-hide">
<span localize-me="">Add Attachment</span>
</span>
<input data-bind="upload: addAttachments,
enable: !uploading()" type="file"/>
</a>
I've tried some other ways of getting the element, but since this is quite (imo) "messy" html, with no unique ID's or good class names, I've been unable to figure out how.
And it REALLY bugs me that I cannot find it by the XPath. There are 8 elements on the page, all visible and accessible, but this ONE element is impossible to find with Selenium.
The element is there; I can manually click the button on the page while Selenium runs it.
UPDATE:
I also tried using .Enabled instead of .Displayed. Same result.
UPDATE 2:
There are two answers below, and I have to select one as the "winner".
Shubham Jain gives an answer that, while not the exact thing I was trying to to, is a very good work-around. By using JavaScriptExecutor to try clicking the button, it also checks if the button is visible. However, the answer given doesn't do what it tries to do; Clicking doesn't work quite that way. See Solution below to see the correct/working code to click a button using JavaScriptExectutor.
smit9234's answer is exactly what I'm trying to do, although clicking doesn't work that way. To click the button, JS is necessary in this case. However, the question was how to check .Displayed, and that works with the modified XPath he gave me from the code excerpt.
Solution
The XPath of the element (button) is, according to FirePath:
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input
This, however, doesn't work. Selenium simply cannot find it, even though it's clearly there.
THIS XPath, however, does work:
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/span/span
However, it works with reagards to the .Displayed check. It does NOT work with Click(). To be able to click the button, I began with Shubham Jain's code example and created this method in the Driver class, to be able to use JavaScript (with Selenium's JavaScriptExecutor) to click the button:
using OpenQA.Selenium.Interactions;
public static void JSClick (string xpath) {
IWebElement icon = Instance.FindElement(By.XPath(xpath));
Actions ob = new Actions(Instance);
ob.Click(icon);
IAction action = ob.Build();
action.Perform();
}
Looking at the html snippet you posted, it seems like this is a file attachment function. Based on the html structure of the snippet, try using the following xpath:
.//*[#id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/span/span
You should then be able to use the click(); method to click the "Add Attachments"
I assume that clicking on the input doesn't do anything, however you should be able to use the sendKeys(); method for sending the "file path" to the input element.
Use below XPath :-
//input[#type='file' and contains(#data-bind,'upload: addAttachments')]
You can use javascriptexecutorof selenium to click on button. It operated directly on JS of page.
In java :-
WebElement element = driver.findElement(By.id("gbqfd"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);
I don't know more about c# but I believe it something like
IWebElement clicks = driver.FindElement(By.Id("gbqfq"));
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].click();", clicks);
Change the locator in above elements as per your convenience.
Below you will find more details of javascriptexecutor
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
Hope it will help you :)
May be input element is not visible on the page. you may not use displayed function for that element and try with enabled as given below.
public static void WaitForEnabled (string xpath) {
var wait = new WebDriverWait(GCDriver.Instance,
TimeSpan.FromSeconds(10));
wait.Until(driver =>
driver.FindElement(By.XPath(xpath)).Enabled);
}
if the above is not working, you try to click on anchor tag instead of input.
It seems like it's not clickable. It looks like there's some javascript on the page with a function called "uploading()".
since you're button has this on it
enable: !uploading()
just a test to verify if this is actually the cause, put a breakpoint before your click. on the browser dev tools stick a breakpoint in the uploading() function on the javascript file and see what it's returning.
If this is the case you'll have to use the javascript executor to bypass this.
We've got a new page we're automating, and some of the features coming through with the bootstrap template are causing some complications for automation.
Traditionally, with a checkbox or radio button, we use a tag to identify it:
[FindsBy(How = How.CssSelector, Using = "body [autotag='prf_rd_1']")]
private IWebElement myElement;
At which point you can use element.isSelected in Webdriver code to see if it's ticked.
However, with bootstrap devs have changed to use a button which is either active or not active, eg:
<button class="btn" autotag="prf_bt1" btn-radio="availabilityType.key" ng-model="model.availability.time" type="button"> … </button>
<button class="btn **active**" autotag="prf_bt1" btn-radio="availabilityType.key" ng-model="model.availability.time" type="button"> … </button>
(Hmm, not sure how to highly the word active in a code snippet, if anyone knows please feel free to edit)
So, now we can't look for 'isSelected', as it doesn't work like a checkbox.
Does anyone have a code sample for determining whether a button has active class in its css, without using XPATH? Currently we would use the CssSelector as above, and this way elements can move, text can change but as long as that autotag is still there, it's all good. However, I'm unclear how I could do this AND look for other CSS (the class) at the same time to determine if it's active.
If I understand you correctly, you just want a CSS selector that can locate an element that contains a specific value inside a specific attribute, in this case, it's class.
That's easy, an elaborate way to do this would be:
button[class*='active']
The *= is an attribute wildcard, allowing you to say "where A is somewhere inside that attribute's value".
To specifically look for a button that has a class that contains active and have an auto-tag attribute which is set to prf_bt1:
button[class*='active'][auto-tag='prf_bt1']
You can use either of these methods to get status of an element,
getAttribute
getCssValue
isEnabled
You can get more details on these methods at here.