CodedUI Find lower level List Item without an ID? - c#

I am experimenting with CodedUI using C# and am having some trouble. I have got a <div> containing an ID, and then a non-uniquely identified <ul> with several <li> tags like the below:
<div id="uniqueIdValue" class"long_class" activetabindex="0" sfwtabcontainer="true">
<ul class="long_class2">::before
<li class="sharedListItemClass" sfwtabheader="true">...</li>
<li class="sharedListItemClass" sfwtabheader="true">
History
</li>
<li class="sharedListItemClass" sfwtabheader="true">...</li>
::after
</ul>
How can I setup a Mouse.Click(...) on the the second list item (or the <a> within) containing my <a> tag with test of "History"?
I have tried every combination I can think of to specify this tag by itself, all the way up to specifying the parent and trying to get the "TagInstance":
var container = new HtmlControl(_bw);
HtmlDiv nameForDiv = new HtmlDiv(container);
nameForDiv.SearchProperties[HtmlDiv.PropertyNames.Id] = "uniqueDivIdentifier";
nameForDiv.SearchProperties[HtmlDiv.PropertyNames.Class] = "long Multiple_Classes";
var historyTab = new HtmlHyperlink(nameForDiv);
historyTab.SearchProperties[HtmlHyperlink.PropertyNames.Href] = "#someValue";
historyTab.SearchProperties[HtmlHyperlink.PropertyNames.TagInstance] = "2";
Mouse.Click(historyTab)
Resulting in the control cannot be found. Can anyone help me with this?

Something like this:
var browser = BrowserWindow.Launch("url");
private void ClickLink()
{
var parent = GetPaneID(browser, "uniqueIdValue");
var child = parent.GetChildren()[0];
var child2 = child.GetChildren()[1];
var child3 = child2.GetChildren()[0];
Mouse.Click(child3);
}
where method GetPaneId() looks like this:
public HtmlDiv GetPaneID(UITestControl parent, string id)
{
var gpane = new HtmlDiv(parent);
gpane.SearchProperties.Add(HtmlDiv.PropertyNames.Id, id);
return gpane;
}

Related

Looping through an List to select an Element in Selenium

