Sunday, December 28, 2014

A Solution for Karma Testing Polymer on IE (10 & 11)


I coded in WordPad yesterday. 15 years of successfully repressing that sensation and now I fear I may never recover.

Still, I successfully got Karma & Jasmine to test Polymer code with Internet Explorer yesterday. So it was worth it. Kinda.

Regardless, I am happy to have gotten testing of Polymer on IE working, but I still have a few outstanding questions that I'd like answered before moving on to less traumatizing subjects. My IE Polymer tests work with karma-ie-launcher and IE10. I would like to be able to run karma-webdriver-launcher and use it on both IE10 and IE11.

Switching to karam-webdriver-launcher would mean no more WordPad coding (since the code resides on the host machine, not the guest VM), so I will start there. I already have Karma configuration in place that should work:
module.exports = function(config) {
  config.set({
    // ...
    // Use IP so Windows guest VM can connect to host Karma server
    hostname: '192.168.1.129',
    customLaunchers: {
      'IE10': {
        base: 'WebDriver',
        config: {
          hostname: 'localhost',
          port: 4410
        },
        browserName: 'internet explorer',
        name: 'Karma'
      }
    },
    browsers: ['IE10']
  });
};
I was able to use this to connect to webdriver on Windows the other day, I just could not get the tests to pass. Without changing the tests, I still get very unhelpful failures:
$ karma start --single-run 
INFO [karma]: Karma v0.12.28 server started at http://192.168.1.129:9876/
INFO [launcher]: Starting browser internet explorer via Remote WebDriver
INFO [IE 10.0.0 (Windows 8)]: Connected on socket WUsG_gAEAHJFhm1lLF0G with id 61543069
IE 10.0.0 (Windows 8) ERROR
  Object doesn't support property or method 'indexOf'
  at /home/chris/repos/polymer-book/play/plain_forms/js/node_modules/karma-jasmine/lib/jasmine.js:1759
IE 10.0.0 (Windows 8): Executed 1 of 3 ERROR (0.645 secs / 0.547 secs)
This indexOf failure seems to come from calling a “contains” matcher in my tests on undefined values. As I found yesterday, that is more of a symptom of larger Karma issues than individual test failures.

So I try yesterday's wait-a-browser-event-loop / set-timeout-zero solution in my tests:
  describe('properties', function(){
    it('updates value when internal state changes', function(done) {
      el.model.firstHalfToppings.push('pepperoni');
      el.async(function(){
        setTimeout(function(){
          expect(el.value).toContain('pepperoni');
          done();
        }, 0);
      });
    });
  });
The el here is my <x-pizza> pizza building Polymer element. The asyc() method from Polymer accepts a callback that will be invoked after Polymer has updated the UI and all bound variables. That works on its own in Chrome and Firefox, but, as I found yesterday, Polymer's IE implementation seems to have a bug that requires an additional browser event loop before everything is ready.

And, with that set-timeout-zero, I have my IE WebDriver tests passing:
$ karma start --single-run 
INFO [karma]: Karma v0.12.28 server started at http://192.168.1.129:9876/
INFO [launcher]: Starting browser internet explorer via Remote WebDriver
INFO [IE 10.0.0 (Windows 8)]: Connected on socket oggMD2c6Q8c4-xq-Lk_- with id 68843724
IE 10.0.0 (Windows 8): Executed 3 of 3 SUCCESS (0.54 secs / 0.543 secs)
So what about IE11? Things were even worse in that VM because I have yet to get the console in the Web Developer Tools to start successfully, making troubleshooting next to impossible. Perhaps the set-timeout-zero fix works there as well?

In the Windows VM, I fire up a good old command prompt (I can't believe that it hasn't changed in 10+ years). In there, I start WebDriver via the webdriver node.js package:
C:\Users\IEUser>webdriver-manager start --seleniumPort 4411
I run the IE10 WebDriver on port 4410 and the IE11 WebDriver on 4411. So I update my karma.conf.js accordingly:
module.exports = function(config) {
  config.set({
    // ...
    // Use IP so Windows guest VM can connect to host Karma server
    hostname: '192.168.1.129',

    customLaunchers: {
      'IE10': { /* ... */ },
      'IE11': {
        base: 'WebDriver',
        config: {
          hostname: 'localhost',
          port: 4411
        },
        browserName: 'internet explorer',
        name: 'Karma'
      }
    },

    browsers: ['IE11']
  });
};
Unfortunately, when I try to run the same Karma tests against IE11, I find:
$ karma start --single-run 
INFO [karma]: Karma v0.12.28 server started at http://192.168.1.129:9876/
INFO [launcher]: Starting browser Internet Explorer 11 via Remote WebDriver
INFO [IE 11.0.0 (Windows 7)]: Connected on socket xu5uT_EaFT6kfCVrTOpE with id 86153250
IE 11.0.0 (Windows 7) <x-pizza> properties updates value when internal state changes FAILED
        TypeError: Unable to get property 'firstHalfToppings' of undefined or null reference
           at Anonymous function (/home/chris/repos/polymer-book/play/plain_forms/js/test/XPizzaSpec.js:29:7)
IE 11.0.0 (Windows 7) <x-pizza> syncing <input> values updates the input FAILED
...
IE 11.0.0 (Windows 7): Executed 3 of 3 (2 FAILED) (0.4 secs / 0.396 secs)
INFO [WebDriver]: Killed Karma test.
For whatever reason, it seems that my Polymer element is taking more than the usual single event loop to register in IE11. A single event loop is all that is required in Chrome, Firefox, and IE10. But IE11 requires an additional 10 milliseconds before it is ready:
describe('<x-pizza>', function(){
  var el, container;

  beforeEach(function(done){
    container = document.createElement("div");
    container.innerHTML = '<x-pizza></x-pizza>';
    document.body.appendChild(container);
    el = document.querySelector('x-pizza');

    setTimeout(done, 10); // Delay for elements to register in Polymer
  });

  describe('properties', function(){
    it('updates value when internal state changes', function(done) {
      // Same async + set-timeout-zero test here...
    });
  });
});
With that, I have my tests passing on IE11:
$ karma start --single-run 
INFO [karma]: Karma v0.12.28 server started at http://192.168.1.129:9876/
INFO [launcher]: Starting browser Internet Explorer 11 via Remote WebDriver
INFO [IE 11.0.0 (Windows 7)]: Connected on socket sQqPBHAEvsL1ujLtULSD with id 7115351
IE 11.0.0 (Windows 7): Executed 3 of 3 SUCCESS (0.634 secs / 0.566 secs)
And this seems to work reliably. I run through 10 single-run rounds of tests and all pass each time. If I drop down to 2 milliseconds, then tests start failing on occasion. If I really, really needed IE testing, I might bump these timeout delays for 50 or 100 milliseconds. For now, I'm just happy with a reliable local solution.

So it is ugly. It is rife with callbacks, set-timeout-zeros and other more arbitrary set-timeouts. But I have a working solution for testing Polymer on Internet Explorer. And I didn't even need to fire up WordPad.


Day #38

No comments:

Post a Comment