Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure that setup callback is invoked with the correct context. #12

Merged
merged 1 commit into from
Jan 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions lib/ember-test-helpers/test-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default Klass.extend({

initSetupSteps: function() {
this.setupSteps = [];
this.contextualizedSetupSteps = [];

if (this.callbacks.beforeSetup) {
this.setupSteps.push( this.callbacks.beforeSetup );
Expand All @@ -47,42 +48,50 @@ export default Klass.extend({
this.setupSteps.push(this.setupTestElements);

if (this.callbacks.setup) {
this.setupSteps.push( this.callbacks.setup );
this.contextualizedSetupSteps.push( this.callbacks.setup );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to delete setup from this.callbacks before contextualizeCallbacks is called. Otherwise, setup will get added to cache['setup'].

Perhaps we need another array, something like postSetupSteps, that will be invoked with the proper this.context. And then we should allow invokeSteps to take a context argument, which will be either this or this.context.

I can do this as a separate PR if you like or we can chat on IRC.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe to be clear we should introduce both contextualizedSetupSteps and contextualizedTeardownSteps, both of which will be invoked with the module's context.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I'll update in a few....

delete this.callbacks.setup;
}
},

initTeardownSteps: function() {
this.teardownSteps = [];
this.contextualizedTeardownSteps = [];

if (this.callbacks.beforeTeardown) {
this.teardownSteps.push( this.callbacks.beforeTeardown );
delete this.callbacks.beforeTeardown;
if (this.callbacks.teardown) {
this.contextualizedTeardownSteps.push( this.callbacks.teardown );
delete this.callbacks.teardown;
}

this.teardownSteps.push(this.teardownContainer);
this.teardownSteps.push(this.teardownContext);
this.teardownSteps.push(this.teardownTestElements);

if (this.callbacks.teardown) {
this.teardownSteps.push( this.callbacks.teardown );
delete this.callbacks.teardown;
if (this.callbacks.afterTeardown) {
this.teardownSteps.push( this.callbacks.afterTeardown );
delete this.callbacks.beforeTeardown;
}
},

setup: function() {
this.invokeSteps(this.setupSteps);
this.contextualizeCallbacks();
this.invokeSteps(this.contextualizedSetupSteps, this.context);
},

teardown: function() {
this.invokeSteps(this.contextualizedTeardownSteps, this.context);
this.invokeSteps(this.teardownSteps);
this.cache = null;
},

invokeSteps: function(steps) {
invokeSteps: function(steps, _context) {
var context = _context;
if (!context) {
context = this;
}

for (var i = 0, l = steps.length; i < l; i++) {
steps[i].call(this);
steps[i].call(context);
}
},

Expand Down
21 changes: 21 additions & 0 deletions tests/test-module-for-component-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,24 @@ test("$", function(){
equal($.trim(this.$('.color-name').text()), 'green');
equal($.trim(this.$().text()), 'Pretty Color: green');
});

moduleForComponent('pretty-color', 'component:pretty-color -- this.render in setup', {
beforeSetup: function() {
setupRegistry();
},

setup: function() {
this.subject({
name: 'red'
});

this.render();
}
});

test("className", function(){
// calling `this.$` or `this.subject.$` would
// force it to `render` initially, so we access the `ember-testing`
// div contents directly
equal($.trim($('#ember-testing').text()), 'Pretty Color: red');
});
65 changes: 45 additions & 20 deletions tests/test-module-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,69 @@ function setupRegistry() {
var a = 0;
var b = 0;
var beforeSetupOk = false;
var beforeTeardownOk = false;
var afterTeardownOk = false;

var callbackOrder, setupContext, teardownContext, beforeSetupContext, afterTeardownContext;

moduleFor('component:x-foo', 'TestModule callbacks', {
beforeSetup: function() {
setupRegistry();
beforeSetupContext = this;
callbackOrder = [ 'beforeSetup' ];

beforeSetupOk = (a === 0);
b += 1;
setupRegistry();
},

setup: function() {
a += 1;
},
setupContext = this;
callbackOrder.push('setup');

beforeTeardown: function() {
beforeTeardownOk = (a === 1);
b -= 1;
ok(setupContext !== beforeSetupContext);
},

teardown: function() {
a -= 1;
teardownContext = this;
callbackOrder.push('teardown');

deepEqual(callbackOrder, [ 'beforeSetup', 'setup', 'teardown']);
equal(setupContext, teardownContext);
},

afterTeardown: function() {
afterTeardownContext = this;
callbackOrder.push('afterTeardown');

deepEqual(callbackOrder, [ 'beforeSetup', 'setup', 'teardown', 'afterTeardown']);
equal(afterTeardownContext, beforeSetupContext);
ok(afterTeardownContext !== teardownContext);
}
});

test("beforeSetup callback is called prior to any test setup", function() {
ok(beforeSetupOk);
equal(b, 1);
test("setup callbacks called in the correct order", function() {
deepEqual(callbackOrder, [ 'beforeSetup', 'setup' ]);
});

test("setup callback is called prior to test", function() {
equal(a, 1);
moduleFor('component:x-foo', 'component:x-foo -- setup context', {
beforeSetup: function() {
setupRegistry();
},

setup: function() {
this.subject({
name: 'Max'
});

this.container.register('service:blah', Ember.Object.extend({
purpose: 'blabering'
}));
}
});

test("teardown callback is called after test", function() {
equal(a, 1);
test("subject can be initialized in setup", function() {
equal(this.subject().name, 'Max');
});

test("beforeTeardown callback is called prior to any test teardown", function() {
ok(beforeTeardownOk);
equal(b, 1);
test("can lookup factory registered in setup", function() {
var service = this.container.lookup('service:blah');

equal(service.get('purpose'), 'blabering');
});