Page.js 1.2.0

Along with better API docs the page.js 1.2.0 is released, the client-side micro router.

page.js router logo

The additions are subtle, the first is a ctx.querystring property exposing the query string, followed by the complimenting ctx.pathname to reference the ctx.path void of query string. @ovaillancourt also added support for passing query strings in the first place, which was arguably a bug, and added .defaultPrevented support to opt-out of page’s handling (as well as browser defaults of course).

Mocha 1.3.0

A relatively minor release this time but we’ve still got some cool new features!

Scrolling HTML reporter

The window will now scroll to follow along with larger test suites, and the statistics are fixed to the upper right-hand corner, a small but nice touch.

Custom reporters

Mocha has quite a few bundled reporters now, so future reporters that are not deemed important enough to provide the convenience of being in core should be published to npm. Some less important reporters may be removed from core and published to npm in the future.

This new feature also allows you to use localized private reporters. The --reporter NAME flag now behaves like require(), so for example you could do --reporter ./myreporter, or a third-party npm module such as --reporter lcov-reporter.

For details on creating and finding third-party reporters visit the wiki.

Grep inversion

The awesome --grep feature can now be inverted with the aptly named --invert flag. For example suppose you had tests tagged as @slow, and you wanted to run only slow tests you might use --grep @slow, however if you wanted to run only fast tests --grep @slow --invert would do the trick.

Along with this change --grep PATTERN is now escaped, meaning chars that used to behave as regexp special chars are now escaped.

Changelog

Here’s the full changelog:

1.3.0 / 2012-07-05

  • add window scrolling to HTML reporter
  • add v8 --trace-* option support
  • add support for custom reports via --reporter MODULE
  • add --invert switch to invert --grep matches
  • fix export of Nyan reporter. Closes #495
  • fix escaping of HTML suite titles. Closes #486
  • fix done() called multiple times with an error test
  • change --grep - regexp escape the input

Mocha 1.2.0 - now with more nyan!

Nyan

@atsuya added an awesome new nyan reporter:

Client-side test initialization

You can now initialize a client-side test setup with the mocha init <path> command. This will copy over mocha.css, mocha.js and generate a default tests.html file for you.

Working browser example

A lot of people were asking for a working browser example to reference, so I added one to the bottom of mocha’s site, you can find it here. This example test suite uses chai for assertions.

Wildcard global leaks

Global leak wildcard matching was added to flag globals such as “callback123” and “callback456” with “callback*” created by libraries like jQuery as acceptable since there’s little you can do to avoid this.

mocha 1.1.0

The Mocha javascript test framework version 1.1.0 is out. If you want a quick glance here’s the changelog:

Changelog

  • Added: check each mocha(1) arg for directories to walk
  • Added --recursive [tricknotes]
  • Added context for BDD [hokaccha]
  • Added styling for new clickable titles
  • Added clickable suite titles to HTML reporter
  • Added warning when strings are thrown as errors
  • Changed: green arrows again in HTML reporter styling
  • Changed ul/li elements instead of divs for better copy-and-pasting [joliss]
  • Fixed issue #325 - add better grep support to js api
  • Fixed: save timer references to avoid Sinon interfering.

Directory arguments

Mocha will now iterate the arguments passed and load files in any given directories (non-recursively). For example you may now use mocha spec if you have tests in ./spec instead of mocha spec/* - which is especially helpful for the unfortunate few stuck on windows.

Recursive

The new --recursive flag compliments the previous feature, but walks the directories recursively.

Filter with clickable titles

Suite titles are now clickable, auto-grepping. For example if you have the following suite:

full suite

You could use ?grep=SOMESTRING, or simply click the title to re-execute tests within that suite as shown here:

durations only

That’s it for now :)

Redis Lua scripting is badass

Roughly a year ago Salvatore Sanfilippo the author of Redis wrote a blog post discussing the inclusion of Lua as a scripting language. I finally decided to try this out, and let’s just say it’s pretty badass.

Lua is a great fit for Redis, they have similar philosophies, being simple, small, and fast. Suppose for example you have 200,000 jobs, each represented in Redis as a hash, and you want to map/reduce the job duration, the new scripting capabilities make this really easy!

Here’s the node setup script to generate these jobs:

  var redis = require('redis')
    , db = redis.createClient();

  var n = 500000
    , pending = n
    , ms;

  while (n--) {
    ms = Math.random() * 200 | 0;
    db.hset('job:' + n, 'duration', ms, function(){
      --pending || process.exit();
    })
  }

Next here is what you might consider scripting in your host language without the new Redis scripting feature, manually reducing the value:

  var redis = require('redis')
    , db = redis.createClient();

  var n = 200000
    , start = new Date
    , pending = n
    , ms = 0;

  while (n--) {
    db.hget('job:' + n, 'duration', function(err, n){
      if (err) throw err;
      ms += ~~n;
      --pending || (function(){
        console.log('%d minutes spent processing jobs', ms / (1000 * 60) | 0);
        console.log('took %ds', (new Date - start) / 1000 | 0);
        process.exit();
      })();
    })
  }

On my Air this took roughly 7s, not too great, keep in mind that there is no throttling here I’m just plastering it with 200k commands. Now let’s try it with Lua! The following script is ad-hoc, but it’ll do the trick. To signal an error all you have to do is return a table with the err slot. redis.call() is effectively the public Redis API exposed to your Redis script, so you can use it just like you would your host language Redis bindings or redis-cli(1).

   local sum = 0
   for i = 0, 200000, 1 do
     local key = "job:" .. i
     local ms = tonumber(redis.call("hget", key, "duration"))
     if ms == nil then return { err = key .. " is not an integer" } end
     sum = sum + ms
   end
   return sum

Here I’ve embedded it in the JS script, but you could of course generate these, load them from files etc (beware of redis-injection?).

   var redis = require('redis')
     , db = redis.createClient();

   var script = '\
   local sum = 0 \
   for i = 0, 200000, 1 do \
     local key = "job:" .. i \
     local ms = tonumber(redis.call("hget", key, "duration")) \
     if ms == nil then return { err = key .. " is not an integer" } end \
     sum = sum + ms \
   end \
   return sum';

   var start = new Date;

   db.eval(script, 0, function(err, ms){
     if (err) throw err;
     console.log('%d minutes spent processing jobs', ms / (1000 * 60) | 0);
     console.log('took %dms', new Date - start | 0);
     process.exit();
   });

After running the script with the new EVAL command what previously took several seconds dropped to ~850ms, much better. EVAL and EVALSHA are actually a lot more flexible than I’ve explained here, accepting keys and arbitrary arguments.

Check out antirez.com/post/an-update-on-redis-and-lua.html for more.