How do I verify in WatiN that a <ul> contains certain links - watin

Let's say we have the following list in an HTML document:
<ul id="menu">
<li>Home</li>
<li>Page</li>
</ul>
How do I verify with WatiN that "menu" contains exactly those hyperlinks, in a concise manner?

You can look for the UL with id of menu, and then check its decendants to see if there are links which the links you're expecting. It would be something along these lines (forgive me if I don't have the method names quite right).
var menuDiv = Browser.Current.Div(Find.ById("menu"));
Assert.That(menuDiv.Find.By("href", "/Page").Exists);

I ended up with this solution, it was the best I could think of:
private static void CheckMenu(string title)
{
Browser browser = WebBrowser.Current;
// Verify menu
WatiN.Core.List menu = browser.List("menu");
var links = menu.OwnListItems.Select(item => item.Links[0]).ToList();
Assert.That(links.Count, Is.EqualTo(2));
CheckLink(links[0], "/", "Home");
CheckLink(links[1], "/Page", "Page");
}
private static void CheckLink(Link link, string path, string text)
{
// The href value is translated to an absolute URL, gah :/
Assert.That(link.GetAttributeValue("href"), Is.StringMatching(
string.Format("[^:]+://[^/]+{0}", path)));
Assert.That(link.Text, Is.EqualTo(text));
}
Basically, I verify that there are two list items, and that they contain a link "Home" pointing to "/" and a link "Page" pointing to "/Page".

Related

Watir - scraping a grid of items

I'm trying to scrape the app URLs from a directory that's laid out in a grid:
<div id="mas-apps-list-tile-grid" class="mas-app-list">
<div class="solution-tile-container">
<div class="solution-tile-content-container">
<a href="url.com/app/345">
<div class="solution-tile-container">
<div class="solution-tile-content-container">
<a href="url.com/app/567">
... and so on
Here are my 2 lines of Watir code that are supposed to create an array with all URLs from a page:
company_listings = browser.div(id: 'mas-apps-list-tile-grid')
companies = company_listings.map { |div| div.a.href }
But instead of an array with URLs, 'companies' returns:
#<Watir::Map: located: false; {:id=>"mas-apps-list-tile-grid", :tag_name=>"div"} --> {:tag_name=>"map"}>
What am I doing wrong?
The #map method for a Watir::Element (or specifically Watir::Div in this case) returns a Watir::Map element. This is used for locating <map> tags/elements on the page.
In contrast, the #map method for a Watir::ElementCollection will iterate over each of the matching elements. This is what is missing.
You have a couple of options. If you want all the links in the grid, the most straightforward approach is to create a #links or #as element collection:
company_grid = browser.div(id: 'mas-apps-list-tile-grid')
company_hrefs = company_grid.links.map { |a| a.href }
If there are only some links you care about, you'll need to use the link's parents to narrow it down. For example, maybe it's just links located in a "solution-tile-content-container" div:
company_grid = browser.div(id: 'mas-apps-list-tile-grid')
company_listings = company_grid.divs(class: 'solution-tile-content-container')
company_hrefs = company_listings.map { |div| div.a.href }

How can I check the URL path to apply a condition (Razor)

I am using code like this to detect the browser and apply a condition to display or not display <label>:
#{
var settings = Model.PartFieldDefinition.Settings.GetModel();
System.Web.HttpBrowserCapabilitiesBase theBrow = Request.Browser;
}
<fieldset>
#{
if ((theBrow.Browser == "IE") && (theBrow.MajorVersion < 10))
{
#:<label>#Model.DisplayName</label>
#://Some Code for inputs
}
else
{
#://Some Code for inputs
}
}
</fieldset>
I have been trying to figure out if I can (and if so, how) I could utilize this logic to detect what path in the website the user is in to display or not display <label>
For example, on any other path I want the label displayed. However, for the pages under ~/Services (the path), I want to be able to hide the label.
It's a little bit more complicated than that. The code is in an editor template that gets used all over the site. If I use CSS in the editor template to "hide" the label I will affect all the pages. I was hoping with the above logic I can avoid that and only apply my logic on certain pages under a path.
Thanks.
Update
I have tried the following:
#{
string CurrentURL = Request.ApplicationPath;
}
<fieldset>
#{
if ((CurrentURL == "Services")) // also tried "/Services"
// rest of code left out for brevity
}
but the labels are hidden on all pages, even outside the path "~/Services". Am stuck on the syntax.
Found answer
I did the following:
#{
string CurrentURL = Request.Url.AbsoluteUri;
}
<fieldset>
#{
if (CurrentURL.Contains("Services"))
}
and it worked. I don't know if anyone can comment, but which would be better to use: Request.Url.AbsoluteUri or Request.Url.ToString() (both of which work)?

How to perform click event on an element present in the anchor tag?

