diff --git a/create-ava-rule.js b/create-ava-rule.js index ac1b189..1791a0a 100644 --- a/create-ava-rule.js +++ b/create-ava-rule.js @@ -216,12 +216,13 @@ module.exports = () => { // eslint-disable-line eslint-plugin/prefer-object-rule return { hasTestModifier: mod => getTestModifierNames(currentTestNode).includes(mod), - hasNoHookModifier: () => { + hasNoUtilityModifier: () => { const modifiers = getTestModifierNames(currentTestNode); return !modifiers.includes('before') && !modifiers.includes('beforeEach') && !modifiers.includes('after') && - !modifiers.includes('afterEach'); + !modifiers.includes('afterEach') && + !modifiers.includes('macro'); }, isInTestFile: () => isTestFile, isInTestNode: () => currentTestNode, diff --git a/rules/no-identical-title.js b/rules/no-identical-title.js index 0a92e67..e6ac1e5 100644 --- a/rules/no-identical-title.js +++ b/rules/no-identical-title.js @@ -26,7 +26,7 @@ const create = context => { CallExpression: visitIf([ ava.isInTestFile, ava.isTestNode, - ava.hasNoHookModifier + ava.hasNoUtilityModifier ])(node => { const args = node.arguments; const titleNode = args.length > 1 || ava.hasTestModifier('todo') ? args[0] : undefined; diff --git a/rules/no-unknown-modifiers.js b/rules/no-unknown-modifiers.js index f1c2f2b..985640c 100644 --- a/rules/no-unknown-modifiers.js +++ b/rules/no-unknown-modifiers.js @@ -14,7 +14,8 @@ const modifiers = new Set([ 'serial', 'skip', 'todo', - 'failing' + 'failing', + 'macro' ]); const unknownModifiers = node => util.getTestModifiers(node) diff --git a/rules/test-title-format.js b/rules/test-title-format.js index 378f025..aca5f7d 100644 --- a/rules/test-title-format.js +++ b/rules/test-title-format.js @@ -17,7 +17,7 @@ const create = context => { CallExpression: visitIf([ ava.isInTestFile, ava.isTestNode, - ava.hasNoHookModifier + ava.hasNoUtilityModifier ])(node => { const requiredLength = ava.hasTestModifier('todo') ? 1 : 2; const hasTitle = node.arguments.length >= requiredLength; diff --git a/rules/test-title.js b/rules/test-title.js index e0c1623..f15d706 100644 --- a/rules/test-title.js +++ b/rules/test-title.js @@ -10,7 +10,7 @@ const create = context => { CallExpression: visitIf([ ava.isInTestFile, ava.isTestNode, - ava.hasNoHookModifier + ava.hasNoUtilityModifier ])(node => { const firstArgumentIsFunction = node.arguments.length === 0 || util.isFunctionExpression(node.arguments[0]); diff --git a/rules/use-t.js b/rules/use-t.js index f1b2017..7c5bdb6 100644 --- a/rules/use-t.js +++ b/rules/use-t.js @@ -11,18 +11,24 @@ const create = context => { ava.isInTestFile, ava.isTestNode ])(node => { - const functionArgIndex = node.arguments.length - 1; - if (functionArgIndex > 1) { + const index = node.arguments.length - 1; + if (index > 1) { return; } - const functionArg = node.arguments[functionArgIndex]; + let implementationArg = node.arguments[index]; + if (ava.hasTestModifier('macro') && implementationArg.type === 'ObjectExpression') { + const execProperty = implementationArg.properties.find(p => { + return p.key.name === 'exec'; + }); + implementationArg = execProperty && execProperty.value; + } - if (!functionArg || !functionArg.params || functionArg.params.length === 0) { + if (!implementationArg || !implementationArg.params || implementationArg.params.length === 0) { return; } - if (functionArg.params[0].name !== 't') { + if (implementationArg.params[0].name !== 't') { context.report({ node, message: 'Test parameter should be named `t`.' diff --git a/test/no-unknown-modifiers.js b/test/no-unknown-modifiers.js index 0351aed..6b67bb9 100644 --- a/test/no-unknown-modifiers.js +++ b/test/no-unknown-modifiers.js @@ -26,6 +26,7 @@ ruleTester.run('no-unknown-modifiers', rule, { `${header}test.after.always(t => {});`, `${header}test.afterEach.always(t => {});`, `${header}test.failing(t => {});`, + `${header}test.macro(t => {});`, // Shouldn't be triggered since it's not a test file 'test.foo(t => {});' ], diff --git a/test/test-title.js b/test/test-title.js index 0b22cfd..8ed4d21 100644 --- a/test/test-title.js +++ b/test/test-title.js @@ -22,6 +22,7 @@ ruleTester.run('test-title', rule, { header + 'test.after(t => {});', header + 'test.beforeEach(t => {});', header + 'test.afterEach(t => {});', + header + 'test.macro(t => {});', header + 'test.cb.before(t => {}); test.before.cb(t => {});', header + 'notTest(t => { t.pass(); t.end(); });', header + 'test([], arg1, arg2);', diff --git a/test/use-t.js b/test/use-t.js index b26af07..8258383 100644 --- a/test/use-t.js +++ b/test/use-t.js @@ -27,6 +27,9 @@ ruleTester.run('use-t', rule, { header + 'test((t, foo) => {});', header + 'test(function (t) {});', header + 'test(testFunction);', + header + 'test.macro(testFunction);', + header + 'test.macro(t => {});', + header + 'test.macro({exec: t => {}, title: () => "title"});', header + 'test.todo("test name");', // Shouldn't be triggered since it's not a test file 'test(foo => {});', @@ -50,6 +53,14 @@ ruleTester.run('use-t', rule, { { code: header + 'test(function (foo) {});', errors: parameterNotNamedTErrors + }, + { + code: header + 'test.macro(function (foo) {});', + errors: parameterNotNamedTErrors + }, + { + code: header + 'test.macro({ exec(foo) {} });', + errors: parameterNotNamedTErrors } ] });