PageObject implementation (CoffeeScript, CasperJS) I'm using CasperJS and CoffeeScript for integration testing of a hobby project. Page Objects seem to be a useful abstraction. I had two major requirements:


Support for node.js style callbacks - mainly because tests can then be written using async.waterfall
Support extending (subclassing) to encapsulate common functionality, like a sidebar or a navbar


Here's the code, followed by a brief example of how I use it. It's a bit long, but that's about the shortest meaningful example I can give.

class PO # Base PO
  @casper: null

  # name: The name of the page object. Used to access it as PO[name], which is kind of like a forward declaration
  # selector: The page represented by this PO is considered to be ready for usage once this is visible
  # mixin: An object; properties of this will be mixed into the new instance
  constructor: (@name, @selector, mixin) -&gt;
    if PO[@name] isnt undefined
      throw "Failed creating PO #{@name}: a PO instance or class method with this name already exists"
    PO[@name] = this
    @__defineGetter__ 'casper', -&gt; PO.casper
    this[key] = val for key, val of mixin

  waitUntilVisible: (cb) -&gt; @casper.waitUntilVisible @selector, cb

  # Switch to po, and call the callback cb with err and the po as parameters
  next: (cb, po, err=null) -&gt;
    t0 = Date.now()
    msg = "Switching to PO #{po.name}"
    @casper.log msg, 'debug'
    po.waitUntilVisible =&gt;
      @casper.log "#{msg}: done in #{Date.now() - t0}ms", 'debug'
      cb err, po
    po

new PO 'navbar', '',
  tabs: {}
  logout: (cb) -&gt;
    @casper.click '#logout'
    @casper.waitFor (=&gt; not @haveLogin()), (=&gt; cb null, PO['login'])

  haveLogin: (cb) -&gt; 
    result = nick == @casper.evaluate -&gt; $('#current-user-nick').text()
    cb? result
    result

  addTab: ({name, switchSelector, readySelector, po}) -&gt;
    @tabs[name] = arguments[0]

  toTab: (name, cb) -&gt;
    cb "Navbar tab #{name} not known", null unless name of @tabs
    tab = @tabs[name]
    @casper.click tab.switchSelector
    @casper.waitUntilVisible tab.readySelector, =&gt; cb null, PO[tab.po]


class PON extends PO # PO with navbar
  constructor: (name, selector, mixin) -&gt;
    super name, selector, mixin
    @navbar = PO['navbar']


new PON 'login', '.login-form',
  # ...

module.exports = (casper) -&gt;
  PO.casper = casper
  PO['login']
Do we need to attach a casper reference to the PO class?
By using the module pattern you inject the dependency anyway.
Here is the P0 class with a tiny refactoring:

module.exports = (casper) -&gt;

  class PO      
    constructor: (@name, @selector, mixin={}) -&gt;
      if PO[@name]?
        throw new Error "Failed creating PO #{@name}: ..."
      PO[@name] = @
      @[key] ?= val for own key,val of mixin

    waitUntilVisible: (cb) -&gt;
      casper.waitUntilVisible @selector, cb
      @

    next: (po, cb) -&gt;
      t0 = Date.now()
      msg = "Switching to PO #{po.name}"
      casper.log msg, 'debug'
      po.waitUntilVisible (err) -&gt;
        casper.log "#{msg}: done in #{Date.now() - t0}ms", 'debug'
        cb err, po


Then you would use it like this:

casper = require 'casper'
PO     = require('MyModuleName') casper

new PO 'navbar', '',
  tabs: {}
  logout: (cb) -&gt;
    casper.click '#logout'
    casper.waitFor (=&gt; not @haveLogin()), (err) -&gt; cb err, PO.login

  haveLogin: (cb) -&gt;
    result = nick is casper.evaluate -&gt; ($ '#current-user-nick').text()
    cb? result
    result

  addTab: ({name, switchSelector, readySelector, po}) -&gt;
    @tabs[name] = arguments[0]

  toTab: (name, cb) -&gt;
    cb new Error "Navbar tab #{name} not known" unless name of @tabs
    tab = @tabs[name]
    casper.click tab.switchSelector
    casper.waitUntilVisible tab.readySelector, (err)-&gt; cb err, PO[tab.po]


On extending the class you can skip the constructor (as long as it's the same like the one of the superclass) and attach the PO['navbar'] to the prototype.

class PON extends PO
  navbar: PO.navbar