Los Techies : Blogs about software and anything tech!

WatiN and INamingContainer adventures


I decided to add a simple WatiN acceptance test today to validate our login page.  When a user enters invalid credentials, the page should show an error message.

To test this, I need to set the text of the username and password, and click the Login button.  Since I didn't want just any textbox, but specifically the username and the password, I like to use the element ID's to find them.

We're using the ASP.NET Login control to provide the login interface, which has the textboxes, the button, and the error message in one package.  When I want to get the ID, this is what it winds up being:

ctl00_ctl00_ContentPlaceHolderMain_CenterContent_ctl00_ctlLogin_UserName

Well that's no fun.  The INamingContainer interface puts out some crazy HTML element IDs to guarantee uniqueness.  Luckily I can use regular expressions to search for elements ending in "UserName", and that works for the button, too.

However, the error message does not have an ID around it, so I have to dig into the login control manually to fish it out:

Table loginControl = browser.Table(new Regex("._ctlLogin$"));
TableCell errorCell =
    loginControl.TableBodies[0].TableRows[0].TableCells[0].
        Tables[0].TableBodies[0].TableRows[3].TableCells[0];

Since I don't have access to the innards of the HTML in the Login control, this is what I have to resort to.

I'm really looking forward to MVC framework, where I can take back control over the HTML generated.  At least WatiN will be easier.

Kick It on DotNetKicks.com
Posted Jan 23 2008, 03:16 PM by bogardj
Filed under: ,

Comments

Darrell Mozingo wrote re: WatiN and INamingContainer adventures
on 01-24-2008 7:51 AM

You can use the LayoutTemplate section of the Login control to specify your own HTML, and therefore control IDs. See:

msdn2.microsoft.com/.../system.web.ui.webcontrols.login.layouttemplate(VS.80).aspx

msdn2.microsoft.com/.../ms178339(VS.80).aspx

ftorres wrote re: WatiN and INamingContainer adventures
on 01-24-2008 9:50 PM

Interresting problem to solve, The next version of InCisif.net (2.1) will support this problem during recording and run time and produce clear code like this one:

Page.Control(AspNetId("butCreateAccount")).Click(); //  ASP.NET ID:ctl00$ContentPlaceHolder1$butCreateAccount

Page.WaitForPage(@"/frmCreateAccount.aspx");

Page.Control(AspNetId("FirstName")).Text = "Joe"; //  ASP.NET ID:ctl00$ContentPlaceHolder1$FirstName

Page.Control(AspNetId("LastName")).Text = "Doe"; //  ASP.NET ID:ctl00$ContentPlaceHolder1$LastName

Page.Control(AspNetId("butOK")).Click(); //  ASP.NET ID:ctl00$ContentPlaceHolder1$butOK

Page.WaitForPage(@"/MainMenu.aspx");

The function AspNetId can be override and the default implementation look like this:

    public virtual string AspNetId(string id){

           string t = string.Format(@"re:(.*\${0}$)|(.*_{0}$)", id);

           if(Page.Control(t)!=null)return t;

           return id;

       }

Frederic Torres

<a href="http://www.InCisif.net">www.InCisif.net</a>

Web Testing with C# or VB.NET

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems