Monday, June 3, 2013

Async Dart Tests with State

‹prev | My Chain | next›

The Dart version of the ICE Code Editor is very nearly ready for moving out to public beta. There are a couple must-have features that need to be completed first. Some ought to be pretty straight-forward. One that worries me a little is the auto-save feature in ICE.

Auto-save by and of itself should not be too hard. What worries me is the implications to existing functionality. Hopefully my test suite will catch any such problems.

So I start with a new test:
  group("Auto Save", (){
    var editor;

    setUp(()=> editor = new Full(enable_javascript_mode: false));

    test("is on by default", (){
      helpers.createProject('Test Project');
      editor.content = '<h1>test</h1>';

      var store = new Store();
      expect(
        store['Test Project']['code'],
        equals('<h1>test</h1>')
      );
    });
  });
During one of my #pairwithme sessions, my pair forced me to finally create the createProject() helper method. It still uses all of the on-screen UI elements to create a project, but it is more compact. Once I have the project, I set some HTML content and check my expectations against the localStorage Store data.

Since I have not implemented this feature yet, it fails:
FAIL: Auto Save is on by default
  Expected: '<h1>test</h1>'
       but: was null:<null> (not type String).
I expose the onChange stream from the js-interop proxied ACE code editor in the full-screen class. With that, I can establish a listener that updates the data store's content whenever a change takes place:
class Full {
  Full({enable_javascript_mode: true}) {
    // ...
    editorReady
      ..then((_)=> _startAutoSave())
      // ...
  }
  // ...
  _startAutoSave() {
    ice.onChange.listen((_){
      var title = store.projects.first['title'];
      store[title] = {'code': ice.content};
    });
  }
}
Brilliant. Except my test still fails exactly the same way:
FAIL: Auto Save is on by default
  Expected: '<h1>test</h1>'
       but: was null:<null> (not type String).
In the end, I am unable to get this working. The feature works if I test it in the actual full-screen IDE. The test even passes when run as a solo, asynchronous test:
    solo_test("is on by default", (){
      helpers.createProject('Test Project');
      editor.content = '<h1>test</h1>';

      _test(_) {
        expect(
          editor.store['Test Project']['code'],
          equals('<h1>test</h1>')
        );
      }

      editor.editorReady.then(expectAsync1(_test));
    });
But, when run as part of a test suite—a test suite that is also writing data in localStorage—I am unable to get the tests passing. I may have finally reached the limit of what I can test at a functional level. Tomorrow, I may take a step back and write an actual unit test.


Day #771

No comments:

Post a Comment