There are 2 buttons on the different pages, BEREKEN and VERTEL... Part 1 of code works fine, I can access and click the button, Part 2 of the code does not work. I am not sure why.
Part 1:
<button type="button" class="btn btn-primary" ng-click="next(formstep1, 2);calculate(formstep1, 2);" ng-disabled=""><span>
Bereken
</span></button>
Code used in Selenium:
searchButton = driver.FindElement(By.CssSelector(".btn.btn-primary"));
searchButton.Click();
Part 2:
<button type="button" class="btn btn-primary" ng-click="next(formstep2, 3);calculate(formstep2, 3);" ng-disabled=""><span>
Vertel ons iets over de woning
</span></button>
Code used in Selenium:
searchButton = driver.FindElement(By.CssSelector(".btn.btn-primary"));
searchButton.Click();
I have had this problem when the original element, though not visible, is still part of the DOM. Therefor FindElement will locate the first element in the DOM which is not visible (in this case "Bereken") and return the error. If you search the DOM when the Vertel button is present you will probably find multiple elements with the class you are matching on.
For example the ng-click attribute is unique and you can match on a substring of its value like this:
//Bereken
berekenButton = FindElement(By.CssSelector("button[ng-click*='formstep1']"));
//Vertel
vertelButton = FindElement(By.CssSelector("button[ng-click*='formstep2']"));
^ matches on prefix, # matches on suffix, * matches on substring.
Related
Button type is Input.
<input type="submit" value="Send" class="wpcf7-form-control wpcf7-submit btn solid">
I want to click this Button using code, try to click on Button By ClassName.
My code is as per below but not get any success.
string url1 = "myUrl";
IWebDriver driver = new ChromeDriver(Application.StartupPath);
driver.Navigate().GoToUrl(url1);
driver.FindElement(By.ClassName("wpcf7-form-control .wpcf7-submit btn solid")).Click();
This throws the following error :
Compound class names not allowed. Cannot have whitespace in class name. Use CSS selectors instead. and not use single class because there is a other class with same name.
driver.FindElement(By.XPath("//input[#type='submit']")).Click();
I would try to avoid using XPath, Instead I would add an Id to your input.
The reason being XPath is more likely to be changed over time than Id.
Also if you add another element with the same HTML, selenium will not be able to differentiate between them and will always select the first element.
Using Id also makes your code more readable.
You can try this:
<input type="submit" value="Send" Id="YourButtonId" class="wpcf7-form-control wpcf7-submit btn solid">
And
driver.FindElement(By.Id("YourButtonId")).Click();
I'm having some issues with automating a website using PhantomJS/Selenium WebDriver in C#.
Part of the website has a check on addresses; entering in an address it can't verify (or just not entering an address at all) brings up a modal div with buttons in it. Depending on the situation, it will either give you the closest address, or the option to just continue without an address, but the button always has the same id. The HTML for this div (for the "no address entered" version) is here:
<div id="confirmAddress" class="col-xs-5 active-popupbox">
<div class="row vert-offset-top-2">
<p style="margin-left:55px;" class="h3">No Customer Address Provided</p>
<br>
<div style="margin-left:42px;margin-bottom:0px;" class="modal-body">No Customer Address Was Entered. We recommend having the Customer provide an address.</div>
<br>
<div class="col-xs-6">
<button type="submit" class="btn btn-default" style="margin-left:45px;width:200px;" id="confirmBack" name="confirmBack" align="center">Enter Address</button> </div>
<div class="col-xs-6">
<button type="submit" class="btn btn-default" id="confirmPopUp" name="confirmPopUp" align="center">Proceed with No Address</button>
</div>
</div>
</div>
The button I need to click is the last button, <button type="submit" class="btn btn-default" id="confirmPopUp" name="confirmPopUp" align="center">Proceed with No Address</button>
However, despite seemingly being able to find the element in my code and calling Click() on it, grabbing screenshots show that it apparently doesn't register the click since the modal popup stays on the page and the next part errors out due to not finding the elements I'm asking it to find.
Here is the relevant portion of my code:
File.WriteAllText(#"C:\Users\user1\Documents\Testing\source0.html",
_driver.PageSource);
_driver.FindElementById("contactinfo_next").Click();
if (_driver.FindElementByClassName("active-popupbox").Displayed)
{
_driver.GetScreenshot().SaveAsFile(#"C:\users\user1\documents\testing\screenshot01.png", ImageFormat.Png);
_driver.FindElementById("confirmPopUp").Click();
}
_driver.GetScreenshot().SaveAsFile(#"C:\users\user1\documents\testing\screenshot02.png", ImageFormat.Png);
I use the class name to find the div since they apparently have different id's depending on whether the address was "not provided" or "wasn't verifiable but a close match was found", but the class is always the same.
I have PhantomJS grabbing the source before clicking the "contactinfo_next" button, which is what brings up the modal div, and have confirmed that no div with class "active-popupbox" exists before the contactinfo_next button is clicked. "screenshot01.png" does get saved, which means that it is finding the div... but it still doesn't register the button click.
I have tried clicking other elements in the div to bring it "into focus", calling Click() twice on the button, assigning the div to a variable called div and then finding the button using div.FindElements(By.Id("confirmPopUp")) and clicking on each element in the collection, nothing has worked.
Has anyone else run into this issue?
Thanks!
EDIT: I'm using the following NuGet packages for this:
PhantomJS
Selenium WebDriver PhantomJS cross platform
Selenium WebDriver Support Classes
Selenium WebDriver
Okay so I don't know if this is specific to this site that I'm trying to automate, but resizing the PhantomJS viewport worked - in my screenshots, the modal's buttons were overlapping each other. Not sure why it matters but this is what ended up solving my problem. ¯\_(ツ)_/¯
To resize the viewport (requires System.Drawing):
_driver.Manage().Window.Size = new Size(1920, 1080);
Hope this helps anyone else who has a similar problem in the future
I am new to Selenium. In a specific scenario I am not able to catch an input element. below is the code:
<ul class = "form1">
<li class="firstName">
<input placeholdervalue="First name" tabindex="1" placeholder="First name" class="text" placeholdevalue="First name" data-input-rule="name" data-value-rule="required" maxlength="20" type="text">
</li>
</ul>
I want to locate input element. I tried locating it using locator By.ClassName, By.CssSelector("input[class='text placeholder']") and also tried:
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("input[className='text' and placeholdevalue='First name'"))).SendKeys("Vipul");
but input element is not getting selected.
Please let me know the right way to select input element.
I would use a dot notation to match the classes of ul, li and input elements:
By.CssSelector("ul.form1 li.firstName input.text")
If the element still cannot be found, then there could two most commonly met reasons:
it is inside an iframe and you need to switch to it
you need to wait for the element to appear
I'll expand these items in case you would still have problems finding the element.
Thanks for the reply.
It worked with this,
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(20));
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("ul.form1 li.firstName input.text"))).SendKeys("Vipul");
Is this the right way of using wait?
Also, can anybody point out to resources which explain working with frames using selenium webdriver?
-Amit
My end goal is to be able to click Yes or No on a webpage.
Using fire bug I can see the Yes and No buttons reside in a class called "btn-group"
<div class="btn-group btn-group-default answer-toggle" aria-label="..." role="group">
<button class="btn ng-pristine ng-valid active btn-secondary ng-touched" btn-radio="true" ng-model="consultation.previousSoundVoid" ng-class="{'btn-secondary': consultation.previousSoundVoid}" type="button">
Yes
</button>
<button class="btn ng-pristine ng-untouched ng-valid" btn-radio="false" ng-model="consultation.previousSoundVoid" ng-class="{'btn-secondary': consultation.previousSoundVoid == false}" type="button">
No
</button>
</div>
I think I could find Element by XPath but I am trying to improve my Selenium skill.
I am hoping there is a way to first find the "btn-group" class then somehow choose Yes or No within that.
Or be able to create variables for both the Yes and No options. If I do:
var button = Driver.Instance.FindElements(By.ClassName("btn"));
It returns 21 options. I found that:
button[15].Text returns "Yes"
button[16].Text returns "No"
Instead of having to look through all 21 results and worrying about if the index changes, can I search the results by text somehow?
The best way is to identify those element using text and xpath since they do not have any unique id
//button[.='Yes']
Desperate to use cssSelector?
.btn.ng-pristine.ng-valid.active.btn-secondary.ng-touched
since it is a compound class
You can also go for nth-child() with css
[role='group']>button:nth-child(1)
whereas 2 will let you select the button with text No
Case 1: When answer-toggle is unique in the HTML page
Driver.Instance.FindElements(By.XPath("//div[contains(#class,'answer-toggle')]//button[contains(text(),'Yes')]")).Click();
This will first locate a div that has answer-toggle in its class name and the find a button that has text Yes
Case 2: answer-toggle is not unique in your HTML page the you can use the complete class name as follows
Driver.Instance.FindElements(By.XPath("//div[#class='btn-group btn-group-default answer-toggle']//button[contains(text(),'Yes')]")).Click();
or
Driver.Instance.FindElements(By.XPath("//div[#class,'btn-group btn-group-default answer-toggle']//button[contains(text(),'Yes')]")).Click();
Case 3: If there is only one button in your HTML page that has text "Yes"
Driver.Instance.FindElements(By.XPath("//button[contains(text(),'Yes')]")).Click();
Same thing applies for No button. You just have to replace Yes with No.
There are definitely multiple options to locate the buttons, but I think that answer-toggle class sounds a good thing to rely on:
var buttons = Driver.Instance.FindElements(By.CssSelector("div.answer-toggle button.btn"));
My html looks this way:
<button type="submit" class="img" name="save" value="0">Speichern</button>
<button type="submit" class="img" name="save" value="1">Speichern und Schließen</button>**
When i parse the request by using Page.Request.Form[i] the value of the key "save" is "Speichern und Schließen" and not 1 an I don't see any possibility to get the correct value. Is there a way to get the correct value (0 or 1 and not "Speichern und Schließen")?
The tag defines a push button.
Inside a button element you can put content, like text or images. This is the difference between this element and buttons created with the input element.
Always specify the type attribute for the button. The default type for Internet Explorer is "button", while in other browsers (and in the W3C specification) it is "submit".
http://www.w3schools.com/tags/tag_button.asp