From ff25588e3eb2d0694e360c1d9db805aaff7f66f4 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 7 Feb 2020 21:40:07 +0100 Subject: [PATCH] chore(deps): removed dependency on micromatch for expect-expect (#517) * chore: removed dependency on micromatch for expect-expect * chore(deps): removed dependency on micromatch for expect-expect * fix: wildcards should always match to the end of string or a dot --- docs/rules/expect-expect.md | 4 +- package.json | 4 +- src/rules/__tests__/expect-expect.test.ts | 150 ++++++++++++++-------- src/rules/expect-expect.ts | 31 ++++- yarn.lock | 12 -- 5 files changed, 129 insertions(+), 72 deletions(-) diff --git a/docs/rules/expect-expect.md b/docs/rules/expect-expect.md index 43441a279..9be3a2b32 100644 --- a/docs/rules/expect-expect.md +++ b/docs/rules/expect-expect.md @@ -43,8 +43,8 @@ it('should work with callbacks/async', () => { ### `assertFunctionNames` This array option whitelists the assertion function names to look for. Function -names can be a glob pattern like `request.*.expect` (see -[micromatch](https://github.com/micromatch/micromatch) for syntax) +names can use wildcards like `request.*.expect`, `request.**.expect`, +`request.*.expect*` Examples of **incorrect** code for the `{ "assertFunctionNames": ["expect"] }` option: diff --git a/package.json b/package.json index 8b9d1d226..a4a5de106 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,7 @@ "typecheck": "tsc -p ." }, "dependencies": { - "@typescript-eslint/experimental-utils": "^2.5.0", - "micromatch": "^4.0.2" + "@typescript-eslint/experimental-utils": "^2.5.0" }, "devDependencies": { "@babel/cli": "^7.4.4", @@ -51,7 +50,6 @@ "@semantic-release/git": "^7.0.17", "@types/eslint": "^6.1.3", "@types/jest": "^24.0.15", - "@types/micromatch": "^4.0.0", "@types/node": "^12.6.6", "@typescript-eslint/eslint-plugin": "^2.5.0", "@typescript-eslint/parser": "^2.5.0", diff --git a/src/rules/__tests__/expect-expect.test.ts b/src/rules/__tests__/expect-expect.test.ts index 852bb393a..9f95dc597 100644 --- a/src/rules/__tests__/expect-expect.test.ts +++ b/src/rules/__tests__/expect-expect.test.ts @@ -28,65 +28,15 @@ ruleTester.run('expect-expect', rule, { options: [{ assertFunctionNames: ['expectSaga'] }], }, { - code: `test('verifies expect method call', () => { - class Foo { - expect(k) { - return k; - } - } - new Foo().expect(123); - });`, + code: `test('verifies expect method call', () => new Foo().expect(123));`, options: [{ assertFunctionNames: ['Foo.expect'] }], }, { - code: `test('verifies deep expect method call', () => { - class Foo { - expect(k) { - return k; - } - } - let tester = { - foo: function() { - return new Foo() - } - } - tester.foo().expect(123); - });`, + code: `test('verifies deep expect method call', () => tester.foo().expect(123));`, options: [{ assertFunctionNames: ['tester.foo.expect'] }], }, { - code: `test('wildcard chained function', () => { - class Foo { - expect(k) { - return k; - } - } - let tester = { - foo: function() { - return new Foo() - } - } - tester.foo().expect(123); - });`, - options: [{ assertFunctionNames: ['tester.*.expect'] }], - }, - { - code: `test('verifies recursive expect method call', () => { - class Foo { - expect(k) { - return this; - } - bar() { - return this; - } - } - let tester = { - foo: function() { - return new Foo() - } - } - tester.foo().bar().expect(456); - });`, + code: `test('verifies recursive expect method call', () => tester.foo().bar().expect(456));`, options: [{ assertFunctionNames: ['tester.foo.bar.expect'] }], }, { @@ -162,3 +112,97 @@ ruleTester.run('expect-expect', rule, { }, ], }); + +// { +// code: `test('wildcard chained function', () => tester.foo().expect(123));`, +// options: [{ assertFunctionNames: ['tester.*.expect'] }], +// }, + +ruleTester.run('wildcards', rule, { + valid: [ + { + code: `test('should pass', () => tester.foo().expect(123));`, + options: [{ assertFunctionNames: ['tester.*.expect'] }], + }, + { + code: `test('should pass **', () => tester.foo().expect(123));`, + options: [{ assertFunctionNames: ['**'] }], + }, + { + code: `test('should pass *', () => tester.foo().expect(123));`, + options: [{ assertFunctionNames: ['*'] }], + }, + { + code: `test('should pass', () => tester.foo().expect(123));`, + options: [{ assertFunctionNames: ['tester.**'] }], + }, + { + code: `test('should pass', () => tester.foo().expect(123));`, + options: [{ assertFunctionNames: ['tester.*'] }], + }, + { + code: `test('should pass', () => tester.foo().bar().expectIt(456));`, + options: [{ assertFunctionNames: ['tester.**.expect*'] }], + }, + { + code: `test('should pass', () => request.get().foo().expect(456));`, + options: [{ assertFunctionNames: ['request.**.expect'] }], + }, + { + code: `test('should pass', () => request.get().foo().expect(456));`, + options: [{ assertFunctionNames: ['request.**.e*e*t'] }], + }, + ], + invalid: [ + { + code: `test('should fail', () => request.get().foo().expect(456));`, + options: [{ assertFunctionNames: ['request.*.expect'] }], + errors: [ + { + messageId: 'noAssertions', + type: AST_NODE_TYPES.CallExpression, + }, + ], + }, + { + code: `test('should fail', () => request.get().foo().bar().expect(456));`, + options: [{ assertFunctionNames: ['request.foo**.expect'] }], + errors: [ + { + messageId: 'noAssertions', + type: AST_NODE_TYPES.CallExpression, + }, + ], + }, + { + code: `test('should fail', () => tester.request(123));`, + options: [{ assertFunctionNames: ['request.*'] }], + errors: [ + { + messageId: 'noAssertions', + type: AST_NODE_TYPES.CallExpression, + }, + ], + }, + { + code: `test('should fail', () => request(123));`, + options: [{ assertFunctionNames: ['request.*'] }], + errors: [ + { + messageId: 'noAssertions', + type: AST_NODE_TYPES.CallExpression, + }, + ], + }, + { + code: `test('should fail', () => request(123));`, + options: [{ assertFunctionNames: ['request.**'] }], + errors: [ + { + messageId: 'noAssertions', + type: AST_NODE_TYPES.CallExpression, + }, + ], + }, + ], +}); diff --git a/src/rules/expect-expect.ts b/src/rules/expect-expect.ts index 258b6b4ee..fdec2eed1 100644 --- a/src/rules/expect-expect.ts +++ b/src/rules/expect-expect.ts @@ -7,7 +7,6 @@ import { AST_NODE_TYPES, TSESTree, } from '@typescript-eslint/experimental-utils'; -import micromatch from 'micromatch'; import { TestCaseName, createRule, @@ -15,6 +14,31 @@ import { getTestCallExpressionsFromDeclaredVariables, } from './utils'; +/** + * Checks if node names returned by getNodeName matches any of the given star patterns + * Pattern examples: + * request.*.expect + * request.**.expect + * request.**.expect* + */ +function matchesAssertFunctionName( + nodeName: string, + patterns: readonly string[], +): boolean { + return patterns.some(p => + new RegExp( + `^${p + .split('.') + .map(x => { + if (x === '**') return '[a-z\\.]*'; + return x.replace(/\*/g, '[a-z]*'); + }) + .join('\\.')}(\\.|$)`, + 'ui', + ).test(nodeName), + ); +} + export default createRule< [Partial<{ assertFunctionNames: readonly string[] }>], 'noAssertions' @@ -75,7 +99,10 @@ export default createRule< const name = getNodeName(node.callee); if (name === TestCaseName.it || name === TestCaseName.test) { unchecked.push(node); - } else if (name && micromatch.isMatch(name, assertFunctionNames)) { + } else if ( + name && + matchesAssertFunctionName(name, assertFunctionNames) + ) { // Return early in case of nested `it` statements. checkCallExpressionUsed(context.getAncestors()); } diff --git a/yarn.lock b/yarn.lock index 3a64f0bf1..09c232aa5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1279,11 +1279,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/braces@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/braces/-/braces-3.0.0.tgz#7da1c0d44ff1c7eb660a36ec078ea61ba7eb42cb" - integrity sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw== - "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -1353,13 +1348,6 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== -"@types/micromatch@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/micromatch/-/micromatch-4.0.0.tgz#c57e0b11518c930465ce923f44342e1bb4bef309" - integrity sha512-bavSCssCRRlbUI639WG0Y30AOowkI5CdxyyrC5eVbsb0BJIbgS5ROfwlwDYHsOmgS59iYlre9sstIA5wfVNKBA== - dependencies: - "@types/braces" "*" - "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"