I'm attempting to write a Page Class for Links within the Header of the website I'm testing. I have the following link structure below
<ul>
<li>Home</li>
<li>About Us </li>
<li>Account</li>
<li>Orders</li>
<li>Administration Portal</li>
</ul>
What I want to do is store these into a List, then when a user select one of the links, it will take then to the page they should go to.
I have started with the following code below
List<IWebElement> headerElements = new List<IWebElement>();
headerElements.Add(WebDriver.FindElement(By.LinkText("Home")));
headerElements.Add(WebDriver.FindElement(By.LinkText("About Us")));
headerElements.Add(WebDriver.FindElement(By.LinkText("Account")));
headerElements.Add(WebDriver.FindElement(By.LinkText("Orders")));
headerElements.Add(WebDriver.FindElement(By.LinkText("Administration Portal")));
headerElements.Add(WebDriver.FindElement(By.LinkText("Log in / Register")));
headerElements.Add(WebDriver.FindElement(By.LinkText("Log off")));
I was thinking for using a for loop to do this, would this be the best way. I'm trying to avoid writting methods like the one below for each link
public void SelectCreateNewReferralLink()
{
var selectAboutUsLink = ( new WebDriverWait(WebDriver, new TimeSpan(50))).Until
(ExpectedConditions.ElementExists(By.CssSelector("#main > a:nth-of-type(1)")));
selectCreateNewReferralLink.Click();
}
I'm using C#, with WebDriver attempting to write this
Any Help would be great
Thanks
Chris
You could have a method that knows the root of the list (the ul element) and takes the title (string or enum) as a parameter.
Something like (in pseudo-java code):
selectLink(String title) {
driver.findElement(By.cssSelector("ul li a[title='" + title + "']").click();
}

Selecting Span Class Element

Using Selenium / C#
I have an automated test case where a user logs in (jonpark2), once the user has done so their username is stored in the text of a span class, I need to select this element and then verify an assert on it.
I have the below to try and select this:
public static void Userloggedin()
{
var userlogedin = Driver.Instance.FindElement(By.ClassName("username"));
var selectelement = new SelectElement(userlogedin);
selectelement.SelectByText("JonPark2");
}
When I run this i encounter the error OpenQa.Selenium.Support.UI.unexpectedTagNameException:Element should have been select but was div.
The below html shows in more detail what I am trying to select:
<div class="content-wrapper">
<div class="float-left">
<div class="float-right">
<section id="login">
<p>
<a title="Manage your account" class="username" href="Account/Manage">
Text - Empty Text Node
<span class="username">
Text - JonPark2
Can anyone point out where I have gone wrong ?
You are trying to select something that is not part of a <select>.
try this:
public static void Userloggedin()
{
return (
"JonPark2" == Driver.Instance.FindElement(By.cssSelector("section#login span.username")).Text;
)
}
You can select that element by XPath:
var spanElement = Driver.Instance.FindElement(By.XPath("//span[contains(#class, 'username')]"));
And then take text:
var textInSpan = spanElement.Text

Using a C# WebForms asp:BulletedList with 3 urls in the list

I need to keep using a list box to do this as there are a number of other dependencies on the control being a list box.
Ultimately I want each list item to consist of 3 distinct URL's so:
Url1 Url2 Url3
which would be HTML of:
<ul>
<li>Url1Url2Url3</li>
</ul>
So in my ASPX page I am maintaing there is already:
<asp:BulletedList ID="lstDashboards" runat="server" DisplayMode="Text"</asp:BulletedList>
And in code behind I have the following to populate the list:
private void GuiSideMenuBuild(Int64 aUserId)
{
//Always clear any dashboards
lstDashboards.Items.Clear();
//Get the dashboards from the database
DashboardsForUserGetDto userDashboards = DashboardBL.Instance.DashboardsForUserGet(Convert.ToInt32(aUserId));
const string HREF_DASHBOARD_EDIT = "Edit...";
const string HREF_DASHBOARD_DELETE = "Delete...";
foreach (TableDashboardDashboardDtoBase userDashboard in userDashboards.Dashboards)
{
string listItemText = userDashboard.Title;
if (userDashboard.DashboardId == DashboardId)
listItemText += HREF_DASHBOARD_EDIT + HREF_DASHBOARD_DELETE;
ListItem listItem = new ListItem
{
Text = listItemText,
Value = Convert.ToString(userDashboard.DashboardId),
Selected = userDashboard.DashboardId == DashboardId
};
lstDashboards.Items.Add(listItem);
}
}
However the HTML that the control is producing has escaped all the supplied HTML so that I end up with something like:
<<a href="#" id="...
which means that the resulting HTML is "broken" and the URL's don't work. So my question is:
How can I keep using the existing list box (ie. asp:BulletedList) but supply it Text for the item so that it will produce valid HTML so that I can have 3 separate URL's?
I have already tried HTML Encoding the string before adding it to listItem.Text but that makes no difference.
I don't see any need for a UserControl here - you don't use any server-side components, you're just generating markup. Why not just do this in your .aspx page?
<ul>
<% foreach (TableDashboardDashboardDtoBase userDashboard in userDashboards.Dashboards)
{
%>
<li>Url1Url2Url3</li>
<%
}
%>
</ul>
Either that, or use a repeater:
HTML
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate><ul></HeaderTemplate>
<ItemTemplate><li>Url1Url2Url3</li></ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
Code Behind
Repeater1.DataSource = userDashboards.Dashboards
Repeater1.DataBind()

Create Hyperlinks from controller in asp.net MVC

I have a controller, which creates breadcrumbs as follows:
Software > Windows 7 > Outlook 2007
The code to create this is:
ViewBag.breadcrumbs = string.Join(" > ", cbh.Select(i => i.Title));
Is there a straightforward way of making the breadcrumbs hyperlinks, which would point to (i.ParentID) ie:
Software -> forum/index/12
Windows 7 -> forum/index/19
Outlook 2007 -> forum/index/23
Or should I just loop through cbh and manually build <a href=...> strings, and pass those to the view?
Thank you,
Mark
Your best bet is to put the required items into the model then loop through them.
Try something like this:
Model
public class Model
{
public struct BreadCrumb
{
public string Title;
public string Url;
}
public List<BreadCrumb> Breadcrumbs { get; set; }
}
View
#{ int index = 0; }
#foreach(var crumb in this.Model.Breadcrumbs)
{
#(crumb.Title)
if(index < this.Model.Breadcrumbs.Count - 1)
{
<span>></span>
}
index++;
}
Yes, you should build your breadcrumb links in the view. If it helps, you can create a BreadCrumbModel class (if you don't already have one).
ViewBag.breadcrumbs = cbh.Select(i => new BreadCrumbModel()
{
Id = i.Id,
Title = i.Title
});
#{
var printSeparator = false;
}
#foreach(BreadCrumbModel bc in ViewBag.breadcrumbs)
{
#if(printSeparator)
{
<span class="breadcrumb-separator"> > </span>
}
<span class="breadcrumb">
#Html.ActionLink(bc.Title, "index", "forum", new { id = bc.Id });
</span>
#{
printSeparator = true;
}
}
If you want to have breadcrumbs between different controllers and actions (not just forum / index), then add those as properties of your BreadCrumbModel.

