New version of canopy has been released today. This version includes an improved set of selectors:
Relative selectors.
New functions elementWithin and elementsWithin provide an ability to select element/elements in DOM sub-tree:
elementWithin : (string -> IWebElement -> IWebElement) elementsWithin : (string -> ISearchContext -> IWebElement list)
You are able to write more complex page parsing code, for example like this:
elements "#div.section-item"
|> Seq.map(fun el ->
let name = (el |> elementWithin "h2").Text
let items = el |> elementsWithin "li a"
|> List.map (fun a -> a.GetAttribute("href"))
name, items)
XPath support.
From now, all selectors support XPath. There was also introduced new parent selector that returns parent web element.
parent : (IWebElement -> IWebElement)
"/some/xpath/query" << "some value" "/some/xpath/query" == "some value" let results = elements "xpath/query"
Options selectors.
Three new options selectors were added: someElement, someElementWithin, someParent. All the selectors behave in the following way:
- Return Some(element) if exactly one element match to the selector
- Return None if there is no such elements
- Throw an exception in other cases.
someElement : (string -> IWebElement option) someElementWithin : (string -> ISearchContext -> IWebElement option) someParent : (ISearchContext -> IWebElement option)
With these selectors you can use all power of F# Options type:
let currentUser =
someElement "#profile a"
|> Option.bind (fun el -> el |> parent |> Some)
|> Option.bind (fun el -> el |> getHref |> getParamFromUrl "id" |> Some)
|> Option.bind (fun id -> Person(id) |> Some)
Feel free to try it in action!


One more interesting task is to explore local network and check which computers are alive.
I have faced with an interesting F# behaviour on the null check. I tried to make a
Detailed pretty printed exception is a key to understand the real cause of the problem. We have a piece of code in C# that was reused for many projects, which formats exceptions sequence into human readable form with all exception details.