Repository: lo1tuma/eslint-plugin-mocha (ts)

Issue:
no-exclusive-tests: additionalTestFunctions should support methods
I'm using this plugin with selenium-webdriver tests that uses wrapped mocha functions as methods of `test` object:

``` js
test.describe('Google Search', function() {
  var driver;

  test.before(function() {
    driver = new webdriver.Builder()
        .forBrowser('firefox')
        .build();
  });

  test.it('should append query to title', function() {
    driver.get('http://www.google.com');
    driver.findElement(By.name('q')).sendKeys('webdriver');
    driver.findElement(By.name('btnG')).click();
    driver.wait(until.titleIs('webdriver - Google Search'), 1000);
  });

  test.after(function() {
    driver.quit();
  });
});
```

Full example from selenium repo: https://github.com/SeleniumHQ/selenium/blob/master/javascript/node/selenium-webdriver/example/google_search_test.js

Setting `additionalTestFunctions` does not work:

```
  "settings": {
    "mocha/additionalTestFunctions": [
      "test.describe",
      "test.it"
    ]
  }
```

Is it possible to support this?
Thanks!


Pull request:
Support MemberExpression for additionalTestFunctions
Fixes #102 

Patch:
diff --git a/lib/util/ast.js b/lib/util/ast.js
index d3fd5dd..471673c 100644
--- a/lib/util/ast.js
+++ b/lib/util/ast.js
@@ -10,9 +10,13 @@ var describeAliases = [ 'describe', 'xdescribe', 'describe.only', 'describe.skip
                       'test', 'test.only', 'test.skip',
                       'specify', 'specify.only', 'specify.skip' ];
 
+function getPropertyName(property) {
+    return property.name || property.value;
+}
+
 function getNodeName(node) {
     if (node.type === 'MemberExpression') {
-        return node.object.name + '.' + node.property.name;
+        return getNodeName(node.object) + '.' + getPropertyName(node.property);
     }
     return node.name;
 }
@@ -38,5 +42,7 @@ function isTestCase(node) {
 module.exports = {
   isDescribe: isDescribe,
   isHookIdentifier: isHookIdentifier,
-  isTestCase: isTestCase
+  isTestCase: isTestCase,
+  getPropertyName: getPropertyName,
+  getNodeName: getNodeName
 };


Test patch:
diff --git a/lib/rules/no-exclusive-tests.js b/lib/rules/no-exclusive-tests.js
index c151052..ffdac9b 100644
--- a/lib/rules/no-exclusive-tests.js
+++ b/lib/rules/no-exclusive-tests.js
@@ -1,6 +1,7 @@
 'use strict';
 
-var getAdditionalTestFunctions = require('../util/settings').getAdditionalTestFunctions;
+var getAdditionalTestFunctions = require('../util/settings').getAdditionalTestFunctions,
+    astUtils = require('../util/ast');
 
 module.exports = function (context) {
     var mochaTestFunctions = [
@@ -17,11 +18,13 @@ module.exports = function (context) {
     mochaTestFunctions = mochaTestFunctions.concat(additionalTestFunctions);
 
     function matchesMochaTestFunction(object) {
-        return object && mochaTestFunctions.indexOf(object.name) !== -1;
+        var name = astUtils.getNodeName(object);
+
+        return mochaTestFunctions.indexOf(name) !== -1;
     }
 
     function isPropertyNamedOnly(property) {
-        return property && (property.name === 'only' || property.value === 'only');
+        return property && astUtils.getPropertyName(property) === 'only';
     }
 
     function isCallToMochasOnlyFunction(callee) {
diff --git a/test/rules/no-exclusive-tests.js b/test/rules/no-exclusive-tests.js
index 9a1d686..11d3fef 100644
--- a/test/rules/no-exclusive-tests.js
+++ b/test/rules/no-exclusive-tests.js
@@ -22,7 +22,23 @@ ruleTester.run('no-exclusive-tests', rules['no-exclusive-tests'], {
         'var calledOnly = it.only; calledOnly.call(it)',
         'var dynamicOnly = "only"; suite[dynamicOnly]()',
         'specify()',
-        'specify.skip()'
+        'specify.skip()',
+        {
+            code: 'a.b.c.skip()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'a.b.c' ]
+                }
+            }
+        },
+        {
+            code: 'a[b].c.skip()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'a.b.c' ]
+                }
+            }
+        }
     ],
 
     invalid: [
@@ -105,7 +121,51 @@ ruleTester.run('no-exclusive-tests', rules['no-exclusive-tests'], {
                 }
             },
             errors: [ { message: expectedErrorMessage, column: 8, line: 1 } ]
+        },
+        {
+            code: 'foo.bar.only()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'foo.bar' ]
+                }
+            },
+            errors: [ { message: expectedErrorMessage, column: 9, line: 1 } ]
+        },
+        {
+            code: 'foo.bar["only"]()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'foo.bar' ]
+                }
+            },
+            errors: [ { message: expectedErrorMessage, column: 9, line: 1 } ]
+        },
+        {
+            code: 'foo["bar"].only()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'foo.bar' ]
+                }
+            },
+            errors: [ { message: expectedErrorMessage, column: 12, line: 1 } ]
+        },
+        {
+            code: 'foo["bar"]["only"]()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'foo.bar' ]
+                }
+            },
+            errors: [ { message: expectedErrorMessage, column: 12, line: 1 } ]
+        },
+        {
+            code: 'a.b.c.only()',
+            settings: {
+                mocha: {
+                    additionalTestFunctions: [ 'a.b.c' ]
+                }
+            },
+            errors: [ { message: expectedErrorMessage, column: 7, line: 1 } ]
         }
     ]
-
 });