I hate a problem unsolved. I really ought to move onto more useful ground, but I cannot for the life of me understand why I cannot get The Intern tester running with Polymer elements. So tonight, I try to remove one potential problem point from the equation: Sauce Labs.
Really, there is no reason that this should work, but if nothing else, running locally will give me more real time feedback on what might possibly be going on here. But I'll be honest here, I hate Selenium locally (which is one of the reasons I really appreciate Sauce Labs).
Running it is easy enough. I download the latest standalone server from the download page. I can then run the server immediately with:
$ java -jar Downloads/selenium-server-standalone-2.44.0.jar 00:07:06.282 INFO - Launching a standalone server 00:07:06.366 INFO - Java: Oracle Corporation 24.65-b04 00:07:06.366 INFO - OS: Linux 3.13.0-37-generic amd64 00:07:06.388 INFO - v2.44.0, with Core v2.44.0. Built from revision 76d78cf ... 00:07:06.606 INFO - Started HttpContext[/wd,/wd] 00:07:06.611 INFO - Started SocketListener on 0.0.0.0:4444But for the life of me, I cannot figure out how to install the Firefox driver. How stupid is that? This must be so obvious to just about everyone else, but I've got nothing.
Eventually, I read that the extension is contained in the standalone server. I would think that would mean that I could install it from the running server, but if that is case, I am unable to make it happen. So I unzip the JAR file:
$ unzip ../selenium-server-standalone-2.44.0.jar ... creating: org/openqa/grid/selenium/ creating: org/openqa/grid/selenium/proxy/ creating: org/openqa/grid/selenium/utils/ inflating: org/openqa/grid/selenium/GridLauncher.class inflating: org/openqa/grid/selenium/proxy/DefaultRemoteProxy$1.class inflating: org/openqa/grid/selenium/proxy/DefaultRemoteProxy.class inflating: org/openqa/grid/selenium/utils/WebProxyHtmlRenderer.classThat does contain the XPI:
$ find | grep xpi$ ./org/openqa/selenium/firefox/webdriver.xpiArmed with that, I install it by directly pointing Firefox to the location on disk:
After allowing this to occur:
I am ready to make some changes to the Intern
tests/intern.js
configuration code. I switch from a specific browser version on Sauce Labs to my local Firefox: environments: [
// { browserName: 'chrome', version: '34', platform: [ 'Linux' ] }
{ browserName: 'firefox' }
]
I switch from the Sauce Labs tunnel to no tunnel: // Name of the tunnel class to use for WebDriver tests
//tunnel: 'SauceLabsTunnel',
tunnel: 'NullTunnel',
useSauceConnect: false,
Finally, I add webdriver configuration (this may not be necessary): webdriver: {
host: 'localhost',
port: 4444
},
With that in place, I am ready to try again… which results in:$ ./node_modules/.bin/intern-runner config=tests/intern Listening on 0.0.0.0:9000 Starting tunnel... Initialised firefox 34.0 on LINUX Test main - index - <x-pizza> FAILED on firefox 34.0 on LINUX: CancelError: Timeout reached on main - index - <x-pizza> Error: Timeout reached on main - index - <x-pizza> at Error <anonymous> at new ErrorCtor <node_modules/intern/node_modules/dojo/errors/create.js:13:21> at null._onTimeout <node_modules/intern/lib/Test.js:180:38> at Timer.listOnTimeout [as ontimeout] <timers.js:110:15>Unfortunately, this seems even worse than yesterday. The timeout is occurring while waiting for the Polymer element's shadow root property to come into existence:
'<x-pizza>': function () {
return this.remote
.get(require.toUrl('../index.html'))
.setFindTimeout(5000)
.findByXpath('//body[not(@unresolved)]')
.then(pollUntil('return document.querySelector("x-pizza").shadowRoot;', 1000))
.findByTagName('x-pizza')
// .execute('return document.querySelector("x-pizza");')
.then(function (el) {
console.log(el);
console.log(el.$);
console.log(el.constructor);
console.log(el.shadowRoot);
console.log(el[0]);
assert.isDefined(el.shadowRoot);
});
}
That at least happened with Sauce Labs, but never returns locally. This is baffling because I can see the <x-pizza>
element just starting to be resolved after Polymer has initialized and removed the unresolved
attribute from the <body>
:Unfortunately, I cannot think of anything else to try tonight that I had not already tried last night with Sauce Labs. If nothing else, I can see very definitely tonight that the
<x-pizza>
element is present and should have a shadowRoot
(which is where the SVG pizza resides). But for whatever reason, the Intern is unable to access this element for testing.I think I am ready to give up on Intern for real now, but I may give Protractor a whirl with this tomorrow. Even if this particular WebDriver tool cannot yet test Polymer, perhaps another tool can.
Day #23
Hello Chris,
ReplyDeleteThanks for the great write up about Intern and Polymer. It helped me get up and running with Intern to test Polymer.
In your case it should be related to the fact that custom elements do not have 'shadowRoot' in FireFox as it has not yet been implemented in FireFox. There are some Polyfills to do the job. So even manually in the console the following would return `false`:
```
var pizza_elements = document.getElementsByTagName('x-pizza');
pizza_elements[0].hasOwnProperty('shadoRoot'); // Returns false in FireFox, return true in Chrome
```
Remove FireFox from the environments and see how it works. Then you would be able to adopt the tests accordingly.
Thanks for the great blog posts, they have been very helpful. Keep up the great work.
Even in Firefox, the Polymer element has a shadowRoot property (even if it's not a hasOwnProperty). The test is accessing it as a regular property, so I don't know why it would behave differently in Chrome. Still, I'll be sure to give it a try.
DeleteGlad you were able to get it working!
Thanks Chris. I came up with some thing which works but it is pretty ugly.
DeleteYou have to return whatever you want to test in the `pollUntil` function. It wraps it in a Promise and in the `then` part you could grab the value and do the assert.
The sad part is returning the element itself won't work as you will get the same:
stale element reference: element is not attached to the page document
So in case of your code it would be something like this:
'': function () {
return this.remote
.get(require.toUrl('../index.html'))
.setFindTimeout(5000)
.findByXpath('//body[not(@unresolved)]')
.then(pollUntil(function () {
if (document.querySelector("x-pizza").shadowRoot) {
return document.querySelector("x-pizza").shadowRoot.querySelector("nested-x-pizza").id;
}
return null;
}, [], 1000))
.then(function (pizzaId) {
assert.equal(pizzaId, 'expectedValue');
}, function (err) {
});
}
Yup, that sounds similar to what I wound up doing in Protractor (another webdriver testing tool): http://japhr.blogspot.com/2014/12/protractor-can-test-polymer-sort-of.html.
DeleteI begin to think that webdriver-based tools are not appropriate for testing Polymer, mostly because of the inability to access the shadow dom (but for other reasons as well).
Web Component Tester uses Polymer.whenReady() to wait till polymer has done all its microtasks. May be you can try it out. I have internjs on my to learn list still –
ReplyDeleteYup, I use Polymer.whenReady() in the book for testing as well. Unfortunately, webdriver does not grant access to the Polymer top-level object (as best I can tell). Without it, that doesn't work :(
DeleteThanks Chris.
ReplyDeleteFor future references I summarized my experience in a blog post: http://mmxgroup.net/2014/12/16/testing-a-google-polymer-project-using-internjs/
Cool! Saves me the trouble of having to figure it out and write it up myself. Thanks :)
Delete