Tuesday, December 23, 2014

Can't Protractor Polymer on Internet Explorer


All right, let's see if I can figure out what went wrong while running my Polymer + Protractor tests in Internet Explorer. On the face of it, Polymer and Protractor are not an obvious combination since Polymer is a web component (not an application) and Protractor is designed to test single-page applications, specifically AngularJS. Also, WebDriver (on which Protractor is based) does not support shadow DOM. That said, there are some definite reasons to like the Polymer + Protractor combination. Plus, tests should work on all browsers, including Internet Explorer.

Emphasis on should.

I am unsure where I went wrong the other night, but trying to run this stuff on IE11 instead of 10 seemed a next logical step. So I retrace my steps from that post (and from the source post). On the windows virtual machine, I install node.js. I install Java. I open a command prompt and install protractor globally (npm install -g protractor).

Side note, I omitted installing the IE WebDriver in the previous post. When I try to start WebDriver without it, I see:
C:\Users\IEUser>webdriver-manager start --seleniumPort=4411
Selenium Standalone is not present. Install with webdriver-manager update --standalone
The fix is to tell the webdriver manager to install the IE driver:
C:\Users\IEUser>webdriver-manager update --ie
With that, I can start my WebDriver server:
C:\Users\IEUser>webdriver-manager start --seleniumPort=4411
20:27:18.602 INFO - Launching a standalone server
Setting system property webdriver.ie.driver to C:\Users\IEUser\AppData\Roaming\npm\node_modules\protractor\selenium\IEDriverServer.exe
20:27:18.894 INFO - Java: Oracle Corporation 25.25-b02
20:27:18.908 INFO - OS: Windows 7 6.1 x86
20:27:18.922 INFO - v2.44.0, with Core v2.44.0. Built from revision 76d78cf
20:27:19.145 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4411/wd/hub
...
20:27:19.353 INFO - Started SocketListener on 0.0.0.0:4411
Back on my Linux machine, I update the protractor.conf.js to point to this IE11 instance of WebDriver:
exports.config = {
  seleniumAddress: 'http://localhost:4411/wd/hub',
  capabilities: {
    'browserName': 'internet explorer',
    'platform': 'ANY',
    'version': '11'
  },
  // seleniumAddress: 'http://localhost:4444/wd/hub',
  specs: ['tests/XPizzaSpec.js'],
  onPrepare: function() {
    require('./tests/polymerBrowser.js');
    require('./tests/xPizzaComponent.js');
  }
};
And, I also need to point the specs to my IP address instead of localhost so that the IE VM can connect to it:
describe('', function(){
  beforeEach(function(){
    browser.get('http://192.168.1.129:8000');
    // browser.get('http://localhost:8000');
  });
  // Tests here...
});
Last, I add a port forwarding rule on the VM so that my Protractor tests on the Linux box can connect to that WebDriver address on post 4411 of localhost.

With that… I see the exact same behavior that I saw the other night with IE10:
$ protractor --verbose
Using the selenium server at http://localhost:4411/wd/hub
[launcher] Running 1 instances of WebDriver
<x-pizza>
  has a shadow DOM - pass
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
The last active task was:
WebDriver.findElements(By.cssSelector("x-pizza"))
    at [object Object].webdriver.WebDriver.schedule (/home/chris/local/node-v0.10.20/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:345:15)
    at [object Object].webdriver.WebDriver.findElements (/home/chris/local/node-v0.10.20/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:934:17)
  ...
  updates value when internal state changes - fail
Sigh.

As I saw with IE, the first test, which asks the Polymer element to send back its shadow DOM innerHTML via a Protractor executeScript(), works. The second test, which adds pepperoni toppings to the <x-pizza> element then asserts on the value attribute, fails. What is weird about the failure is that I can see the pepperoni toppings added in WebDriver IE:



So the problem is not interacting with the Polymer element, it is querying the value property. Interacting with the element involved a bit of hackery since Protractor does not support the shadow DOM, but the hackery would seem to work. What does not work is the thing that should work without any hackery at all—querying element attributes.

Of course, the hackery could be partially to blame. This works in Chrome and Firefox, but that does not necessarily work in all browsers. To see if that is the case, I remove the page object that updates the pizza toppings:
describe('<x-pizza>', function(){
  beforeEach(function(){
    browser.get('http://192.168.1.129:8000');
    // browser.get('http://localhost:8000');
  });

  it('updates value when internal state changes', function() {
    // new XPizzaComponent().
    //   addFirstHalfTopping('pepperoni');

    expect($('x-pizza').getAttribute('value')).
      toMatch('pepperoni');
  });
});
The test should fail, but hopefully it will be an assertion failure, not a timeout.

Unfortunately, it has no effect.

I am at a loss at what to try next. The developer tools on my IE11 installation are useless (I mean more than normal—I cannot type in the console). I would like to be able to test against IE, but it is not that important to me. I am inclined to set this aside until inspiration (or a driver update) arrive. Until then, I will likely move onto to other topics.


Day #33

1 comment: