diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js index 628beffa8f8..cb79e6f410d 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js @@ -1,4 +1,4 @@ -import { moduleFor, RenderingTestCase, runTask } from 'internal-test-helpers'; +import { expectDeprecation, moduleFor, RenderingTestCase, runTask } from 'internal-test-helpers'; import { action, set } from '@ember/object'; import Mixin from '@ember/object/mixin'; @@ -11,7 +11,7 @@ moduleFor( 'Components test: send', class extends RenderingTestCase { ['@test sending to undefined actions triggers an error'](assert) { - assert.expect(2); + assert.expect(4); let component; @@ -31,11 +31,15 @@ moduleFor( this.render('{{foo-bar}}'); - runTask(() => component.send('foo', 'bar')); + expectDeprecation(() => { + runTask(() => component.send('foo', 'bar')); + }, /send\(\) is deprecated/); - expectAssertion(() => { - return component.send('baz', 'bar'); - }, /had no action handler for: baz/); + expectDeprecation(() => { + expectAssertion(() => { + return component.send('baz', 'bar'); + }, /had no action handler for: baz/); + }, /send\(\) is deprecated/); } ['@test `send` will call send from a target if it is defined']() { @@ -59,11 +63,13 @@ moduleFor( this.render('{{foo-bar}}'); - runTask(() => component.send('foo', 'baz')); + expectDeprecation(() => { + runTask(() => component.send('foo', 'baz')); + }, /send\(\) is deprecated/); } ['@test a handled action can be bubbled to the target for continued processing']() { - this.assert.expect(2); + this.assert.expect(3); let component; @@ -91,11 +97,13 @@ moduleFor( this.render('{{foo-bar poke="poke"}}'); - runTask(() => component.send('poke')); + expectDeprecation(() => { + runTask(() => component.send('poke')); + }, /send\(\) is deprecated/); } ["@test action can be handled by a superclass' actions object"](assert) { - this.assert.expect(4); + this.assert.expect(5); let component; @@ -136,11 +144,13 @@ moduleFor( this.render('{{x-index}}'); - runTask(() => { - component.send('foo'); - component.send('bar', 'HELLO'); - component.send('baz'); - }); + expectDeprecation(() => { + runTask(() => { + component.send('foo'); + component.send('bar', 'HELLO'); + component.send('baz'); + }); + }, /send\(\) is deprecated/); } ['@test actions cannot be provided at create time'](assert) { @@ -186,9 +196,11 @@ moduleFor( set(this.context, 'shouldRender', false); }); - expectAssertion(() => { - component.send('trigger-me-dead'); - }, "Attempted to call .send() with the action 'trigger-me-dead' on the destroyed object 'component:rip-alley'."); + expectDeprecation(() => { + expectAssertion(() => { + component.send('trigger-me-dead'); + }, "Attempted to call .send() with the action 'trigger-me-dead' on the destroyed object 'component:rip-alley'."); + }, /send\(\) is deprecated/); } } ); diff --git a/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts b/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts index 29c13f32c7c..ab3d37b2b58 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts +++ b/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts @@ -4,7 +4,7 @@ import Mixin from '@ember/object/mixin'; import { get } from '@ember/-internals/metal'; -import { assert } from '@ember/debug'; +import { assert, deprecate } from '@ember/debug'; /** `Ember.ActionHandler` is available on some familiar classes including @@ -164,6 +164,7 @@ const ActionHandler = Mixin.create({ ``` @property actions + @deprecated Use the `@action` decorator instead. @type Object @default null @public @@ -197,11 +198,18 @@ const ActionHandler = Mixin.create({ ``` @method send + @deprecated Use direct method calls instead. @param {String} actionName The action to trigger @param {*} context a context to send with the action @public */ send(actionName: string, ...args: any[]) { + deprecate('send() is deprecated. Please use direct method calls instead.', false, { + for: 'ember-source', + id: 'action-handler', + since: { available: '6.8.0' }, + until: '7.0.0', + }); assert( `Attempted to call .send() with the action '${actionName}' on the destroyed object '${this}'.`, !this.isDestroying && !this.isDestroyed diff --git a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts index e4448ab7392..18bd3fcfd24 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts +++ b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts @@ -5,7 +5,7 @@ import { context } from '@ember/-internals/environment'; import { get, computed } from '@ember/-internals/metal'; import Mixin from '@ember/object/mixin'; -import { assert } from '@ember/debug'; +import { assert, deprecate } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; /** @@ -102,11 +102,23 @@ const TargetActionSupport = Mixin.create({ ``` @method triggerAction + @deprecated Use a direct method call or closure action instead. @param opts {Object} (optional, with the optional keys action, target and/or actionContext) @return {Boolean} true if the action was sent successfully and did not return false @private */ triggerAction(opts: { action?: string; target?: unknown; actionContext?: unknown } = {}) { + deprecate( + 'triggerAction is deprecated. Please use a direct method call or closure action instead.', + false, + { + for: 'ember-source', + id: 'target-action-support', + since: { available: '6.8.0' }, + until: '7.0.0', + } + ); + let { action, target, actionContext } = opts; action = action || get(this, 'action'); target = target || getTarget(this); diff --git a/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js b/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js index be9eb69ea7b..c78161b0b56 100644 --- a/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js +++ b/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js @@ -1,7 +1,7 @@ import { context } from '@ember/-internals/environment'; import EmberObject from '@ember/object'; import TargetActionSupport from '../../lib/mixins/target_action_support'; -import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; +import { expectDeprecation, moduleFor, AbstractTestCase } from 'internal-test-helpers'; let originalLookup = context.lookup; let lookup; @@ -18,15 +18,17 @@ moduleFor( } ['@test it should return false if no target or action are specified'](assert) { - assert.expect(1); + assert.expect(2); let obj = EmberObject.extend(TargetActionSupport).create(); - assert.ok(false === obj.triggerAction(), 'no target or action was specified'); + expectDeprecation(() => { + assert.ok(false === obj.triggerAction(), 'no target or action was specified'); + }, /triggerAction is deprecated/); } ['@test it should support actions specified as strings'](assert) { - assert.expect(2); + assert.expect(3); let obj = EmberObject.extend(TargetActionSupport).create({ target: EmberObject.create({ @@ -38,11 +40,13 @@ moduleFor( action: 'anEvent', }); - assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + expectDeprecation(() => { + assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + }, /triggerAction is deprecated/); } ['@test it should invoke the send() method on objects that implement it'](assert) { - assert.expect(3); + assert.expect(4); let obj = EmberObject.extend(TargetActionSupport).create({ target: EmberObject.create({ @@ -55,11 +59,13 @@ moduleFor( action: 'anEvent', }); - assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + expectDeprecation(() => { + assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + }, /triggerAction is deprecated/); } ['@test it should find targets specified using a property path'](assert) { - assert.expect(2); + assert.expect(3); let Test = {}; lookup.Test = Test; @@ -75,11 +81,13 @@ moduleFor( action: 'anEvent', }); - assert.ok(true === myObj.triggerAction(), 'a valid target and action were specified'); + expectDeprecation(() => { + assert.ok(true === myObj.triggerAction(), 'a valid target and action were specified'); + }, /triggerAction is deprecated/); } ['@test it should use an actionContext object specified as a property on the object'](assert) { - assert.expect(2); + assert.expect(3); let obj = EmberObject.extend(TargetActionSupport).create({ action: 'anEvent', actionContext: {}, @@ -92,11 +100,13 @@ moduleFor( }, }), }); - assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + expectDeprecation(() => { + assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + }, /triggerAction is deprecated/); } ['@test it should find an actionContext specified as a property path'](assert) { - assert.expect(2); + assert.expect(3); let Test = {}; lookup.Test = Test; @@ -112,11 +122,13 @@ moduleFor( }), }); - assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + expectDeprecation(() => { + assert.ok(true === obj.triggerAction(), 'a valid target and action were specified'); + }, /triggerAction is deprecated/); } ['@test it should use the target specified in the argument'](assert) { - assert.expect(2); + assert.expect(3); let targetObj = EmberObject.create({ anEvent() { assert.ok(true, 'anEvent method was called'); @@ -126,14 +138,16 @@ moduleFor( action: 'anEvent', }); - assert.ok( - true === obj.triggerAction({ target: targetObj }), - 'a valid target and action were specified' - ); + expectDeprecation(() => { + assert.ok( + true === obj.triggerAction({ target: targetObj }), + 'a valid target and action were specified' + ); + }, /triggerAction is deprecated/); } ['@test it should use the action specified in the argument'](assert) { - assert.expect(2); + assert.expect(3); let obj = EmberObject.extend(TargetActionSupport).create({ target: EmberObject.create({ @@ -142,14 +156,17 @@ moduleFor( }, }), }); - assert.ok( - true === obj.triggerAction({ action: 'anEvent' }), - 'a valid target and action were specified' - ); + + expectDeprecation(() => { + assert.ok( + true === obj.triggerAction({ action: 'anEvent' }), + 'a valid target and action were specified' + ); + }, /triggerAction is deprecated/); } ['@test it should use the actionContext specified in the argument'](assert) { - assert.expect(2); + assert.expect(3); let context = {}; let obj = EmberObject.extend(TargetActionSupport).create({ target: EmberObject.create({ @@ -160,14 +177,16 @@ moduleFor( action: 'anEvent', }); - assert.ok( - true === obj.triggerAction({ actionContext: context }), - 'a valid target and action were specified' - ); + expectDeprecation(() => { + assert.ok( + true === obj.triggerAction({ actionContext: context }), + 'a valid target and action were specified' + ); + }, /triggerAction is deprecated/); } ['@test it should allow multiple arguments from actionContext'](assert) { - assert.expect(3); + assert.expect(4); let param1 = 'someParam'; let param2 = 'someOtherParam'; let obj = EmberObject.extend(TargetActionSupport).create({ @@ -186,14 +205,16 @@ moduleFor( action: 'anEvent', }); - assert.ok( - true === obj.triggerAction({ actionContext: [param1, param2] }), - 'a valid target and action were specified' - ); + expectDeprecation(() => { + assert.ok( + true === obj.triggerAction({ actionContext: [param1, param2] }), + 'a valid target and action were specified' + ); + }, /triggerAction is deprecated/); } ['@test it should use a null value specified in the actionContext argument'](assert) { - assert.expect(2); + assert.expect(3); let obj = EmberObject.extend(TargetActionSupport).create({ target: EmberObject.create({ anEvent(ctx) { @@ -202,10 +223,13 @@ moduleFor( }), action: 'anEvent', }); - assert.ok( - true === obj.triggerAction({ actionContext: null }), - 'a valid target and action were specified' - ); + + expectDeprecation(() => { + assert.ok( + true === obj.triggerAction({ actionContext: null }), + 'a valid target and action were specified' + ); + }, /triggerAction is deprecated/); } } ); diff --git a/packages/@ember/-internals/views/lib/mixins/action_support.ts b/packages/@ember/-internals/views/lib/mixins/action_support.ts index f7d79862587..a85c533ad4c 100644 --- a/packages/@ember/-internals/views/lib/mixins/action_support.ts +++ b/packages/@ember/-internals/views/lib/mixins/action_support.ts @@ -3,7 +3,7 @@ */ import { get } from '@ember/-internals/metal'; import Mixin from '@ember/object/mixin'; -import { assert, inspect } from '@ember/debug'; +import { assert, deprecate, inspect } from '@ember/debug'; /** @class ActionSupport @@ -15,6 +15,13 @@ interface ActionSupport { } const ActionSupport = Mixin.create({ send(actionName: string, ...args: unknown[]) { + deprecate('send() is deprecated. Please use direct method calls instead.', false, { + for: 'ember-source', + id: 'action-support', + since: { available: '6.8.0' }, + until: '7.0.0', + }); + assert( `Attempted to call .send() with the action '${actionName}' on the destroyed object '${this}'.`, !this.isDestroying && !this.isDestroyed diff --git a/packages/@ember/controller/tests/controller_test.js b/packages/@ember/controller/tests/controller_test.js index 62778cec084..df44488b64b 100644 --- a/packages/@ember/controller/tests/controller_test.js +++ b/packages/@ember/controller/tests/controller_test.js @@ -3,8 +3,15 @@ import Service, { service } from '@ember/service'; import EmberObject, { get } from '@ember/object'; import Mixin from '@ember/object/mixin'; import { setOwner } from '@ember/-internals/owner'; -import { runDestroy, buildOwner } from 'internal-test-helpers'; -import { moduleFor, ApplicationTestCase, AbstractTestCase, runTask } from 'internal-test-helpers'; +import { + runDestroy, + buildOwner, + expectDeprecation, + moduleFor, + ApplicationTestCase, + AbstractTestCase, + runTask, +} from 'internal-test-helpers'; import { action } from '@ember/object'; moduleFor( @@ -73,7 +80,7 @@ moduleFor( 'Controller event handling', class extends AbstractTestCase { ['@test Action can be handled by a function on actions object'](assert) { - assert.expect(1); + assert.expect(2); let TestController = Controller.extend({ actions: { poke() { @@ -82,11 +89,13 @@ moduleFor( }, }); let controller = TestController.create(); - controller.send('poke'); + expectDeprecation(() => { + controller.send('poke'); + }, /send\(\) is deprecated/); } ['@test A handled action can be bubbled to the target for continued processing'](assert) { - assert.expect(2); + assert.expect(3); let owner = buildOwner(); let TestController = Controller.extend({ @@ -112,13 +121,15 @@ moduleFor( setOwner(controller, owner); - controller.send('poke'); + expectDeprecation(() => { + controller.send('poke'); + }, /send\(\) is deprecated/); runDestroy(owner); } ["@test Action can be handled by a superclass' actions object"](assert) { - assert.expect(4); + assert.expect(5); let SuperController = Controller.extend({ actions: { @@ -149,9 +160,11 @@ moduleFor( }); let controller = IndexController.create({}); - controller.send('foo'); - controller.send('bar', 'HELLO'); - controller.send('baz'); + expectDeprecation(() => { + controller.send('foo'); + controller.send('bar', 'HELLO'); + controller.send('baz'); + }, /send\(\) is deprecated/); } ['@test .send asserts if called on a destroyed controller']() { @@ -169,9 +182,11 @@ moduleFor( let controller = owner.lookup('controller:application'); runDestroy(owner); - expectAssertion(() => { - controller.send('trigger-me-dead'); - }, "Attempted to call .send() with the action 'trigger-me-dead' on the destroyed object 'controller:rip-alley'."); + expectDeprecation(() => { + expectAssertion(() => { + controller.send('trigger-me-dead'); + }, "Attempted to call .send() with the action 'trigger-me-dead' on the destroyed object 'controller:rip-alley'."); + }, /send\(\) is deprecated/); } } ); diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js index d9f33febc3d..daf3d5f7301 100644 --- a/packages/ember/tests/routing/query_params_test.js +++ b/packages/ember/tests/routing/query_params_test.js @@ -749,21 +749,14 @@ moduleFor( ); this.setSingleQPController('application', 'foo', 1, { + router: service(), increment: action(function () { this.incrementProperty('foo'); - this.send('refreshRoute'); + this.router.refresh(); }), }); - this.add( - 'route:application', - class extends Route { - @action - refreshRoute() { - this.refresh(); - } - } - ); + this.add('route:application', Route); await this.visitAndAssert('/'); assert.equal(getTextOf(document.getElementById('test-value')), '1'); diff --git a/packages/ember/tests/routing/router_service_test/non_application_test_test.js b/packages/ember/tests/routing/router_service_test/non_application_test_test.js index 077bd4b8a2e..3849bc2eac1 100644 --- a/packages/ember/tests/routing/router_service_test/non_application_test_test.js +++ b/packages/ember/tests/routing/router_service_test/non_application_test_test.js @@ -110,7 +110,7 @@ moduleFor( this.render('{{foo-bar}}'); run(function () { - componentInstance.send('transitionToSister'); + componentInstance.transitionToSister(); }); assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); diff --git a/packages/ember/tests/routing/router_service_test/transitionTo_test.js b/packages/ember/tests/routing/router_service_test/transitionTo_test.js index 10c1a9a1e55..dc903d79f67 100644 --- a/packages/ember/tests/routing/router_service_test/transitionTo_test.js +++ b/packages/ember/tests/routing/router_service_test/transitionTo_test.js @@ -119,7 +119,7 @@ moduleFor( return this.visit('/').then(() => { run(function () { - componentInstance.send('transitionToSister'); + componentInstance.transitionToSister(); }); assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); @@ -151,7 +151,7 @@ moduleFor( return this.visit('/').then(() => { run(function () { - componentInstance.send('transitionToSister'); + componentInstance.transitionToSister(); }); assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); @@ -186,7 +186,7 @@ moduleFor( await this.visit('/'); run(function () { - componentInstance.send('transitionToDynamic'); + componentInstance.transitionToDynamic(); }); assert.equal(this.routerService.get('currentRouteName'), 'dynamic'); @@ -231,7 +231,7 @@ moduleFor( await this.visit('/'); run(function () { - componentInstance.send('transitionToDynamic'); + componentInstance.transitionToDynamic(); }); assert.equal(this.routerService.get('currentRouteName'), 'dynamic');