Sunday, December 15, 2013

Async Polymer Tests (JS)


After a minor inconvenience testing an asynchronous Dart Polymer element, I wonder how it works to do the same with JavaScript?

The answer is that it works surprisingly difficultly.

I am somewhat surprised as I already have a testing chapter in Patterns in Polymer, so I thought I had this figured out. I am still using Karma as the test runner with Jasmine as the testing framework. I have to perform some hackery to get the Polymer library and my custom Polymers loaded in the proper order. Still, I though I had this sussed out.

The list of files in my Karma configuration is:
    /**
     * Don't include Polymer HTML and JS because Polymer is very
     * particular about the order in which they are added. Serve them,
     * but defer loading to the test setup. Include test HTML
     * fixtures.
     */
    // list of files / patterns to load in the browser
    files: [
      'test/PolymerSetup.js',
      {pattern: 'scripts/**', included: false, served: true},
      'test/**/*Spec.js'
    ],
The entry that is causing me grief is the middle one. When I check that glob on the filesystem, it includes my parent.html Polymer (along with the Polymer library and the child.html Polymer):
s -1 scripts/**
scripts/child.html
scripts/parent.html
scripts/polymer.min.js
scripts/polymer.min.js.map
But when I try to run my tests, I find that my parent.html is 404ing:
➜  parent_child git:(master) ✗ karma start
INFO [karma]: Karma v0.10.4 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 32.0.1700 (Linux)]: Connected on socket bnd9TqMfxiLeUMXYog0b
WARN [web-server]: 404: /base/scripts/parent.html
...
Hunh?

This worked previously. Otherwise, how could I have written a chapter on the subject? After a time, I realize that the only difference between my earlier, working Karma configuration and this new one is that the former also has a preprocessor entry that matches my text fixtures:
    preprocessors: {
      'test/*.html': 'html2js'
    },
I have no test fixtures for this test, so I had not included the setting.

If I do include it in my karma.conf.js file this time, it also works. But I have no idea why this would be. The file pattern for the html2js preprocessor does not match the missing scripts/parent.html file. In fact, if I include just the preprocessor setting with no value, then it still works:
    // Without this, Karma will not serve HTML files :-\
    preprocessors: null,
Ultimately, I can find no useful explanation as to why this would behave this way.

Stumped, I move on to the actual tests which, thanks to Jasmine's asynchronous testing support are fairly easy. I need to wait for a timer in the Polymer update itself the counter. If I wait for 1500 milliseconds, then check my expectation, then the test ought to pass:
  it('updates the parent', function() {
    waits(1500);
    runs(function(){
      expect(el.shadowRoot.textContent).toContain('Count: 1');
    });
  });
And that works fine. After doing the same for the child element, I have two passing JavaScript tests to mirror the two passing Dart tests. I am a little bummed about the preprocessor requirement, though I can live with it. Especially given the other hackery that I include in my Polymer test setup for JavaScript, that is barely a cause for concern. Still, I would like to understand that better, so mental note made for a possible follow-up post.

Day #966

1 comment: