How to find a nested selenium WebElement in C# with LINQ? - c#

I've been learning about LINQ and am trying to apply it to finding certain web elements on the page with selenium.
I have an angular site which displays a table made up of divs. All the rows in a column, including the header, have the same attributes (e.g. css selector/classname etc).
I want to find all the input boxes within a column that are visible, and came up with this...
var applyBoxes2 = from box in driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
where box.Text != "Apply?"
select box;
var clickableBox = from box in applyBoxes2
where box.FindElement(By.TagName("input")).Displayed == true
select box.FindElement(By.TagName("input"));
The first query is required as the first row is the header, and doesn't contain an input field. If I don't have this query my second query will fall over when trying to do the findelement = "input".
Does anybody know if I can combine these 2 statements? So first I would filter out the header, then I would find each input box within each div.
Any thoughts on how else this could be improved on would be welcomed.
Many thanks,

Use the && operator, it short circuits when it doesn't pass the 1st statement. So in your case it won't try to find an element if the text is Apply?.
var clickableBox = from box in driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
where box.Text != "Apply?" && box.FindElement(By.TagName("input")).Displayed == true
select box.FindElement(By.TagName("input"));

You can do something like this
var clickableBox = driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
.Where(box => box.Text != "Apply?")
.Select(box => box.FindElement(By.TagName("input")))
.Where(boxElement => boxElement.Displayed);

You can use let clause,
to perform inner clause.
Code will be like this:
var applyBoxes2 = from box in driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
let clickableBox = box.FindElement(By.TagName("input"))
where box.Text != "Apply?" && clickableBox?.Displayed = True
select clickableBox;

Related

Check if Combo box is empty C#

I am trying to check if a combo box is empty using C# in a Windows Application Form. Below are two possible ways:
if (string.IsNullOrEmpty(comboBox1.Text))
if (comboBox1.SelectedIndex == -1)
In order to ensure that the user would ONLY select a value from the drop down and NOT write it s own answer, which is the best approach?
From my research the second method (if (comboBox1.SelectedIndex == -1)) will satisfy my needs. Am l right?
If your concern is only making sure that users choose an item from the list available, simply change your combobox's DropDownStyle to DropDownList
or if you want to allow them to type but then ensure it is on the list, you can do something like this:
var txt = comboBox1.Text;
if(string.IsNullOrEmpty())
return;
var test = comboBox1.Items?.OfType<string>().ToList().Any(x => x?.Trim() == txt?.Trim());
so if test is false, it means what they have selected/typed does not exist in list of available items
for combobox you can use this code below to check if it's empty or not
if(comboBox1.Items.Count == 0 )
{
// your code
}
This is what i try and it 's work. Feel free to comment:
if (comboBox1.SelectedIndex > -1 )

Checking a box by label or index with a variable in Selenium C#

