Releasenotes WatiN 1.2.0.4000
This page contains the release notes for WatiN 1.2.0.4000, released on 1 Oktober 2007.
You can download this release here.
Changes in general
I like to thank all who have contributed to this release with code and suggestions. A special thanks to Jeff Brown who contributed a lot of new functionality and ideas for this release!
Create new IE instance in new process
To avoid the sharing of session info between Internet Explorer instances, support is added to create an Internet Explorer instance in a new process. This option is available as a param on all constructors of the IE object. By default WatiN will create new IE instances in the same process (as in previous releases).
bool startInNewProcess = true;
using(IE ie = new IE(someUrlToGoTo, startInNewProcess))
{
// do something
}
Cookies and caches
To clean up any Internet Explorer caches, IE.ClearCookies or IE.ClearCache are added. You can call these methods at any time during the live of an IE instance, but you are advised to call these methods directly after creating an IE instance. If you call these methods at a later moment, be aware Internet Explorer still might have cached items in memory which is not cleared by these calls! The only way to make sure this memory cache is cleared is to make use of the new IE.ReOpen() method. This method closes and reopens a new IE instance which effectively solves the problem.
using(IE ie = new IE())
{
ie.ClearCache;
ie.ClearCookies;
ie.GoTo(someUrlToGoTo);
// do something
}
To manipulte Cookies and/or to read cookie information, IE.GetCookie() and IE.SetCookie are added.
using(IE ie = new IE(someUrlToGoTo))
{
string setvalue = "test-cookie=abc; expires=Wed, 01-Jan-2020 00:00:00 GMT";
ie.SetCookie("http://1.watin.com/", setvalue);
string getvalue = ie.GetCookie("http://1.watin.com/", "test-cookie");
Assert.AreEqual("test-cookie=abc", getvalue);
}
New Find.By methods
The Find.ByCustom() methods are replaced by the new Find.By() methods. Find.ByCustom is marked [Obsolete] and will be removed in the next release.
Two new overloads are added for Find.ByUrl() which make it possible to ignore the querystring part of a url. (Thanks to Seth Behunin for this contrib).
A new Find.ByAlt(id) and 3 overloads are added to find Area elements by the value of the Alt attribute.
All Find.ByXXX methods have two new overloads. One accepting an object which implements the IComparer interface. This way you can create your own Comparer objects and use these to find matching elements. The other is .Net 2.0 specific and accepts a method of type Predicate
using(IE ie = new IE(someUrlToGoTo))
{
ie.TextField(Find.ById(new EndsWithComparer("txtName"))).TypeText("Found");
// The following syntax is only available in the .Net 2.0 version;
ie.TextField(Find.ById(WhichEndsWithTxtName)).TypeText("Found");
}
public bool WhichEndsWithTxtName(string value)
{
return value.EndsWith("txtName");
}
public class EndsWithComparer : WatiN.Core.Comparers.BaseComparer
{
private string _valueToCompareWith;
public EndsWithComparer(string value)
{
_valueToCompareWith = value;
}
public override bool Compare(string value)
{
return value.EndsWith(_valueToCompareWith);
}
}
Changed Attribute to AttributeConstraint
Renamed Attribute class to AttributeConstraint to get ride of the name clash with System.Attribute and it better expresses what the class is meant for. The Attribute class is marked [Obsolete] and will be removed in the next release.
Almost all classes inheriting from AttributeConstraint are marked [Obsolete]. These classed are overhead since their functionality was only used by WatiN in the Find class. These classes will be removed in the next release.
Added support for Area element
Within Image maps the Area elements define to clickable areas. The new support for Area elements combined with the new Find.ByAlt() makes it possible to automate
Area area = ie.Area(Find.ByAlt("Alternative text"));
Improve speed of finding not natively supported elements
To find an element which is not natively supported by Watin, like the LI element for instance, one had to use this kind of code:
Element item1 = ie.Element(Find.By("tagname", "li") && Find.ById("item1")));
Since looping through all elements on a page with many elements is not that speedy, a new overload is added to ie.Element which accepts a tagname as an argument. This gives you the same speed with which WatiN supported elements are found.
Element item1 = ie.Element("li", Find.ById("item1"));
Added Element.Ancestor
Added new functionality to the Element class to get an Ancestor of an element. This can be used in situations where you need to lookup a known element to find an other element within the same container element. The following overloads are available:
Element.Ancestor(Type)
Element.Ancestor(AttributeConstraint)
Element.Ancestor(Type, AttributeConstraint)
Element.Ancestor(TagName)
Element.Ancestor(TagName, AttributeConstraint)
Element.Ancestor<T>, .Net 2.0 only
Element.Ancestor<T>(AttributeConstraint), .Net 2.0 only
The following example looks for a specific textfield within a table row and then clicks on the edit button within the table row. This is the simplified html hierarchie:
TR
TD
INPUT text, id='fieldInRow1'
TD
INPUT button, text='edit'
Type type = typeof(TableRow);
TableRow row = (TableRow)ie.TextField("fieldInRow1").Ancestor(type);
row.Button(Find.ByText("edit")).Click();
// .Net 2.0 version
TableRow row = ie.TextField("fieldInRow1").Ancestor<TableRow>;
row.Button(Find.ByText("edit")).Click();
Save snapshots of webpages
In some situations it might be handy to be able to take a snapshot of the webpage that is shown in the browser. Based on the code of WebCapture article on CodeProject WatiN now offers this functionality. You can store images in the following formats: jpg, tif, gif, png, bmp.
To create a snapshot simply call the CaptureWebPageToFile method.
public void CaptureWatinMainPage()
{
using(IE ie = new IE("watin.sourceforge.net")
{
ie.CaptureWebPageToFile("c:\tmp\watin main page.jpg");
}
}
If you want more control over the size and quality of the snapshots you can use the new WatiN.Core.CaptureWebPage class instead.
New Settings
By using the IE.Settings properties it is possible to change some of the default values used by WatiN. This release adds the following new settings.
By default WatiN moves the mousepointer out of the way to prevent unexpected behavior during the tests. You can disable this functionality like this:
IE.Settings.AutoMoveMousePointerToTopLeft = false; // default is true
By default WatiN tests make the created Internet Explorer instances visible to the user. You can run your test invisible by changing the following setting. Be aware that HTMLDialogs and any popup windows will be shown even if you set this setting to false (this is default behavior of Internet Explorer which currently can't be suppressed).
IE.Settings.MakeNewIeInstanceVisible = false; // default is true
In situations where you don't want or need WatiN to handle the popup dialogs you can prevent starting the DialogWatcher by changing this setting. If you set this to false, any calls to ie.DialogWatcher.Add(dialogHandler) will result in an exception.
IE.Settings.AutoStartDialogWatcher = false; // default is true
Setting the properties of the (java)script Event object
When you have javascript in your webpage which handles some event on an element is most likely uses the event object to retrieve some info regarding the event. For example, in an onkeypress event you want to check the event.keycode to filter certain characters. Until now WatiN had no support to set these properies. This release adds an overload to Element.FireEvent which accepts the eventname and a NameValueCollection property names and their values. These will be set on the Event object passed in when firing the event.
The following example fires the onmousedown event and sets the button property on the event object to the value 2 (the right mousebutton).
NameValueCollection eventProperties = new NameValueCollection();
eventProperties.Add("button", "2");
ie.Div("rightMousePopUpMenu").FireEvent("onmousedown", eventProperties);
Changes to TextField.TypeText
TypeText makes use of the new functionality to set properties of the event object. TypeText fires the onkeydown, onkeypress and onkeyup events and sets the keyCode property to the ascii value of the typed character.
TypeText will also honour the maxlength value set on a textfield. The text to type will be cut off if it exceeds the maxlength value.
Added Eval functionality
In the previous release a RunScript method was added to inject and execute javascript code in the browser. With the new Eval method you can inject and execute javascript and get a return value as a result. If there is an error in the javascript, Eval will throw a JavaScriptException with the error message thrown by the javascript runtime inside the browser.
The following example uses Eval to show a confirm dialog. It then asserts that you clicked the cancel button by checking the result value.
[Test]
public void TestEval()
{
IE.Settings.AutoStartDialogWatcher = false;
using (IE ie = new IE())
{
string result = ie.Eval("window.confirm('Click Cancel')");
Assert.That(result, NUnit.Framework.SyntaxHelpers.Is.EqualTo("false"));
}
}
Added ReturnDialogHandler
The new ReturnDialogHandler can be used to automate the return dialog typically used to inform the user about something when they leave or close a web page.
// the html
<body onbeforeunload='javascript:return "Any changes you may have made will NOT be saved.";'>
using (IE ie = new IE(OnBeforeUnloadJavaDialogURI))
{
ReturnDialogHandler returnDialogHandler = new ReturnDialogHandler();
ie.AddDialogHandler(returnDialogHandler);
// can't use ie.Close() here cause this will cleanup the registered
// returnDialogHandler which leads to a timeout on the WaitUntilExists
InternetExplorer internetExplorer = (InternetExplorer) ie.InternetExplorer;
internetExplorer.Quit();
returnDialogHandler.WaitUntilExists();
returnDialogHandler.OKButton.Click();
}
TypeText will also honour the maxlength value set on a textfield. The text to type will be cut off if it exceeds the maxlength value.
Customize the IE.WaitForComplete logic
When some action is executed on an element (like clicking a link or selecting an item in a selectlist) WatiN will look and wait for a postback to be finished. It does this by calling the WaitForComplete method on the DomContainer. This wait logic has been implemented to wait until everything on the page is loaded. If your webpages have many/big images and if the test(s) doesn't require the image(s)/movies/etc to be loaded, your tests are waiting unnecessarily (performance is an issue with UI testing).
With this release WatiN offers some new ways to changing this default behavior when needed. First you need to create a new class inheriting from the IE class. Then you can override the WaitForComplete method and inject your own class which implements the IWait inteface. You can also use an even simpler option; use the (build in) element.WaitUntilExists functionality. This waits with a max of 30 seconds (see also IE.Settings for changing this default) for an element to appear on a page.
The following example uses IENoWaitForComplete class which completely disables the default WaitForComplete logic. The execution of the test totally depends on the (build in) auto wait functionality, which waits for the element to exist before executing any action on it.
private class IENoWaitForComplete : IE
{
public IENoWaitForComplete(string url) : base(url) {}
public override void WaitForComplete()
{
// Skip Wait logic because of movies loaded and show on page
}
}
public void NameShouldAlwaysBeEmpty()
{
using (IE ie = new IENoWaitForComplete("www.example.com"))
{
// By default Watin waits until the link is on the page before
// executing the Click. In this case it opens a new webpage
ie.Link(Find.ByText("Log in")).Click();
// Wait until the next page is loaded by checking
// if the link "Log out" exists before the code proceeds
ie.Link(Find.ByText("Log out")).WaitUntilExists();
// Check to see if the name textfield is empty
Assert.IsNull(ie.TextField("name").Value);
}
}
Another option is to inherit the WaitForComplete class and override any of the methods to change the behavior. In your override of WaitForComplete you can use this custom WaitForComplete class like this
private class IEWithCustomWaitForComplete : IE
{
public IEWithCustomWaitForComplete(string url) : base(url) {}
public override void WaitForComplete()
{
WaitForComplete(new MyWaitForCompleteClass())
}
}
API Changes
See this page for a full list of all the API changes between version 1.1.0.4000 and 1.2.0.4000
SourceForge Trackers
Added Feature requests:
1793996 Hide browser at initilization of an IE instance
1793979 Control auto move of the mouse pointer at IE initialization
1759481 Sleep in WaitForComplete() in order to view postbacks
1664472 Add support for setting the event properties when firing an event
1563044 Hiding the IE window
Add the http protocol to the url if it is omitted
Fixed Bugs:
1801634 Ie.Element(x).Click throws System.NullReferenceException
1761030 RunScript
1697343 GetFrameCountFromHTMLDocument fails using framework 1.1
RunScript(scriptcode, language) ignores the language param