Skip to content

Commit

Permalink
Core: Add QUnit.test.if() and QUnit.module.if()
Browse files Browse the repository at this point in the history
Closes #1772.

Co-authored-by: Steve McClure <[email protected]>
  • Loading branch information
Krinkle and smcclure15 authored Jul 9, 2024
1 parent 894d3cc commit a165ab8
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 17 deletions.
16 changes: 11 additions & 5 deletions docs/api/QUnit/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ All tests inside a module will be grouped under that module. Tests can be added

Modules can be nested inside other modules via a [module scope](#module-scope). In the output, tests are generally prefixed by the names of all parent modules. E.g. "Grandparent > Parent > Child > my test".

The `QUnit.module.only()`, `QUnit.module.skip()`, and `QUnit.module.todo()` methods are aliases for `QUnit.module()` that apply the behaviour of [`QUnit.test.only()`](./test.only.md), [`QUnit.test.skip()`](./test.skip.md) or [`QUnit.test.todo()`](./test.todo.md) to all a module's tests at once.
`QUnit.module.only( name, … )`<br>
`QUnit.module.todo( name, … )`<br>
`QUnit.module.skip( name, … )`<br>
`QUnit.module.if( name, condition, … )`

These methods are aliases for `QUnit.module()` that apply the behaviour of [`QUnit.test.only()`](./test.only.md), [`QUnit.test.todo()`](./test.todo.md), [`QUnit.test.skip()`](./test.skip.md) or [`QUnit.test.if()`](./test.if.md) to all a module's tests at once.

<span id="nested-scope"></span><span id="nested-module-scope"></span>

Expand Down Expand Up @@ -119,10 +124,11 @@ Example: [§ Hooks via module options](#hooks-via-module-options).

## Changelog

| [QUnit 2.4](https://github.com/qunitjs/qunit/releases/tag/2.4.0) | The `QUnit.module.only()`, `QUnit.module.skip()`, and `QUnit.module.todo()` aliases were introduced.
| [QUnit 2.0](https://github.com/qunitjs/qunit/releases/tag/2.0.0) | The `before` and `after` options were introduced.
| [QUnit 1.20](https://github.com/qunitjs/qunit/releases/tag/1.20.0) | The `scope` feature was introduced.
| [QUnit 1.16](https://github.com/qunitjs/qunit/releases/tag/1.16.0) | The `beforeEach` and `afterEach` options were introduced.<br/>The `setup` and `teardown` options were deprecated in QUnit 1.16 and removed in QUnit 2.0.
| UNRELEASED | Added `QUnit.module.if()` alias.
| [QUnit 2.4](https://github.com/qunitjs/qunit/releases/tag/2.4.0) | Added `QUnit.module.only()`, `QUnit.module.skip()`, and `QUnit.module.todo()` aliases.
| [QUnit 2.0](https://github.com/qunitjs/qunit/releases/tag/2.0.0) | Added `before` and `after` options.
| [QUnit 1.20](https://github.com/qunitjs/qunit/releases/tag/1.20.0) | Introduce `scope` feature.
| [QUnit 1.16](https://github.com/qunitjs/qunit/releases/tag/1.16.0) | Added `beforeEach` and `afterEach` options.<br/>The `setup` and `teardown` options were deprecated in QUnit 1.16 and removed in QUnit 2.0.

## Examples

Expand Down
5 changes: 3 additions & 2 deletions docs/api/QUnit/test.each.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ version_added: "2.16.0"

`QUnit.test.each( name, dataset, callback )`<br>
`QUnit.test.only.each( name, dataset, callback )`<br>
`QUnit.test.todo.each( name, dataset, callback )`<br>
`QUnit.test.skip.each( name, dataset, callback )`<br>
`QUnit.test.todo.each( name, dataset, callback )`
`QUnit.test.if.each( name, condition, dataset, callback )`

Add tests using a data provider.

Expand All @@ -35,7 +36,7 @@ Use this method to add multiple tests that are similar, but with different data

Each test case is passed one value of your dataset.

The [`only`](./test.only.md), [`skip`](./test.skip.md), and [`todo`](./test.todo.md) variants are also available, as `QUnit.test.only.each`, `QUnit.test.skip.each`, and `QUnit.test.todo.each` respectively.
The [`only`](./test.only.md), [`todo`](./test.todo.md), [`skip`](./test.skip.md), and [`if`](./test.if.md) variants are also available, as `QUnit.test.only.each`, `QUnit.test.todo.each`, `QUnit.test.skip.each`, and `QUnit.test.if.each` respectively.

## Examples

Expand Down
45 changes: 45 additions & 0 deletions docs/api/QUnit/test.if.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
layout: page-api
title: QUnit.test.if()
excerpt: Add a test that may be skipped.
groups:
- main
redirect_from:
- "/QUnit/test.if/"
version_added: "unreleased"
---

`QUnit.test.if( name, condition, callback )`

Add a test that only runs if a condition is true.

| parameter | description |
|-----------|-------------|
| `name` (string) | Title of unit being tested |
| `condition` (string) | Expression to decide if the test should be run |
| `callback` (function) | Function that performs the test |

If the condition is true, this is equivalent to calling [`QUnit.test()`](./test.md).

If the conditional is false, this is equivalent to calling [`QUnit.test.skip()`](./test.skip.md), and test will not run. Instead, it will be listed in the results as a "skipped" test.

As a codebase becomes bigger, you may need to conditionally skip an entire group of tests. You can use [`QUnit.module.if()`](./module.md) to recursively skip all tests in a module based on a given condition.

## Examples

```js
QUnit.module('MyApp');

// Skip if executed without a DOM
QUnit.test.if('render', typeof document !== 'undefined', function (assert) {
assert.strictEqual(MyApp.render(), '<p>Hello world!</p>');
});
```

```js
QUnit.module.if('MyApp', typeof document !== 'undefined');

QUnit.test('render', function (assert) {
assert.strictEqual(MyApp.render(), '<p>Hello world!</p>');
});
```
4 changes: 4 additions & 0 deletions docs/api/QUnit/test.skip.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ This test will be listed in the results as a "skipped" test. The callback and th

As a codebase becomes bigger, you may sometimes want to temporarily disable an entire group of tests at once. You can use [`QUnit.module.skip()`](./module.md) to recursively skip all tests in the same module.

## See also

* [`QUnit.test.if( name, condition, callback )`](./test.if.md)

## Changelog

| [QUnit 2.12](https://github.com/qunitjs/qunit/releases/tag/2.12.0) | The `QUnit.skip()` method was renamed to `QUnit.test.skip()`.<br/>Use of `QUnit.skip()` remains supported as an alias.
Expand Down
8 changes: 8 additions & 0 deletions src/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ module.skip = function (name, options, scope) {
processModule(name, options, scope, { skip: true });
};

module.if = function (name, condition, options, scope) {
if (focused) {
return;
}

processModule(name, options, scope, { skip: !condition });
};

module.todo = function (name, options, scope) {
if (focused) {
return;
Expand Down
18 changes: 16 additions & 2 deletions src/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default function Test (settings) {
});

if (this.skip) {
// Skipped tests will fully ignore any sent callback
// Skipped tests will fully ignore (and dereference for garbage collect) any sent callback
this.callback = function () {};
this.async = false;
this.expected = 0;
Expand Down Expand Up @@ -970,6 +970,9 @@ extend(test, {
skip: function (testName) {
addTest({ testName, skip: true });
},
if: function (testName, condition, callback) {
addTest({ testName, callback, skip: !condition });
},
only: function (testName, callback) {
addOnlyTest({ testName, callback });
},
Expand Down Expand Up @@ -1007,7 +1010,18 @@ test.skip.each = function (testName, dataset) {
});
});
};

test.if.each = function (testName, condition, dataset, callback) {
runEach(dataset, (data, testKey) => {
addTest({
testName: makeEachTestName(testName, testKey),
callback,
withData: true,
stackOffset: 5,
skip: !condition,
data: condition ? data : undefined
});
});
};
test.only.each = function (testName, dataset, callback) {
runEach(dataset, (data, testKey) => {
addOnlyTest({
Expand Down
37 changes: 37 additions & 0 deletions test/cli/fixtures/test-if.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
QUnit.test.if('skip me', false, function (assert) {
assert.true(false);
});

QUnit.test.if('keep me', true, function (assert) {
assert.true(true);
});

QUnit.test('regular', function (assert) {
assert.true(true);
});

QUnit.test.if.each('skip dataset', false, ['a', 'b'], function (assert, _data) {
assert.true(false);
});

QUnit.test.if.each('keep dataset', true, ['a', 'b'], function (assert, data) {
assert.true(true);
assert.equal(typeof data, 'string');
});

QUnit.module.if('skip group', false, function () {
QUnit.test('skipper', function (assert) {
assert.true(false);
});
});

QUnit.module.if('keep group', true, function (hooks) {
let list = [];
hooks.beforeEach(function () {
list.push('x');
});
QUnit.test('keeper', function (assert) {
assert.true(true);
assert.deepEqual(list, ['x']);
});
});
18 changes: 18 additions & 0 deletions test/cli/fixtures/test-if.tap.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# name: no tests
# command: ["qunit", "test-if.js"]

TAP version 13
ok 1 # SKIP skip me
ok 2 keep me
ok 3 regular
ok 4 # SKIP skip dataset [0]
ok 5 # SKIP skip dataset [1]
ok 6 keep dataset [0]
ok 7 keep dataset [1]
ok 8 # SKIP skip group > skipper
ok 9 keep group > keeper
1..9
# pass 5
# skip 4
# todo 0
# fail 0
6 changes: 3 additions & 3 deletions test/main/deepEqual.js
Original file line number Diff line number Diff line change
Expand Up @@ -1825,7 +1825,7 @@ var hasES6Map = (function () {
}
}());

QUnit[hasES6Set ? 'test' : 'skip']('Sets', function (assert) {
QUnit.test.if('Sets', hasES6Set, function (assert) {
var s1, s2, s3, s4, o1, o2, o3, o4, m1, m2, m3;

// Empty sets
Expand Down Expand Up @@ -1898,7 +1898,7 @@ QUnit[hasES6Set ? 'test' : 'skip']('Sets', function (assert) {
assert.equal(QUnit.equiv(s1, s2), true, 'Sets with different insertion orders');
});

QUnit[hasES6Map ? 'test' : 'skip']('Maps', function (assert) {
QUnit.test.if('Maps', hasES6Map, function (assert) {
var m1, m2, m3, m4, o1, o2, o3, o4, s1, s2, s3;

// Empty maps
Expand Down Expand Up @@ -2016,7 +2016,7 @@ var hasES6Symbol = (function () {
return typeof Symbol === 'function';
}());

QUnit[hasES6Symbol ? 'test' : 'skip']('Symbols', function (assert) {
QUnit.test.if('Symbols', hasES6Symbol, function (assert) {
var a = Symbol(1);
var b = Symbol(1);

Expand Down
4 changes: 2 additions & 2 deletions test/main/stacktrace.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Skip in environments without Error#stack support
(QUnit.stack() ? QUnit.module : QUnit.module.skip)('stacktrace', function () {
QUnit.module.if('stacktrace', !!QUnit.stack(), function () {
function fooCurrent () {
return QUnit.stack();
}
Expand Down Expand Up @@ -65,7 +65,7 @@
// We do that for failed assertions, but for passing tests we omit
// source details in these older browsers.
var supportsUnthrownStack = !!(new Error().stack);
(supportsUnthrownStack ? QUnit.module : QUnit.module.skip)('source details', function () {
QUnit.module.if('source details', supportsUnthrownStack, function () {
QUnit.test('QUnit.test()', function (assert) {
var stack = norm(QUnit.config.current.stack);
var line = stack.split('\n')[0];
Expand Down
2 changes: 1 addition & 1 deletion test/main/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ QUnit.module('test', function () {
assert.true(true);
});

(typeof document !== 'undefined' ? QUnit.module : QUnit.module.skip)('fixture management', function (hooks) {
QUnit.module.if('fixture management', typeof document !== 'undefined', function (hooks) {
/* global document */
var failure = false;
var values = [
Expand Down
3 changes: 2 additions & 1 deletion test/reorderError1.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-env browser */
QUnit.module('Test call count - first case');
QUnit[window.sessionStorage ? 'test' : 'skip'](
QUnit.test.if(
'does not skip tests after reordering',
!!window.sessionStorage,
function (assert) {
assert.equal(window.totalCount, 3);
}
Expand Down
3 changes: 2 additions & 1 deletion test/reorderError2.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-env browser */
QUnit.module('Test call count - second case');
QUnit[window.sessionStorage ? 'test' : 'skip'](
QUnit.test.if(
'does not skip tests after reordering',
!!window.sessionStorage,
function (assert) {
assert.equal(window.totalCount, 2);
}
Expand Down

0 comments on commit a165ab8

Please sign in to comment.