I need to reuse sets of setup and cleanup logic in multiple QUnit modules without code duplication. These pieces of logic are already encoded as "module hook" objects as per the QUnit API. Some of the hooks might be async
. Here is an example - The content of these hooks doesn't really mean anything, it's just for demonstration.
const fruitHook = {
async before () {
this.banana = { ripeness: await generateRandomInitialRipeness() };
this.apple = { ripeness: await generateRandomInitialRipeness() };
},
beforeEach () {
this.banana.ripeness += 1;
this.apple.ripeness += 1;
}
};
const nutHook = {
before () {
this.walnut = { cracked: false };
this.peanut = { cracked: false };
}
};
I would like to combine these hooks in different ways as needed by my QUnit modules.
// This module needs the fruitHook
QUnit.module('TestFruits', fruitHook);
// This module needs the nutHook
QUnit.module('TestNuts', nutHook);
// This module needs both
QUnit.module('TestFruitsAndNuts', /* ??? */);
In a real use case, I would have a larger set of hooks that need to be combined into various different subsets. Does QUnit offer a way to combine these hooks?
I can write my own "hooks concatenator" utility:
function concatenateHooks (hooks) {
const resultingHook = {
async before () {
for (const hook of hooks) {
if (typeof hook.before === 'function') {
await hook.before.call(this);
}
}
},
async beforeEach () { /* ... */ }
async afterEach () { /* ... */ }
async after () { /* ... */ }
}
}
And use it like so:
QUnit.module('TestFruitsAndNuts', concatenateHooks([fruitHook, nutHook]);
In my implementation I'm forcing all hooks to become async
, though I suspect I could make it a bit more elaborate to avoid awaiting if all passed hooks are synchronous.
Is there a feature in QUnit that does this and that I've missed?
I need to reuse sets of setup and cleanup logic in multiple QUnit modules without code duplication. These pieces of logic are already encoded as "module hook" objects as per the QUnit API. Some of the hooks might be async
. Here is an example - The content of these hooks doesn't really mean anything, it's just for demonstration.
const fruitHook = {
async before () {
this.banana = { ripeness: await generateRandomInitialRipeness() };
this.apple = { ripeness: await generateRandomInitialRipeness() };
},
beforeEach () {
this.banana.ripeness += 1;
this.apple.ripeness += 1;
}
};
const nutHook = {
before () {
this.walnut = { cracked: false };
this.peanut = { cracked: false };
}
};
I would like to combine these hooks in different ways as needed by my QUnit modules.
// This module needs the fruitHook
QUnit.module('TestFruits', fruitHook);
// This module needs the nutHook
QUnit.module('TestNuts', nutHook);
// This module needs both
QUnit.module('TestFruitsAndNuts', /* ??? */);
In a real use case, I would have a larger set of hooks that need to be combined into various different subsets. Does QUnit offer a way to combine these hooks?
I can write my own "hooks concatenator" utility:
function concatenateHooks (hooks) {
const resultingHook = {
async before () {
for (const hook of hooks) {
if (typeof hook.before === 'function') {
await hook.before.call(this);
}
}
},
async beforeEach () { /* ... */ }
async afterEach () { /* ... */ }
async after () { /* ... */ }
}
}
And use it like so:
QUnit.module('TestFruitsAndNuts', concatenateHooks([fruitHook, nutHook]);
In my implementation I'm forcing all hooks to become async
, though I suspect I could make it a bit more elaborate to avoid awaiting if all passed hooks are synchronous.
Is there a feature in QUnit that does this and that I've missed?
Share Improve this question edited Mar 9 at 16:24 antonio asked Mar 9 at 14:09 antonioantonio 4391 gold badge3 silver badges13 bronze badges1 Answer
Reset to default 1You can use QUnit's module scope to add as many hooks as you need.
QUnit.module('Foo', function (hooks) {
hooks.beforeEach(function () {
this.a = 'Hello';
});
hooks.beforeEach(function () {
this.b = ' world';
});
QUnit.test('example', function (assert) {
assert.equal(this.a + this.b, 'Hello world');
});
});
To provide shared helper function that install shooks, I recommend passing the hooks
object, like so:
function setupFruit(hooks) {
hooks.beforeEach(function () {
this.a = 'Hello';
});
}
function setupVeg(hooks) {
hooks.beforeEach(function () {
this.b = ' world';
});
}
QUnit.module('Foo', function (hooks) {
setupFruit(hooks);
setupVeg(hooks);
QUnit.test('example', function (assert) {
assert.equal(this.a + this.b, 'Hello world');
});
});
Alternatively, if something is needed across all your modules, you can also use a global hook via QUnit.hooks since QUnit 2.18, so that it can be part of all modules without needing to call the shared helper from each module.
Docs:
- https://qunitjs/api/QUnit/module/#hooks
- https://qunitjs/lifecycle/#module-hooks