Skip to content

Commit

Permalink
chore(prefer-strict-equal): migrate to TS (#329)
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath authored and SimenB committed Jul 22, 2019
1 parent ee81058 commit ccbe766
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 37 deletions.
@@ -1,7 +1,7 @@
import { RuleTester } from 'eslint';
import { TSESLint } from '@typescript-eslint/experimental-utils';
import rule from '../prefer-strict-equal';

const ruleTester = new RuleTester();
const ruleTester = new TSESLint.RuleTester();

ruleTester.run('prefer-strict-equal', rule, {
valid: [
Expand Down
35 changes: 0 additions & 35 deletions src/rules/prefer-strict-equal.js

This file was deleted.

40 changes: 40 additions & 0 deletions src/rules/prefer-strict-equal.ts
@@ -0,0 +1,40 @@
import { createRule, isExpectCallWithParent } from './tsUtils';

export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using toStrictEqual()',
recommended: false,
},
messages: {
useToStrictEqual: 'Use toStrictEqual() instead',
},
fixable: 'code',
schema: [],
type: 'suggestion',
},
defaultOptions: [],
create(context) {
return {
CallExpression(node) {
if (!isExpectCallWithParent(node)) {
return;
}

const methodNode = node.parent.property;

if (methodNode && methodNode.name === 'toEqual') {
context.report({
fix(fixer) {
return [fixer.replaceText(methodNode, 'toStrictEqual')];
},
messageId: 'useToStrictEqual',
node: methodNode,
});
}
},
};
},
});
60 changes: 60 additions & 0 deletions src/rules/tsUtils.ts
Expand Up @@ -15,6 +15,66 @@ export const createRule = ESLintUtils.RuleCreator(name => {
return `${REPO_URL}/blob/v${version}/docs/rules/${ruleName}.md`;
});

interface JestExpectIdentifier extends TSESTree.Identifier {
name: 'expect';
}

/**
* Checks if the given `node` is considered a {@link JestExpectIdentifier}.
*
* A `node` is considered to be as such if it is of type `Identifier`,
* and `name`d `"expect"`.
*
* @param {Node} node
*
* @return {node is JestExpectIdentifier}
*/
const isExpectIdentifier = (
node: TSESTree.Node,
): node is JestExpectIdentifier =>
node.type === AST_NODE_TYPES.Identifier && node.name === 'expect';

// represents "expect()" specifically
interface JestExpectCallExpression extends TSESTree.CallExpression {
callee: JestExpectIdentifier;
}

// represents expect usage like "expect().toBe" & "expect().not.toBe"
interface JestExpectCallMemberExpression extends TSESTree.MemberExpression {
object: JestExpectCallMemberExpression | JestExpectCallExpression;
property: TSESTree.Identifier;
}

// represents expect usage like "expect.anything" & "expect.hasAssertions"
interface JestExpectNamespaceMemberExpression
extends TSESTree.MemberExpression {
object: JestExpectIdentifier;
property: TSESTree.Identifier;
}

/**
* Checks if the given `node` is a {@link JestExpectCallExpression}.
*
* @param {Node} node
*
* @return {node is JestExpectCallExpression}
*/
const isExpectCall = (node: TSESTree.Node): node is JestExpectCallExpression =>
node.type === AST_NODE_TYPES.CallExpression &&
isExpectIdentifier(node.callee);

interface JestExpectCallWithParent extends JestExpectCallExpression {
parent: JestExpectCallMemberExpression;
}

export const isExpectCallWithParent = (
node: TSESTree.Node,
): node is JestExpectCallWithParent =>
isExpectCall(node) &&
node.parent !== undefined &&
node.parent.type === AST_NODE_TYPES.MemberExpression &&
node.parent.property.type === AST_NODE_TYPES.Identifier;

export enum DescribeAlias {
'describe' = 'describe',
'fdescribe' = 'fdescribe',
Expand Down

0 comments on commit ccbe766

Please sign in to comment.