Selenium/Chrome - Selecting a Checkbox Input without an ID - c#

Thanks for the assistance in advance.
New to Selenium/Chrome and have had a good run of it until I hit a specific scenario.
I have a modal the contains 5 fields (3 drop-downs and a UL with 2 LI)
Each LI contains a label and input-checkbox.
All of the drop-downs have an Id so they were easy to manipulate with FindElement(By.Id("ID")).SelectText("TEXT");
However the Li's within the Ul do not have them and I have gotten NoSuchElementExceptions with every attempt to locate them.
<ul id="CertificatesToAdd" name="CertificatesToAdd" class="nav nav-list
checkbox-list add-certificate-required" data-trigger="manual" data- placement="top">
<li>
<label class="checkbox" style="font-weight:normal !important;">
<input type="checkbox" class="add-certificate-checkbox"
value="171">
Certificate of Registration
</label>
</li>
<li>
<label class="checkbox" style="font-weight:normal !important;">
<input type="checkbox" class="add-certificate-checkbox"
value="172">
Collection Agency License
</label>
</li>
</ul>
I have tried both of the FindElement lines below the todo and both return
OpenQA.Selenium.NoSuchElementException: Unable to locate element
new SelectElement(BaseTest.Driver.FindElement(By.Id("AddCertificateCountry")))
.SelectByText("Canada");
new SelectElement(BaseTest.Driver.FindElement(By.Id("AddCertificateState")))
.SelectByText("Alberta");
//TODO: correct input value for checkbox
new SelectElement(BaseTest.Driver.FindElement(By.CssSelector(
"#CertificateToAdd>li:nth-child(2)"))).SelectByValue("172");
new SelectElement(BaseTest.Driver.FindElement(By.XPath(
"//*[#id="CertificatesToAdd"]/li[2]/label/input"))).SelectByValue("172");
Any ideas would be helpful and appreciated.

To click on the checkbox associated with the <label> tags you can use the following solutions:
Certificate of Registration:
BaseTest.Driver.FindElement(By.XPath("//label[#class='checkbox'][normalize-space()='Certificate of Registration']/input[#class='add-certificate-checkbox']")).Click();
Collection Agency License:
BaseTest.Driver.FindElement(By.XPath("//label[#class='checkbox'][normalize-space()='Collection Agency License']/input[#class='add-certificate-checkbox']")).Click();

Here you're targeting the li:
new SelectElement(BaseTest.Driver.FindElement(By.CssSelector(
"#CertificateToAdd>li:nth-child(2)"))).SelectByValue("172");
Here your xpath means that input is a child of the label rather than a sibling:
new SelectElement(BaseTest.Driver.FindElement(By.XPath(
"//*[#id="CertificatesToAdd"]/li[2]/label/input"))).SelectByValue("172");
I think you can probably figure it out from there.

Related

Xpath grabbing separate text in between link nodes

I'm currently retrieving text from inside <a> tags utilizing HtmlAgilityPack:
foreach (HtmlNode node in html.DocumentNode.SelectNodes("//div[#class='acTrigger']/a"))
{
lblTest1.Text = lblTest1.Text + ", " + node.InnerText.ToString();
}
and the web code looks like this
<li>
<div class="acTrigger">
<a href="/16014988/d/" onclick="return queueRefinementAnalytics('Category','Battery')">
Battery <em> (1)</em>
</a>
</div>
</li>
<li>
<div class="acTrigger">
<a href="/15568540/d/" onclick="return queueRefinementAnalytics('Category','Brakes')">
Brakes <em> (2)</em>
</a>
</div>
</li>
<li>
<div class="acTrigger">
<a href="/11436914/d/1979-honda-ct90-cables-lines" onclick="return queueRefinementAnalytics('Category','Cables/Lines')">
Cables/Lines <em> (1)</em>
</a>
</div>
</li>
Currently it is returning to me: Battery (1), Brakes (2), Cables/Lines (1) which is obviously all of the inner text. What I would like to know is how to split the two bits apart so I can store them each in a list for later usage. Something along the lines of: Battery, 1, Brakes, 2, Cables/Lines, 1 so as they are returned to me I can just toss them into lists.
The text in between the <em> tags are the number of results on the page that the <a> is taking you to. I could just parse the entire string after getting the line of text, but I feel as if there is a method to do this automatically with XPath and return one piece at a time for me to handle and store. I am very new to XPath and have been attempting to solve this for multiple days myself with no avail. Any help would be greatly appreciated.
Change your XPath expression to //div[#class='acTrigger']/a//text()[normalize-space()] separate text nodes.

