Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion configs/eslint-config-devtools/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const testRules = {
'mocha/no-setup-in-describe': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@mongodb-js/devtools/no-expect-method-without-call': 'error',
};

const jsConfigurations = ['eslint:recommended'];
Expand Down Expand Up @@ -124,7 +125,9 @@ const testOverrides = {
],
env: { mocha: true },
extends: [...testConfigurations],
rules: { ...testRules },
rules: {
...testRules,
},
};

module.exports = {
Expand Down
1 change: 1 addition & 0 deletions configs/eslint-config-devtools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
'react',
'react-hooks',
'filename-rules',
'@mongodb-js/devtools',
],
rules: {
'filename-rules/match': ['error', common.kebabcase],
Expand Down
1 change: 1 addition & 0 deletions configs/eslint-config-devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@babel/eslint-parser": "^7.22.7",
"@babel/preset-env": "^7.22.7",
"@babel/preset-react": "^7.22.5",
"@mongodb-js/eslint-plugin-devtools": "^0.1.0",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"eslint-config-prettier": "^8.3.0",
Expand Down
3 changes: 3 additions & 0 deletions configs/eslint-plugin-devtools/.depcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignores:
- '@mongodb-js/prettier-config-devtools'
- '@mongodb-js/eslint-config-devtools'
2 changes: 2 additions & 0 deletions configs/eslint-plugin-devtools/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.nyc-output
dist
9 changes: 9 additions & 0 deletions configs/eslint-plugin-devtools/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';
module.exports = {
root: true,
extends: ['@mongodb-js/eslint-config-devtools'],
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig-lint.json'],
},
};
6 changes: 6 additions & 0 deletions configs/eslint-plugin-devtools/.mocharc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict';
module.exports = {
...require('@mongodb-js/mocha-config-devtools'),
spec: ['rules/**/*.test.js'],
watchFiles: ['rules/**/*.js'],
};
1 change: 1 addition & 0 deletions configs/eslint-plugin-devtools/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"@mongodb-js/prettier-config-devtools"
6 changes: 6 additions & 0 deletions configs/eslint-plugin-devtools/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict';
module.exports = {
rules: {
'no-expect-method-without-call': require('./rules/no-expect-method-without-call'),
},
};
36 changes: 36 additions & 0 deletions configs/eslint-plugin-devtools/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@mongodb-js/eslint-plugin-devtools",
"description": "Custom eslint rules for DevTools",
"homepage": "https://github.com/mongodb-js/devtools-shared",
"version": "0.1.0",
"repository": {
"type": "git",
"url": "https://github.com/mongodb-js/devtools-shared.git"
},
"files": [
"dist"
],
"license": "SSPL",
"main": "index.js",
"scripts": {
"eslint": "eslint",
"prettier": "prettier",
"lint": "npm run eslint . && npm run prettier -- --check .",
"depcheck": "depcheck",
"check": "npm run lint && npm run depcheck",
"check-ci": "npm run check",
"test": "mocha",
"test-cov": "nyc --compact=false --produce-source-map=false -x \"**/*.spec.*\" --reporter=lcov --reporter=text --reporter=html npm run test",
"test-watch": "npm run test -- --watch",
"test-ci": "npm run test-cov",
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
},
"devDependencies": {
"@mongodb-js/mocha-config-devtools": "^1.0.5",
"@mongodb-js/prettier-config-devtools": "^1.0.1",
"depcheck": "^1.4.7",
"eslint": "^7.25.0",
"mocha": "^8.4.0",
"nyc": "^15.1.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use strict';

const PROPERTY_TERMINATORS = [
'ok',
'true',
'false',
'null',
'undefined',
'exist',
'empty',
'arguments',
];

function followNodeChainToExpectCall(node) {
while (node) {
if (node.type === 'CallExpression') {
if (node.callee.type === 'Identifier' && node.callee.name === 'expect') {
return node;
}
if (node.callee.type === 'MemberExpression') {
node = node.callee.object;
continue;
}
}

// Continue on the node chain (e.g. .not, .to).
if (node.type === 'MemberExpression') {
node = node.object;
continue;
}

break;
}
}

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description:
'Require invocation of expect method assertions (e.g., to.throw())',
},
messages: {
methodNotInvoked:
'expect().to.[METHOD] must be invoked with parentheses, e.g., expect(() => someFn()).to.throw()',
},
},

create(context) {
return {
MemberExpression(node) {
if (
node.type !== 'MemberExpression' ||
PROPERTY_TERMINATORS.includes(node.property.name) ||
node.property.name === 'expect'
) {
return null;
}

const isInvoked =
node.parent &&
node.parent.type === 'CallExpression' &&
node.parent.callee === node;

const isPartOfLongerChain =
node.parent &&
node.parent.type === 'MemberExpression' &&
node.parent.object === node;

if (isInvoked || isPartOfLongerChain) {
return null;
}

const expectCall = followNodeChainToExpectCall(node);
if (!expectCall) {
return null;
}

context.report({
node,
messageId: 'methodNotInvoked',
});
},
};
},
};
Loading
Loading