Skip to content

Commit

Permalink
support integration-mode component tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ef4 committed Apr 8, 2015
1 parent 532da8c commit 6e19bd1
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 101 deletions.
2 changes: 0 additions & 2 deletions lib/ember-test-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import isolatedContainer from 'ember-test-helpers/isolated-container';
import TestModule from 'ember-test-helpers/test-module';
import TestModuleForComponent from 'ember-test-helpers/test-module-for-component';
import TestModuleForModel from 'ember-test-helpers/test-module-for-model';
import TestModuleForIntegration from 'ember-test-helpers/test-module-for-integration';
import { getContext, setContext } from 'ember-test-helpers/test-context';
import { setResolver } from 'ember-test-helpers/test-resolver';

Expand All @@ -14,7 +13,6 @@ export {
TestModule,
TestModuleForComponent,
TestModuleForModel,
TestModuleForIntegration,
getContext,
setContext,
setResolver
Expand Down
8 changes: 6 additions & 2 deletions lib/ember-test-helpers/isolated-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ function exposeRegistryMethodsWithoutDeprecations(container) {
export default function isolatedContainer(fullNames) {
var resolver = getResolver();
var container;
var registry;

var normalize = function(fullName) {
return resolver.normalize(fullName);
};

if (Ember.Registry) {
var registry = new Ember.Registry();
registry = new Ember.Registry();
registry.normalizeFullName = normalize;

container = registry.container();
Expand Down Expand Up @@ -83,5 +84,8 @@ export default function isolatedContainer(fullNames) {
var normalizedFullName = resolver.normalize(fullName);
container.register(fullName, resolver.resolve(normalizedFullName));
}
return container;
return {
container: container,
registry: registry
};
}
112 changes: 109 additions & 3 deletions lib/ember-test-helpers/test-module-for-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,45 @@ import { getResolver } from './test-resolver';

export default TestModule.extend({
init: function(componentName, description, callbacks) {
// Allow `description` to be omitted
if (!callbacks && typeof description === 'object') {
callbacks = description || {};
description = null;
}

this.componentName = componentName;

this._super.call(this, 'component:' + componentName, description, callbacks);
if (callbacks.needs || callbacks.unit || callbacks.integration === false) {
this.isUnitTest = true;
} else if (callbacks.integration) {
this.isUnitTest = false;
} else {
Ember.deprecate("the component:" + componentName + " test module is implicitly running in unit test mode, which will change to integration test mode by default in an upcoming version of ember-test-helpers. Add `unit: true` or a `needs:[]` list to explicitly opt in to unit test mode.");
this.isUnitTest = true;
}

if (!this.isUnitTest) {
callbacks.integration = true;
}

this.setupSteps.push(this.setupComponent);
if (description) {
this._super.call(this, 'component:' + componentName, description, callbacks);
} else {
this._super.call(this, 'component:' + componentName, callbacks);
}

if (this.isUnitTest) {
this.setupSteps.push(this.setupComponentUnitTest);
} else {
this.callbacks.subject = function() {
throw new Error("component integration tests do not support `subject()`.");
};
this.setupSteps.push(this.setupComponentIntegrationTest);
this.teardownSteps.push(this.teardownComponent);
}
},

setupComponent: function() {
setupComponentUnitTest: function() {
var _this = this;
var resolver = getResolver();
var container = this.container;
Expand Down Expand Up @@ -55,5 +86,80 @@ export default TestModule.extend({

return subject.$.apply(subject, arguments);
};
},

setupComponentIntegrationTest: function() {
var self = this;
var context = this.context;
context.dispatcher = Ember.EventDispatcher.create();
context.dispatcher.setup({}, '#ember-testing');
this.actionHooks = {};

context.render = function(template) {
if (!template) {
throw new Error("in a component integration test you must pass a template to `render()`");
}
if (Ember.isArray(template)) {
template = template.join('');
}
if (typeof template === 'string') {
template = Ember.Handlebars.compile(template);
}
self.component = Ember.View.create({
context: context,
controller: self,
template: template,
container: self.container
});
Ember.run(function() {
self.component.appendTo('#ember-testing');
});
};

context.$ = function() {
return self.component.$.apply(self.component, arguments);
};

context.set = function(key, value) {
Ember.run(function() {
Ember.set(context, key, value);
});
};

context.get = function(key) {
return Ember.get(context, key);
};

context.on = function(actionName, handler) {
self.actionHooks[actionName] = handler;
};

},

setupContext: function() {
this._super.call(this);
if (!this.isUnitTest) {
this.context.factory = function() {};
}
},


send: function(actionName) {
var hook = this.actionHooks[actionName];
if (!hook) {
throw new Error("integration testing template received unexpected action " + actionName);
}
hook.apply(this, Array.prototype.slice.call(arguments, 1));
},

teardownComponent: function() {
var component = this.component;
if (component) {
Ember.run(function() {
component.destroy();
});
}
}


});
89 changes: 0 additions & 89 deletions lib/ember-test-helpers/test-module-for-integration.js

This file was deleted.

5 changes: 4 additions & 1 deletion lib/ember-test-helpers/test-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export default Klass.extend({

setContext({
container: this.container,
registry: this.registry,
factory: factory,
dispatcher: null
});
Expand Down Expand Up @@ -213,7 +214,9 @@ export default Klass.extend({


_setupIsolatedContainer: function() {
this.container = isolatedContainer(this.needs);
var isolated = isolatedContainer(this.needs);
this.container = isolated.container;
this.registry = isolated.registry;
},

_setupIntegratedContainer: function() {
Expand Down
3 changes: 3 additions & 0 deletions tests/test-module-for-component-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ test('clears out views from test to test', function() {
///////////////////////////////////////////////////////////////////////////////

moduleForComponent('pretty-color', {
unit: true,
beforeSetup: function() {
setupRegistry();
}
Expand Down Expand Up @@ -215,6 +216,7 @@ test("$", function(){
});

moduleForComponent('pretty-color', 'component:pretty-color -- this.render in setup', {
unit: true,
beforeSetup: function() {
setupRegistry();
},
Expand All @@ -236,6 +238,7 @@ test("className", function(){
});

moduleForComponent('boring-color', 'component:boring-color -- still in DOM in willDestroyElement', {
unit: true,
beforeSetup: function() {
setupRegistry();
},
Expand Down
25 changes: 21 additions & 4 deletions tests/test-module-for-integration-test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import Ember from 'ember';
import { TestModuleForIntegration } from 'ember-test-helpers';
import { TestModuleForComponent } from 'ember-test-helpers';
import test from 'tests/test-support/qunit-test';
import qunitModuleFor from 'tests/test-support/qunit-module-for';
import { setResolverRegistry } from 'tests/test-support/resolver';

function moduleForIntegration(name, description, callbacks) {
var module = new TestModuleForIntegration(name, description, callbacks);
function moduleForComponent(name, description, callbacks) {
var module = new TestModuleForComponent(name, description, callbacks);
qunitModuleFor(module);
}

moduleForIntegration('Better Integration Tests', {

moduleForComponent('Component Integration Tests', {
integration: true,
beforeSetup: function() {
setResolverRegistry({
'template:components/my-component': Ember.Handlebars.compile(
Expand All @@ -24,6 +26,21 @@ test('it can render a template', function() {
equal(this.$('span').text(), 'Hello');
});

test('it complains if you try to use bare render', function() {
var self = this;
throws(function() {
self.render();
}, /in a component integration test you must pass a template to `render\(\)`/);
});

test('it complains if you try to use subject()', function() {
var self = this;
throws(function() {
self.subject();
}, /component integration tests do not support `subject\(\)`\./);
});


test('it can access the full container', function() {
this.set('myColor', 'red');
this.render('{{my-component name=myColor}}');
Expand Down

0 comments on commit 6e19bd1

Please sign in to comment.