Friday, June 18, 2010

Video: Mailboxes in CodeSmith Insight

The primary goal of CodeSmith Insight is to "unite different forms of communication", and email is a crucial medium with which users communicate with us. This is why Insight is capable of both importing and sending email, and this is why Insight includes a complete email client build into it's web UI.

Insight's email capabilities are all controlled by Mailboxes inside the system. To help demonstrate the configuration and use of these Mailboxes, I have created a new tutorial video:

Mailboxes in Insight

Enjoy!

Friday, June 11, 2010

Selenium 2 and WebDriver Extensions for .NET

If you have not had a change to play around with the Selenium 2 and WebDriver, let me assure you that it is worth checking out! We have been using WebDriver to help create unit tests for our new product, CodeSmith Insight, which is build using ASP.NET MVC2 for the back end and the ExtJS framework for our AJAX client.

Despite already being infinitely better than Selenium 1, it is still under development and in need of some polish. The good news is that by simply implementing a few extension methods, it can become a bit more versatile and a lot easier to work with.

Below are just definitions for the extension methods, please download the code from here.

LINQ Driver Extensions

The Find methods for WebDriver work with different selectors, but none of which support using LINQ expressions to search the resulting elements.

public static IWebElement FindElement(this IWebDriver driver, By by, Func<IWebElement, bool> predicate)
public static IEnumerable<IWebElement> FindElements(this IWebDriver driver, By by, Func<IWebElement, bool> predicate)

// Example
IWebElement el = driver.FindElement(By.CssSelector("input"), e => e.Value == "Save");

WaitFor Driver Extensions

WebDriver is great when working with elements that already exist on the page, but it is not so good at working with dynamic page elements. This is a slightly hacky solution, but I created added Wait method to the driver itself that just sleeps the current thread, and then I added WaitFor methods that sleep while waiting for elements to appear. This makes it much easier to work with elements that result from AJAX calls.

public static void Wait(this IWebDriver driver, int seconds = DefaultTimeout)
public static IWebElement WaitForElement(this IWebDriver driver, By by, Func<IWebElement, bool> predicate = null, int seconds = DefaultTimeout)
public static IEnumerable<IWebElement> WaitForElements(this IWebDriver driver, By by, Func<IWebElement, bool> predicate = null, int seconds = DefaultTimeout)

// Example
IWebElement el = driver.WaitForElement(By.CssSelector("div.success"), e => e.Text == "Cart saved!");

FrameSwitcher

When switching between frames on a webpage, WebDriver actually changes the target of your Driver object. I created the FrameSwitcher class so that I could use a disposable pattern and reference my frame calls inside of a using block.

public static FrameSwitcher SwitchToFrame(this IWebDriver driver, By by)

// Example
using (driver.SwitchToFrame(By.Id("email_iframe")))
{
    driver.FindElement(By.CssSelector("input.to")).SendKeys("tom@codesmithtools.com");
    driver.FindElement(By.CssSelector("button.send")).Click();
}

IJavaScriptExecutor

I did not feel that their documentation made it readily apparent, but you can still execute JavaScript against the web page. This is done by casting your WebDriver as IJavaScriptExecutor.

public static IJavaScriptExecutor GetJavaScriptExecutor(this IWebDriver driver)

// Example
var js = driver.GetJavaScriptExecutor();
js.ExecuteScript("Insight.getMainViewport().viewTreePanel.setClick(true);");

Real Time Web Analytics