0

I've started playing around with CodeceptJs and I've got it up working quite easily. I'm currently using it with NightmareJs and all seems fine.

The specific area I'm testing is a gallery that fetches data from an interface via JSONP creating a list of images wrapped in <div>s.

A portion of the tests I'm implementing is like the following:

Feature('gallery')
Scenario('clicking on an element adds "selected" class', (I) => {
  I.amOnPage('/')
  I.seeElement('#gallery .col-md-3')
  I.click('#gallery .col-md-3')
  I.seeElement('#gallery .selected')
})

Now since the elements can be any number, it's currently silently using the first element, but in order to give it a bit more entropy I wanted to pick an element at random, something like the following

Scenario('clicking on an element adds "selected" class', (I) => {
  I.amOnPage('/')
  I.seeMoreThanElements('#gallery .col-md-3', 1)
  I.clickOnRandomElement('#gallery .col-md-3')
  I.seeElement('#gallery .selected')
})

Or even better, if I could grab the list of elements so I can decide which one to click on, like:

Scenario('clicking on an element adds "selected" class', (I) => {
  I.amOnPage('/')
  I.seeMoreThanElements('#gallery .col-md-3', 1)
  const elements = I.grabRandomElement('#gallery .col-md-3')
  const random = getRandomInt(1, elements.length)
  I.click(`#gallery .col-md-3:nth-child(${random})`)
  I.seeElement(`#gallery .col-md-3.selected:nth-child(${random})`)
})

The current helpers available don't allow me to perform some particular actions, so I started implementing a custom handler as described in the guide at http://codecept.io/helpers/

In my configuration I have the following:

"helpers": {
  "Nightmare": {
    "url": "http://localhost:3000"
  },
  "DOMElements": {
    "require": "./__tests__/helpers/domelements_helper.js"
  }
}

and domelements_helper.js currently looks like the following:

'use strict'
let assert = require('assert')

class DOMElements extends Helper {
  seeMoreThanElements (locator, count) {
    this.helpers['Nightmare']._locate(locator).then(function (els) {
      return assert(els.length >= count, `Found more than ${count} elements`)
    })
  }
}

module.exports = DOMElements

This doesn't - clearly - work. This is where I'm getting a bit confused.

First of all, I'm using the default Node.js assertion library, and if there's any need I'm happy to move over to something more robust like Protractor or Chai-as-promised, but the slimmer the better.

Secondly, the documentation clearly states the following:

any helper method should return a value in order to be added to promise chain

Which doesn't really make sense... should I return a promise or should I handle the whole thing within the then() statement? As returning a basic value doesn't really do much. Even then, how do I handle failed assertions?

I've also seen a Nightmare clientscript in the code base but I have no idea if it's of any use for my case, as I've just started digging through the code base in order to understand a little bit better how to customise and extend CodeceptJs.

Any pointers are really appreciated

Mr Peach
  • 1,324
  • 1
  • 13
  • 19

1 Answers1

1

since nobody seems to have got this far, I'm going to add an answer as I seem to have found how this thing works by going through the codebase and understand a bit more how it works.

tl;dr: the quick solution is the following:

/* __tests__/helpers/domelements_helper.js */
const assert = require('assert')

class DOMElements extends Helper {

  seeMoreThanElements (locator, count) {
    return this.helpers['Nightmare']._locate(locator)
      .then((elementsArray) => {
        if (elementsArray.length < count) {
          return assert.fail(elementsArray.length, count, `Found more than ${count} elements`)
        }
      })
  }
}

module.exports = DOMElements

The way the whole thing works is by promises and you have to handle failure appropriately so that the whole system can fail gracefully (sorta).

In particular _locate() returns a promise and everything has to be handled asynchronously, although by design this seems to be quite awkward and it's making things particularly hard to implement, at least in the current state.

Mr Peach
  • 1,324
  • 1
  • 13
  • 19