npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mocha-test-dsl

v0.3.2

Published

Modern testing DSL built on top of [mocha](https://mochajs.org/)

Downloads

28

Readme

Mocha Test DSL

Modern testing DSL built on top of mocha

  • Use chaining to allow for easier composition.
  • Use optional prepare class/object to describe how to setup and tear down run context.
  • Use env and check objects to encapsulate:
    • the environment to test in
    • the test functions (expectations) on the result

The prepare, env and check objects can either be:

  • simple objects with functions
  • classes for even more power and reuse, polymorhism etc.
test('Component model')
  .for('a mongo DB connection', {
    prepare
  })
  .that('the delete command')
    .will('delete a single component', async () => {
      let result = await action.delete();
      check.for(result)
        .wasDeleted()
        .isIndexed(false)
    })
    .run()

Install

npm i mocha-test-dsl --save-dev

Usage

const test = require('mocha-test-dsl');

We recommend using an env folder to setup the environment used for the test. A typical testing file structure would look as follows:

/actions
  /env
    index.js
    check.js
    action.js
    dbenv.js
    utils.js

  create.spec.js
  delete.spec.js
  ...
  index.js

Checker

env/check.js

We recommend making the checker chainable and have both an environment constructor and a method to set the result for all method to access as an instance variable, in order to be consistent.

class Checker {
  constructor(env) {
    this.env = env;
    this.index = this.env.index;
    this.name = this.env.name;
  }

  get isNameIndexed() {
    return this.index[this.name];
  }

  for(res) {
    this.res = res;
  }

  wasDeleted(expected = true) => {
    expect(this.res.deleted).to.eql(expected);
    return this;
  }

  isIdexed(expected = true) => {
    expect(this.isNameIndexed).to.eql(expected);
    return this;
  }
}

module.export = function(res) {
  return new Checker(res);
}

Prepare and cleanup test environment

env/prepare.js

class Prepare {
  constructor(env) {
    this.env = env;
  }

  before() {
    this.env.connection.open();
  }

  beforeEach() {
    this.env.action = new Action();
  }

  afterEach() {
    this.env.action = null;
  }

  // clean up
  after() {
    this.env.connection.close();
  }
}

module.exports = (x) => {
  return new Prepare(x);
}

Some prepacked action for testing

env/action.js

module.exports = {
  delete: async (filePath = './helper.js') => {
    try {
      await fs.stat(path.join(__dirname, filePath));
      return true;
    } catch (err) {
      return false;
    }
  }
}

Export full set of variables needed for testing

env/index.js

const test = require('mocha-test-dsl');
const check = require('./check');
const prepare = require('./prepare');
const action = require('./action');

module.exports = {
  test,
  check,
  prepare,
  action
}

Clean test

Then use as follows for a super clean and effective test:

const { prepare, test, checker, action, dbenv } = require('./env');

// set up initial environment needed by prepare
const prepare = prepare(dbenv)

// (optionally) make prepare environment accessible by checker
const check = checker(prepare.env);

test('Component model')
  .for('a mongo DB connection', {
    prepare
  })
  .that('the delete command')
    .will('delete a single component', async () => {
      let result = await action.delete();
      check.for(result)
        .wasDeleted()
        .isIndexed(false)
    })
    .run()

Since chain syntax is enabled, we can compose and reuse tests elegantly from individual parts:


let component = test('Component model')

let action = {
  delete: component.that('delete action'),
  create: component.that('create action')
  // ...
}

// continue chaining...
let action.delete.default = action.delete.item
  .when('default indexed', {
    prepare: new Prepare()
  })

let action.delete.notIndexed = action.delete.item
  .when('not indexed', {
    prepare: new Prepare({indexed: false})
  })

// Note: again the above could be placed in a different file for reuse across the test suite
action.delete.default
  .should('delete a single component', async () => {
    let result = await model.action.delete();
    check.for(result)
      .wasDeleted();
  })
  .and('also update index', async () => {
    // since check is global and set from previous test we can reuse directly here if we like
    check
      .isIdexed(false);
  })
  .run()

action.delete.notIndexed
    .should('not delete it', async () => {
      let result = await model.action.delete();
      check.for(result)
        .wasDeleted(false);
    })
    .and('still not indexed', async () => {
      check
        .wasIdexed(false);
    })
    .run()

We recommend using check chaining to reduce the should chains and make multiple checks to check for a specific kind of outcome, such as checking the returned value and making checks on the actual environment affected.

Use should chaining only when you need to, in order to make the test output more clear and to group logical types of outcome tests.

PS: Always mock the environment when you can!

Aliases

To make the DSL more fluent, the following aliases are available:

that - when, for, on, in, while

should - will, it, and, but, can

DSL rules

  • test followed by any number of chained that (or alias).
  • Any that can chain with any number of chained should (or alias)
  • To run a test chain add a run() call at the end of a should chain.

Enable/Disable tests

To enable/disable a test, simply remove or comment/uncomment the final `.run()`` method!

Development

Here some tips on further developing this handy testing DSL.

Fork the repo. Start development on a new feature branch

git co -b my-feature

When done, push the feature branch to your forked repo

git push origin my-feature

Then from your git site (such as github or similar), create a Pull Request (PR).

Build

npm run build - builds /src folder and puts resulting ES5 .js files in /dist

Auto build

npm run watch - builds /src and watches for changes to /src files for auto-build!

Troubleshooting

If you still get an error, try removing the dist folder:

rm -r dist

Then recompile via build or watch task and start server again.

Run Test or Test suite

To run the tests, the Koa server app must be running...

npm test (runs test command in Makefile)

License

MIT