diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts b/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts index 9aacfbc375a..c8718480236 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts @@ -141,6 +141,12 @@ class InteractiveCustomModifierManager install(state: CustomModifierState) { let { element, args, delegate, modifier, tag } = state; + + assert( + 'Custom modifier managers must define their capabilities using the capabilities() helper function', + typeof delegate.capabilities === 'object' && delegate.capabilities !== null + ); + let { capabilities } = delegate; if (capabilities.disableAutoTracking === true) { diff --git a/packages/@ember/-internals/glimmer/tests/integration/custom-modifier-manager-test.js b/packages/@ember/-internals/glimmer/tests/integration/custom-modifier-manager-test.js index 9cb1c426a2e..caedda7718b 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/custom-modifier-manager-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/custom-modifier-manager-test.js @@ -36,6 +36,24 @@ class CustomModifierManager { moduleFor( 'Basic Custom Modifier Manager', class extends ModifierManagerTest { + '@test throws a useful error when missing capabilities'() { + this.registerModifier( + 'foo-bar', + setModifierManager(() => { + return { + createModifier() {}, + installModifier() {}, + updateModifier() {}, + destroyModifier() {}, + }; + }, {}) + ); + + expectAssertion(() => { + this.render('

hello world

'); + }, /Custom modifier managers must define their capabilities/); + } + '@test can register a custom element modifier and render it'(assert) { let ModifierClass = setModifierManager( owner => {