Selenium - Cannot select drop-down - c#

Picked up on a small learning project, to find the cheapest car rental by modifying dates.
Website: Costco Travel
Flow: Select Province -> Rental Cars -> Enter Airport code, change date, times.
Issue: Cannot select Pick-up Time or Drop-off Time.
My code so far (works well) -
var rootDir = Directory.GetParent(Environment.CurrentDirectory);
var chromeDriverDir = rootDir.EnumerateDirectories("ChromeDriver", SearchOption.AllDirectories);
if ((chromeDriverDir != null) && (chromeDriverDir.Count() == 0))
Environment.Exit(-1);
var Driver = new ChromeDriver(chromeDriverDir.ToList()[0].FullName);
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
Driver.Manage().Window.Position = new System.Drawing.Point(0, 0);
Driver.Manage().Window.Maximize();
Driver.Navigate().GoToUrl("https://www.costcotravel.ca/");
Driver.FindElementByXPath("//label[contains(text(), \"Ontario\")]").Click(); // Select Province
Driver.FindElementByXPath("//button[contains(text(), \"Continue\")]").Click(); // Click on Continue
Driver.FindElementByXPath("//li[#data-tab=\"rental-cars\"]/a").Click(); // Click on "Rental Cars" Driver.FindElementById("pickupLocationTextWidget").SendKeys("yyz");
Driver.FindElementByXPath("//li[#class=\"airport\" and #data-value=\"YYZ\"]").Click(); // Select the airport
Driver.FindElementById("pickupDateWidget").Clear(); Driver.FindElementById("pickupDateWidget").SendKeys("01/05/2018"); // Select pick-up date
Driver.FindElementByXPath("//div[#id=\"pickup_time_widget\"]/input").Click();
Now, the issue -
Approach 1
new SelectElement(Driver.FindElementById("pickupTimeWidget")).SelectByText("11:00 AM");
'element not visible: Element is not currently visible and may not be
manipulated
Approach 2
Driver.FindElementByXPath("//div[#id=\"pickup_time_widget\"]/div/ul/li[#data-value=\"07:30 AM\"]").Click();
element not visible
Approach 3 - knew it wouldn't work, but tried it anyway.
new SelectElement(Driver.FindElementByXPath("//div[#id=\"pickup_time_widget\"]/div/ul/li[#data-value=\"07:30 AM\"]")).SelectByIndex(5);
Element should have been select but was li
Any help on selecting a value from pickuptime/dropofftime drop-downs is greatly appreciated! Usually, I have seen many websites implementing just the select tag, but this website also has ul/li tags, which is making it complicated. Or maybe I am over thinking. Please help!

There are underlying select elements that power these dropdowns. But, they are invisible and changed whenever the values in the "ul->li" dropdowns change.
There are two general options here:
make the select elements visible and use the SelectElement class to control the dropdowns
let the select elements be invisible and instead control the "ul->li" dropdown
The first option would just require setting the style of the select elements to "display: block":
IWebElement element = Driver.FindElementById("pickupTimeWidget");
((IJavaScriptExecutor)Driver).ExecuteScript("arguments[0].style = 'display:block';", element);
new SelectElement(element).SelectByText("11:00 AM");
The second option would first require a click to open up a dropdown:
IWebElement dropdown = Driver.FindElementById("pickup_time_widget");
dropdown.Click();
Then, finding a dropdown item by value/text and clicking it:
IWebElement dropdownItem = dropdown.FindElementByXpath(".//li[. = '11:00 AM']");
dropdownItem.Click();

Related

select radio button by index

I am using C# selenium driver in visual studio for automating my scripts.The data in my radio button gets dynamically generated and I want to select the radio button using index . These are the ways I tried
Method 1
new SelectElement(driver.FindElement(By.Id("XX"))).SelectByIndex(2);Click();
In first method , I am not able to relate the Click to the element
Method 2
IWebElement element = driver.FindElement(By.("XX"));
System.Threading.Thread.Sleep(2000);
element.Click();
In method 2 , I am not sure how to pass the index.
This is my HTML code :
<input type="radio" name="XXXX" id="XXXX" value="5273786">.
So These radio buttons get dynamically generated. For eg, if I have 3 radio buttons, all 3 radio buttons have the same id and name but a different value.
So it would be great if you could let me know how to select the first radio button by passing its value or by selecting the radio button using index.
You should try as below :-
if you to select radio button by their value try as below using By.XPath() :-
IWebElement element = driver.FindElement(By.Xpath("//input[#value = '5273786']"));
element.Click();
Or try as below using By.Id() :-
IList<IWebElement> elements = driver.FindElements(By.TagName("select"));
var element = selectElements.Where(se => se.GetAttribute('value') == '5273786');
element.Click();
if you want to select radio button using index try as below using By.Xpath() :-
IWebElement element = driver.FindElement(By.Xpath("(//input[#id = 'XXXX'])[1]"));
element.Click();
Or try as below using By.Id() :-
IList<IWebElement> elements = driver.FindElements(By.Id("XXXX"));
elements[0].Click();
Hope it helps...:)

Filling two nested drop dwon list when editing an entry in c#

