diff --git a/packages/ember-views/lib/components/component.js b/packages/ember-views/lib/components/component.js index ebaf47007a8..0110b1f2370 100644 --- a/packages/ember-views/lib/components/component.js +++ b/packages/ember-views/lib/components/component.js @@ -158,6 +158,23 @@ var Component = View.extend(TargetActionSupport, { this.layout = this.defaultLayout; } + + // If in a tagless component, assert that no event handlers are defined + assert( + `You can not define a function that handles DOM events in the \`${this}\` tagless component since it doesn't have any DOM element.`, + this.tagName !== '' || !(() => { + let eventDispatcher = this.container.lookup('event_dispatcher:main'); + let events = (eventDispatcher && eventDispatcher._finalEvents) || {}; + + for (let key in events) { + let methodName = events[key]; + + if (typeof this[methodName] === 'function') { + return true; // indicate that the assertion should be triggered + } + } + } + )()); }, template: null, diff --git a/packages/ember-views/lib/system/event_dispatcher.js b/packages/ember-views/lib/system/event_dispatcher.js index 7f807df11a7..bb7352d078b 100644 --- a/packages/ember-views/lib/system/event_dispatcher.js +++ b/packages/ember-views/lib/system/event_dispatcher.js @@ -149,7 +149,7 @@ export default EmberObject.extend({ */ setup(addedEvents, rootElement) { var event; - var events = assign({}, get(this, 'events'), addedEvents); + var events = this._finalEvents = assign({}, get(this, 'events'), addedEvents); if (!isNone(rootElement)) { set(this, 'rootElement', rootElement); diff --git a/packages/ember-views/tests/views/component_test.js b/packages/ember-views/tests/views/component_test.js index 35d1c61ba13..53e96518197 100644 --- a/packages/ember-views/tests/views/component_test.js +++ b/packages/ember-views/tests/views/component_test.js @@ -5,6 +5,9 @@ import Service from 'ember-runtime/system/service'; import { Registry } from 'ember-runtime/system/container'; import inject from 'ember-runtime/inject'; import { get } from 'ember-metal/property_get'; +import Application from 'ember-application/system/application'; +import ApplicationInstance from 'ember-application/system/application-instance'; +import isEnabled from 'ember-metal/features'; import EmberView from 'ember-views/views/view'; import Component from 'ember-views/components/component'; @@ -279,3 +282,97 @@ QUnit.test('component with target', function() { appComponent.send('foo', 'baz'); }); + +let app, appInstance; + +QUnit.module('Ember.Component - tagless components assertions', { + teardown() { + if (appInstance) { + run(appInstance, 'destroy'); + } + + if (app) { + run(app, 'destroy'); + } + } +}); + + +QUnit.test('throws an error if an event function is defined in a tagless component', function() { + app = run(Application, 'create', { rootElement: '#qunit-fixture', autoboot: false }); + if (!isEnabled('ember-application-visit')) { + run(app.__deprecatedInstance__, 'destroy'); + } + + run(function() { + appInstance = ApplicationInstance.create({ application: app }); + appInstance.setupEventDispatcher(); + }); + + let TestComponent = Component.extend({ + tagName: '', + container: appInstance, + click() { } + }); + + expectAssertion(function() { + TestComponent.create(); + }, /You can not define a function that handles DOM events in the .* tagless component since it doesn't have any DOM element./); +}); + +QUnit.test('throws an error if an Application custom event handler is defined in a tagless component', function() { + app = run(Application, 'create', { + rootElement: '#qunit-fixture', + autoboot: false, + customEvents: { + awesome: 'sauce' + } + }); + + if (!isEnabled('ember-application-visit')) { + run(app.__deprecatedInstance__, 'destroy'); + } + + run(function() { + appInstance = ApplicationInstance.create({ application: app }); + appInstance.setupEventDispatcher(); + }); + + let TestComponent = Component.extend({ + tagName: '', + container: appInstance, + sauce() { } + }); + + expectAssertion(function() { + TestComponent.create(); + }, /You can not define a function that handles DOM events in the .* tagless component since it doesn't have any DOM element./); +}); + +QUnit.test('throws an error if an ApplicationInstance custom event handler is defined in a tagless component', function() { + app = run(Application, 'create', { rootElement: '#qunit-fixture', autoboot: false }); + + if (!isEnabled('ember-application-visit')) { + run(app.__deprecatedInstance__, 'destroy'); + } + + run(function() { + appInstance = ApplicationInstance.create({ + application: app, + customEvents: { + love: 'hurts' + } + }); + appInstance.setupEventDispatcher(); + }); + + let TestComponent = Component.extend({ + tagName: '', + container: appInstance, + hurts() { } + }); + + expectAssertion(function() { + TestComponent.create(); + }, /You can not define a function that handles DOM events in the .* tagless component since it doesn't have any DOM element./); +});