Monday, March 30, 2015

Gulp and web-component-tester


I hope to build on last night's success with web-component-tester. With relatively little effort or confusion, I was able to write a simple-yet-legitimate test with this newish testing tool for Polymer. Tonight, I would like explore the automated test watching facilities.

First up, I will try Gulp for automated test watchers. I have never used Gulp before, mostly because the "Try Now" button on the homepage takes me to an install page instead of a live demo. I am easily confused by such things, but today I push through and follow the installation instructions so that I can then try.

Global and local install works fine:
$ npm install --global gulp
$ npm install --save-dev gulp
Next, I create a gulpfile.js as recommended on the web-component-tester page:
var gulp = require('gulp');
require('web-component-tester').gulp.init(gulp);
That fails because I do not have web-component-tester installed locally. The wct instructions only mention globally installing it, but it is clearly needed locally for Gulp. So I install it:
$ npm install --save-dev web-component-tester
With that, my package.json now contains:
{
  "name": "wct_sample",
  "devDependencies": {
    "gulp": "^3.8.11",
    "web-component-tester": "^2.2.6"
  }
}
More importantly, my gulplfile.js works and I can run last night's test:
gulp test:local
[23:52:52] Using gulpfile ~/repos/polymer-book/play/web-component-tester/js/gulpfile.js
[23:52:52] Starting 'wct:local'...
Starting Selenium server for local browsers
Selenium server running on port 45226
Web server running on port 33654 and serving from /home/chris/repos/polymer-book/play/web-component-tester
chrome 41                Beginning tests via http://localhost:33654/js/test/index.html?cli_browser_id=0
chrome 41                Tests passed
firefox 36               Beginning tests via http://localhost:33654/js/test/index.html?cli_browser_id=1
firefox 36               Tests passed
Test run ended with great success

chrome 41 (1/0/0)                       firefox 36 (1/0/0) 
That is of little use to me, however. The wct command-line from last night does the same exact thing without extra installation and configuration. What I want is a file watcher that will run the test:local task whenever my Polymer code or tests change.

For that, I create a default task in gulpfile.js that establishes a gulp.watch():
var gulp = require('gulp');
require('web-component-tester').gulp.init(gulp);

gulp.task('default', function() {
  gulp.watch(['elements/**', 'test/**'], ['test:local']);
});
Now I can start gulp with no command-line arguments and it will watch for changes:
$ gulp
[00:14:48] Using gulpfile ~/repos/polymer-book/play/web-component-tester/js/gulpfile.js
[00:14:48] Starting 'default'...
[00:14:48] Finished 'default' after 11 ms
...
If I make a change to an of the files being watched, my test runs:
$ gulp
[00:14:48] Using gulpfile ~/repos/polymer-book/play/web-component-tester/js/gulpfile.js
[00:14:48] Starting 'default'...
[00:14:48] Finished 'default' after 11 ms
[00:16:21] Starting 'wct:local'...
Starting Selenium server for local browsers
Selenium server running on port 54671
Web server running on port 42314 and serving from /home/chris/repos/polymer-book/play/web-component-tester
chrome 41                Beginning tests via http://localhost:42314/js/test/index.html?cli_browser_id=0
chrome 41                Tests passed
firefox 36               Beginning tests via http://localhost:42314/js/test/index.html?cli_browser_id=1
firefox 36               Tests passed
Test run ended with great success

chrome 41 (1/0/0)                       firefox 36 (1/0/0)                    
[00:16:28] Finished 'wct:local' after 6.29 s
[00:16:28] Starting 'test:local'...
[00:16:28] Finished 'test:local' after 16 μs
I prefer for my test suite to run when I first start a test watched task. To get that to work, I add test:local as a dependency for the default task:
var gulp = require('gulp');
require('web-component-tester').gulp.init(gulp);

gulp.task('default', ['test:local'], function() {
  gulp.watch(['elements/**', 'test/**'], ['test:local']);
});
Now my tests run as soon as I start the default watcher:
$ gulp
[00:24:52] Using gulpfile ~/repos/polymer-book/play/web-component-tester/js/gulpfile.js
[00:24:52] Starting 'wct:local'...
Starting Selenium server for local browsers
Selenium server running on port 47399
Web server running on port 60784 and serving from /home/chris/repos/polymer-book/play/web-component-tester
chrome 41                Beginning tests via http://localhost:60784/js/test/index.html?cli_browser_id=0
chrome 41                Tests passed
firefox 36               Beginning tests via http://localhost:60784/js/test/index.html?cli_browser_id=1
firefox 36               Tests passed
Test run ended with great success

chrome 41 (1/0/0)                       firefox 36 (1/0/0)                    
[00:24:58] Finished 'wct:local' after 6.1 s
[00:24:58] Starting 'test:local'...
[00:24:58] Finished 'test:local' after 18 μs
[00:24:58] Starting 'default'...
[00:24:58] Finished 'default' after 13 ms
The only thing left is popup notifications. If there is an easy way to get that working, it escapes me. Upon first pass at Gulp, the streams and events and all are a tad bewildering to me. So in the end, I fall back to manually installing node-notifier:
$ npm install --save-dev node-notifier
From there, I drop the web-component-tester Gulp tasks and directly invoke the testing tasks. If those fail, the I manually send notifications on error:
var gulp = require('gulp');
// require('web-component-tester').gulp.init(gulp);
var wct = require('web-component-tester').test;
var notifier = require('node-notifier');

gulp.task('default', function() {
  gulp.watch('{elements,test}/**', function(done) {
    wct({plugins: {local: {}, sauce: false}}, function(error){
      if (error) {
        notifier.notify({
          'title': 'Build failed',
          'message': '' + error
        });
      }
      else {
        notifier.notify({'title': 'Build passed', 'message': 'Yay!'});
      }
    });
  });
});
That is pretty ugly. It works, but here has to be a simpler way to accomplish. For me, the answer is likely going to be Grunt, which I already use elsewhere in Patterns in Polymer. Unless someone else has an easy way to get this working cleanly in Gulp?


Day #14

No comments:

Post a Comment