-
Notifications
You must be signed in to change notification settings - Fork 11
Html Inspection
The most common usage of Headless is to work with HTML documents. There are three models of HTML inspection in Headless. You can inspect the HTML page and find an element using a manual, page or dynamic model.
The manual model refers to coding directly against IHtmlElementFinder to get a reference to a HTML element. It is very verbose and not reusable as it is the underlying engine that the page and dynamic models use.
using Headless;
using (var browser = new Browser())
{
var page = browser.GoTo(new Uri("https://mysite.com"));
var query = page.Find<HtmlInput>().ByName("Query");
query.Value = "Headless browser testing";
var search = page.Find<HtmlButton>().ByName("Search");
var resultsPage = search.Click();
// Assert page results
}
The page model refers to creating custom classes that inherit from HtmlPage. These classes can then expose properties that represent HTML elements expected on that page. The page model classes can also provide functional behavior such has executing a log on process for a given account.
While page model may appear to be more code, it provides the benefits of encapsulation, intellisense and ease of refactoring.
using Headless;
public class HomeIndexPage : HtmlPage
{
public HtmlLink SignIn
{
get
{
return Find<HtmlLink>().ByText("Sign in");
}
}
public override Uri TargetLocation
{
get
{
return HomeLocation.Index;
}
}
}
public class SignInPage : HtmlPage
{
public HtmlInput UserName
{
get
{
return Find<HtmlInput>().ByName("UserName");
}
}
public HtmlInput Password
{
get
{
return Find<HtmlInput>().ByName("Password");
}
}
public HtmlButton Submit
{
get
{
return Find<HtmlButton>().ByText("Sign in");
}
}
public override Uri TargetLocation
{
get
{
return HomeLocation.SignIn;
}
}
}
public class AccountIndexPage : HtmlPage
{
public override Uri TargetLocation
{
get
{
return AccountLocation.Index;
}
}
}
[TestMethod]
public void SignInRedirectsToAccountIndexPageTest()
{
using (var browser = new Browser())
{
var homePage = browser.GoTo<HomeIndexPage>();
var signInPage = homePage.SignIn.Click<SignInPage>();
signInPage.UserName.Value = "account name";
signInPage.Password.Value = "account password";
// The response from a click using the page model will validate location and 200 status code by default
signInPage.Submit.Click<AccountIndexPage>();
}
}
The dynamic model uses the dynamic keyword to provide dynamic searching for HTML elements. This model is the most succinct, but sacrifices intellisense, encapsulation and refactoring support. The searching logic uses the following order of precedence when attempting to match an element from a property name:
- Match by id attribute
- Match by name attribute
- Match by case sensitive exact text
- Match by case insensitive exact text
using Headless;
[TestMethod]
public void SignInRedirectsToAccountIndexPageTest()
{
using (var browser = new Browser())
{
var homePage = browser.GoTo(HomeLocation.Index);
var signInPage = homePage.SignIn.Click();
signInPage.UserName.Value = "account name";
signInPage.Password.Value = "account password";
// The response from a click using the dynamic model will only validate a 200 status code by default,
// it does not validate the ultimate location because there is no known target
var accountPage = signInPage.Submit.Click();
// Validate final url of the page against an expected value
accountPage.IsOn(AccountLocation.Index).Should().BeTrue();
}
}