How to check multiple boxes using C# for Selenium - c#

I am having a problem being able to check both of these "checkboxes" when trying to run a test for Selenium using C#.
Here is what I have for the first checkbox and that does work and checks the box.
driver.FindElement(By.XPath("//label[#for='LegitimateCompanyAgreementCheckBox']")).Click();
However if I simply use the label for the other checkbox, which is "TermsOfServiceCheckBox", it does not check the box, but it actually opens up a link because the this checkbox has 2 hyperlinks inside the wording.
For example if I try using:
driver.FindElement(By.XPath("//label[#for='TermsOfServiceCheckBox']")).Click();
This will not check the box, it will actually open up the link for /terms-of-service.
Here is the code for both checkboxes I need to check.
<div class="asp-checkbox">
<span class="checkbox gaClick" data-category="companySignup" data-action="legitimateCompanyChecked" data-noninteraction="true">
<input id="LegitimateCompanyAgreementCheckBox" type="checkbox" name="ctl00$MainContent$LegitimateCompanyAgreementCheckBox">
<label for="LegitimateCompanyAgreementCheckBox">I am a legitimate estate sale company or auction company and have the documents necessary to conduct business in my state (if any).</label>
</span>
<label for="LegitimateCompanyAgreementCheckBox"></label>
<span id="LegitimateCompanyAgreementCheckBox_requredCheckBoxValidor" controltovalidate="LegitimateCompanyAgreementCheckBox" style="color:Red;visibility:hidden;">*
</span>
</div>
<span class="checkbox gaClick" data-category="companySignup" data-action="agreeToTermsChecked" data-noninteraction="true">
<input id="TermsOfServiceCheckBox" type="checkbox" name="ctl00$MainContent$TermsOfServiceCheckBox">
<label for="TermsOfServiceCheckBox">I agree to EstateSales.NET's Terms of Service
and Privacy Policy.
</label>
</span>

We need not click on label tag in this case. The actual checkbox is the input tag.
Try Xpath as :: driver.FindElement(By.Id("LegitimateCompanyAgreementCheckBox")).Click();
or
driver.FindElement(By.XPath("//input[#id='LegitimateCompanyAgreementCheckBox']")).Click();
Following is with Wait:-
var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 120));
WebElement element = wait.until(ExpectedConditions.ElementIsVisible(By.Id("LegitimateCompanyAgreementCheckBox")));
element.Click();

Related

Select radio button with dynamic Id, using CSS selector or Xpath

I'm using C# in Visual Studio to select multiple yes or no questions. Below is the first button to select "yes". The id is not static so can't use that, and I'm not sure which path (CSS or Xpath) is the most efficient for this route.
<div class="row form-group">
<label class="form-label col-md-4 col-lg-3">Was everything satisfactory?</label>
<div class="col-md-7 col-lg-8"><fieldset class="form-group form-radio-group" id="__BVID__385">
<div tabindex="-1" role="group"><div role="radiogroup" tabindex="-1" class="" id="__BVID__386">
<div class="custom-control custom-control-inline custom-radio">
<input type="radio" autocomplete="off" class="custom-control-input" value="true" id="__BVID__387" name="__BVID__386">
<label class="custom-control-label" for="__BVID__387">Yes</label>
</div>
</div>
</div>
Its best to use Xpath when you have dynamic CSS Ids, name.
Based on your requirement ('select multiple yes or no questions') you should have a relation b/w Questions and option.
you can make a Xpath relationship between two elements like in below samples.
//label[contains(.,'Was everything satisfactory?')]/following-sibling::div/fieldset/div/div/div/label[.='Yes' or .='No']
Or
//label[.='Yes' or .='No']/ancestor::div/parent::body/label[contains(.,'Was everything satisfactory')]
Update these Xpaths as per your requirement
If you are better of using XPath or CSS selector comes down to the element at hand and personal preferences. The article linked by E. Wiest has some good points.
In your concrete case, you can either use a CSS selector like :checked
input[type='radio']:checked
if you want to select the subsequent label for instance
input[type='radio']:checked+label
Or some XPath as suggested
//label[contains(text(), "Yes")]/preceding::input
Personally, I also consider XPath to be more powerful but a CSS selector is usually equally adequate.

