From 9b75af63fd1660e2861e64bac583bc622e44238e Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 4 Jun 2016 17:38:16 -0400 Subject: [PATCH 1/8] Remove usage of `context` in `moduleForComponent`. Setting `context` or `controller` on an `Ember.Component` was absolutely not supposed to work (ever), but this library worked around that to serve its own needs when `Ember.View` was deprecated and removed. This PR makes `moduleForComponent` work properly against canary (soon to be 2.7.0), by avoiding this archaic concept and simply tracking the things `set` on the test context manually. --- .../test-module-for-component.js | 61 +++++++++------ lib/ember-test-helpers/test-module.js | 10 ++- lib/ember-test-helpers/wait.js | 21 +++++- tests/test-module-for-component-test.js | 74 +++++++++++++++++++ 4 files changed, 141 insertions(+), 25 deletions(-) diff --git a/lib/ember-test-helpers/test-module-for-component.js b/lib/ember-test-helpers/test-module-for-component.js index bc786a78c..ab19af375 100644 --- a/lib/ember-test-helpers/test-module-for-component.js +++ b/lib/ember-test-helpers/test-module-for-component.js @@ -3,6 +3,8 @@ import Ember from 'ember'; import { getResolver } from './test-resolver'; import hasEmberVersion from './has-ember-version'; +const BASE_COMPONENT_KEYS = (Object.keys || Ember.keys)(Ember.Component.create()); + export default TestModule.extend({ isComponentTestModule: true, @@ -126,17 +128,19 @@ export default TestModule.extend({ var module = this; var context = this.context; - this.actionHooks = {}; + var actions = this.actionHooks = {}; + var setContext = this._setBuffer = { actions }; context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); - context.actions = module.actionHooks; (this.registry || this.container).register('component:-test-holder', Ember.Component.extend()); context.render = function(template) { // in case `this.render` is called twice, make sure to teardown the first invocation - module.teardownComponent(); + if (module.component) { + context.clearRender(); + } if (!template) { throw new Error("in a component integration test you must pass a template to `render()`"); @@ -147,12 +151,9 @@ export default TestModule.extend({ if (typeof template === 'string') { template = Ember.Handlebars.compile(template); } - module.component = module.container.lookupFactory('component:-test-holder').create({ - layout: template - }); - module.component.set('context' ,context); - module.component.set('controller', context); + var Component = module.container.lookupFactory('component:-test-holder').extend(setContext); + setContext = module._setBuffer = module.component = Component.create({ layout: template }); Ember.run(function() { module.component.appendTo('#ember-testing'); @@ -165,7 +166,7 @@ export default TestModule.extend({ context.set = function(key, value) { var ret = Ember.run(function() { - return Ember.set(context, key, value); + return Ember.set(setContext, key, value); }); if (hasEmberVersion(2,0)) { @@ -175,7 +176,7 @@ export default TestModule.extend({ context.setProperties = function(hash) { var ret = Ember.run(function() { - return Ember.setProperties(context, hash); + return Ember.setProperties(setContext, hash); }); if (hasEmberVersion(2,0)) { @@ -184,31 +185,49 @@ export default TestModule.extend({ }; context.get = function(key) { - return Ember.get(context, key); + return Ember.get(setContext, key); }; context.getProperties = function() { var args = Array.prototype.slice.call(arguments); - return Ember.getProperties(context, args); + return Ember.getProperties(setContext, args); }; context.on = function(actionName, handler) { - module.actionHooks[actionName] = handler; - }; - - context.send = function(actionName) { - var hook = module.actionHooks[actionName]; - if (!hook) { - throw new Error("integration testing template received unexpected action " + actionName); - } - hook.apply(module, Array.prototype.slice.call(arguments, 1)); + setContext.actions = setContext.actions || {}; + setContext.actions[actionName] = handler; }; context.clearRender = function() { + setContext = this._setBuffer = { actions }; + + for (var key in module.component) { + if (BASE_COMPONENT_KEYS.indexOf(key) === -1) { + setContext[key] = Ember.get(module.component, key); + } + } module.teardownComponent(); }; }, + setupInject: function() { + var module = this; + + if (Ember.inject) { + var keys = (Object.keys || Ember.keys)(Ember.inject); + + keys.forEach(function(typeName) { + module.context.inject[typeName] = function(name, opts) { + var alias = (opts && opts.as) || name; + var instance = module.container.lookup(typeName + ':' + name); + + Ember.set(module.context, alias, instance); + Ember.set(module._setBuffer, alias, instance); + }; + }); + } + }, + setupContext: function() { this._super.call(this); diff --git a/lib/ember-test-helpers/test-module.js b/lib/ember-test-helpers/test-module.js index 193dddd10..c26c9dfab 100644 --- a/lib/ember-test-helpers/test-module.js +++ b/lib/ember-test-helpers/test-module.js @@ -128,12 +128,20 @@ export default AbstractTestModule.extend({ Ember.setOwner(context, this.container.owner); } + this.setupInject(); + }, + + setupInject: function() { + var module = this; + var context = this.context; + if (Ember.inject) { var keys = (Object.keys || Ember.keys)(Ember.inject); + keys.forEach(function(typeName) { context.inject[typeName] = function(name, opts) { var alias = (opts && opts.as) || name; - Ember.set(context, alias, context.container.lookup(typeName + ':' + name)); + Ember.set(context, alias, module.container.lookup(typeName + ':' + name)); }; }); } diff --git a/lib/ember-test-helpers/wait.js b/lib/ember-test-helpers/wait.js index 75d726ce2..81e86a593 100644 --- a/lib/ember-test-helpers/wait.js +++ b/lib/ember-test-helpers/wait.js @@ -27,6 +27,22 @@ export function _setupAJAXHooks() { jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests); } +var checkWaiters; + +if (Ember.Test.waiters) { + checkWaiters = () => { + if (Ember.Test.waiters.any(([context, callback]) => !callback.call(context) )) { + return true; + } + + return false; + }; +} else if (Ember.__loader.registry['ember-testing/test/waiters']) { + checkWaiters = Ember.__loader.require('ember-testing/test/waiters').checkWaiters; +} else { + checkWaiters = () => false; +} + export default function wait(_options) { var options = _options || {}; var waitForTimers = options.hasOwnProperty('waitForTimers') ? options.waitForTimers : true; @@ -43,12 +59,11 @@ export default function wait(_options) { return; } - if (waitForWaiters && Ember.Test.waiters && Ember.Test.waiters.any(([context, callback]) => { - return !callback.call(context); - })) { + if (waitForWaiters && checkWaiters()) { return; } + // Stop polling self.clearInterval(watcher); diff --git a/tests/test-module-for-component-test.js b/tests/test-module-for-component-test.js index ab6493a9b..dc7f3c098 100644 --- a/tests/test-module-for-component-test.js +++ b/tests/test-module-for-component-test.js @@ -253,6 +253,12 @@ if (hasEmberVersion(1,13)) { this.on('colorChange', function(arg) { equal(arg, 'foo'); }); this.render(Ember.Handlebars.compile("{{changing-color change=(action 'colorChange')}}")); }); + + test('handles a closure actions when set on the test context', function() { + expect(1); + this.set('colorChange', function(arg) { equal(arg, 'foo'); }); + this.render(Ember.Handlebars.compile("{{changing-color change=(action colorChange)}}")); + }); } var testModule; @@ -497,6 +503,70 @@ test('it can setProperties and getProperties', function() { equal(this.$('.bar').text(), '2'); }); +test('two way bound arguments are updated', function() { + var instance; + setResolverRegistry({ + 'component:my-component': Ember.Component.extend({ + init: function() { + this._super(); + instance = this; + }, + didInsertElement: function() { + Ember.run.schedule('afterRender', () => { + this.set('foo', 'updated!'); + }); + } + }) + }); + + this.set('foo', 'original'); + this.render('{{my-component foo=foo}}'); + + equal(instance.get('foo'), 'updated!'); + equal(this.get('foo'), 'updated!'); +}); + +test('two way bound arguments are available after clearRender is called', function() { + setResolverRegistry({ + 'component:my-component': Ember.Component.extend({ + didInsertElement: function() { + Ember.run.schedule('afterRender', () => { + this.set('foo', 'updated!'); + this.set('bar', 'updated bar!'); + }); + } + }) + }); + + this.set('foo', 'original'); + this.render('{{my-component foo=foo bar=bar}}'); + this.clearRender(); + + equal(this.get('foo'), 'updated!'); + equal(this.get('bar'), 'updated bar!'); +}); + +test('rendering after calling clearRender', function() { + setResolverRegistry({ + 'component:my-component': Ember.Component.extend({ + didInsertElement: function() { + Ember.run.schedule('afterRender', () => { + let currentFoo = this.get('foo') || ''; + this.set('foo', currentFoo + 'more foo '); + }); + } + }) + }); + + this.render('{{my-component foo=foo}}'); + equal(this.get('foo'), 'more foo ', 'precond - renders initially'); + this.clearRender(); + + this.render('{{my-component foo=foo}}'); + equal(this.get('foo'), 'more foo more foo ', 'uses the previously rendered value'); + this.clearRender(); +}); + var origDeprecate; moduleForComponent('Component Integration Tests: implicit views are not deprecated', { integration: true, @@ -549,12 +619,16 @@ test('can inject a service directly into test context', function() { unicorn: Ember.inject.service(), layout: Ember.Handlebars.compile('{{unicorn.sparkliness}}') })); + this.register('service:unicorn', Ember.Component.extend({ sparkliness: 'extreme' })); + this.inject.service('unicorn'); this.render("{{x-foo}}"); + equal(this.$('.x-foo').text().trim(), "extreme"); + this.set('unicorn.sparkliness', 'amazing'); equal(this.$('.x-foo').text().trim(), "amazing"); }); From 33c7a4e35d2b26a7dea87462e3b557c792a5c345 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 4 Jun 2016 17:44:51 -0400 Subject: [PATCH 2/8] Update ember-try configuration. --- config/ember-try.js | 126 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 20 deletions(-) diff --git a/config/ember-try.js b/config/ember-try.js index d96909181..43a38a128 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -64,40 +64,126 @@ module.exports = { } }, { - name: 'ember-release', + name: 'ember-2.3', dependencies: { - "ember": "components/ember#release" + "ember": "~2.3.0" }, devDependencies: { - "ember-data": "~2.2.0" + "ember-data": "~2.3.0" + } + }, + { + name: 'ember-2.4', + bower: { + dependencies: { + "ember": "~2.4.0" + }, + devDependencies: { + "ember-cli-shims": "ember-cli/ember-cli-shims#0.1.0" + }, + resolutions: { + "ember": "~2.4.0" + } }, - resolutions: { - "ember": "release" + npm: { + devDependencies: { + "ember-data": "~2.4" + } } }, { - name: 'ember-beta', - dependencies: { - "ember": "components/ember#beta" + name: 'ember-2.5', + bower: { + dependencies: { + "ember": "~2.5.0" + }, + devDependencies: { + "ember-cli-shims": "ember-cli/ember-cli-shims#0.1.0" + }, + resolutions: { + "ember": "~2.5.0" + } }, - devDependencies: { - "ember-data": "~2.2.0" + npm: { + devDependencies: { + "ember-data": "~2.5" + } + } + }, + { + name: 'ember-2.6', + bower: { + dependencies: { + "ember": "~2.6.0-beta.1" + }, + devDependencies: { + "ember-cli-shims": "ember-cli/ember-cli-shims#0.1.0" + }, + resolutions: { + "ember": "~2.6.0-beta.1" + } }, - resolutions: { - "ember": "beta" + npm: { + devDependencies: { + "ember-data": "^2.5.0" + } } }, { - name: 'ember-canary', - allowedToFail: true, - dependencies: { - "ember": "components/ember#canary" + name: 'ember-release', + bower: { + dependencies: { + "ember": "components/ember#release" + }, + devDependencies: { + "ember-cli-shims": "ember-cli/ember-cli-shims#0.1.0" + }, + resolutions: { + "ember": "release" + } }, - devDependencies: { - "ember-data": "~2.2.0" + npm: { + devDependencies: { + "ember-data": "^2.5.0" + } + } + }, + { + name: 'ember-beta', + bower: { + dependencies: { + "ember": "components/ember#beta" + }, + devDependencies: { + "ember-cli-shims": "ember-cli/ember-cli-shims#0.1.0" + }, + resolutions: { + "ember": "beta" + } }, - resolutions: { - "ember": "canary" + npm: { + devDependencies: { + "ember-data": "^2.5.0" + } + } + }, + { + name: 'ember-canary', + bower: { + dependencies: { + "ember": "components/ember#canary" + }, + devDependencies: { + "ember-cli-shims": "ember-cli/ember-cli-shims#0.1.0" + }, + resolutions: { + "ember": "canary" + } + }, + npm: { + devDependencies: { + "ember-data": "^2.5.0" + } } }, { From 965b1541302feec0200cbe54fff0d7ba1cfdab7c Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 4 Jun 2016 22:44:16 -0400 Subject: [PATCH 3/8] Fix issues against 2.6 beta branch. --- lib/ember-test-helpers/wait.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/ember-test-helpers/wait.js b/lib/ember-test-helpers/wait.js index 81e86a593..1421967c9 100644 --- a/lib/ember-test-helpers/wait.js +++ b/lib/ember-test-helpers/wait.js @@ -27,20 +27,21 @@ export function _setupAJAXHooks() { jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests); } -var checkWaiters; +var _internalCheckWaiters; +if (Ember.__loader.registry['ember-testing/test/waiters']) { + _internalCheckWaiters = Ember.__loader.require('ember-testing/test/waiters').checkWaiters; +} -if (Ember.Test.waiters) { - checkWaiters = () => { +function checkWaiters() { + if (_internalCheckWaiters) { + return _internalCheckWaiters(); + } else if (Ember.Test.waiters) { if (Ember.Test.waiters.any(([context, callback]) => !callback.call(context) )) { return true; } + } - return false; - }; -} else if (Ember.__loader.registry['ember-testing/test/waiters']) { - checkWaiters = Ember.__loader.require('ember-testing/test/waiters').checkWaiters; -} else { - checkWaiters = () => false; + return false; } export default function wait(_options) { From fb639ba063dcf6fb6f3e3ae4250e0ebfabfaa342 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 4 Jun 2016 23:29:49 -0400 Subject: [PATCH 4/8] Fix for Ember 1.x. --- .../test-module-for-component.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/ember-test-helpers/test-module-for-component.js b/lib/ember-test-helpers/test-module-for-component.js index ab19af375..11d3774dd 100644 --- a/lib/ember-test-helpers/test-module-for-component.js +++ b/lib/ember-test-helpers/test-module-for-component.js @@ -5,6 +5,13 @@ import hasEmberVersion from './has-ember-version'; const BASE_COMPONENT_KEYS = (Object.keys || Ember.keys)(Ember.Component.create()); +let ACTION_KEY; +if (hasEmberVersion(2,0)) { + ACTION_KEY = 'actions'; +} else { + ACTION_KEY = '_actions'; +} + export default TestModule.extend({ isComponentTestModule: true, @@ -129,7 +136,8 @@ export default TestModule.extend({ var context = this.context; var actions = this.actionHooks = {}; - var setContext = this._setBuffer = { actions }; + var setContext = this._setBuffer = { }; + setContext[ACTION_KEY] = {}; context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); @@ -194,12 +202,12 @@ export default TestModule.extend({ }; context.on = function(actionName, handler) { - setContext.actions = setContext.actions || {}; - setContext.actions[actionName] = handler; + setContext[ACTION_KEY][actionName] = handler; }; context.clearRender = function() { - setContext = this._setBuffer = { actions }; + setContext = this._setBuffer = { }; + setContext[ACTION_KEY] = actions; for (var key in module.component) { if (BASE_COMPONENT_KEYS.indexOf(key) === -1) { From 2278295733a363ec072d884e86ac63911cdba91a Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 4 Jun 2016 21:19:26 -0400 Subject: [PATCH 5/8] Use `{{partial` to swap the rendered template. --- .../test-module-for-component.js | 57 ++++++++----------- tests/test-module-for-integration-test.js | 4 +- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/lib/ember-test-helpers/test-module-for-component.js b/lib/ember-test-helpers/test-module-for-component.js index 11d3774dd..281abcba6 100644 --- a/lib/ember-test-helpers/test-module-for-component.js +++ b/lib/ember-test-helpers/test-module-for-component.js @@ -3,8 +3,6 @@ import Ember from 'ember'; import { getResolver } from './test-resolver'; import hasEmberVersion from './has-ember-version'; -const BASE_COMPONENT_KEYS = (Object.keys || Ember.keys)(Ember.Component.create()); - let ACTION_KEY; if (hasEmberVersion(2,0)) { ACTION_KEY = 'actions'; @@ -134,22 +132,26 @@ export default TestModule.extend({ setupComponentIntegrationTest: function() { var module = this; var context = this.context; - - var actions = this.actionHooks = {}; - var setContext = this._setBuffer = { }; - setContext[ACTION_KEY] = {}; + var templateRenderCount = 0; context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); - (this.registry || this.container).register('component:-test-holder', Ember.Component.extend()); + var registry = this.registry || this.container; + registry.register('component:-test-holder', Ember.Component.extend()); + registry.register('template:-empty', Ember.Handlebars.compile('')); - context.render = function(template) { - // in case `this.render` is called twice, make sure to teardown the first invocation - if (module.component) { - context.clearRender(); - } + var Component = module.container.lookupFactory('component:-test-holder').extend({ + actions: {} + }); + var component = module.component = Component.create({ + layout: Ember.Handlebars.compile('{{partial __renderedTemplate__}}'), + + __renderedTemplate__: 'empty' + }); + Ember.run(component, 'appendTo', '#ember-testing'); + context.render = function(template) { if (!template) { throw new Error("in a component integration test you must pass a template to `render()`"); } @@ -160,12 +162,9 @@ export default TestModule.extend({ template = Ember.Handlebars.compile(template); } - var Component = module.container.lookupFactory('component:-test-holder').extend(setContext); - setContext = module._setBuffer = module.component = Component.create({ layout: template }); - - Ember.run(function() { - module.component.appendTo('#ember-testing'); - }); + var templateName = '-test-helpers-' + templateRenderCount++; + registry.register('template:' + templateName, template); + Ember.run(component, 'set', '__renderedTemplate__', templateName); }; context.$ = function() { @@ -174,7 +173,7 @@ export default TestModule.extend({ context.set = function(key, value) { var ret = Ember.run(function() { - return Ember.set(setContext, key, value); + return Ember.set(component, key, value); }); if (hasEmberVersion(2,0)) { @@ -184,7 +183,7 @@ export default TestModule.extend({ context.setProperties = function(hash) { var ret = Ember.run(function() { - return Ember.setProperties(setContext, hash); + return Ember.setProperties(component, hash); }); if (hasEmberVersion(2,0)) { @@ -193,28 +192,20 @@ export default TestModule.extend({ }; context.get = function(key) { - return Ember.get(setContext, key); + return Ember.get(component, key); }; context.getProperties = function() { var args = Array.prototype.slice.call(arguments); - return Ember.getProperties(setContext, args); + return Ember.getProperties(component, args); }; context.on = function(actionName, handler) { - setContext[ACTION_KEY][actionName] = handler; + module.component[ACTION_KEY][actionName] = handler; }; context.clearRender = function() { - setContext = this._setBuffer = { }; - setContext[ACTION_KEY] = actions; - - for (var key in module.component) { - if (BASE_COMPONENT_KEYS.indexOf(key) === -1) { - setContext[key] = Ember.get(module.component, key); - } - } - module.teardownComponent(); + Ember.run(component, 'set', '__renderedTemplate__', 'empty'); }; }, @@ -230,7 +221,7 @@ export default TestModule.extend({ var instance = module.container.lookup(typeName + ':' + name); Ember.set(module.context, alias, instance); - Ember.set(module._setBuffer, alias, instance); + Ember.set(module.component, alias, instance); }; }); } diff --git a/tests/test-module-for-integration-test.js b/tests/test-module-for-integration-test.js index e06342af7..2a66816d7 100644 --- a/tests/test-module-for-integration-test.js +++ b/tests/test-module-for-integration-test.js @@ -262,8 +262,7 @@ moduleForIntegration('TestModuleForIntegration | willDestoryElement', { var actuallyInDOM = Ember.$.contains(document, this.$()[0]); ok((actuallyInDOM === true) && (stateIndicatesInDOM === true), 'component should still be in the DOM'); - } - + } }) }); } @@ -272,7 +271,6 @@ moduleForIntegration('TestModuleForIntegration | willDestoryElement', { test('still in DOM in willDestroyElement', function() { expect(1); this.render("{{my-component}}"); - }); moduleForIntegration('TestModuleForIntegration: force willDestroyElement via clearRender', { From c199ef0626693b8fbd19f8479bd2c9a35319cc48 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 5 Jun 2016 17:50:48 -0400 Subject: [PATCH 6/8] Refactor to use outlet techniques. --- .../test-module-for-component.js | 83 +++++++++---------- tests/test-module-for-component-test.js | 4 +- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/lib/ember-test-helpers/test-module-for-component.js b/lib/ember-test-helpers/test-module-for-component.js index 281abcba6..8faaa682a 100644 --- a/lib/ember-test-helpers/test-module-for-component.js +++ b/lib/ember-test-helpers/test-module-for-component.js @@ -132,24 +132,17 @@ export default TestModule.extend({ setupComponentIntegrationTest: function() { var module = this; var context = this.context; - var templateRenderCount = 0; + this.actionHooks = context[ACTION_KEY] = {}; context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); - var registry = this.registry || this.container; - registry.register('component:-test-holder', Ember.Component.extend()); - registry.register('template:-empty', Ember.Handlebars.compile('')); + var OutletView = module.container.lookupFactory('view:-outlet'); + var toplevelView = this._toplevelView = OutletView.create(); + toplevelView.setOutletState({ render: { }, outlets: { }}); - var Component = module.container.lookupFactory('component:-test-holder').extend({ - actions: {} - }); - var component = module.component = Component.create({ - layout: Ember.Handlebars.compile('{{partial __renderedTemplate__}}'), - - __renderedTemplate__: 'empty' - }); - Ember.run(component, 'appendTo', '#ember-testing'); + var element = document.getElementById('ember-testing'); + Ember.run(this._toplevelView, 'appendTo', '#ember-testing'); context.render = function(template) { if (!template) { @@ -162,18 +155,25 @@ export default TestModule.extend({ template = Ember.Handlebars.compile(template); } - var templateName = '-test-helpers-' + templateRenderCount++; - registry.register('template:' + templateName, template); - Ember.run(component, 'set', '__renderedTemplate__', templateName); + Ember.run(function() { + toplevelView.setOutletState({ + render: { + controller: module.context, + template + } + }); + }); }; - context.$ = function() { - return module.component.$.apply(module.component, arguments); + context.$ = function(selector) { + // emulates Ember internal behavor of `this.$` in a component + // https://github.com/emberjs/ember.js/blob/v2.5.1/packages/ember-views/lib/views/states/has_element.js#L18 + return selector ? Ember.$(selector, element) : Ember.$(element); }; context.set = function(key, value) { var ret = Ember.run(function() { - return Ember.set(component, key, value); + return Ember.set(context, key, value); }); if (hasEmberVersion(2,0)) { @@ -183,7 +183,7 @@ export default TestModule.extend({ context.setProperties = function(hash) { var ret = Ember.run(function() { - return Ember.setProperties(component, hash); + return Ember.setProperties(context, hash); }); if (hasEmberVersion(2,0)) { @@ -192,39 +192,36 @@ export default TestModule.extend({ }; context.get = function(key) { - return Ember.get(component, key); + return Ember.get(context, key); }; context.getProperties = function() { var args = Array.prototype.slice.call(arguments); - return Ember.getProperties(component, args); + return Ember.getProperties(context, args); }; context.on = function(actionName, handler) { - module.component[ACTION_KEY][actionName] = handler; + module.actionHooks[actionName] = handler; }; - context.clearRender = function() { - Ember.run(component, 'set', '__renderedTemplate__', 'empty'); + context.send = function(actionName) { + var hook = module.actionHooks[actionName]; + if (!hook) { + throw new Error("integration testing template received unexpected action " + actionName); + } + hook.apply(module.context, Array.prototype.slice.call(arguments, 1)); }; - }, - setupInject: function() { - var module = this; - - if (Ember.inject) { - var keys = (Object.keys || Ember.keys)(Ember.inject); - - keys.forEach(function(typeName) { - module.context.inject[typeName] = function(name, opts) { - var alias = (opts && opts.as) || name; - var instance = module.container.lookup(typeName + ':' + name); - - Ember.set(module.context, alias, instance); - Ember.set(module.component, alias, instance); - }; + context.clearRender = function() { + Ember.run(function() { + toplevelView.setOutletState({ + render: { + controller: module.context, + randomKey: 'empty' + } + }); }); - } + }; }, setupContext: function() { @@ -242,10 +239,10 @@ export default TestModule.extend({ }, teardownComponent: function() { - var component = this.component; + var component = this._toplevelView; if (component) { Ember.run(component, 'destroy'); - this.component = null; + this._toplevelView = null; } } }); diff --git a/tests/test-module-for-component-test.js b/tests/test-module-for-component-test.js index dc7f3c098..5d36d81a9 100644 --- a/tests/test-module-for-component-test.js +++ b/tests/test-module-for-component-test.js @@ -665,8 +665,8 @@ moduleForComponent('Component Integration Tests: willDestoryElement', { }); test('still in DOM in willDestroyElement', function() { - expect(1); - this.render("{{my-component}}"); + expect(1); + this.render("{{my-component}}"); }); test('is destroyed when rendered twice', function() { From 313186445ad3f7f59f36a82cc870b2ad66168c5a Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 5 Jun 2016 19:01:23 -0400 Subject: [PATCH 7/8] Fix errors with outlet state on 2.5.0. --- lib/ember-test-helpers/test-module-for-component.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ember-test-helpers/test-module-for-component.js b/lib/ember-test-helpers/test-module-for-component.js index 8faaa682a..8fea92c74 100644 --- a/lib/ember-test-helpers/test-module-for-component.js +++ b/lib/ember-test-helpers/test-module-for-component.js @@ -218,7 +218,8 @@ export default TestModule.extend({ render: { controller: module.context, randomKey: 'empty' - } + }, + outlets: {} }); }); }; From 696da08905563b8959ad59e1d6296f623ce30662 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 5 Jun 2016 19:47:43 -0400 Subject: [PATCH 8/8] Add support for Ember < 1.11. --- lib/ember-test-helpers/-legacy-overrides.js | 90 +++++++++ .../test-module-for-component.js | 179 +++++++++--------- 2 files changed, 183 insertions(+), 86 deletions(-) create mode 100644 lib/ember-test-helpers/-legacy-overrides.js diff --git a/lib/ember-test-helpers/-legacy-overrides.js b/lib/ember-test-helpers/-legacy-overrides.js new file mode 100644 index 000000000..55edb019e --- /dev/null +++ b/lib/ember-test-helpers/-legacy-overrides.js @@ -0,0 +1,90 @@ +import Ember from 'ember'; + +import hasEmberVersion from './has-ember-version'; + +export function preoutletRefactorSetupIntegrationForComponent() { + var module = this; + var context = this.context; + + this.actionHooks = {}; + + context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); + context.dispatcher.setup({}, '#ember-testing'); + context.actions = module.actionHooks; + + (this.registry || this.container).register('component:-test-holder', Ember.Component.extend()); + + context.render = function(template) { + // in case `this.render` is called twice, make sure to teardown the first invocation + module.teardownComponent(); + + 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); + } + module.component = module.container.lookupFactory('component:-test-holder').create({ + layout: template + }); + + module.component.set('context' ,context); + module.component.set('controller', context); + + Ember.run(function() { + module.component.appendTo('#ember-testing'); + }); + }; + + context.$ = function() { + return module.component.$.apply(module.component, arguments); + }; + + context.set = function(key, value) { + var ret = Ember.run(function() { + return Ember.set(context, key, value); + }); + + if (hasEmberVersion(2,0)) { + return ret; + } + }; + + context.setProperties = function(hash) { + var ret = Ember.run(function() { + return Ember.setProperties(context, hash); + }); + + if (hasEmberVersion(2,0)) { + return ret; + } + }; + + context.get = function(key) { + return Ember.get(context, key); + }; + + context.getProperties = function() { + var args = Array.prototype.slice.call(arguments); + return Ember.getProperties(context, args); + }; + + context.on = function(actionName, handler) { + module.actionHooks[actionName] = handler; + }; + + context.send = function(actionName) { + var hook = module.actionHooks[actionName]; + if (!hook) { + throw new Error("integration testing template received unexpected action " + actionName); + } + hook.apply(module, Array.prototype.slice.call(arguments, 1)); + }; + + context.clearRender = function() { + module.teardownComponent(); + }; +} diff --git a/lib/ember-test-helpers/test-module-for-component.js b/lib/ember-test-helpers/test-module-for-component.js index 8fea92c74..f6e2d9589 100644 --- a/lib/ember-test-helpers/test-module-for-component.js +++ b/lib/ember-test-helpers/test-module-for-component.js @@ -2,6 +2,7 @@ import TestModule from './test-module'; import Ember from 'ember'; import { getResolver } from './test-resolver'; import hasEmberVersion from './has-ember-version'; +import { preoutletRefactorSetupIntegrationForComponent } from './-legacy-overrides'; let ACTION_KEY; if (hasEmberVersion(2,0)) { @@ -129,101 +130,107 @@ export default TestModule.extend({ }; }, - setupComponentIntegrationTest: function() { - var module = this; - var context = this.context; + setupComponentIntegrationTest: (function() { + if (!hasEmberVersion(1,11)) { + return preoutletRefactorSetupIntegrationForComponent; + } else { + return function() { + var module = this; + var context = this.context; - this.actionHooks = context[ACTION_KEY] = {}; - context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); - context.dispatcher.setup({}, '#ember-testing'); + this.actionHooks = context[ACTION_KEY] = {}; + context.dispatcher = this.container.lookup('event_dispatcher:main') || Ember.EventDispatcher.create(); + context.dispatcher.setup({}, '#ember-testing'); - var OutletView = module.container.lookupFactory('view:-outlet'); - var toplevelView = this._toplevelView = OutletView.create(); - toplevelView.setOutletState({ render: { }, outlets: { }}); - - var element = document.getElementById('ember-testing'); - Ember.run(this._toplevelView, 'appendTo', '#ember-testing'); - - 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); - } - - Ember.run(function() { - toplevelView.setOutletState({ - render: { - controller: module.context, - template - } - }); - }); - }; + var OutletView = module.container.lookupFactory('view:-outlet'); + var toplevelView = module.component = OutletView.create(); + toplevelView.setOutletState({ render: { }, outlets: { }}); - context.$ = function(selector) { - // emulates Ember internal behavor of `this.$` in a component - // https://github.com/emberjs/ember.js/blob/v2.5.1/packages/ember-views/lib/views/states/has_element.js#L18 - return selector ? Ember.$(selector, element) : Ember.$(element); - }; - - context.set = function(key, value) { - var ret = Ember.run(function() { - return Ember.set(context, key, value); - }); + var element = document.getElementById('ember-testing'); + Ember.run(module.component, 'appendTo', '#ember-testing'); - if (hasEmberVersion(2,0)) { - return ret; - } - }; + 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); + } - context.setProperties = function(hash) { - var ret = Ember.run(function() { - return Ember.setProperties(context, hash); - }); + Ember.run(function() { + toplevelView.setOutletState({ + render: { + controller: module.context, + template + } + }); + }); + }; + + context.$ = function(selector) { + // emulates Ember internal behavor of `this.$` in a component + // https://github.com/emberjs/ember.js/blob/v2.5.1/packages/ember-views/lib/views/states/has_element.js#L18 + return selector ? Ember.$(selector, element) : Ember.$(element); + }; + + context.set = function(key, value) { + var ret = Ember.run(function() { + return Ember.set(context, key, value); + }); + + if (hasEmberVersion(2,0)) { + return ret; + } + }; - if (hasEmberVersion(2,0)) { - return ret; - } - }; + context.setProperties = function(hash) { + var ret = Ember.run(function() { + return Ember.setProperties(context, hash); + }); - context.get = function(key) { - return Ember.get(context, key); - }; + if (hasEmberVersion(2,0)) { + return ret; + } + }; - context.getProperties = function() { - var args = Array.prototype.slice.call(arguments); - return Ember.getProperties(context, args); - }; + context.get = function(key) { + return Ember.get(context, key); + }; - context.on = function(actionName, handler) { - module.actionHooks[actionName] = handler; - }; + context.getProperties = function() { + var args = Array.prototype.slice.call(arguments); + return Ember.getProperties(context, args); + }; - context.send = function(actionName) { - var hook = module.actionHooks[actionName]; - if (!hook) { - throw new Error("integration testing template received unexpected action " + actionName); - } - hook.apply(module.context, Array.prototype.slice.call(arguments, 1)); - }; + context.on = function(actionName, handler) { + module.actionHooks[actionName] = handler; + }; - context.clearRender = function() { - Ember.run(function() { - toplevelView.setOutletState({ - render: { - controller: module.context, - randomKey: 'empty' - }, - outlets: {} - }); - }); - }; - }, + context.send = function(actionName) { + var hook = module.actionHooks[actionName]; + if (!hook) { + throw new Error("integration testing template received unexpected action " + actionName); + } + hook.apply(module.context, Array.prototype.slice.call(arguments, 1)); + }; + + context.clearRender = function() { + Ember.run(function() { + toplevelView.setOutletState({ + render: { + controller: module.context, + randomKey: 'empty' + }, + outlets: {} + }); + }); + }; + }; + } + })(), setupContext: function() { this._super.call(this); @@ -240,10 +247,10 @@ export default TestModule.extend({ }, teardownComponent: function() { - var component = this._toplevelView; + var component = this.component; if (component) { Ember.run(component, 'destroy'); - this._toplevelView = null; + this.component = null; } } });