2020-08-25 23:57:08 +00:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = void 0 ;
2022-11-10 10:43:16 +00:00
var _utils = require ( "@typescript-eslint/utils" ) ;
var _utils2 = require ( "./utils" ) ;
const findCallbackArg = ( node , isJestEach , context ) => {
if ( isJestEach ) {
return node . arguments [ 1 ] ;
}
const jestFnCall = ( 0 , _utils2 . parseJestFnCall ) ( node , context ) ;
if ( ( jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall . type ) === 'hook' && node . arguments . length >= 1 ) {
2021-02-26 03:58:33 +00:00
return node . arguments [ 0 ] ;
}
2022-11-10 10:43:16 +00:00
if ( ( jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall . type ) === 'test' && node . arguments . length >= 2 ) {
2021-02-26 03:58:33 +00:00
return node . arguments [ 1 ] ;
}
return null ;
} ;
2022-11-10 10:43:16 +00:00
var _default = ( 0 , _utils2 . createRule ) ( {
2020-08-25 23:57:08 +00:00
name : _ _filename ,
meta : {
docs : {
category : 'Best Practices' ,
2022-11-10 10:43:16 +00:00
description : 'Disallow using a callback in asynchronous tests and hooks' ,
recommended : 'error'
2020-08-25 23:57:08 +00:00
} ,
messages : {
2021-02-26 03:58:33 +00:00
noDoneCallback : 'Return a Promise instead of relying on callback parameter' ,
2020-08-25 23:57:08 +00:00
suggestWrappingInPromise : 'Wrap in `new Promise({{ callback }} => ...`' ,
useAwaitInsteadOfCallback : 'Use await instead of callback in async functions'
} ,
schema : [ ] ,
2022-11-10 10:43:16 +00:00
type : 'suggestion' ,
hasSuggestions : true
2020-08-25 23:57:08 +00:00
} ,
defaultOptions : [ ] ,
create ( context ) {
return {
CallExpression ( node ) {
2022-11-10 10:43:16 +00:00
var _getNodeName ;
// done is the second argument for it.each, not the first
const isJestEach = ( ( _getNodeName = ( 0 , _utils2 . getNodeName ) ( node . callee ) ) === null || _getNodeName === void 0 ? void 0 : _getNodeName . endsWith ( '.each' ) ) ? ? false ;
if ( isJestEach && node . callee . type !== _utils . AST _NODE _TYPES . TaggedTemplateExpression ) {
// isJestEach but not a TaggedTemplateExpression, so this must be
// the `jest.each([])()` syntax which this rule doesn't support due
// to its complexity (see jest-community/eslint-plugin-jest#710)
2020-08-25 23:57:08 +00:00
return ;
}
2022-11-10 10:43:16 +00:00
const callback = findCallbackArg ( node , isJestEach , context ) ;
const callbackArgIndex = Number ( isJestEach ) ;
if ( ! callback || ! ( 0 , _utils2 . isFunction ) ( callback ) || callback . params . length !== 1 + callbackArgIndex ) {
return ;
}
const argument = callback . params [ callbackArgIndex ] ;
if ( argument . type !== _utils . AST _NODE _TYPES . Identifier ) {
2020-08-25 23:57:08 +00:00
context . report ( {
node : argument ,
2021-02-26 03:58:33 +00:00
messageId : 'noDoneCallback'
2020-08-25 23:57:08 +00:00
} ) ;
return ;
}
if ( callback . async ) {
context . report ( {
node : argument ,
messageId : 'useAwaitInsteadOfCallback'
} ) ;
return ;
}
context . report ( {
node : argument ,
2021-02-26 03:58:33 +00:00
messageId : 'noDoneCallback' ,
2020-08-25 23:57:08 +00:00
suggest : [ {
messageId : 'suggestWrappingInPromise' ,
data : {
callback : argument . name
} ,
fix ( fixer ) {
const {
body
} = callback ;
const sourceCode = context . getSourceCode ( ) ;
const firstBodyToken = sourceCode . getFirstToken ( body ) ;
const lastBodyToken = sourceCode . getLastToken ( body ) ;
const tokenBeforeArgument = sourceCode . getTokenBefore ( argument ) ;
const tokenAfterArgument = sourceCode . getTokenAfter ( argument ) ;
2022-11-10 10:43:16 +00:00
/* istanbul ignore if */
2020-08-25 23:57:08 +00:00
if ( ! firstBodyToken || ! lastBodyToken || ! tokenBeforeArgument || ! tokenAfterArgument ) {
throw new Error ( ` Unexpected null when attempting to fix ${ context . getFilename ( ) } - please file a github issue at https://github.com/jest-community/eslint-plugin-jest ` ) ;
}
const argumentInParens = tokenBeforeArgument . value === '(' && tokenAfterArgument . value === ')' ;
let argumentFix = fixer . replaceText ( argument , '()' ) ;
if ( argumentInParens ) {
argumentFix = fixer . remove ( argument ) ;
}
let newCallback = argument . name ;
if ( argumentInParens ) {
newCallback = ` ( ${ newCallback } ) ` ;
}
let beforeReplacement = ` new Promise( ${ newCallback } => ` ;
let afterReplacement = ')' ;
let replaceBefore = true ;
2022-11-10 10:43:16 +00:00
if ( body . type === _utils . AST _NODE _TYPES . BlockStatement ) {
2020-08-25 23:57:08 +00:00
const keyword = 'return' ;
beforeReplacement = ` ${ keyword } ${ beforeReplacement } { ` ;
afterReplacement += '}' ;
replaceBefore = false ;
}
return [ argumentFix , replaceBefore ? fixer . insertTextBefore ( firstBodyToken , beforeReplacement ) : fixer . insertTextAfter ( firstBodyToken , beforeReplacement ) , fixer . insertTextAfter ( lastBodyToken , afterReplacement ) ] ;
}
} ]
} ) ;
}
} ;
}
} ) ;
exports . default = _default ;