Unable to perform click action on toggle button in selenium C#

While trying to automate my application, one of the webpage has three toggle button and i need to select the same.
Below the HTML code:
<div class="row">
<div class="col-md-12 ">
<label class="control-label dl-padding-top-5" for="consentToBureau">Do you give consent for Capitec to do a credit bureau enquiry?</label>
<span class="pull-right dl-padding-top-5">
<label class="dl-switch">
<input type="checkbox" checked="checked" value="false" name="consentToBureau" id="BureauConcentInput" required="" onchange="hideErrorById('BureauConcent')" class="dl-border-red">
<span class="dl-slider dl-round"></span>
</label>
</span>
<span class="col-md-12 dl-error-msg dl-top-border-red" id="BureauConcentError">Tick to accept the Bureau Concent</span>
</div>
</div>
<div class="row">
<div class="col-md-12">
<label class="control-label dl-padding-top-5" for="acceptTerms">Do you accept these terms of use?</label>
<span class="pull-right dl-padding-top-5">
<label class="dl-switch">
<input type="checkbox" checked="checked" name="acceptTerms" id="TermsAndConditionsInput" required="" onchange="hideErrorById('TermsAndConditions')" class="dl-border-red">
<span class="dl-slider dl-round"></span>
</label>
</span>
<span class="col-md-12 dl-error-msg dl-top-border-red" id="TermsAndConditionsError" style="">Tick to accept the term of use</span>
</div>
</div>
<div class="row">
<div class="col-md-12">
<label class="control-label dl-padding-top-5">Salary paid into Capitec account?</label>
<span class="pull-right dl-padding-top-5">
<label class="dl-switch">
<input type="checkbox" name="CapitecClient" id="isCapitecClientInput" required="" onchange="hideError(this)">
<span class="dl-slider dl-round"></span>
</label>
</span>
</div>
</div>
The click on the each toggle button lands on span class="pull-right dl-padding-top-5" but this class is similar for all three toggle buttons. But each toggle button has unique 'for' attribute and ID.
Below is the code tried but getting error as unable to locate element.
IWebElement Toggle = driver.FindElement(By.CssSelector("input[id='BureauConcentInput']>span[class='dl-slider dl-round']"));
Toggle.Click();
(or)
IWebElement Toggle = driver.FindElement(By.XPath("//*[#id='BureauConcentInput']/span"));
Toggle.Click();
Kindly suggest the right way to locate the element.
When you hover over the element in your browser tools, do you happen to see any visible/highlighted element? If not, that's the first indication that Selenium wouldn't be able to find it as well.
Your XPath was looking for a span child of the element with an id of "BureauConcentInput", however, the span was a sibling (e.g. it was in the same level of the document tree as the element). There are a few ways to getting to the span, but here are two:
//input[#id='BureauConcentInput']/..//span
//input[#id='BureauConcentInput']/following-sibling::span
Without necessarily seeing the page or knowing what UI framework the switches belong to (dl-slider), this answer would be my best guesstimate as the span doesn't seem to be a clickable element to me in its current state:
driver.FindElement(By.XPath("//input[#id='BureauConcentInput']/ancestor::span")).Click();
Update:
It appears as though your footer navbar at the bottom of the page is above the checkbox you want to select. You can attempt to scroll to the element first and then click. Check your window size - that could be an issue as well.
Here is an extension method for Scroll:
public static IWebElement Scroll(this IWebElement element)
{
IWebDriver driver = ((IWrapsDriver)element).WrappedDriver;
string script = "const elementRect = arguments[0].getBoundingClientRect();" +
"const absoluteElementTop = elementRect.top + window.pageYOffset;" +
"const middle = absoluteElementTop - (window.innerHeight / 2);" +
"window.scrollTo(0, middle);";
((IJavaScriptExecutor)driver).ExecuteScript(script, element);
return element;
}
You can use it right before Click() - e.g. driver.FindElement().Scroll().Click();
If that doesn't work, your next option would be to use the scrollIntoView() js method:
public static void ScrollIntoView(this IWebElement driver, string xpath)
{
((IJavaScriptExecutor)driver).ExecuteScript($"document.evaluate(\"{xpath}\", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.scrollIntoView()");
}
You will have to use this on a separate line - e.g. driver.ScrollIntoView("insert xpath here");
You could do something like the below.
driver.FindElement(By.Id("BureauConcentInput")).Click();
driver.FindElement(By.Id("isCapitecClientInput")).Click();
driver.FindElement(By.Id("TermsAndConditionsInput")).Click();
The one question I meant to ask you is, are the checkboxes all unchecked to begin with? If some are checked you you will want another method to determine the current state so that if you want to check the Terms and Conditions box, and it was already checked, you have no just unchecked it.

