2020-08-26 01:57:08 +02:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = void 0 ;
var _experimentalUtils = require ( "@typescript-eslint/experimental-utils" ) ;
var _utils = require ( "./utils" ) ;
2021-02-26 04:58:33 +01:00
const findCallbackArg = node => {
if ( ( 0 , _utils . isHook ) ( node ) && node . arguments . length >= 1 ) {
return node . arguments [ 0 ] ;
}
if ( ( 0 , _utils . isTestCase ) ( node ) && node . arguments . length >= 2 ) {
return node . arguments [ 1 ] ;
}
return null ;
} ;
2020-08-26 01:57:08 +02:00
var _default = ( 0 , _utils . createRule ) ( {
name : _ _filename ,
meta : {
docs : {
category : 'Best Practices' ,
2021-02-26 04:58:33 +01:00
description : 'Avoid using a callback in asynchronous tests and hooks' ,
2020-08-26 01:57:08 +02:00
recommended : 'error' ,
suggestion : true
} ,
messages : {
2021-02-26 04:58:33 +01:00
noDoneCallback : 'Return a Promise instead of relying on callback parameter' ,
2020-08-26 01:57:08 +02:00
suggestWrappingInPromise : 'Wrap in `new Promise({{ callback }} => ...`' ,
useAwaitInsteadOfCallback : 'Use await instead of callback in async functions'
} ,
schema : [ ] ,
type : 'suggestion'
} ,
defaultOptions : [ ] ,
create ( context ) {
return {
CallExpression ( node ) {
2021-02-26 04:58:33 +01:00
const callback = findCallbackArg ( node ) ;
2020-08-26 01:57:08 +02:00
2021-02-26 04:58:33 +01:00
if ( ! callback || ! ( 0 , _utils . isFunction ) ( callback ) || callback . params . length !== 1 ) {
2020-08-26 01:57:08 +02:00
return ;
}
const [ argument ] = callback . params ;
if ( argument . type !== _experimentalUtils . AST _NODE _TYPES . Identifier ) {
context . report ( {
node : argument ,
2021-02-26 04:58:33 +01:00
messageId : 'noDoneCallback'
2020-08-26 01:57:08 +02:00
} ) ;
return ;
}
if ( callback . async ) {
context . report ( {
node : argument ,
messageId : 'useAwaitInsteadOfCallback'
} ) ;
return ;
}
context . report ( {
node : argument ,
2021-02-26 04:58:33 +01:00
messageId : 'noDoneCallback' ,
2020-08-26 01:57:08 +02: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 ) ;
/* istanbul ignore if */
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 ;
if ( body . type === _experimentalUtils . AST _NODE _TYPES . BlockStatement ) {
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 ;