Tuesday, August 6, 2013

Dispatching HttpRequest Events is Pretty Useless in Dart


I have a crazy tight deadline for 3D Game Programming for Kids this week, but the gods of the chain are not to be trifled with. So I hope to find some brief topics to keep things flowing.

Building on last night's post on events in Dart, I realized something today: anything that extends the EventTarget class in Dart supports the dispatchEvent() method. This is important to me because HttpRequest extends EventTarget. I have been struggling mightily to figure out how to test HttpRequest and I think this might a cheap way to do it.

And it works. A bit.

Without a backend, I can create a request, and simulate a response by dispatching a load event:
    test('load event', (){
      var container = new DivElement();
      document.body.append(container);

      var req = new HttpRequest();
      req.onLoad.listen((event) {
        var list = JSON.parse(req.responseText);
        container.innerHtml = graphicNovelsTemplate(list);
      });

      req.dispatchEvent(new Event("load"));

      expect(container.innerHtml, contains('asdf'));
    });
That works in that the test passes. The load event is generated and the onLoad stream sees the event and the content is populated. That is all very well, but I have no way to populate the responseText property because it is final—meaning that only native code can set that value in this case. I also cannot cleanly specify the eventTarget property of the event that I dispatch for similar reasons—the constructor does not expose this and there are no setters (again the native implementation would set this).

Even if I could gain access, I realize now that this would be of limited use. HTTP requests are normally made inside a class that needs testing:
    test("POST /stub responds successfully", (){
      var url = 'http://localhost:31337/comics',
          doc = '{"id":"42", "title": "Sandman", "author":"Neil Gaiman"}';

      var req = new HttpRequest();
      req.open('post', url, async: false);
      req.send(doc);

      var el = query('#comics-list');
      new ComicApp(el, url).
        load().
        then(expectAsync1((_) {
          expect(el.innerHtml, contains('Sandman'));
        }));
    })
In this case, I am testing that, when ComicApp loads data from a live test server, that it properly populates a web page. If I wanted to make use of dispatching events, I would need access to the request object inside ComicApp (and I would need to be able to specify responseText). Exposing the innards of a class's implementation solely to support testing is never a good idea.

In other words, this is pretty much a dead end. But a quick enough one that I can get back to putting the last minute touches on 3D Game Programming for Kids.

Day #835

No comments:

Post a Comment