How to get TextField for password for FindElement() funcion in Selenium 2

<div>
<input id="Email-hidden" class="hidden" type="email" autocomplete="off" readonly="" value="" spellcheck="false" name="Email">
<label class="hidden-label" for="Passwd">Hasło</label>
<input id="Passwd" class="" type="password" placeholder="Hasło" name="Passwd">
</div>
I'm using FireFoxDriver.
I tried IWebElement password = driver.FindElement(By.XPath("//input[#id='Passwd']")); and also with "*" instead of "input"
I've done it with email, but i can't get into the password text field
Do you have any ideas how to solve it?
Look what textfield i Mean
Your screenshot refers to google login page. The page is using some kind of javascript/ajax, thus the password element will not available instantly, and you need to wait until it's available. It's advised to use WebDriverWait.
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); // after 10 seconds we will throw timeout-exception
var element = wait.Until(wd => wd.FindElement(By.XPath("//input[#id='Passwd']")));
element.SendKeys("password is here");

Selenium C#: Assert verifying if text field is uneditable

I am trying to write a script to assert if the text field in question isn't editable. I was attempting to write a verification hidden = "true", because that is what ultimately is hiding the editable text box. How would I be able to verify something like this? and is this the way I should be handling such a verification? Thanks for your responses in advance.
Here is the html
<div id="ctl00_contentMain_sponsorInfo">
<fieldset>
<legend>
Referral Information
</legend>
<ol>
<li>
The name of your referrer is Name…
</li>
<li>
<input id="ctl00_contentMain_sponsorUsername" class="textBig" type="text" hidden="true" style="width:270px;" req="false" max="30" value="Name" name="ctl00$contentMain$sponsorUsername"></input>
</li>
</ol>
</fieldset>
</div>
As you mentioned the best way to test this scenario is to see if the hidden attribute has a value true
IWebElement element = Driver.FindElement(By.Name("ctl00$contentMain$sponsorUsername"));
if (element.GetAttribute("hidden").Contains("true"))
{
Assert.Pass("Your message");
}
Note: You do have to make sure the element exist. You can use some explicit wait with something like
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementExists(By.CssSelector("something ")));
in order to grab the attribute. This case Selenium will work just fine since you are not interacting with the element.
WebDriver interacts only with the visible elements. You can use JavaScriptExecutor.
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string hiddenStatus = (string)js.ExecuteScript("return document.getElementById('ctl00_contentMain_sponsorUsername').hidden");
hiddenStatus will have true/false

"Element is not currently visible and so may not be interacted with" but another is?

