Skip to content

Commit 7375d05

Browse files
committed
assertion-arguments: Validate t.plan() argument is a non-negative integer
Fixes #34
1 parent a2df839 commit 7375d05

3 files changed

Lines changed: 32 additions & 1 deletion

File tree

docs/rules/assertion-arguments.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
Translations: [Français](https://github.com/avajs/ava-docs/blob/main/fr_FR/related/eslint-plugin-ava/docs/rules/assertion-arguments.md)
1212

13-
Enforces passing the right number of arguments to assertion methods like `t.is()`. This rule can optionally also enforce or forbid the use of assertion messages.
13+
Enforces passing the right number of arguments to assertion methods like `t.is()`. Also validates that `t.plan()` is called with a non-negative integer. This rule can optionally also enforce or forbid the use of assertion messages.
1414

1515
Assertion messages are optional arguments that can be given to any assertion call to improve the error message, should the assertion fail.
1616

@@ -25,6 +25,8 @@ test('1', t => {
2525
t.is(value); // Not enough arguments
2626
t.is(value, expected, message, extra); // Too many arguments
2727
t.is(value, expected, false); // Assertion message is not a string
28+
t.plan('1'); // Argument is not a non-negative integer
29+
t.plan(2.5); // Argument is not a non-negative integer
2830
});
2931

3032
/* eslint ava/assertion-arguments: ["error", {"message": "always"}] */
@@ -44,6 +46,7 @@ test('3', t => {
4446
import test from 'ava';
4547

4648
test('1', t => {
49+
t.plan(1);
4750
t.is(value, expected);
4851
t.is(value, expected, message);
4952
});

rules/assertion-arguments.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const MESSAGE_ID_MISSING_MESSAGE = 'missing-message';
1111
const MESSAGE_ID_FOUND_MESSAGE = 'found-message';
1212
const MESSAGE_ID_NOT_STRING = 'not-string-message';
1313
const MESSAGE_ID_OUT_OF_ORDER = 'out-of-order';
14+
const MESSAGE_ID_PLAN_NOT_INTEGER = 'plan-not-integer';
1415

1516
const expectedNbArguments = {
1617
assert: {
@@ -281,6 +282,17 @@ const create = context => {
281282
}
282283

283284
checkArgumentOrder({node, assertion: firstNonSkipMember, context});
285+
286+
if (firstNonSkipMember === 'plan') {
287+
const argument = node.arguments[0];
288+
const staticValue = getStaticValue(argument);
289+
if (
290+
staticValue !== null
291+
&& (typeof staticValue.value !== 'number' || !Number.isInteger(staticValue.value) || staticValue.value < 0)
292+
) {
293+
context.report({node: argument, messageId: MESSAGE_ID_PLAN_NOT_INTEGER});
294+
}
295+
}
284296
}
285297

286298
if (gottenArguments === nArguments.max && nArguments.min !== nArguments.max) {
@@ -430,6 +442,7 @@ export default {
430442
[MESSAGE_ID_FOUND_MESSAGE]: 'Expected no assertion message, but found one.',
431443
[MESSAGE_ID_NOT_STRING]: 'Assertion message should be a string.',
432444
[MESSAGE_ID_OUT_OF_ORDER]: 'Expected values should come after actual values.',
445+
[MESSAGE_ID_PLAN_NOT_INTEGER]: 'Expected `t.plan()` argument to be a non-negative integer.',
433446
},
434447
},
435448
};

test/assertion-arguments.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const missingError = {messageId: 'missing-message'};
1212
const foundError = {messageId: 'found-message'};
1313
const tooFewError = () => ({messageId: 'too-few-arguments'});
1414
const tooManyError = () => ({messageId: 'too-many-arguments'});
15+
const planNotIntegerError = {messageId: 'plan-not-integer'};
1516
const outOfOrderError = (line, column, endLine, endColumn) => ({
1617
messageId: 'out-of-order',
1718
line, column, endLine, endColumn,
@@ -160,6 +161,11 @@ ruleTester.run('assertion-arguments', rule, {
160161
},
161162
valid: [
162163
testCase(false, 't.plan(1);'),
164+
testCase(false, 't.plan(0);'),
165+
testCase(false, 't.plan(100);'),
166+
testCase(false, 't.plan(n);'),
167+
testCase(false, 't.plan(foo());'),
168+
testCase(false, 't.plan(a + b);'),
163169
testCase(false, 't.assert(true, \'message\');'),
164170
testCase(false, 't.deepEqual({}, {}, \'message\');'),
165171
testCase(false, 't.fail(\'message\');'),
@@ -380,6 +386,15 @@ ruleTester.run('assertion-arguments', rule, {
380386
testCase(false, 't.timeout();', tooFewError()),
381387
testCase(false, 't.try();', tooFewError()),
382388

389+
// Invalid t.plan() argument
390+
testCase(false, 't.plan(\'1\');', planNotIntegerError),
391+
testCase(false, 't.plan(2.5);', planNotIntegerError),
392+
testCase(false, 't.plan(-1);', planNotIntegerError),
393+
testCase(false, 't.plan(true);', planNotIntegerError),
394+
testCase(false, 't.plan(null);', planNotIntegerError),
395+
testCase(false, 't.plan.skip(\'1\');', planNotIntegerError),
396+
testCase(false, 'tt.plan(2.5);', planNotIntegerError),
397+
383398
// Too many arguments
384399
testCase(false, 't.plan(1, \'extra argument\');', tooManyError()),
385400
testCase(false, 't.assert(true, \'message\', \'extra argument\');', tooManyError()),

0 commit comments

Comments
 (0)