Skip to content

Commit

Permalink
Add excludedPackages option to the prefer-add-event-listener rule (
Browse files Browse the repository at this point in the history
…#235)

Fixes #174
  • Loading branch information
medusalix authored and sindresorhus committed Feb 7, 2019
1 parent 139ac16 commit f141a4c
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 2 deletions.
20 changes: 20 additions & 0 deletions docs/rules/prefer-add-event-listener.md
Expand Up @@ -40,3 +40,23 @@ foo.bar.addEventListener('click', onClick);
```js
foo.removeEventListener('click', onClick);
```


## Options

### excludedPackages

```js
"unicorn/prefer-add-event-listener": ["error", {"excludedPackages": ["koa", "sax"]}]
```

This option lets you specify a list of packages that disable the rule when imported. By default, `koa` and `sax` are listed.

With `koa`, this would still pass:

```js
const Koa = require('koa');
const app = new Koa();

app.onerror = () => {};
```
39 changes: 38 additions & 1 deletion rules/prefer-add-event-listener.js
Expand Up @@ -55,6 +55,10 @@ const isClearing = node => {
};

const create = context => {
const options = context.options[0] || {};
const excludedPackages = new Set(options.excludedPackages || ['koa', 'sax']);
let isDisabled;

const nodeReturnsSomething = new WeakMap();
let codePathInfo = null;

Expand All @@ -72,11 +76,27 @@ const create = context => {
codePathInfo = codePathInfo.upper;
},

'CallExpression[callee.name="require"] > Literal'(node) {
if (!isDisabled && excludedPackages.has(node.value)) {
isDisabled = true;
}
},

'ImportDeclaration > Literal'(node) {
if (!isDisabled && excludedPackages.has(node.value)) {
isDisabled = true;
}
},

ReturnStatement(node) {
codePathInfo.returnsSomething = codePathInfo.returnsSomething || Boolean(node.argument);
},

'AssignmentExpression:exit'(node) {
if (isDisabled) {
return;
}

const {left: memberExpression, right: assignedExpression} = node;

if (memberExpression.type !== 'MemberExpression') {
Expand Down Expand Up @@ -118,12 +138,29 @@ const create = context => {
};
};

const schema = [
{
type: 'object',
properties: {
excludedPackages: {
type: 'array',
items: {
type: 'string'
},
uniqueItems: true
}
},
additionalProperties: false
}
];

module.exports = {
create,
meta: {
docs: {
url: getDocsUrl(__filename)
},
fixable: 'code'
fixable: 'code',
schema
}
};
128 changes: 127 additions & 1 deletion test/prefer-add-event-listener.js
Expand Up @@ -5,9 +5,19 @@ import rule from '../rules/prefer-add-event-listener';
const ruleTester = avaRuleTester(test, {
env: {
es6: true
},
parserOptions: {
sourceType: 'module'
}
});

const testCaseWithOptions = (code, options) => {
return {
code,
options
};
};

const invalidTestCase = (code, correctCode, eventType, message) => {
return {
code,
Expand All @@ -18,6 +28,15 @@ const invalidTestCase = (code, correctCode, eventType, message) => {
};
};

const invalidTestCaseWithOptions = (code, correctCode, eventType, options) => {
return {
code,
output: correctCode || code,
errors: [{message: `Prefer \`addEventListener\` over \`${eventType}\`.`}],
options
};
};

const expectedBeforeUnloadWithReturnMessage = [
'Prefer `addEventListener` over `onbeforeunload`.',
'Use `event.preventDefault(); event.returnValue = \'foo\'` to trigger the prompt.'
Expand All @@ -31,7 +50,39 @@ ruleTester.run('prefer-add-event-listener', rule, {
'foo.setCallBack = () => {console.log(\'foo\')}',
'setCallBack = () => {console.log(\'foo\')}',
'foo.onclick.bar = () => {}',
'foo[\'x\'] = true;'
'foo[\'x\'] = true;',
`const Koa = require('koa');
const app = new Koa();
app.onerror = () => {};`,
`const sax = require('sax');
const parser = sax.parser();
parser.onerror = () => {};`,
`import Koa from 'koa';
const app = new Koa();
app.onerror = () => {};`,
`import sax from 'sax';
const parser = sax.parser();
parser.onerror = () => {};`,
`import {sax as foo} from 'sax';
const parser = foo.parser();
parser.onerror = () => {};`,
testCaseWithOptions(
`const foo = require('foo');
foo.onerror = () => {};`,
[{excludedPackages: ['foo']}]
),
testCaseWithOptions(
`import foo from 'foo';
foo.onclick = () => {};`,
[{excludedPackages: ['foo']}]
)
],

invalid: [
Expand Down Expand Up @@ -156,6 +207,81 @@ ruleTester.run('prefer-add-event-listener', rule, {
console.log(e);
})`,
'onbeforeunload'
),
invalidTestCase(
`const foo = require('foo');
foo.onerror = () => {};
`,
`const foo = require('foo');
foo.addEventListener('error', () => {});
`,
'onerror'
),
invalidTestCase(
`import foo from 'foo';
foo.onerror = () => {};
`,
`import foo from 'foo';
foo.addEventListener('error', () => {});
`,
'onerror'
),
invalidTestCase(
`foo.onerror = () => {};
function bar() {
const koa = require('koa');
koa.onerror = () => {};
}`,
`foo.addEventListener('error', () => {});
function bar() {
const koa = require('koa');
koa.onerror = () => {};
}`,
'onerror'
),
invalidTestCaseWithOptions(
`const Koa = require('koa');
const app = new Koa();
app.onerror = () => {};`,
`const Koa = require('koa');
const app = new Koa();
app.addEventListener('error', () => {});`,
'onerror',
[{excludedPackages: ['foo']}]
),
invalidTestCaseWithOptions(
`import {Koa as Foo} from 'koa';
const app = new Foo();
app.onerror = () => {};`,
`import {Koa as Foo} from 'koa';
const app = new Foo();
app.addEventListener('error', () => {});`,
'onerror',
[{excludedPackages: ['foo']}]
),
invalidTestCaseWithOptions(
`const sax = require('sax');
const parser = sax.parser();
parser.onerror = () => {};`,
`const sax = require('sax');
const parser = sax.parser();
parser.addEventListener('error', () => {});`,
'onerror',
[{excludedPackages: []}]
)
]
});

0 comments on commit f141a4c

Please sign in to comment.