I've created another question which I think is the cause for this error: Why does the Selenium Firefox Driver consider my modal not displayed when the parent has overflow:hidden?
Selenium version 2.33.0
Firefox driver
The code that causes the error:
System.Threading.Thread.Sleep(5000);
var dimentions = driver.Manage().Window.Size;
var field = driver.FindElement(By.Id("addEmployees-password")); //displayed is true
field.Click(); //works fine
var element = driver.FindElement(By.Id(buttonName)); //displayed is false
element.Click(); //errors out
The button that its trying to click:
<div id="addEmployees" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="addEmployeesLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Add Employee</h3>
</div>
<div class="modal-body">
<p class="alert alert-info">
<input name="addEmployees-username" id="addEmployees-username" />
<input name="addEmployees-password" id="addEmployees-password" type="password" />
<input name="addEmployees-employee" id="addEmployees-employee" />
</p>
</div>
<div class="modal-footer">
<button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</div>
</div>
If I change the call to FindElements then I get ONE element, so there isn't anything else on the page.
If I FindElement on a field that occurs right before the button, say addEmployees-employee, then addEmployees-employee is displayed
In the browser itself, it shows up fine, all i need to do is actually click the button and the desired behavior executes, but the webdriver refuses to consider the element displayed
How is it that one field can be considered displayed and the other is not?
The modal with the add button in the bottom right, all the other elements are displayed = true
The window size is 1200x645 per driver.Manage().Window.Size;
The element location is: 800x355y per driver.FindElement(By.Id(buttonName)).Location
The element dimentions are: 51x30 per driver.FindElement(By.Id(buttonName)).Size
The password element location is: 552x233y per driver.FindElement(By.Id("addEmployees-password")).Size
Brian's response was right: use an explicit wait versus Thread.Sleep(). Sleep() is generally brittle, you're losing five seconds needlessly, and moreover it's just a really rotten practice for automated testing. (It took me a long, LONG time to learn that, so you're not alone there.)
Avoid implicit waits. They generally work for new items being added to the DOM, not for transitions for things like a modal to become active.
Explicit waits have a great set of ExpectedConditions (detailed in the Javadox) which can get you past these problems. Use the ExpectedCondition which matches the state you need for your next action.
Also, see Ian Rose's great blogpost on the topic, too.
Selenium WebDriver does not just check for opacity != 0, visibility = true, height > 0 and display != none on the current element in question, but it also searches up the DOM's ancestor chain to ensure that there are no parent elements that also match these checkers.
(UPDATE After looking at the JSON wire code that all the bindings refer back to, SWD also requires overflow != hidden, as well as a few other cases.)
I would do two things before restructuring the code as #Brian suggests.
Ensure that the "div.modal_footer" element does not have any reason for SWD to consider it to not be visible.
Inject some Javascript to highlight the element in question in your browser so you know absolutely you have selected the right element. You can use this gist as a starting point. If the button is highlighted in a yellow border, then you know you have the right element selected. If not, it means that the element selected is located elsewhere in the DOM. If this is the case, you probably don't have unique IDs as you would expect, which makes manipulation of the DOM very confusing.
If I had to guess, I would say that number two is what you are running into. This has happened to me as well, where a Dev reused an element ID, causing contention in which element you're supposed to find.
After discussing this with you in chat, I think the best solution (for now, at least) is to move the button out of the footer for your modal and into the body of it.
This is what you want (for now):
<div class="modal-body">
<p class="alert alert-info">
<input name="addEmployees-username" id="addEmployees-username" />
<input name="addEmployees-password" id="addEmployees-password" type="password" />
<input name="addEmployees-employee" id="addEmployees-employee" />
<button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</p>
</div>
And not this:
<div class="modal-body">
<p class="alert alert-info">
<input name="addEmployees-username" id="addEmployees-username" />
<input name="addEmployees-password" id="addEmployees-password" type="password" />
<input name="addEmployees-employee" id="addEmployees-employee" />
</p>
</div>
<div class="modal-footer">
<button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</div>
I had the same issue of element not visible so cannot be interacted with. it just got solved. i updated my selenium stand alone server. previous version was 2.33.0 and now it is 2.35.0
In my case the element was already present in the page but it was disabled,
so this didn't work (python):
wait.until(lambda driver: driver.find_element_by_id("myBtn"))
driver.find_element_by_id("myBtn").click()
it failed with error:
“Element is not currently visible and so may not be interacted with"
To solve my problem, I had to wait a couple of seconds ( time.sleep(5) ) until the element became visible.
You can also enable the element using JavaScript, a python example:
driver.execute_script("document.getElementById('myBtn').disabled='' ")
driver.execute_script("document.getElementById('myBtn').click() ")

Categories

Resources