I now know the trick for dynamically generating Polymer definitions. I just don't know how to get that trick to work in Karma / Jasmine tests.
As I found last night, the trick to dynamically generate Polymer elements in regular web pages is to build the
<script>
portions of the definition via document.createElement()
rather than building the <script>
tag via innerHTML assignments. Easy enough, I can live with that.But when I tried to do the same think in my Jasmine tests, I kept getting an error about
Polymer
not being defined:Uncaught ReferenceError: Polymer is not definedBleary eyed, I was unable to figure out why this would be the case. With fresh eyes today, I realize that sample page and my tests are not quite the same. In my sample page, I have hard-coded the
<script>
tag for the Polymer platform:<!doctype html> <html> <head> <script src="bower_components/platform/platform.js"></script> <link rel="import" href="../bower_components/polymer/polymer.html"> <script> var double_el = document.createElement('polymer-element'); double_el.setAttribute('name', 'x-double'); double_el.setAttribute('attributes', 'in out'); var script = document.createElement('script'); script.innerHTML = ' Polymer("x-double", { /* ... */ });'; double_el.appendChild(script); document.getElementsByTagName("head")[0].appendChild(double_el); </script> </head> <body> <!-- ... --> <x-double in="6"></x-double> </body> </html>In my tests, I have been dynamically adding those during test setup:
var script = document.createElement("script"); script.src = "/base/bower_components/platform/platform.js"; document.getElementsByTagName("head")[0].appendChild(script); var link = document.createElement("link"); link.rel = 'import'; link.href = "/base/bower_components/polymer/polymer.html"; document.getElementsByTagName("head")[0].appendChild(link);And indeed, if switch my sample page to use those dynamically built
<script>
and <link>
tags, then I see the same failure in my browser. I cannot hard-code those tags in Karma tests -- Karma decides which tags get added first and how. What ends up working is to assign an
onload
function to the Polymer platform's <script>
tag:var script = document.createElement("script"); script.src = "/base/bower_components/platform/platform.js"; script.onload = defineTestPolymerElements; document.getElementsByTagName("head")[0].appendChild(script); var link = document.createElement("link"); link.rel = 'import'; link.href = "/base/bower_components/polymer/polymer.html"; document.getElementsByTagName("head")[0].appendChild(link);With that, my full test setup for a dynamically defined Polymer element looks like:
var script = document.createElement("script"); script.src = "/base/bower_components/platform/platform.js"; script.onload = defineTestPolymerElements; document.getElementsByTagName("head")[0].appendChild(script); var link = document.createElement("link"); link.rel = 'import'; link.href = "/base/bower_components/polymer/polymer.html"; document.getElementsByTagName("head")[0].appendChild(link); function defineTestPolymerElements() { var double_el = document.createElement('polymer-element'); double_el.setAttribute('name', 'x-double'); double_el.setAttribute('attributes', 'in out'); var script = document.createElement('script'); script.innerHTML = ' Polymer("x-double", {\n' + ' publish: {\n' + ' out: {value: 0, reflect: true}\n' + ' },\n' + ' ready: function(){\n' + ' this.inChanged();\n' + ' },\n' + ' inChanged: function(){\n' + ' this.out = parseInt(this.in) * 2;\n' + ' }\n' + ' });\n'; double_el.appendChild(script); document.getElementsByTagName("head")[0].appendChild(double_el); } // Delay Jasmine specs until polymer-ready var POLYMER_READY = false; beforeEach(function(done) { window.addEventListener('polymer-ready', function(){ POLYMER_READY = true; }); waitsFor(function(){return POLYMER_READY;}); });With that, I think I have finally answered all of the little questions that occurred to me while trying to test code that interacts with any Polymer elements. I did not strictly need to answer these questions to get my task done—testing AngularJS interaction in angular-bind-polymer. Even so, it is good to have a better understanding of all of this. Maybe tomorrow I can actually write the angular-bind-polymer test that I started on 7 days ago!
Day #47
No comments:
Post a Comment