Unable to perform click action on toggle button in selenium C# - 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.

Related

Selenium cannot find Cookie Accept button

Does anybody have any ideas why Selenium cannot find the Cookie Accept button defined below. I have tried a number of methods and wait strategies but nothing seems to work? When the Cookie banner comes up the main window behind greys out. URL: https://portal.everybody.org.uk/lhweb/identity/login?
HTML
<div class="xn-auth-form xn-login-form">
<div id="IJFIX74FEMS85U04VNHN9XD1G6T36PB6" class="xn-component" style=""><xn-cookiebanner-component params="{"newcomponent":"true"}">
<div data-bind="css: { 'xn-modal': isModal, 'xn-visible': isVisible}" class="xn-modal xn-visible">
<div class="xn-cookie-banner-header">
<div class="xn-cookie-banner-name">
<div class="xn-cookie-banner-title">Cookies Policy</div>
<div class="xn-name" style="word-break:keep-all">
<span> Cookies created and stored for this site are fundamental to its functionality and performance. Cookies are not used for marketing purposes, nor are any personally identifiable cookies stored.</span>
</div>
</div>
<div class="xn-buttons">
<button class="xn-button xn-cta" data-bind="click: confirm"><span data-bind="text: confirmationYes">Accept</span></button>
</div>
</div>
</div></xn-cookiebanner-component></div>
<form name="form" method="post" action="/lhweb/identity/login?signin=d367e21d0f8af2faf156cb566b51b78a" novalidate="novalidate">
<input type="hidden" name="idsrv.xsrf" value="GgTgFinGkFku2cMRPEcwMy9qv4fh3dUGJV26u-jv6Os0VF-1gFmP_JNHPRRz_lywbkTZ4XAaUs5atoqRHKu56gAHU_lfv-ZZplq476ZcpfQ" autocomplete="off">
C#
IWebElement button1 = driver.FindElement(By.XPath("/html/body/div[3]/div/div/div/xn-cookiebanner-component/div/div/div[2]/button"));
IWebElement button2 = driver.FindElement(By.Name("Accept"));
You can use the below locators:
XPATH:
.//*[#class='xn-button xn-cta' and #data-bind='click: confirm']
CSS SELECTOR:
.xn-cookie-banner-header .xn-button.xn-cta

How to check multiple boxes using C# for Selenium

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();

How do I check checkboxes on a page using IWebDriver in selenium C#?

I need to select multiple checkbox to Submit the form and the following code response in HTML format.
Here i have 4 check box. when i have launch the browser then first 3 checkbox is always checked and last one always Unchecked. Now i want first 3 checkbox should be uncheck and last one will be checked .how do i this with selenium c#
<div class="formSubSection">
<h4>
Details:</h4>
<div class="formField">
<div class="formFieldCheckBox">
<span title="Imported selector"><input id="aul00_ContentPlaceHolder1_aul02_chkVan" type="checkbox" name=aul00$ContentPlaceHolder1$ctl02$chkVan" checked="checked"><label for="aul00_ContentPlaceHolder1_ctl02_chkVan"> Is the Helpdesk?</label></span>
</div>
</div>
<div class="formField">
<div class="formFieldCheckBox">
<span title="home selector"><input id="aul00_ContentPlaceHolder1_ctl02_chkHome" type="checkbox" name="aul00$ContentPlaceHolder1$ctl02$chkHome" checked="checked"><label for="ctl00_ContentPlaceHolder1_aul02_chkMotorHome"> home?</label></span>
</div>
</div>
<div class="formField">
<div class="formFieldCheckBox">
<span title="Imported selector"><input id="aul00_ContentPlaceHolder1_ctl02_chkHorseBox" type="checkbox" name="aul00$ContentPlaceHolder1$aul02$chkHorseBox" checked="checked"><label for="aul00_ContentPlaceHolder1_aul02_chkHorseBox"> Is the vehicle?</label></span>
</div>
</div>
<div class="formField">
<div class="formFieldCheckBox">
<span title="car selector"><input id="aul00_ContentPlaceHolder1_aul02_chkCar" type="checkbox" name="aul00$ContentPlaceHolder1$ctl02$chkCar" checked="checked"><label for="ctl00_ContentPlaceHolder1_aul02_chkCar"> Is the Driver?</label></span>
</div>
</div>
</div>
It depends are you web elements have dynamical id and names.
I wold suggest solution to get all 4 elements (according to your post, I do not know rest of the DOM) and just to iterate trought the for loop. Something like
for(int i=0;i<driver.findElements(By.Class("formFieldCheckBox"));i++)
{
if(i>=5)
{
if(!driver.findElements(By.Class("formFieldCheckBox")).get(i).isSelected())
driver.findElements(By.Class("formFieldCheckBox")).get(i).click();
}
else
{
if(driver.findElements(By.Class("formFieldCheckBox")).get(i).isSelected())
driver.findElements(By.Class("formFieldCheckBox")).get(i).click();
}
}
This is the Java solution, but almost same code is for C#. Try it and let me know did it help.

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.

How to check in razor view if field is valid?

I use bootstrap with ASP.NET Core and to indicate form field validation errors i want to add has-errors class to form-group div when given field has an error. The view looks like that:
<div class="form-group">
<label asp-for="Fragment.Content" class="col-lg-2 control-label "></label>
<div class="col-lg-10">
<textarea asp-for="Fragment.Content" class="form-control content-editor"></textarea>
<span class="help-block">A longer block of help text that breaks onto a new line and may extend beyond one line.</span>
<span asp-validation-for="Fragment.Content"></span>
</div>
</div>
I would like to do something like:
<div class="form-group" asp-add-class-if-error="has-errors" for-field="Fragment.Content"/>
I know i can write my own tag helper, however i am curious if there is a built-in solution.
I found that you can use:
#using Microsoft.AspNetCore.Mvc.ModelBinding
#if(ViewData.ModelState.GetFieldValidationState("Fragment.Content") == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
// something here
}

Categories

Resources