Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With WatiN, I'd like to wait for a jQuery event

I'm hoping that someone out there has done this. I have some custom jQuery modifications that utilize the jQuery event system in order to launch certain events for processing. I'd like to be able to do automated testing in response to these.

Has anyone worked on a better tie in from WatiN to jQuery? I've seen a few posts on a passthrough for jQuery selectors, as well as a post here about waiting for given text to change... Would be cool if someone added jQuery selection, and event support... even the document.getElementsBySelector might be nice.

like image 612
Tracker1 Avatar asked Jan 20 '11 00:01

Tracker1


1 Answers

I don't know if it is what you expect, but I had some time to investigate and I came with a solution to the question : With WatiN, I'd like to wait for a jQuery event.

The goal is to write in C#:

Browser.WaitForEvent("#link", "onclick");

I wrote a test page (available on http://www.sp4ce.net/debug.html) where it triggers a onclick event on the link when you click on the button.

Then I wrote the extension method .WaitForEvent

public static void WaitForEvent(this Browser browser, string selector, string eventname)
{
   using (EventMonitorWatcher monitor = new EventMonitorWatcher(browser, selector, eventname))
   {
      int timeWaited = 0;
      var maxTimeWait = Settings.WaitForCompleteTimeOut * 1000;
      do
      {
         Thread.Sleep(Settings.SleepTime);
         timeWaited += Settings.SleepTime;
      }
      while (!monitor.IsEventCalled() && timeWaited < maxTimeWait);
   }
}

This methods uses a EventMonitorWatcher that check is the event has been called.

public class EventMonitorWatcher : IDisposable
{
   private readonly Browser _browser;
   private readonly string _selector;
   private readonly string _eventname;

   public EventMonitorWatcher(Browser browser, string selector, string eventname)
   {
      _browser = browser;
      _selector = selector;
      _eventname = eventname;
      _browser.Eval(string.Format("startEventMonitor('{0}', '{1}')", _selector, _eventname));
   }

   public bool IsEventCalled()
   {
      string result = _browser.Eval(string.Format(
      "isEventCalled('{0}', '{1}')", _selector, _eventname));
      return result == "true";
   }

   public void Dispose()
   {
      _browser.Eval(string.Format("stopEventMonitor('{0}', '{1}')", _selector, _eventname));
   }
}

This monitor use three javascript (jquery powered) methods that starts a monitoring, stops a monitoring and checks if the event has been called.

startEventMonitor = function(selector, event) {
    $(selector).data('eventMonitorResult', false);
    var eventMonitorHandler = function() {
        $(selector).data('eventMonitorResult', true)
    };
    $(selector).data('eventMonitorHandler', eventMonitorHandler);
    $(selector).bind(event, eventMonitorHandler);
};

stopEventMonitor = function(selector, event) {
    $(selector).undbind(event, $(selector).data('eventMonitorHandler'));
    $(selector).data('eventMonitorResult', false);
};

isEventCalled = function(selector, event) {
    return $(selector).data('eventMonitorResult');
};

Here you are, you then need to inject this javascript as a string your page when you run the browser.

[Test]
public void Test()
{
    using(var browser = new IE("http://www.sp4ce.net/debug.html")
    {
        browser.Eval(JavaScript);
        browser.WaitForEvent("#link", "onclick");
    }
}

In this test, when you click on the "click" button, the test should end directly and your browser be closed;

like image 112
Baptiste Pernet Avatar answered Oct 31 '22 07:10

Baptiste Pernet