Up today, I continue my efforts to build something of a testing solution for Polymer elements. The built-in testing Dart solutions have been more than up to the task with Polymer.dart, but the JavaScript testing setup has proved trickier. To resolve the various annoyances, I have what I think is a relatively simple approach, but with some definite opinions. This seems ideal for extracting into a node.js package, if only to ease my own Polymer testing.
Last night, I extracted a bunch of the Karma configuration out into eee-polymer-tests. Now that it is a GitHub project, I can specify it as a development dependency in custom Polymer elements:
{ "name": "parent-events", "devDependencies": { "eee-polymer-tests": "eee-c/eee-polymer-tests" } }After
npm install
(following the traditional rm -rf node_modules
), I have Karma, Jasmine, and other testing requirements as well as settings from eee-polymer-tests:$ rm -rf node_modules $ npm install karma-chrome-launcher@0.1.4 node_modules/karma-chrome-launcher karma@0.12.23 node_modules/karma karma-jasmine@0.2.2 node_modules/karma-jasmine eee-polymer-tests@0.0.1 node_modules/eee-polymer-tests $ ls -l node_modules/eee-polymer-tests total 16 -rw-r--r-- 1 chris chris 2022 Aug 31 01:06 karma-common.conf.js -rw-r--r-- 1 chris chris 1078 Aug 31 01:06 LICENSE -rw-r--r-- 1 chris chris 1340 Aug 31 22:02 package.json -rw-r--r-- 1 chris chris 306 Aug 31 01:06 README.mdThanks to NPM peer dependencies, the Karma and Jasmine packages are installed for easy use in my element's tests. Thanks to the
karma-common.conf.js
from last night, my own karma.conf.js
is nothing more than:module.exports = function(config) { var common = require('./node_modules/eee-polymer-tests/karma-common.conf.js'); config.set(common.mixin_common_opts(config, { // ... })); };With no other setup required, my tests still pass:
$ karma start --single-run INFO [karma]: Karma v0.12.23 server started at http://localhost:9876/ INFO [launcher]: Starting browser Chrome INFO [Chrome 37.0.2062 (Linux)]: Connected on socket B3i3n_dnKrvjoYei80Jc with id 60115395 Chrome 37.0.2062 (Linux): Executed 2 of 2 SUCCESS (0.076 secs / 0.072 secs)That is pretty good, but I would like to be able to generate some of the testing code that is currently required to make all of this work:
. ├── bower.json ├── elements │ └── click-sink.html ├── index.html ├── karma.conf.js ├── package.json └── test ├── ClickSinkSpec.js └── PolymerSetup.jsThe
bower.json
file exposes a hidden dependency on Bower. The only real consideration for Bower is that my tests expect Polymer dependencies to be installed in bower_components
. I will defer consideration of that until another day. For now, I would like to write a script that creates the other three files in the list. I start with
test/PolymerSetup.js
, which is nearly boilerplate except for the inclusion of the main Polymer element at the very end of the file:// Delay Jasmine specs until Polymer is ready var POLYMER_READY = false; beforeEach(function(done) { /* wait for polymer-ready */ }); // 1. Load Polymer before any code that touches the DOM. var script = document.createElement("script"); script.src = "/base/bower_components/platform/platform.js"; document.getElementsByTagName("head")[0].appendChild(script); // 2. Load component(s) var link = document.createElement("link"); link.rel = "import"; link.href = "/base/elements/click-sink.html"; document.getElementsByTagName("head")[0].appendChild(link);I am unsure if there are any standard templating solutions for Node.js (a quick search did not turn one up), so regular expressions it is!
I create a
templates/PolymerSetup.js
file in eee-polymer-test that is identical to the current setup from my working tests. The only change is a mustache-like placeholder for the element name:// Identical up to... // 2. Load component(s) var link = document.createElement("link"); link.rel = "import"; link.href = "/base/elements/{{element-name}}.html"; document.getElementsByTagName("head")[0].appendChild(link);I would prefer that eee-polymer-tests be installed globally (i.e. with
npm install -g
), but that is not going to be an option because of last night's peer dependencies. Instead, this will be run as:$ ./node_modules/eee-polymer-tests/cli.js click-sinkGiven that execution path, the template path will be
./node_modules/eee-polymer-tests/templates/PolymerSetup.js
. There is probably a way to determine this path relative to the currently executing script, but I will leave that for another day.I just want to be able to read the template and write the template with the element applied. The read should look something like:
#!/usr/bin/env node var element = process.argv[2]; var fs = require('fs'); fs.readFile('./node_modules/eee-polymer-tests/templates/PolymerSetup.js', 'utf8', function (err,data) { if (err) { return console.log(err); } writeSetup(data); });The
writeSetup()
can then do the opposite with writeFile()
:function writeSetup(template) { var content = template.replace(/\{\{element-name\}\}/g, element); fs.writeFile('./test/PolymerSetup.js', content); }That takes care of globally replacing the
{{element-name}}
template placeholder (thanks to the g
modified on the regular expression). And that seems to do the trick. I run that code—overwriting the current
PolymerSetup.js
—and re-run the tests to find everything still passing.This seems quite promising for my needs. I am unsure if anyone else will find it similarly useful, but I am definitely filling a need of my own here. I think tomorrow I will continue with this, adding in some overwrite protection. That aside, this is already quite close to what I need.
Day #169