Wednesday, June 18, 2014

Getting Started on grunt-contrib-jasmine for Polymer Testing (Thwarted)


Yesterday was one of those days that I start something I truly believe is easy only to wind up fighting every single decision and ultimately fail to accomplish my task. With a day between me and that failure, I believe my failure was not so much due to underestimating the difficulty of the problem. Rather, it was a stubborn inability to recognize that I was fighting my chosen tools too much.

I am trying to test the new apply-author-styles tag. It is a relatively simple Polymer element to be used in other Polymer elements so that these elements can adapt the same styles that are used on the page using the elements. That is, if my page styles <button> elements to have orange borders, then <apply-author-styles> inside another custom element should ensure that <button> elements in the custom element will have an orange border as well.

To test, I need two things: a page with styles and a custom Polymer element with <apply-author-styles> in its template. Yesterday I got the latter setup without difficulty. The <x-foo> test element should do the trick nicely:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../apply-author-styles.html">
<polymer-element name="x-foo" noscript>
  <template>
    <apply-author-styles></apply-author-styles>
    <button id=test type=button>Test</button>
  </template>
</polymer-element>
After some unrelated fights with both Karma and Jasmine, I finally realized that I had no way to hand alter the test page that Karma uses as its testing environment. I had no way to add the various styles that I need to test.

To be clear, I could dynamically add <link> and <style> tags to the Karma test page, but part of the functionality that I spiked into <apply-author-styles> was to ignore dynamically added styles. I fought with Karma. A lot. Eventually I found that there is no way to specify an alternate test context page in Karma. Which just stinks.

So I am faced with two options: fight Karma again or trying something new. Both have their appeal (I think I could hack in basic support for alternate context.html), but I opt for something new tonight. Specifically, grunt-contrib-jasmine.

I start by installing it:
$ npm install grunt-contrib-jasmine --save-dev
...
Done. Phantomjs binary available at /home/chris/repos/apply-author-styles/node_modules/grunt-contrib-jasmine/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/lib/phantom/bin/phantomjs
grunt-contrib-jasmine@0.6.5 node_modules/grunt-contrib-jasmine
├── es5-shim@2.3.0
├── lodash@2.4.1
├── rimraf@2.1.4 (graceful-fs@1.2.3)
├── chalk@0.4.0 (has-color@0.1.7, ansi-styles@1.0.0, strip-ansi@0.1.1)
└── grunt-lib-phantomjs@0.4.0 (eventemitter2@0.4.13, semver@1.0.14, temporary@0.0.8, phantomjs@1.9.7-9)
I believe that I am going to need a simple web server to test this, so I also install grunt-contrib-connect:
$ npm install grunt-contrib-connect --save-dev
In addition to the previous dependencies that I have in this project, my package.json configuration file now looks like:
{
  "name": "apply-author-styles",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-contrib-jasmine": "~0.6.5",
    "grunt-contrib-connect": "~0.8.0"
  }
}
I add both tasks to my Gruntfile.js:
module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // ...
  });
  // ...
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-contrib-connect');
};
Then I configure both such that the tests will run on port 8100:
module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // ...
    connect: {
      server: {
        options: {
          port: 8100
        }
      }
    },
    jasmine: {
      src: ['app/**/*.js'],
      options: {
        host: 'http://127.0.0.1:8100/',
        specs: 'test/*Spec.js',
      }
    }
  });
  // ...
};
The last thing that I need in there is a task that will start the test server and then run my tests:
module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    // ...
  });
  // ...
  grunt.registerTask('default', ['connect', 'jasmine']);
};
I make this my default task because I hope that this will be my main use for Grunt in this project.

I already have NOP spec in the test directory from my work yesterday and, it works:
$ grunt
Running "connect:server" (connect) task
Started connect web server on http://0.0.0.0:8100

Running "jasmine:src" (jasmine) task
Testing jasmine specs via PhantomJS

 <apply-author-styles>
   styles of elements using is
     ✓ should apply page CSS from <style> tags

1 spec in 0.017s.
>> 0 failures

Done, without errors.
All of this looks promising… until I try to add Polymer to the mix. I have a setup script that I can add as a helper in grunt-contrib-jasmine:
    // ...
    jasmine: {
      src: ['app/**/*.js'],
      options: {
        host: 'http://127.0.0.1:8100/',
        helpers: ['test/PolymerSetup.js'],
        specs: 'test/*Spec.js'
      }
    }
    // ...
The setup script adds the usual Polymer links and scripts to the page <head> and it works fine in Karma. But, when I run this in grunt-contrib-jasmine, I get:
➜  apply-author-styles git:(master) ✗ grunt
Running "connect:server" (connect) task
Started connect web server on http://0.0.0.0:8100

Running "jasmine:src" (jasmine) task
Testing jasmine specs via PhantomJS


log: platform.js is not the first script on the page. See http://www.polymer-project.org/docs/start/platform.html#setup for details.
>> ReferenceError: Can't find variable: Window at
>> http:/127.0.0.1:8100/bower_components/platform/platform.js:13 
>> http:/127.0.0.1:8100/bower_components/platform/platform.js:13 
...
And then I realize that I have already given up on PhantomJS (which is used by grunt-contrib-jasmine) with Polymer.

Ugh. I just don't think any of the objections from back then have been resolved. So it looks like I'm back to Karma and that ugliness. Sometimes it really is difficult to be so obsessive about testing...



Day #97

No comments:

Post a Comment