Skip to content

Commit 316ea5e

Browse files
authored
Merge pull request #10 from cibernox/transform-subject
Implement this.subject transformation
2 parents 71fb433 + 1a7eb9b commit 316ea5e

3 files changed

Lines changed: 188 additions & 8 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { moduleFor, test } from 'ember-qunit';
2+
3+
moduleFor('service:flash', 'Unit | Service | Flash', {
4+
unit: true
5+
});
6+
7+
test('should allow messages to be queued', function (assert) {
8+
let subject = this.subject();
9+
});
10+
11+
moduleFor('service:non-singleton-service', 'Unit | Service | NonSingletonService', {
12+
unit: true
13+
});
14+
15+
test('does something', function (assert) {
16+
let subject = this.subject({ name: 'James' });
17+
});
18+
19+
moduleFor('model:foo', 'Unit | Model | Foo', {
20+
unit: true
21+
});
22+
23+
test('has some thing', function (assert) {
24+
let subject = this.subject();
25+
});
26+
27+
test('has another thing', function (assert) {
28+
let subject = this.subject({ size: 'big' });
29+
});
30+
31+
moduleForModel('foo', 'Integration | Model | Foo', {
32+
integration: true
33+
});
34+
35+
test('has some thing', function (assert) {
36+
let subject = this.subject();
37+
});
38+
39+
moduleForModel('foo', 'Unit | Model | Foo', {
40+
needs: ['serializer:foo']
41+
});
42+
43+
test('has some thing', function (assert) {
44+
let subject = this.subject();
45+
});
46+
47+
moduleForComponent('foo-bar', 'Unit | Component | FooBar', {
48+
unit: true,
49+
});
50+
51+
test('has some thing', function (assert) {
52+
let subject = this.subject();
53+
});
54+
55+
test('has another thing', function (assert) {
56+
let subject = this.subject({ size: 'big' });
57+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { module, test } from 'qunit';
2+
import { setupTest } from 'ember-qunit';
3+
4+
module('Unit | Service | Flash', function(hooks) {
5+
setupTest(hooks);
6+
7+
test('should allow messages to be queued', function (assert) {
8+
let subject = this.owner.lookup('service:flash');
9+
});
10+
});
11+
12+
module('Unit | Service | NonSingletonService', function(hooks) {
13+
setupTest(hooks);
14+
15+
test('does something', function (assert) {
16+
let subject = this.owner.factoryFor('service:non-singleton-service').create({ name: 'James' });
17+
});
18+
});
19+
20+
module('Unit | Model | Foo', function(hooks) {
21+
setupTest(hooks);
22+
23+
test('has some thing', function (assert) {
24+
let subject = this.owner.factoryFor('model:foo').create();
25+
});
26+
27+
test('has another thing', function (assert) {
28+
let subject = this.owner.factoryFor('model:foo').create({ size: 'big' });
29+
});
30+
});
31+
32+
module('Integration | Model | Foo', function(hooks) {
33+
setupTest(hooks);
34+
35+
test('has some thing', function (assert) {
36+
let subject = this.owner.factoryFor('model:foo').create();
37+
});
38+
});
39+
40+
module('Unit | Model | Foo', function(hooks) {
41+
setupTest(hooks);
42+
43+
test('has some thing', function (assert) {
44+
let subject = this.owner.factoryFor('model:foo').create();
45+
});
46+
});
47+
48+
module('Unit | Component | FooBar', function(hooks) {
49+
setupTest(hooks);
50+
51+
test('has some thing', function (assert) {
52+
let subject = this.owner.factoryFor('component:foo-bar').create();
53+
});
54+
55+
test('has another thing', function (assert) {
56+
let subject = this.owner.factoryFor('component:foo-bar').create({ size: 'big' });
57+
});
58+
});

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)