Separated elements overlooked, now combined

Currently in the process of learning MVC and I think it's interfering with HTML code. I have just a basic navigational menu as a list and two <li> items seem to combine into one. Any way to make sure the two are separated when live?
#if ((Request.Url.AbsolutePath.ToString().ToLower() != "/home/index") && (Request.Url.AbsolutePath.ToString() != "/"))
{
<nav data-spy="affix" data-offset-top="500" style="border-radius:0px; left: 0" ng-hide="sideBar" id="nav">
<img src="~/Content/images/open.png" ng-model="sideBar" id="sideBarOpen" style="left:0px; top:0;"/>
<div id="sideBar" style="left: -200px">
<ul>
<li> Home </li>
<li><br /></li>
<li>About Me</li>
#############
<li>Experience</li>
<li>Resume</li>
############ These two seem to be recognized as 1 <li> and not two.
<li>Contact</li>
</ul>
<img src="/Content/images/myPic.jpg" />
</div>
</nav>
<div id="sideBarBack" style="width:0%;">
</div>
}
Youre missing a quotation mark in the id="> part. This is not a valid html so your wen browser tries to workaround that resulting in the two elements combined.
To fix that instead of:
<li>Experience</li>
use a correct tag attribute id="":
<li>Experience</li>

Using Selenium (C#) Select an item from a drop down by text

I have been trying to figure this out and could use some help from Selenium experts here. I have a dropdown on my page that I am trying to select an option for from the test and I cant seem to get this right.
I have tried the following example I see commonly for select Item. The options always show text as an empty string "" even though I can see in the HTML markup the option text is there.
wait.Until(d => ExpectedConditions.ElementExists(By.Id("Cars")));
var carStatusDropDown = new SelectElement(_driver.FindElement(By.Id("Cars")));
carStatusDropDown.SelectByText(filter.CarStatus);
I figured its because maybe the options are not visible to the browser, so then I tried to click on the button next to dropdown (Bootstrap) so it would be open before it selects the text
wait.Until(ElementIsClickable(By.XPath("/html/body/div[2]/div[2]/div/div[2]/div[1]/div/form/fieldset/div[3]/div/div[1]/span[2]/div/div/span")));
IWebElement ddlButton = _driver.FindElement(By.XPath("/html/body/div[2]/div[2]/div/div[2]/div[1]/div/form/fieldset/div[3]/div/div[1]/span[2]/div/div/span"));
ddlButton.Click();
wait.Until(d => ExpectedConditions.ElementExists(By.Id("Cars")));
var carStatusDropDown = new SelectElement(_driver.FindElement(By.Id("Cars")));
carStatusDropDown.SelectByText(filter.CarStatus);
I can see the ddlButton opens the dropdown but am still getting >OpenQA.Selenium.ElementNotVisibleException
when it tries to SelectByText. In VS I can see the the options text still shows "" and the Displayed property is false for them. How can I find the options, Any feedback would be appreciated, I am posting the HTML below whats weird is that there are two drop downs one as a <ul> and a <select> one the appears below, I am trying to access the <select> one in the test code. The select one in firebug shows up as faded in the markup?!?
HTML:
<div class="combobox-container">
<input type="hidden" name="Estimate.EstimateStatus" value=" ">
<input type="text" autocomplete="off"
placeholder="All"class="combobox">
<ul class="typeahead typeahead-long dropdown-menu" style="top:
112px;left: 445.117px; display: none;">
<li data-value="Approved" class=""><a href="#"><strong>
</strong>A<strong></strong>p<strong></strong>p<strong>
</strong>r<strong></strong>o<strong></strong>v<strong>
</strong>e<strong></strong>d<strong></strong></a>
</li>
<li data-value="Hold" class=""><a href="#"><strong>
</strong>H<strong>
</strong>o<strong></strong>l<strong></strong>d<strong></strong>
</a>
</li>
<li data-value="In Progress"><a href="#"><strong></strong>I<strong>
</strong>n<strong></strong> <strong></strong>P<strong>
</strong>r<strong></strong>o<strong></strong>g<strong>
</strong>r<strong></strong>e<strong></strong>s<strong>
</strong>s<strong></strong></a>
</li>
<li data-value="Not Reviewed" class="active">
<a href="#"><strong></strong>N<strong>
</strong>o<strong></strong>t<strong></strong> <strong>
</strong>R<strong></strong>e<strong></strong>v<strong>
</strong>i<strong></strong>e<strong></strong>w<strong>
</strong>e<strong></strong>d<strong></strong></a>
</li>
<li data-value="Rejected"><a href="#"><strong></strong>R<strong>
</strong>e<strong></strong>j<strong></strong>e<strong>
</strong>c<strong></strong>t<strong></strong>e<strong>
</strong>d<strong></strong></a>
</li>
</ul>
<span class="add-on btn dropdown-toggle" data-dropdown="dropdown">
<span class="caret"></span>
<span class="combobox-clear">
</span>
</div>
<select id="Cars" class="combobox"
onchange="javascript:OnCarsStatusChanged();" style="display: none;">
<option value=" " selected="selected">All</option>
<option value="3ad8cf29-f0b7-441f-
81bc-c5cfe7c0d73d">Approved</option>
<option value="19b573c8-fc88-4abe-9c19-9ffc580a1ffe">Hold</option>
<option value="e3a8b2bd-c3eb-47c3-95e7-f15da2f3d25b">In
Progress
</option>
<option value="962e4bce-1ca5-404f-b7a0-6a3a42ad91a0">Not
Reviewed
</option>
<option value="c110e83a-5a93-4553-
a907-02a47ca97467">Rejected</option>
</select>
It does seems like there is another action depended on this dropdwon. By default this dropdown is NOT visible. So, best will be to see what previous action makes it visible.
However, another workaround can be to execute a simple javascript, make the dropdown list visible and select the intended element you need.
removeAttribute should remove the style attribute to make the list visible.
((IJavaScriptExecutor)Driver).ExecuteScript("document.getElementById('Cars').removeAttribute('style');");
By id = By.Id('Cars');
var carStatusDropDown = new SelectElement(_driver.FindElement(id));
carStatusDropDown.SelectByText(filter.CarStatus);

Selenium select not working on some objects

I am having trouble with setting a Select object through Selenium. This Select object has some JavaScript associated with it that populates it's 'options' when the page is loaded. I believe this is causing it to behave differently. Normally I can set a Select object with the following:
SelectElement sel = new SelectElement(ele);
sel.SelectByText(value);
With this specific object, the same code will execute successfully (no exceptions thrown), however the value does not get set. Note that I put sleeps and re-trys in and I am confident the Select object is fully loaded before the code is executed (otherwise an exception would occur).
The two Select objects giving me this trouble also appear different from standard html Select objects which reinforces my belief that they are not standard Selects. The first two drop downs in this image are the troublesome ones, while the rest work as expected:
Unfortunately this is a private page that I cannot give you access to, but hopefully this HTML snippet is enough:
<h3>Details of your primary qualification, examination, or assessment</h3>
<script type="text/javascript" src="/assets/js/jquery.ui.widget.js"></script>
<script type="text/javascript" src="/assets/js/jquery.ui.position.js"></script>
<script type="text/javascript" src="/assets/js/jquery.ui.selectmenu.js"></script>
<script type="text/javascript">
j$(document).ready(function () {
j$(".field [id$='_drpInstitution']").selectmenu();
j$(".field [id$='_drpName']").selectmenu();
j$(".field [id$='_drpInstitution']").change(function () {
__doPostBack('content_0$ucCourse$drpInstitution', '');
});
j$(".field [id$='_drpName']").change(function () {
__doPostBack('content_0$ucCourse$drpName', '');
});
});
</script>
<div class="field">
<label for="content_0_ucCourse_drpInstitution" id="content_0_ucCourse_lblInstitution">Name of Australian institution (university/college/examining body):<em class="required">*</em></label>
<select name="content_0$ucCourse$drpInstitution" id="content_0_ucCourse_drpInstitution" class="field-l Institution">
<option value="-1">- Select -</option>
<option selected="selected" value="Australian Catholic University">Australian Catholic University</option>
<option value="Avondale College of Higher Education">Avondale College of Higher Education</option>
<option value="Central Queensland University">Central Queensland University</option>
<option value="Charles Darwin University">Charles Darwin University</option>
<option value="Other">- Other -</option>
</select>
<em class="hint">If your institution does not appear in the list, please select 'Other' and enter your institution in the text box that appears.</em>
<span id="content_0_ucCourse_vldInstitution" style="display:none;"></span>
</div>
When I inspect the Dropdown box, instead of getting the Select object I get the following Span:
<span>
<a class="ui-selectmenu ui-widget ui-state-default ui-selectmenu-dropdown ui-state-active ui-corner-top" id="content_0_ucCourse_drpInstitution-button" role="button" href="#nogo" tabindex="0" aria-haspopup="true" aria-owns="content_0_ucCourse_drpInstitution-menu" style="width: 460px;" aria-disabled="false">
<span class="ui-selectmenu-status">Australian Catholic University</span>
<span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span>
</a>
</span>
When I inspect the resulting drop down list, I get a UL located in the footer:
<div class="ui-selectmenu-menu" style="z-index: 2; top: 786px; left: 741px;">
<ul class="ui-widget ui-widget-content ui-selectmenu-menu-dropdown ui-corner-bottom" aria-hidden="true" role="listbox" aria-labelledby="content_0_ucCourse_drpInstitution-button" id="content_0_ucCourse_drpInstitution-menu" style="width: 460px; height: 189px;" aria-disabled="false" tabindex="0" aria-activedescendant="ui-selectmenu-item-562">
<li role="presentation" class="">- Select -</li>
<li role="presentation" class="ui-selectmenu-item-selected">Australian Catholic University</li>
<li role="presentation" class="">Avondale College of Higher Education</li>
<li role="presentation">University of Wollongong</li>
<li role="presentation">Victoria University</li>
<li role="presentation" class="ui-corner-bottom">- Other -</li>
</ul>
</div>
None of this appears in the Page Source, so it is all generated on the fly. I am currently working around the Select issue by clicking the hyperlink object id=content_0_ucCourse_drpInstitution-button and then clicking the hyperlink object text=Australian Catholic University
Any better workarounds would be appreciated.
As you've already discovered, the dropdown is not represented by select->option in this case.
Handle it as is - find the a element by Id (which would be your "select"), click it to open up the dropdown; then, find the a element with text "Australian Catholic University" (which would be your "option") by link text:
IWebElement select = driver.FindElement(By.Id("content_0_ucCourse_drpInstitution-button"));
select.Click();
IWebElement option = select.FindElement(By.LinkText("Australian Catholic University"));
option.Click();
We can also think about the problem differently - if they've hidden the select element from us - we'll just make it visible. Cannot guarantee it would work since I cannot reproduce the problem:
((IJavaScriptExecutor)Driver).ExecuteScript("arguments[0].hidden = false; arguments[0].style.visibility='visible';", element);
where element is pointing to your select tag.
Then, after making the element visible try using SelectByText():
element.SelectByText("Australian Catholic University");

MVC how to auto select check boxes whos Label contains a word that user specifies

So I've got this popup in my site with a list of checkboxes for filtering purposes. The List can be anywhere from a couple items to a hundred items. Now say the user wants to only select check boxes with the word "create" in it's label. Going through a hundred check boxes looking for creates is unruly and no ones going to want to do it. What I'm thinking is implementing a text box input at the bottom of the popup where the user can input a word, hit select and in the list of checkboxes, only the items that contain that word will be checked.
The first idea that came to mind to do this is use jquery have the button relate to a controller function which will reassess the view model based on that users string. But I'm not if that the best solution. Is there a way to do this in just the view?
Try something like this:
Your HTML:
<div class="box">
<input type="checkbox" name="check">
<label>Create</label>
</div>
<div class="box">
<input type="checkbox" name="check">
<label>Other value</label>
</div>
<div class="box">
<input type="checkbox" name="check">
<label>Create user</label>
</div>
Your JQuery code:
$(function(){
$('.box').each(function(){
var box = $(this);
if ($('label', box).html().toLowerCase().indexOf("create") > 0) {
$('input[type=checkbox]', box).attr('checked', 'checked');
}
else $('input[type=checkbox]', box).removeAttr('checked');
});
});
This is a better solution suggested by #AnoopJoshi
$("label:contains('Create')").closest(".box").find("input[type=checkbox]").prop(‌​"checked", true);
I hope this help!

Categories