Home

Awesome

QUnit Decorators

Allow QUnit tests to be written and organized with JavaScript or TypeScript decorators. Inspired by mocha-typescript.

Build Status Version semantic-release

Setting this up in your project

npm install --save-dev qunit-decorators

or

yarn add -D qunit-decorators

Writing your tests

When using qunit-decorators, you’ll use classes organize modules, and methods for your tests

import { suite, test } from 'qunit-decorators';

@suite // <-- decorate your modules with @suite
class UserLoginTests {

  // ↓ decorate your test methods with @test
  @test 'login without password should fail'(assert: Assert) {
    let { result } = loginWithoutPassword(); // the thing being tested
    assert.equal(result, 'ERROR', 'User receives an error'); // ✅
  }
  
  foo() {} // <-- You're free to put other non-test methods on the class too!
}

In the example above your test module would get its name from the class (UserLoginTests), and it would contain a test that gets its name from the method (login without password should fail). If you want to have a method name that's different from the name of the test, you can also pass an argument to these decorators.

see: QUnit.module and QUnit.test

import { suite, test } from 'qunit-decorators';

@suite('User authentication test suite')
class UserLoginTests {

  @test('Missing password case errors as expected')
  testMethod(assert: Assert) {
    let { result } = loginWithoutPassword(); // the thing being tested
    assert.equal(result, 'ERROR', 'User receives an error'); // ✅
  }

}

Skipping & Focusing

Sometimes it's useful to temporarily focus on a subset of tests while writing new code. QUnit allows you to focus on a combination of modules and tests within modules.

see: QUnit.only

import { suite, test } from 'qunit-decorators';

@suite.only('Working on some new tests')
class MyNewTests { ... }

@suite
class ExistingFeatureTests {

  @test.only 'Fixing something else too'() { ... }

}

Alternatively, you may choose specific tests or modules to skip in a similar way

see: QUnit.skip

import { suite, test } from 'qunit-decorators';

@suite.skip('Things that take a long time')
class SlowTests { ... }

@suite
class ExistingFeatureTests {

  @test.skip 'a buggy test I am still working on'() { ... }

}

Particularly while in the middle of a code change, you'll sometimes have tests that won't pass because you haven't gotten to them yet. You may mark these tests with @test.todo, and they'll pass as long as at least one assertion fails.

see: QUnit.todo

import { suite, test } from 'qunit-decorators';

@suite
class WIPBugFixes {

  @test.todo 'We\'ll get to this Soon™️'(assert) {
    assert.ok(false);
  }

}

Module Hooks

When defining a QUnit suite, you have an opportunity to set up one or more hooks to customize code that runs before or after your tests.

see: QUnit.module

There are a variety of ways you can provide functions for hooks, and qunit-decorators doesn't interfere with their normal capabilities and operation (i.e., if you return a promise from a hook, QUnit will wait for that promise to resolve before running other hooks or tests).

You may define hooks as member functions on the module's class

import { suite, test } from 'qunit-decorators';
import Pretender from 'pretender';

let server;

@suite('A better test module')
class BetterModule {
  before() {
    server = new Pretender();
  }
  after() {
    server.shutdown();
  }
  
  beforeEach() { ... }
  afterEach() { ... }
}

or pass the hooks passed into the @suite decorator as an object

import { suite, test } from 'qunit-decorators';
import Pretender from 'pretender';

let server;
const myHooks = {
  before() {
    // Start intercepting XHR
    server = new Pretender();
  },
  after() {
    // Restore original XHR
    server.shutdown();
  }
}

@suite('A good test module', myHooks)
class GoodModule {

}

or pass in a callback that receives an object which may be used to register hooks

import { suite, test } from 'qunit-decorators';
import Pretender from 'pretender';

@suite('A better test module', hooks => {
  let server;
  hooks.before(() => {
    server = new Pretender();
  });
  hooks.after(() => {
    server.shutdown();
  });
})
class BetterModule {

}

(c) 2018 LinkedIn