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














