@@ -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 , options ;
107+ let moduleName , subject , options ;
108108 let calleeArguments = p . node . expression . arguments . slice ( ) ;
109109 let lastArgument = calleeArguments [ calleeArguments . length - 1 ] ;
110110 if ( lastArgument . type === 'ObjectExpression' ) {
@@ -113,15 +113,23 @@ module.exports = function(file, api, options) {
113113 moduleName = calleeArguments [ 1 ] || calleeArguments [ 0 ] ;
114114
115115 let setupIdentifier = 'setupTest' ;
116- if ( calleeName === `moduleForComponent` && options ) {
116+ if ( options ) {
117117 let hasIntegration = options . properties . some ( p => p . key . name === 'integration' ) ;
118118
119- if ( hasIntegration ) {
120- setupIdentifier = 'setupRenderingTest' ;
119+ if ( calleeName === `moduleForComponent` ) {
120+ if ( hasIntegration ) {
121+ setupIdentifier = 'setupRenderingTest' ;
122+ } else {
123+ subject = j . literal ( `component:${ calleeArguments [ 0 ] . value } ` ) ;
124+ }
125+ } else if ( calleeName === 'moduleForModel' ) {
126+ subject = j . literal ( `model:${ calleeArguments [ 0 ] . value } ` ) ;
127+ } else if ( ! hasIntegration ) {
128+ subject = calleeArguments [ 0 ] ;
121129 }
122130 }
123131
124- return [ moduleName , options , setupIdentifier ] ;
132+ return [ moduleName , options , setupIdentifier , subject ] ;
125133 }
126134
127135 function updateModuleForToNestedModule ( ) {
@@ -147,7 +155,7 @@ module.exports = function(file, api, options) {
147155 }
148156
149157 function createModule ( p ) {
150- let [ moduleName , options , setupType ] = parseModule ( p ) ;
158+ let [ moduleName , options , setupType , subject ] = parseModule ( p ) ;
151159
152160 // Create the new `module(moduleName, function(hooks) {});` invocation
153161 let callback = j . functionExpression (
@@ -178,7 +186,7 @@ module.exports = function(file, api, options) {
178186 } ) ;
179187 }
180188
181- return [ moduleInvocation , callback . body . body , setupType ] ;
189+ return [ moduleInvocation , callback . body . body , setupType , subject ] ;
182190 }
183191
184192 function processRenderingTest ( testExpression ) {
@@ -219,23 +227,80 @@ module.exports = function(file, api, options) {
219227 } ) ;
220228 }
221229
230+ function processSubject ( testExpression , subject ) {
231+ let thisDotSubjectUsage = j ( testExpression ) . find ( j . CallExpression , {
232+ callee : {
233+ type : 'MemberExpression' ,
234+ object : {
235+ type : 'ThisExpression' ,
236+ } ,
237+ property : {
238+ name : 'subject' ,
239+ } ,
240+ } ,
241+ } ) ;
242+
243+ if ( thisDotSubjectUsage . size ( ) === 0 ) {
244+ return ;
245+ }
246+
247+ thisDotSubjectUsage . forEach ( p => {
248+ let options = p . node . arguments [ 0 ] ;
249+ let subjectType = subject . value . split ( ':' ) [ 0 ] ;
250+ let isSingletonSubject = ! [ 'model' , 'component' ] . includes ( subjectType ) ;
251+
252+ // if we don't have `options` and the type is a singleton type
253+ // use `this.owner.lookup(subject)`
254+ if ( ! options && isSingletonSubject ) {
255+ p . replace (
256+ j . callExpression (
257+ j . memberExpression (
258+ j . memberExpression ( j . thisExpression ( ) , j . identifier ( 'owner' ) ) ,
259+ j . identifier ( 'lookup' )
260+ ) ,
261+ [ subject ]
262+ )
263+ ) ;
264+ } else {
265+ p . replace (
266+ j . callExpression (
267+ j . memberExpression (
268+ j . callExpression (
269+ j . memberExpression (
270+ j . memberExpression ( j . thisExpression ( ) , j . identifier ( 'owner' ) ) ,
271+ j . identifier ( 'factoryFor' )
272+ ) ,
273+ [ subject ]
274+ ) ,
275+ j . identifier ( 'create' )
276+ ) ,
277+ [ options ] . filter ( Boolean )
278+ )
279+ ) ;
280+ }
281+ } ) ;
282+ }
283+
222284 let programPath = root . get ( 'program' ) ;
223285 let bodyPath = programPath . get ( 'body' ) ;
224286
225287 let bodyReplacement = [ ] ;
226- let currentModuleCallbackBody , currentTestType ;
288+ let currentModuleCallbackBody , currentTestType , currentSubject ;
227289 bodyPath . each ( expressionPath => {
228290 let expression = expressionPath . node ;
229291 if ( isModuleDefinition ( expressionPath ) ) {
230292 let result = createModule ( expressionPath ) ;
231293 bodyReplacement . push ( result [ 0 ] ) ;
232294 currentModuleCallbackBody = result [ 1 ] ;
233295 currentTestType = result [ 2 ] ;
296+ currentSubject = result [ 3 ] ;
234297 } else if ( currentModuleCallbackBody ) {
235298 currentModuleCallbackBody . push ( expression ) ;
236299
237300 if ( currentTestType === 'setupRenderingTest' ) {
238301 processRenderingTest ( expression ) ;
302+ } else if ( currentTestType === 'setupTest' ) {
303+ processSubject ( expression , currentSubject ) ;
239304 }
240305 } else {
241306 bodyReplacement . push ( expression ) ;
0 commit comments