Skip to content

Commit 143c013

Browse files
author
Robert Jackson
committed
Implement this.subject handling.
1 parent 7ce802f commit 143c013

1 file changed

Lines changed: 73 additions & 8 deletions

File tree

ember-qunit-codemod.js

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)