i have two nested drop down list.
one drop down show group,the other show sub group.
i have coded data source of subgroup drop down list on group drop down list selected indexed change event.
What I'm trying to do is set a drop down list to be whatever its value is in the database when editing an entry.
i have used data row.
i have two tables.documentgroup(GroupId,parentId,groupTitle,subGroupTitle) and documents(DocID,GroupID,Title,url)
in my drop down lists i have added list item like this
<asp:ListItem Text = "--select group--" Value = ""></asp:ListItem>
when i click on editing a document,i have this.
protected void grdDocuments_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "DoEdit")
{
GC.Collect();
GC.WaitForPendingFinalizers();
int DocID = Convert.ToInt32(e.CommandArgument);
ViewState["DocumentID"] = DocID;
ViewState["EditMode"] = "Edit";
DataTable dtDocuments = DataLayer.Documents.SelectRow(DocID).Tables["Documents"];
if (dtDocuments.Rows.Count != 0)
{
DataRow drDocuments = dtDocuments.Rows[0];
txtDocTitle.Text = drDocuments["DocTitle"].ToString();
txtDocPubYear.Text = drDocuments["DocPubYear"].ToString();
ddlDocGroupTitle.SelectedValue = drDocuments["ParentID"].ToString();
ddlDocSubGroupTitle.SelectedValue = drDocuments["DocGroupID"].ToString();
ViewState["DocCurrentUrl"] = drDocuments["DocUrl"].ToString();
mvDocuments.SetActiveView(vwEdit);
}
}
but i get this error
'ddlDocSubGroupTitle' has a SelectedValue which is invalid because it
does not exist in the list of items. Parameter name: value
and this is the same for ddldocgroupTitle.
i have made an inner join between two tables.
what should i do?
I could not really grasp your question, but it looks like you want to have 2 dropdown, and upon selection in the first, the second gets populated/filtered correct?!?
I recommend that you use javascript/Jquery to do so. Upon page load, issue a ajax get request to fill the "main" dropdown, and upon selection on the first one, you issue a second ajax request to fetch the possible values of the second one...
A alternative is to fetch the items for the first dropdown AND all the values possible for the second, storing the result in some hidden-field data. Then upon selection of the first value, you can only filter + display relevant data.

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
}

Unexpected results when using .net ajax & paging in sharepoint web part with c#

Alright so when the web part loads I pull from a list like so in the CreateChildControls() function:
String userGroup = GetProfileProperty(SPContext.Current.Web.CurrentUser.LoginName);//get user login's newsgroup // "All";
if (!string.IsNullOrEmpty(userGroup) && !userGroup.Equals("All"))
{
qry.RowLimit = 5;
camlquery = "<Where><Contains><FieldRef Name='Intended_x0020_Audience' /><Value Type='MultiChoice'>" + userGroup + "</Value></Contains></Where><OrderBy><FieldRef Name='Start_x0020_Date' Ascending='False' /></OrderBy>";
qry.Query = camlquery;
items = newsList.GetItems(qry);
//Print items inside a ajax panel....
}
else
{
qry.RowLimit = 5;
camlquery = "<OrderBy><FieldRef Name='Start_x0020_Date' Ascending='False' /></OrderBy>";
qry.Query = camlquery;
items = newsList.GetItems(qry);
////Print items inside a ajax panel....
}
I do not use paging yet, but I have stored the query list in a var items. When the user clicks a button the update panel clears out the current controls and does another query to get the new items, but this time I use paging.(see below)
int lastID = items[items.Count - 1].ID;//last news item id of current page
//Get Web Context
SPWeb web = SPContext.Current.Web;
//Clear old panel
UpdatePanel up = (UpdatePanel)FindControl("Panel");
up.ContentTemplateContainer.Controls.Clear();//clear container of old news items
SPQuery qry = new SPQuery();//get query
qry.RowLimit = 5;
string camlquery = "<OrderBy><FieldRef Name='Start_x0020_Date' Ascending='False' /></OrderBy>";
qry.Query = camlquery;
SPListItemCollectionPosition position = new SPListItemCollectionPosition("Paged=TRUE&p_ID=" + lastID.ToString());
qry.ListItemCollectionPosition = position;
items = web.Lists["News Wire"].GetItems(qry);// newsList.GetItems(qry);
//print items inside ajax panel....
It does change the page, but it returns more items than necessary. I'll get five when the webpart first loads, but when I click the button that triggers the event to get more list records, I get the first item of the next page and also the first page's first 3 items. Note: My list only has six items in it. I limited my RowLimit to 5, but when I load the second page I get 4 items and 3 from the first page.
If you're paging forwards, you can pass the ListItemCollectionPosition from your first query's results (SPListItemCollection) to the next query - you don't have to mess about constructing it by hand.
You'll need to store it somewhere after you get the first set of results - I've used ViewState before, you could use a hidden control in the update panel as well.
When you're paging backwards, you do need to create the string as you are doing. You also need to include a key/value to indicate that you're going backwards, and you need to include an indication of your sort. (You might be able to get this from the auto-generated forward-paging value.) (I think missing the sort is why your forwards paging isn't working, too.)
This is the resource I used when I was trying to get this working myself, although it's a little hazy now.

wp7 - App.ViewModel collection Selection

I have a collection:
App.ViewModel.historyItemCollection
That has 4 properties:
id
name
meterValue
meterDate
I would like to bind to my listbox by id. So if I select house #2 (in the collection) I only want to show the history information for house 2.
I tried a couple of different selects/where statements when trying to bind it to my form:
lbHistory.ItemsSource = App.ViewModel.historyItemCollection.Where(history => history.id= houseIndex);
If there are any links that say how to do this, please just point me there? Part of my problem I couldn't figure out what this was called so my searches were fruitless.
Thanks!
I haven't tested this code, so forgive me if it doesn't work.
lbHistory.ItemsSource = from item in App.ViewModel.historyItemCollection
where item.id == houseIndex
select item;
If there can be more than one match, and you only want to show the first, use:
lbHistory.ItemsSource = ( from item in App.ViewModel.historyItemCollection
where item.id == houseIndex
select item ).FirstOrDefault();

Categories

Resources