<div class="buttonClear_bottomRight">
<div class="buttonBlueOnWhite">
<a onclick="$find('{0}').close(true); callPostBackFromAlert();" href="#">Ok</a><div
class='rightImg'>
</div>
</div>
</div>
In the above code i wanted to click on Ok button present in the anchor tag.But an id is not generated because of which i cannot directly perform a click action. I tried a work around mentioned below.
IElementContainer elm_container = (IElementContainer)pw.Element(Find.ByClass(classname));
foreach (Element element in elm_container.Elements)
{
if (element.TagName.ToString().ToUpper() == "A")
{
element.Click();
}
}
But here elm_container returns null for intial instances due to which we cannot traverse through it. Is there any other easy method to do it ?
Try this...
Div div = browser.Div(Find.ByClass("buttonClear_bottomRight")).Div(Find.ByClass("buttonBlueOnWhite"));
Debug.Assert(div.Exists);
Link link = div.Link(lnk => lnk.GetAttributeValue("onclick").ToLower().Contains(".close(true)"));
Debug.Assert(link.Exists);
link.Click();
Hope it helps!
You can simply Click on the link by finding its text
var OkButton = Browser.Link(Find.ByText("Ok"));
if(!OkButton.Exists)
{
\\Log error here
}
OkButton.Click();
Browser.WaitForCompplete();
Or you can find the div containing the link like,
var ContainerDiv = Browser.Div(Find.ByClass("buttonBlueOnWhite"));
if(!ContainerDiv.Exists)
{
\\Log error here
}
ContainerDiv.Links.First().Click();
Browser.WaitForComplete();

Ajax.ActionLink without href attribute for better SEO

I am using Ajax.ActionLink to display an hyperlink and when clicked make an ajax request (for example the flag hyperlink in this site, report, etc) and put the result in some div, this all can be easily done with this method, but the problems comes with SEO, because this hyperlink actually have and href attribute and the spider follow the url.
I want an anchor without href to make it SEO friendly and extension method to do all that, but with all the overloads of Ajax.ActionLink example:
Ajax.SEOFriendlyActionLink("my hyperlink", "action", "controller" ... more options)
this can generate something like this
<a urlForAjax="url here">my hyperlink</a>
Of course making the ajax callbacks.
Is there any thing like this out there?
The solution is as follows:
Ajax.ActionLink("my hyperlink", "", "" ... new AjaxOptions() { Url = Url.Action("action", "controller") ... })
It will generate something like this:
< a href="/" data-ajax-url="url here" ...> </a>
The solution given by #kyw is good but have one drawback. The link can be opened in newtab which is propably not the behaviour we are looking for.
We will change code a little :
Ajax.ActionLink("my hyperlink", "", "" ... new AjaxOptions() { Url = Url.Action("action", "controller") ... }, new { href = "!!"})
Now we need some jQuery :
$('a[href$="!!"]').each(function (index, element) {
element.removeAttribute("href");
});
From now on every link which href is ending on !! will have this attribute removed, thus it will disable option to open link in new tab.

Getting raw text using #Html.ActionLink in Razor / MVC3?

Given the following Html.ActionLink:
#Html.ActionLink(Model.dsResults.Tables[0].Rows[i]["title"].ToString(), "ItemLinkClick",
new { itemListID = #Model.dsResults.Tables[0].Rows[i]["ItemListID"], itemPosNum = i+1 }, ...
Data from the model contains HTML in the title field. However, I am unable to display the HTML encoded values. ie. underlined text shows up with the <u>....</u> around it.
I've tried Html.Raw in the text part of the ActionLink, but no go.
Any suggestions?
If you still want to use a helper to create an action link with raw HTML for the link text then I don't believe you can use Html.ActionLink. However, the answer to this stackoverflow question describes creating a helper which does this.
I would write the link HTML manually though and use the Url.Action helper which creates the URL which Html.ActionLink would have created:
<a href="#Url.Action("ItemLinkClick", new { itemListID = #Model.dsResults.Tables[0].Rows[i]["ItemListID"], itemPosNum = i+1 })">
#Html.Raw(Model.dsResults.Tables[0].Rows[i]["title"].ToString())
</a>
MVCHtmlString.Create should do the trick.
Using the actionlink below you do not need to pass html in the model. Let the css class or inline style determine how the href is decorated.
#Html.ActionLink(Model.dsResults.Tables[0].Rows[i]["title"], "ItemLinkClick", "Controller", new { #class = "underline", style="text-decoration: underline" }, null)
those are the cases that you should take the other path
#{
string title = Model.dsResults.Tables[0].Rows[i]["title"].ToString(),
aHref = String.Format("/ItemLinkClick/itemListID={0}&itemPosNum={1}...",
Model.dsResults.Tables[0].Rows[i]["ItemListID"],
i+1);
}
#Html.Raw(title)
Remember that Razor helpers, help you, but you can still do things in the HTML way.
You could also use this:
<a class='btn btn-link'
href='/Mycontroler/MyAction/" + item.ID + "'
data-ajax='true'
data-ajax-method='Get'
data-ajax-mode='InsertionMode.Replace'
data-ajax-update='#Mymodal'>My Comments</a>

Resources