I have a form that automates tasks on a page by user input but I'm having trouble interacting with an element on the page. It's a CheckBoxList with dynamic names and number of elements. The HTML looks like this:
<ol id="ratingModification_SupplierContact_content">
<label><input type="checkbox" name="searchQuery.vehicleGroups[0].isSelected" value="on" class="vehGrp"> abcd ef (ghi)</label> <br>
<label><input type="checkbox" name="searchQuery.vehicleGroups[1].isSelected" value="on" class="vehGrp"> jklm no (pqr)</label> <br>
</ol>
Where " abcd ef (ghi)" is the label of the first checkbox.
I already have a button that extracts the labels from the elements and puts them in an array designed with help from users here:
var vehicleGroupInputElements = Builder.Driver.FindElements(By.ClassName("vehGrp"));
var vehicleGroupNames = vehicleGroupInputElements.Select(f => f.FindElement(By.XPath(".."))).Select(f => f.Text).ToArray();
And I populate my form's CheckedListBox with:
vehicleGroupList.Items.AddRange(vehicleGroupNames);
But when I try to send the user selection back to the page I run into issues. I have tried selecting based on index via IndexOf() and the ClassName but can't figure out the syntax to make it work. Failed example:
foreach (int userChecks in vehicleGroupList.CheckedItems)
{
int checkIndex = vehicleGroupList.Items.IndexOf(userChecks);
var checkTarget = Builder.Driver.FindElements(By.ClassName("vehGrp"));
checkTarget.IndexOf(checkIndex).Click();
}
Which won't compile because int checkIndex cant convert to an IWebElement. I have also tried to build a string to address the index with xpath but it can't find the element or throws a no compound names exception. Failed example:
foreach (int userChecks in vehicleGroupList.CheckedItems)
{
int checkIndex = vehicleGroupList.Items.IndexOf(userChecks);
string elementTarget = "searchQuery.vehicleGroups[" + checkIndex + "].isSelected";
var checkTarget = Builder.Driver.FindElements(By.XPath(string.Format("//option[contains(text(), {0}]", elementTarget))).Click();
}
I've also tried to find the element by label via xpath similar to the above but it never finds it. What is the correct way to find the elements and check them?
When you want to click on each checkbox you can use :
var vehicleGroupInputElements = Builder.Driver.FindElements(By.ClassName("vehGrp"));
foreach (IWebElement checkbox in vehicleGroupInputElements)
{
checkbox.Click();
}
Just looked into Xpath syntax and found the answer. With the help of Chrome's 'copy Xpath' function in inspect mode, I found the path needed and successfully clicked the input element.
Example Xpath of the first input is as follows (notice the HTML for label[index] is 1 more than the way C# would count.)
//*[#id="ratingModification_SupplierContact_content"]/label[1]/input
And solution as follows
//Retrieves the checked items from the form and sends them to the page.
foreach (object checkedItem in vehicleGroupList.CheckedItems)
{
//Gets the index of the checked items.
int checkedIndex = vehicleGroupList.Items.IndexOf(checkedItem);
//Adds 1 to the index to match format of the page HTML.
checkedIndex++;
//Puts the index+1 into a string.
string indexText = checkedIndex.ToString();
//Finds the element by index+1.
var clickTarget = Builder.Driver.FindElement(By.XPath(string.Format("//*[#id='ratingModification_SupplierContact_content']/label[" +indexText+ "]/input")));
clickTarget.Click();

Filtering Children in Entity Framework Query

I have a database which it's schema is as follows:
As you can see, We have WareCategories which will be category of the wares i'm going to be working in my website. WareTypes which will be Definition of each Item type. Categories define properties in the table WarePropertyDefinitions and WareProperties define values for each property that has been defined in WarePropertyDefinitions table.
Now i have a search page that users search for items in OldWares and user selects category and i show the user all properties defined in WarePropertyDefinitions and user fills the data if he likes better results. But my problem is that i can't filter WareTypes based on WareProperties because it's from the type ICollection and i can't access filter options.
How can i apply this kind of filtering based on properties?
Thanks in advance...
Edit:
This is a part of the code i'm presenting to describe more:
var lst = WareCategory.GetItem(Convert.ToInt32(ddlChildren.SelectedValue)).WarePropertyDefinitions.ToList();
foreach (var ListItem in lst)
{
var value = BaseHelper.FindFormValue("PropertyValue" + ListItem.Id.ToString());
if (!string.IsNullOrEmpty(value))
{
query = query.Where(m => m.WareType.WareProperties.);
}
}
}
This segment of code is in my search function and as you can see i'm going to generate a list of items in WarePropertyDefinition that user selected via a drop down menu called ddlChildren. I'm going to iterate in this definition and user entered value for each property (the value variable will hold the value user entered and i will check if user have entered anything in the textbox) i will include it in where section (through this i will add it in where clause that ultimately filters my selection). but as you can see the code is incomplete because i don't know how to complete it.
Use the Any() extension method, for example:
query = query.Where(m => m.WareType.WareProperties.Any(wp => wp.Id == 5));
I have fixed the my problem by this code:
query = query.Where(m => m.WareType.WareProperties.Any(wp => wp.WarePropertyDefinition_Id == ListItem.Id && wp.TextValue == value));
but because #user3159792's answer was the basic of my problem i have selected his answer as the default answer to my problem. very thanks.

Linq join two objects to match customer selected records

I have two List T objects. One is a list of forums available and the other the forums the user has selected. This is executing during a jquery ajax call and will be populating a listbox.
The purpose is that I want to flag the forums the user has subscribed to with "selected" which will of course render in the html listbox as a highlighted row.
I started to write this query and stopped short.
var result = (from exf in ExtForum
join custfrm in customer.ExternalForums on
exf.Id equals custfrm.Id
select new { id=exf.Id, name=exf.ForumName, isSelected=(true ? "selected" : "") })
.ToList();
This will only return the forums that match. What I need is a left outer query but in thinking about that I don't think that is correct either. Well it is sort of correct as it would return all available forums but now I am back to square one of figuring out how I would flag my matches.
My approach which is open to improvement is to return basically a string object to jquery that then updates the html control.
ddlExtBoards.append($('<option></option>').val(option.id).html(option.name + " " + option.isSelected));
So advice / direction on what approach to accomplish this "match" would be very much appreciated.
The purpose is that I want to flag the forums the user has subscribed to with "selected"
A left-join is what you want here, this means that all the records in ExtForum are included at least once and any other ones that match the join
var results = (from exf in ExtForum
join custfrm in customer.ExternalForums on
exf.Id equals custfrm.Id into customerForums
from custForum in customerForums.DefaultIfEmpty()
select new
{
id = exf.Id,
name = exf.ForumName,
isSelected = custForum != null
}

WebForms Passing CheckboxList Values To List<T>

I have a GridView which I have a List bound to - I want to be able to allow filter of the data based on multiple CheckBoxLists.
For arguments sake let's say I have a List of Jobs, and I want to filter the jobs by code - So I would have a CheckBoxList like
C#
ASP.NET
php
F#
etc..
If someone selects multiple codes, how do you pass the values into a List to rebind to the GridView? Is there a way to pass values as an array? Or maybe a comma seperated string?
Any examples (I'm a C# boy) would be greatly appreciated, and I hope I have explained it properly :S
use an ObservableCollection<T> . it automatically allows the gridview to "observe" that the underlying datasource has changed and thus update itself.
wherever you do your filtering for the gridview you have to build the list manually before you filter.
var languages = new List<string>();
foreach (ListItem item in cblLanguages.Items)
{
if (item.Selected)
{
languages.Add(item.Value);
}
}
then when you filter you can do something like (example using linq2sql)
var jobs = db.Jobs.Where(x => langauges.Contains(x.LanguageCode));
gvJobs.DataSource = jobs;
gvJobs.DataBind();
I'm not sure I completely understand your question. But I often do the following to get ListItems into a form queryable via LINQ to objects:
var items = cblLanguages.Items.Cast<ListItem>();
// Selected Items
var selectedItems = items.Where(li => li.Selected);
// Item's containing 'C'
var itemsWithC = items.Where(li => li.Text.Contains("C"));
// Values between 2 and 5
var itemsBetween2And5 = from li in items
let v = Convert.ToInt32(li.Value)
where 2 <= v && v <= 5
select li;

Categories

Resources