How to implement a list of dropboxes in C#

I am currently working on a C# project using ASP.NET. And I'd like to implement a list of dropboxes. So a User starts with a dropbox and can select a method and next to the dropbox is a + and - button, which enables a user to add more dropboxes. So I am wondering how can I implement that is it possible to build a List of dropboxes in ASP.NET?
You don't need any server side code for this, client side scripting is ideal solution for your needs.
Having such HTML:
<div id="MainPlaceholder">
<div id="DropDownPlaceholder">
<select name="myDropDown">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
</select>
<button type="button" onclick="AddDropDown(this);">+</button>
<button type="button" onclick="RemoveDropDown(this);">-</button>
</div>
</div>
You need the following pure JavaScript to make it work:
<script type="text/javascript">
var added_counter = 0;
function AddDropDown(sender) {
var parent = sender.parentNode;
//make fresh clone:
var oClone = parent.cloneNode(true);
//append to main placeholder:
parent.parentNode.appendChild(oClone);
//store change in global variable:
added_counter++;
}
function RemoveDropDown(sender) {
//don't allow to remove when there is only one left
if (added_counter <= 0) {
alert("One drop down must exist");
return;
}
var parent = sender.parentNode;
//disable so value won't be passed when form submitted:
parent.getElementsByTagName("select")[0].disabled = true;
//hide:
parent.style.display = "none";
//store change in global variable:
added_counter--;
}
</script>
The code has comments, but if you need any further explanation please feel free to ask.
Live test case.
Edit: As you need to read the selected values on the server side code, better approach would be to change the name of each cloned drop down:
var totalAddedCounter = 0;
function AddDropDown(sender) {
var parent = sender.parentNode;
//make fresh clone:
var oClone = parent.cloneNode(true);
//assign unique name:
oClone.getElementsByTagName("select")[0].name += "_" + totalAddedCounter;
//append to main placeholder:
parent.parentNode.appendChild(oClone);
//store change in global variable:
added_counter++;
totalAddedCounter++;
}
Now the tricky part is reading those values. Instead of plain dropboxlistID.Text you will have to iterate over all posted values looking for what you need:
foreach (string key in Request.Form.Keys)
{
if (key.StartsWith("dropboxlistID"))
{
string text = Request.Form[key];
//.....
}

Categories

Resources