Thursday, September 4, 2014

Generating Code from NPM that Installs Bower(!)


I have my eee-polymer-tests testing package for custom Polymer elements in pretty good shape. It will install and configure the necessary Karma configuration and skeleton tests to run a single, generated test on a Polymer element (which passes!). But...

My approach assumes two things: that the element definition is located in the elements subdirectory of the current package and that Bower is being used to install Polymer and its dependencies. Neither is a particularly poor assumption. The elements subdirectory is my personal preference, but I like it because it keeps my custom elements separate from any apparatus used to maintain the code. The Polymer project itself uses Bower for its elements, so I am OK sticking with it.

But, unlike all of the other checks that I have in eee-polymer-tests:
What is the name of the Polymer element being tested? click-sink

Generating test setup for: click-sink
[WARN] File exists: karma.conf.js. (use --force to overwrite)
[WARN] File exists: test/PolymerSetup.js. (use --force to overwrite)
[WARN] File exists: test/ClickSinkSpec.js. (use --force to overwrite)
I am not checking for the proper elements subdirectory, nor the Polymer + Bower configuration.

Testing for the existence of the elements directory is pretty straight-forward after my previous efforts:
function okElements() {
  if (!fs.existsSync('elements')) {
    var message = '[WARN] There is no elements subdirectory for Polymer elements. Tests will fail!';
    console.log(message.red);
    return false;
  }
  return true;
}
Checking for the existence of the bower.json is pretty much the same, except for the filename. I can even read the NPM module's package.json, which is what is running the generator in eee-polymer-tests, and write a corresponding bower.json if it does not already exist:
  var npmJson = JSOaN.parse(fs.readFileSync('package.json'));
  var bowerJson = {
    "name": npmJson.name,
    "version": "0.0.0",
    "description": npmJson.description,
    "ignore": [
      "**/.*",
      "node_modules",
      "bower_components",
      "test",
      "tests"
    ],
    "dependencies": {
      "polymer": "Polymer/polymer"
    }
  };
This gives me the brilliant idea to install Bower as part of eee-polymer-tests and ensure that Polymer is installed. Installing Bower is easy enough with NPM—it is, after all, the JavaScript package manager that is installed with the NPM JavaScript package manager. I add it to the list of eee-polymer-tests' dependencies:
{
  "name": "eee-polymer-tests",
  // ...
  "dependencies": {
    "colors": ">0.0",
    "minimist": ">0.0",
    "bower": ">0.0"
  },
  "peerDependencies": {
    "karma-jasmine": "~0.2.0",
    "karma-chrome-launcher": ">0.0"
  }
}
To actually install, it turns out that Bower has an API:
var bower = require('bower');
function generateBower() {
  // ...
  bower.commands
    .install(['Polymer/polymer'], { save: true }, { /* custom config */ })
    .on('end', function (installed) {
        console.log(installed);
     });
}
Which works quite as expected. Well, the installed object that is logged is just an empty object literal, but it does save changes to the bower.json file that is currently installed.

As cool as that is, I lean toward not using it. I have no idea if any besides myself will have use for eee-polymer-tests. Generating a simple test structure with it is one thing (and will be quite helpful), but I already install bower out of habit. I will likely file this under “good to know,” but focus elsewhere. Like actually writing some new tests tomorrow.

Update: Ah, the heck with it. I added bower generation after all: bfe13c3.

Day #173

No comments:

Post a Comment