@@ -104,7 +104,7 @@ module.exports = function(file, api, options) {
104104 function parseModule ( p ) {
105105 let calleeName = p . node . expression . callee . name ;
106106 // Find the moduleName and the module's options
107- let moduleName , subject , options ;
107+ let moduleName , subject , options , hasCustomSubject ;
108108 let calleeArguments = p . node . expression . arguments . slice ( ) ;
109109 let lastArgument = calleeArguments [ calleeArguments . length - 1 ] ;
110110 if ( lastArgument . type === 'ObjectExpression' ) {
@@ -127,9 +127,11 @@ module.exports = function(file, api, options) {
127127 } else if ( ! hasIntegration ) {
128128 subject = calleeArguments [ 0 ] ;
129129 }
130+
131+ hasCustomSubject = options . properties . some ( p => p . key . name === 'subject' ) ;
130132 }
131133
132- return [ moduleName , options , setupIdentifier , subject ] ;
134+ return [ moduleName , options , setupIdentifier , subject , hasCustomSubject ] ;
133135 }
134136
135137 function updateModuleForToNestedModule ( ) {
@@ -143,6 +145,10 @@ module.exports = function(file, api, options) {
143145 return POSSIBLE_MODULES . some ( matcher => j . match ( nodePath , matcher ) ) ;
144146 }
145147
148+ function isMethod ( nodePath ) {
149+ return j . match ( nodePath , { value : { type : 'FunctionExpression' } } ) ;
150+ }
151+
146152 const LIFE_CYCLE_METHODS = [
147153 { key : { name : 'before' } , value : { type : 'FunctionExpression' } } ,
148154 { key : { name : 'beforeEach' } , value : { type : 'FunctionExpression' } } ,
@@ -155,7 +161,7 @@ module.exports = function(file, api, options) {
155161 }
156162
157163 function createModule ( p ) {
158- let [ moduleName , options , setupType , subject ] = parseModule ( p ) ;
164+ let [ moduleName , options , setupType , subject , hasCustomSubject ] = parseModule ( p ) ;
159165
160166 // Create the new `module(moduleName, function(hooks) {});` invocation
161167 let callback = j . functionExpression (
@@ -170,6 +176,8 @@ module.exports = function(file, api, options) {
170176 ) ;
171177
172178 if ( options ) {
179+ let customMethodBeforeEachBody ;
180+
173181 options . properties . forEach ( property => {
174182 if ( isLifecycleHook ( property ) ) {
175183 let lifecycleStatement = j . expressionStatement (
@@ -182,11 +190,45 @@ module.exports = function(file, api, options) {
182190 lifecycleStatement . comments = property . comments ;
183191
184192 callback . body . body . push ( lifecycleStatement ) ;
193+ } else if ( isMethod ( property ) ) {
194+ if ( ! customMethodBeforeEachBody ) {
195+ customMethodBeforeEachBody = j . blockStatement ( [ ] ) ;
196+
197+ let beforeEachInvocation = j . expressionStatement (
198+ j . callExpression (
199+ j . memberExpression ( j . identifier ( 'hooks' ) , j . identifier ( 'beforeEach' ) ) ,
200+ [
201+ j . functionExpression (
202+ null ,
203+ [
204+ /* no arguments */
205+ ] ,
206+ customMethodBeforeEachBody
207+ ) ,
208+ ]
209+ )
210+ ) ;
211+
212+ callback . body . body . push ( beforeEachInvocation ) ;
213+ }
214+
215+ let methodAssignment = j . expressionStatement (
216+ j . assignmentExpression (
217+ '=' ,
218+ j . memberExpression ( j . thisExpression ( ) , property . key ) ,
219+ property . value
220+ )
221+ ) ;
222+
223+ // preserve any comments that were present
224+ methodAssignment . comments = property . comments ;
225+
226+ customMethodBeforeEachBody . body . push ( methodAssignment ) ;
185227 }
186228 } ) ;
187229 }
188230
189- return [ moduleInvocation , callback . body . body , setupType , subject ] ;
231+ return [ moduleInvocation , callback . body . body , setupType , subject , hasCustomSubject ] ;
190232 }
191233
192234 function processRenderingTest ( testExpression ) {
@@ -301,7 +343,7 @@ module.exports = function(file, api, options) {
301343 let bodyPath = programPath . get ( 'body' ) ;
302344
303345 let bodyReplacement = [ ] ;
304- let currentModuleCallbackBody , currentTestType , currentSubject ;
346+ let currentModuleCallbackBody , currentTestType , currentSubject , currentHasCustomSubject ;
305347 bodyPath . each ( expressionPath => {
306348 let expression = expressionPath . node ;
307349 if ( isModuleDefinition ( expressionPath ) ) {
@@ -310,12 +352,13 @@ module.exports = function(file, api, options) {
310352 currentModuleCallbackBody = result [ 1 ] ;
311353 currentTestType = result [ 2 ] ;
312354 currentSubject = result [ 3 ] ;
355+ currentHasCustomSubject = result [ 4 ] ;
313356 } else if ( currentModuleCallbackBody ) {
314357 currentModuleCallbackBody . push ( expression ) ;
315358
316359 if ( currentTestType === 'setupRenderingTest' ) {
317360 processRenderingTest ( expression ) ;
318- } else if ( currentTestType === 'setupTest' ) {
361+ } else if ( currentTestType === 'setupTest' && ! currentHasCustomSubject ) {
319362 processSubject ( expression , currentSubject ) ;
320363 }
321364 } else {
0 commit comments