From 8db7026637fe17d4fcb03e0ddad590a668d33045 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 4 Mar 2024 20:15:29 -0500 Subject: [PATCH 1/6] Implement https://github.com/emberjs/rfcs/pull/1006 --- .../-internals/glimmer/lib/helpers/action.ts | 15 ++++++++++++++- .../-internals/glimmer/lib/modifiers/action.ts | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/action.ts b/packages/@ember/-internals/glimmer/lib/helpers/action.ts index 8f2423972ab..49050b5037e 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/action.ts @@ -3,7 +3,7 @@ */ import { get } from '@ember/-internals/metal'; import type { AnyFn } from '@ember/-internals/utility-types'; -import { assert } from '@ember/debug'; +import { assert, deprecate } from '@ember/debug'; import { flaggedInstrument } from '@ember/instrumentation'; import { join } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; @@ -278,6 +278,19 @@ export const ACTIONS = new WeakSet(); @public */ export default internalHelper((args: CapturedArguments): Reference => { + deprecate( + `Usage of the \`(action)\` helper is deprecated. Migrate to native functions and function invocation.`, + false, + { + id: 'template-action', + until: '6.0.0', + for: 'ember-source', + since: { + available: '5.10.0', + enabled: '5.10.0', + }, + } + ); let { named, positional } = args; // The first two argument slots are reserved. // pos[0] is the context (or `this`) diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts index 249eaeb9436..7662951584b 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts @@ -1,7 +1,7 @@ import type { InternalOwner } from '@ember/-internals/owner'; import { uuid } from '@ember/-internals/utils'; import { ActionManager, EventDispatcher, isSimpleClick } from '@ember/-internals/views'; -import { assert } from '@ember/debug'; +import { assert, deprecate } from '@ember/debug'; import { flaggedInstrument } from '@ember/instrumentation'; import { join } from '@ember/runloop'; import { registerDestructor } from '@glimmer/destroyable'; @@ -204,6 +204,19 @@ class ActionModifierManager implements InternalModifierManager Date: Mon, 4 Mar 2024 20:19:39 -0500 Subject: [PATCH 2/6] guess a URL --- packages/@ember/-internals/glimmer/lib/helpers/action.ts | 1 + packages/@ember/-internals/glimmer/lib/modifiers/action.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/action.ts b/packages/@ember/-internals/glimmer/lib/helpers/action.ts index 49050b5037e..d3140388cc0 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/action.ts @@ -283,6 +283,7 @@ export default internalHelper((args: CapturedArguments): Reference => false, { id: 'template-action', + url: 'https://deprecations.emberjs.com/v5.x/#toc_template-action', until: '6.0.0', for: 'ember-source', since: { diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts index 7662951584b..633f43aabd5 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts @@ -209,6 +209,7 @@ class ActionModifierManager implements InternalModifierManager Date: Sat, 9 Mar 2024 15:38:43 -0500 Subject: [PATCH 3/6] Add expectDeprecation to tests to mark places that will need updating when we remove action --- .../integration/application/actions-test.js | 6 +- .../components/contextual-components-test.js | 7 ++ .../components/curly-components-test.js | 8 +- .../components/dynamic-components-test.js | 2 + .../components/input-angle-test.js | 9 ++- .../components/input-curly-test.js | 9 ++- .../components/link-to/routing-angle-test.js | 1 + .../components/link-to/routing-curly-test.js | 2 + .../integration/components/tracked-test.js | 24 ++++++ .../integration/components/utils-test.js | 2 + .../integration/event-dispatcher-test.js | 3 + .../helpers/closure-action-test.js | 47 +++++++++++ .../helpers/element-action-test.js | 80 +++++++++++++++++++ .../tests/integration/helpers/fn-test.js | 1 + .../integration/helpers/readonly-test.js | 4 +- .../tests/integration/helpers/tracked-test.js | 4 + .../glimmer/tests/integration/input-test.js | 4 + .../@ember/application/tests/visit_test.js | 1 + packages/@ember/object/tests/action_test.js | 11 ++- .../ember/tests/component_context_test.js | 2 + packages/ember/tests/controller_test.js | 1 + .../tests/integration/multiple-app-test.js | 1 + .../tests/routing/decoupled_basic_test.js | 11 ++- .../ember/tests/routing/query_params_test.js | 1 + 24 files changed, 228 insertions(+), 13 deletions(-) diff --git a/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js b/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js index a0d3df9d997..b31436f630e 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js @@ -14,6 +14,8 @@ moduleFor( constructor() { setDebugFunction('debug', noop); super(...arguments); + + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); } teardown() { @@ -23,7 +25,7 @@ moduleFor( ['@test actions in top level template application template target application controller']( assert ) { - assert.expect(1); + assert.expect(2); this.add( 'controller:application', @@ -47,7 +49,7 @@ moduleFor( } ['@test actions in nested outlet template target their controller'](assert) { - assert.expect(1); + assert.expect(2); this.add( 'controller:application', diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js index 074e4e4a5c2..6ebc290b8c4 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js @@ -757,6 +757,8 @@ moduleFor( } ['@test renders with dot path and updates attributes'](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + this.registerComponent('my-nested-component', { ComponentClass: Component.extend({ didReceiveAttrs() { @@ -839,6 +841,8 @@ moduleFor( ['@test parameters in a contextual component are mutable when value is a param'](assert) { // This checks that a `(mut)` is added to parameters and attributes to // contextual components when it is a param. + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.registerComponent('change-button', { ComponentClass: Component.extend().reopenClass({ @@ -889,6 +893,7 @@ moduleFor( } ['@test GH#13494 tagless blockless component with property binding'](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.registerComponent('outer-component', { ComponentClass: Component.extend({ message: 'hello', @@ -1442,6 +1447,8 @@ class MutableParamTestGenerator { generate({ title, setup }) { return { [`@test parameters in a contextual component are mutable when value is a ${title}`](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.registerComponent('change-button', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['val'], diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js index d3646a33074..f18ff4a1733 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js @@ -1428,6 +1428,8 @@ moduleFor( ) { let componentInstance = null; + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.registerComponent('non-block', { ComponentClass: Component.extend({ counter: computed({ @@ -3149,6 +3151,8 @@ moduleFor( ['@test returning `true` from an action does not bubble if `target` is not specified (GH#14275)']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.registerComponent('display-toggle', { ComponentClass: Component.extend({ actions: { @@ -3174,7 +3178,9 @@ moduleFor( } ['@test returning `true` from an action bubbles to the `target` if specified'](assert) { - assert.expect(4); + assert.expect(5); + + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.registerComponent('display-toggle', { ComponentClass: Component.extend({ diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js index 7cf3d5aae22..6973b400980 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js @@ -449,6 +449,8 @@ moduleFor( }), }); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let actionTriggered = 0; this.registerComponent('outer-component', { template: diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js index 88f20df47da..edd10998d31 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js @@ -283,7 +283,8 @@ moduleFor( ['@test sends an action with `` when is pressed']( assert ) { - assert.expect(2); + assert.expect(3); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(``, { actions: { @@ -300,7 +301,8 @@ moduleFor( } ['@test sends `insert-newline` when is pressed'](assert) { - assert.expect(2); + assert.expect(3); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(``, { actions: { @@ -319,7 +321,8 @@ moduleFor( ['@test sends an action with `` when is pressed']( assert ) { - assert.expect(2); + assert.expect(3); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(``, { actions: { diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js index 1e8c4589cd9..f0c54952deb 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js @@ -152,7 +152,8 @@ moduleFor( ['@test sends an action with `{{input enter=(action "foo")}}` when is pressed']( assert ) { - assert.expect(2); + assert.expect(3); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(`{{input enter=(action 'foo')}}`, { actions: { @@ -169,7 +170,8 @@ moduleFor( } ['@test sends `insert-newline` when is pressed'](assert) { - assert.expect(2); + assert.expect(3); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(`{{input insert-newline=(action 'foo')}}`, { actions: { @@ -188,7 +190,8 @@ moduleFor( ['@test sends an action with `{{input escape-press=(action "foo")}}` when is pressed']( assert ) { - assert.expect(2); + assert.expect(3); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(`{{input escape-press=(action 'foo')}}`, { actions: { diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js index 259cfe15b6d..687a2175187 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js @@ -1027,6 +1027,7 @@ moduleFor( } async ['@test it defaults to bubbling'](assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'about', ` diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js index 86deedf092f..9a966144be3 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js @@ -1097,6 +1097,8 @@ moduleFor( } async ['@test it defaults to bubbling'](assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.addTemplate( 'about', ` diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js index 8a17d5d007b..ec0784cf567 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js @@ -136,6 +136,8 @@ moduleFor( } '@test tracked properties that are uninitialized do not throw an error'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let CountComponent = Component.extend({ count: tracked(), @@ -162,6 +164,8 @@ moduleFor( } '@test tracked properties rerender when updated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let CountComponent = Component.extend({ count: tracked({ value: 0 }), @@ -185,6 +189,8 @@ moduleFor( } '@test tracked properties rerender when updated outside of a runloop'(assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let done = assert.async(); let CountComponent = Component.extend({ @@ -216,6 +222,8 @@ moduleFor( } '@test nested tracked properties rerender when updated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let Counter = EmberObject.extend({ count: tracked({ value: 0 }), }); @@ -243,6 +251,8 @@ moduleFor( } '@test array properties rerender when updated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let NumListComponent = Component.extend({ numbers: tracked({ initializer: () => A([1, 2, 3]) }), @@ -270,6 +280,8 @@ moduleFor( } '@test getters update when dependent properties are invalidated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let CountComponent = Component.extend({ count: tracked({ value: 0 }), @@ -299,6 +311,8 @@ moduleFor( } '@test getters update when dependent computeds are invalidated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let CountComponent = Component.extend({ _count: 0, @@ -340,6 +354,8 @@ moduleFor( } '@test nested getters update when dependent properties are invalidated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let Counter = EmberObject.extend({ count: tracked({ value: 0 }), @@ -373,6 +389,8 @@ moduleFor( } '@test tracked object passed down through components updates correctly'(assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let Person = EmberObject.extend({ first: tracked({ value: 'Rob' }), last: tracked({ value: 'Jackson' }), @@ -423,6 +441,8 @@ moduleFor( } '@test yielded getters update correctly'() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let PersonComponent = Component.extend({ first: tracked({ value: 'Rob' }), last: tracked({ value: 'Jackson' }), @@ -462,6 +482,8 @@ moduleFor( } '@test yielded nested getters update correctly'() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let Person = EmberObject.extend({ first: tracked({ value: 'Rob' }), last: tracked({ value: 'Jackson' }), @@ -587,6 +609,8 @@ moduleFor( '@test downstream property changes do not invalidate upstream component getters/arguments'( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let outerRenderCount = 0; let innerRenderCount = 0; diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js index af536c1d7b7..b9626ad58a9 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js @@ -49,6 +49,8 @@ moduleFor( }, }); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.add('controller:application', ToggleController); this.addTemplate( diff --git a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js index c665be30561..cac044c9504 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js @@ -134,6 +134,8 @@ moduleFor( } ['@test case insensitive events'](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let receivedEvent; this.registerComponent('x-bar', { @@ -153,6 +155,7 @@ moduleFor( } ['@test case sensitive events'](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); let receivedEvent; this.registerComponent('x-bar', { diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js index 491ec966116..542ff4c2646 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js @@ -9,6 +9,8 @@ moduleFor( 'Helpers test: closure {{action}}', class extends RenderingTestCase { ['@test action should be called']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let outerActionCalled = false; let component; @@ -47,6 +49,8 @@ moduleFor( } ['@test an error is triggered when bound action function is undefined']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + this.registerComponent('inner-component', { template: 'inner', }); @@ -60,6 +64,8 @@ moduleFor( } ['@test an error is triggered when bound action being passed in is a non-function']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + this.registerComponent('inner-component', { template: 'inner', }); @@ -76,6 +82,9 @@ moduleFor( } ['@test [#12718] a nice error is shown when a bound action function is undefined and it is passed as @foo']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.registerComponent('inner-component', { template: '', @@ -91,6 +100,8 @@ moduleFor( } ['@test action value is returned']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let expectedValue = 'terrible tom'; let returnedValue; let innerComponent; @@ -131,6 +142,8 @@ moduleFor( } ['@test action should be called on the correct scope']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let innerComponent; let outerComponent; let actualComponent; @@ -177,6 +190,8 @@ moduleFor( } ['@test arguments to action are passed, curry']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let first = 'mitch'; let second = 'martin'; let third = 'matt'; @@ -226,6 +241,8 @@ moduleFor( } ['@test `this` can be passed as an argument']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let value = {}; let component; let innerComponent; @@ -271,6 +288,8 @@ moduleFor( } ['@test arguments to action are bound']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let value = 'lazy leah'; let innerComponent; @@ -328,6 +347,8 @@ moduleFor( } ['@test array arguments are passed correctly to action']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let first = 'foo'; let second = [3, 5]; let third = [4, 9]; @@ -388,6 +409,8 @@ moduleFor( } ['@test mut values can be wrapped in actions, are settable']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let newValue = 'trollin trek'; let innerComponent; @@ -431,6 +454,8 @@ moduleFor( } ['@test mut values can be wrapped in actions, are settable with a curry']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let newValue = 'trollin trek'; let innerComponent; @@ -474,6 +499,8 @@ moduleFor( } ['@test action can create closures over actions']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let first = 'raging robert'; let second = 'mild machty'; let returnValue = 'butch brian'; @@ -526,6 +553,8 @@ moduleFor( } ['@test provides a helpful error if an action is not present']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let InnerComponent = Component.extend({}); let OuterComponent = Component.extend({ @@ -554,6 +583,8 @@ moduleFor( } ['@test provides a helpful error if actions hash is not present']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let InnerComponent = Component.extend({}); let OuterComponent = Component.extend({}); @@ -574,6 +605,8 @@ moduleFor( } ['@test action can create closures over actions with target']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let innerComponent; let actionCalled = false; @@ -619,6 +652,8 @@ moduleFor( } ['@test value can be used with action over actions']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let newValue = 'yelping yehuda'; let innerComponent; @@ -667,6 +702,8 @@ moduleFor( } ['@test action will read the value of a first property']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let newValue = 'irate igor'; let innerComponent; @@ -710,6 +747,8 @@ moduleFor( } ['@test action will read the value of a curried first argument property']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let newValue = 'kissing kris'; let innerComponent; @@ -754,6 +793,8 @@ moduleFor( } ['@test action closure does not get auto-mut wrapped'](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let first = 'raging robert'; let second = 'mild machty'; let returnValue = 'butch brian'; @@ -823,6 +864,8 @@ moduleFor( } ['@test action should be called within a run loop']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let innerComponent; let capturedRunLoop; @@ -864,6 +907,8 @@ moduleFor( } ['@test closure action with `(mut undefinedThing)` works properly [GH#13959]']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let component; let ExampleComponent = Component.extend({ @@ -914,6 +959,8 @@ moduleFor( ['@test closure actions does not cause component hooks to fire unnecessarily [GH#14305] [GH#14654]']( assert ) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let clicked = 0; let didReceiveAttrsFired = 0; diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js index d5b0728a0ed..6a4d60bc2b6 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js @@ -31,6 +31,8 @@ moduleFor( 'Helpers test: element action', class extends RenderingTestCase { ['@test it can call an action on its enclosing component']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let fooCallCount = 0; let ExampleComponent = Component.extend({ @@ -68,6 +70,8 @@ moduleFor( } ['@test it can call an action with parameters']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let fooArgs = []; let component; @@ -115,6 +119,8 @@ moduleFor( } ['@test it should output a marker attribute with a guid']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.render(''); let button = this.$('button'); @@ -132,6 +138,8 @@ moduleFor( } ['@test it should allow alternative events to be handled']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let showCalled = false; let ExampleComponent = Component.extend({ @@ -157,6 +165,8 @@ moduleFor( } ['@test inside a yield, the target points at the original target']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let targetWatted = false; let innerWatted = false; @@ -201,6 +211,8 @@ moduleFor( } ['@test it should allow a target to be specified']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let targetWatted = false; let TargetComponent = Component.extend({ @@ -237,6 +249,8 @@ moduleFor( } ['@test it should lazily evaluate the target']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let firstEdit = 0; let secondEdit = 0; let component; @@ -287,6 +301,8 @@ moduleFor( } ['@test it should register an event handler']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let shortcutHandlerWasCalled = false; @@ -327,6 +343,8 @@ moduleFor( } ['@test it handles whitelisted bound modifier keys']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let shortcutHandlerWasCalled = false; @@ -369,6 +387,8 @@ moduleFor( } ['@test it handles whitelisted bound modifier keys with current value']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let component; @@ -412,6 +432,8 @@ moduleFor( } ['@test should be able to use action more than once for the same event within a view']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let deleteHandlerWasCalled = false; let originalHandlerWasCalled = false; @@ -481,6 +503,8 @@ moduleFor( } ['@test the event should not bubble if `bubbles=false` is passed']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let deleteHandlerWasCalled = false; let originalHandlerWasCalled = false; @@ -542,6 +566,8 @@ moduleFor( } ['@test the event should not bubble if `bubbles=false` is passed bound']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let deleteHandlerWasCalled = false; let originalHandlerWasCalled = false; @@ -604,6 +630,8 @@ moduleFor( } ['@test the bubbling depends on the bound parameter']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let originalHandlerWasCalled = false; let component; @@ -653,6 +681,8 @@ moduleFor( } ['@test multiple actions with bubbles=false for same event are called but prevent bubbling']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let clickAction1WasCalled = false; let clickAction2WasCalled = false; let eventHandlerWasCalled = false; @@ -692,6 +722,8 @@ moduleFor( } ['@test it should work properly in an #each block']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let ExampleComponent = Component.extend({ @@ -719,6 +751,8 @@ moduleFor( } ['@test it should work properly in a {{#let foo as |bar|}} block']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let ExampleComponent = Component.extend({ @@ -746,6 +780,8 @@ moduleFor( } ['@test it should unregister event handlers when an element action is removed'](assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let ExampleComponent = Component.extend({ actions: { edit() {}, @@ -791,6 +827,8 @@ moduleFor( } ['@test it should capture events from child elements and allow them to trigger the action']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let ExampleComponent = Component.extend({ @@ -819,6 +857,8 @@ moduleFor( } ['@test it should allow bubbling of events from action helper to original parent event']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let originalHandlerWasCalled = false; @@ -851,6 +891,8 @@ moduleFor( } ['@test it should not bubble an event from action helper to original parent event if `bubbles=false` is passed']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let originalHandlerWasCalled = false; @@ -881,6 +923,8 @@ moduleFor( } ['@test it should allow "send" as the action name (#594)']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let sendHandlerWasCalled = false; let ExampleComponent = Component.extend({ @@ -906,6 +950,8 @@ moduleFor( } ['@test it should send the view, event, and current context to the action']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let passedTarget; let passedContext; let targetThis; @@ -957,6 +1003,8 @@ moduleFor( } ['@test it should only trigger actions for the event they were registered on']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let editHandlerWasCalled = false; let ExampleComponent = Component.extend({ @@ -990,6 +1038,8 @@ moduleFor( } ['@test it should allow multiple contexts to be specified']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let passedContexts; let models = [EmberObject.create(), EmberObject.create()]; @@ -1022,6 +1072,8 @@ moduleFor( } ['@test it should allow multiple contexts to be specified mixed with string args']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let passedContexts; let model = EmberObject.create(); @@ -1053,6 +1105,8 @@ moduleFor( } ['@test it should not trigger action with special clicks']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let showCalled = false; let component; @@ -1104,6 +1158,8 @@ moduleFor( } ['@test it can trigger actions for keyboard events']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let showCalled = false; let ExampleComponent = Component.extend({ @@ -1129,6 +1185,8 @@ moduleFor( } ['@test a quoteless parameter should allow dynamic lookup of the actionName']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let lastAction; let actionOrder = []; let component; @@ -1188,6 +1246,8 @@ moduleFor( } ['@test a quoteless string parameter should resolve actionName, including path']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let lastAction; let actionOrder = []; let component; @@ -1248,6 +1308,8 @@ moduleFor( } ['@test a quoteless function parameter should be called, including arguments']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let submitCalled = false; let incomingArg; @@ -1276,6 +1338,8 @@ moduleFor( } ['@test a quoteless parameter that does not resolve to a value asserts']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let ExampleComponent = Component.extend({ actions: { ohNoeNotValid() {}, @@ -1293,6 +1357,8 @@ moduleFor( } ['@test allows multiple actions on a single element']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let clickActionWasCalled = false; let doubleClickActionWasCalled = false; @@ -1332,6 +1398,8 @@ moduleFor( } ['@test allows multiple actions for same event on a single element']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let clickAction1WasCalled = false; let clickAction2WasCalled = false; @@ -1366,6 +1434,8 @@ moduleFor( } ['@test it should respect preventDefault option if provided']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let ExampleComponent = Component.extend({ actions: { show() {}, @@ -1389,6 +1459,8 @@ moduleFor( } ['@test it should respect preventDefault option if provided bound']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let component; let ExampleComponent = Component.extend({ @@ -1426,6 +1498,8 @@ moduleFor( } ['@test it should target the proper component when `action` is in yielded block [GH #12409]']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + let outerActionCalled = false; let innerClickCalled = false; @@ -1479,6 +1553,8 @@ moduleFor( } ['@test element action with (mut undefinedThing) works properly']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let component; let ExampleComponent = Component.extend({ @@ -1527,6 +1603,8 @@ moduleFor( } ['@test it supports non-registered actions [GH#14888]']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + this.render( ` {{#if this.show}} @@ -1547,6 +1625,8 @@ moduleFor( } ["@test action handler that shifts element attributes doesn't trigger multiple invocations"]() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let actionCount = 0; let ExampleComponent = Component.extend({ selected: false, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js index a2aa0b74eda..67118b5a1e9 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js @@ -135,6 +135,7 @@ moduleFor( } '@test can use `this` if bound prior to passing to fn'(assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(`{{stash stashedFn=(fn (action this.myFunc) this.arg1)}}`, { myFunc(arg1) { return `arg1: ${arg1}, arg2: ${this.arg2}`; diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js index aa6415d37cc..7c132026a98 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js @@ -37,7 +37,9 @@ moduleFor( } '@test passing an action to {{readonly}} avoids mutable cell wrapping'(assert) { - assert.expect(4); + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + + assert.expect(5); let outer, inner; this.registerComponent('x-inner', { diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js index 8fe282cbbbc..7d97a452c25 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js @@ -15,6 +15,7 @@ moduleFor( 'Helper Tracked Properties', class extends RenderingTestCase { '@test tracked properties rerender when updated'(assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); let computeCount = 0; let PersonComponent = Component.extend({ @@ -92,6 +93,7 @@ moduleFor( } '@test getters update when dependent properties are invalidated'(assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); let computeCount = 0; let PersonComponent = Component.extend({ @@ -144,6 +146,7 @@ moduleFor( } '@test array properties rerender when updated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let NumListComponent = Component.extend({ numbers: tracked({ initializer: () => A([1, 2, 3]) }), @@ -175,6 +178,7 @@ moduleFor( } '@test custom ember array properties rerender when updated'() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let CustomArray = EmberObject.extend(MutableArray, { init() { this._super(...arguments); diff --git a/packages/@ember/-internals/glimmer/tests/integration/input-test.js b/packages/@ember/-internals/glimmer/tests/integration/input-test.js index 731a01763b8..2ca32fe77ee 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/input-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/input-test.js @@ -202,6 +202,7 @@ moduleFor( } ['@test GH18211 input checked attribute, without a value, works with the action helper']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.render(``, { actions: { someAction() {} }, }); @@ -209,6 +210,7 @@ moduleFor( } ['@test GH18211 input checked attribute, with a value, works with the action helper']() { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.render(``, { actions: { someAction() {} }, }); @@ -216,6 +218,7 @@ moduleFor( } ['@test GH18211 input checked attribute, without a value, works with attributes with values']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(``, { actions: { someAction() {} }, }); @@ -223,6 +226,7 @@ moduleFor( } ['@test GH18211 input checked attribute, without a value, works with event attributes']() { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.render(``, { actions: { someAction() {} }, }); diff --git a/packages/@ember/application/tests/visit_test.js b/packages/@ember/application/tests/visit_test.js index 7b0887c28a7..4b45d706dc9 100644 --- a/packages/@ember/application/tests/visit_test.js +++ b/packages/@ember/application/tests/visit_test.js @@ -625,6 +625,7 @@ moduleFor( } [`@test Ember Islands-style setup`](assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let xFooInitCalled = false; let xFooDidInsertElementCalled = false; diff --git a/packages/@ember/object/tests/action_test.js b/packages/@ember/object/tests/action_test.js index 8acc0dca4de..c246585ea18 100644 --- a/packages/@ember/object/tests/action_test.js +++ b/packages/@ember/object/tests/action_test.js @@ -6,6 +6,8 @@ moduleFor( '@action decorator', class extends RenderingTestCase { '@test action decorator works with ES6 class'(assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + class FooComponent extends Component { @action foo() { @@ -49,7 +51,8 @@ moduleFor( } '@test actions are properly merged through traditional and ES6 prototype hierarchy'(assert) { - assert.expect(4); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + assert.expect(5); let FooComponent = Component.extend({ actions: { @@ -97,6 +100,8 @@ moduleFor( } '@test action decorator super works with native class methods'(assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + class FooComponent extends Component { foo() { assert.ok(true, 'called!'); @@ -121,6 +126,8 @@ moduleFor( } '@test action decorator super works with traditional class methods'(assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let FooComponent = Component.extend({ foo() { assert.ok(true, 'called!'); @@ -239,6 +246,8 @@ moduleFor( } '@test action decorator can be used as a classic decorator with strings'(assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + let FooComponent = Component.extend({ foo: action(function () { assert.ok(true, 'called!'); diff --git a/packages/ember/tests/component_context_test.js b/packages/ember/tests/component_context_test.js index fa88436a09e..884c3370449 100644 --- a/packages/ember/tests/component_context_test.js +++ b/packages/ember/tests/component_context_test.js @@ -186,6 +186,7 @@ moduleFor( ['@test Components trigger actions in the parents context when called from within a block']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'application', ` @@ -219,6 +220,7 @@ moduleFor( ['@test Components trigger actions in the components context when called from within its template']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'application', ` diff --git a/packages/ember/tests/controller_test.js b/packages/ember/tests/controller_test.js index 26c8a020a94..1b8ea9c02f6 100644 --- a/packages/ember/tests/controller_test.js +++ b/packages/ember/tests/controller_test.js @@ -14,6 +14,7 @@ moduleFor( 'Template scoping examples', class extends ApplicationTestCase { ['@test Actions inside an outlet go to the associated controller'](assert) { + expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.add( 'controller:index', Controller.extend({ diff --git a/packages/ember/tests/integration/multiple-app-test.js b/packages/ember/tests/integration/multiple-app-test.js index b151999936a..ab2c4bbb37f 100644 --- a/packages/ember/tests/integration/multiple-app-test.js +++ b/packages/ember/tests/integration/multiple-app-test.js @@ -82,6 +82,7 @@ moduleFor( } [`@test booting multiple applications can properly handle events`](assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let actions = []; this.addFactoriesToResolver(actions, this.resolver); this.addFactoriesToResolver(actions, this.secondResolver); diff --git a/packages/ember/tests/routing/decoupled_basic_test.js b/packages/ember/tests/routing/decoupled_basic_test.js index 69b07d43d27..6827b87c429 100644 --- a/packages/ember/tests/routing/decoupled_basic_test.js +++ b/packages/ember/tests/routing/decoupled_basic_test.js @@ -305,6 +305,7 @@ moduleFor( async ['@test Events are triggered on the controller if a matching action name is implemented']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let done = assert.async(); this.router.map(function () { @@ -351,6 +352,7 @@ moduleFor( async ['@test Events are triggered on the current state when defined in `actions` object']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let done = assert.async(); this.router.map(function () { @@ -387,6 +389,7 @@ moduleFor( async ['@test Events defined in `actions` object are triggered on the current state when routes are nested']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let done = assert.async(); this.router.map(function () { @@ -428,7 +431,8 @@ moduleFor( } ['@test Events can be handled by inherited event handlers'](assert) { - assert.expect(4); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + assert.expect(5); let SuperRoute = Route.extend({ actions: { @@ -480,6 +484,7 @@ moduleFor( async ['@test Actions are not triggered on the controller if a matching action name is implemented as a method']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let done = assert.async(); this.router.map(function () { @@ -524,6 +529,7 @@ moduleFor( } async ['@test actions can be triggered with multiple arguments'](assert) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let done = assert.async(); this.router.map(function () { this.route('root', { path: '/' }, function () { @@ -1222,7 +1228,8 @@ moduleFor( } ['@test Actions can be handled by inherited action handlers'](assert) { - assert.expect(4); + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); + assert.expect(5); let SuperRoute = Route.extend({ actions: { diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js index 4f820f86996..32368b37b09 100644 --- a/packages/ember/tests/routing/query_params_test.js +++ b/packages/ember/tests/routing/query_params_test.js @@ -743,6 +743,7 @@ moduleFor( async ['@test queryParams are updated when a controller property is set and the route is refreshed. Issue #13263 ']( assert ) { + expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'application', '{{this.foo}}{{outlet}}' From 2f57fb90a523325fb7141735cf487aa53fd0625c Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 9 Mar 2024 16:03:50 -0500 Subject: [PATCH 4/6] Remove (action) and {{action}} --- .../-internals/glimmer/lib/helpers/action.ts | 455 ----- .../glimmer/lib/modifiers/action.ts | 299 --- .../@ember/-internals/glimmer/lib/resolver.ts | 8 - .../glimmer/lib/utils/process-args.ts | 5 +- .../integration/application/actions-test.js | 111 -- .../components/curly-components-test.js | 46 +- .../components/dynamic-components-test.js | 10 +- .../components/input-angle-test.js | 26 +- .../components/input-curly-test.js | 47 +- .../helpers/closure-action-test.js | 1065 ----------- .../helpers/element-action-test.js | 1670 ----------------- .../integration/helpers/readonly-test.js | 46 - .../glimmer/tests/integration/input-test.js | 26 +- packages/@ember/-internals/views/index.ts | 1 - .../views/lib/system/action_manager.ts | 16 - .../views/lib/system/event_dispatcher.ts | 85 - packages/@ember/object/tests/action_test.js | 41 +- .../ember/tests/component_context_test.js | 24 +- packages/ember/tests/controller_test.js | 45 - .../tests/routing/decoupled_basic_test.js | 19 +- 20 files changed, 71 insertions(+), 3974 deletions(-) delete mode 100644 packages/@ember/-internals/glimmer/lib/helpers/action.ts delete mode 100644 packages/@ember/-internals/glimmer/lib/modifiers/action.ts delete mode 100644 packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js delete mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js delete mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js delete mode 100644 packages/@ember/-internals/views/lib/system/action_manager.ts delete mode 100644 packages/ember/tests/controller_test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/action.ts b/packages/@ember/-internals/glimmer/lib/helpers/action.ts deleted file mode 100644 index d3140388cc0..00000000000 --- a/packages/@ember/-internals/glimmer/lib/helpers/action.ts +++ /dev/null @@ -1,455 +0,0 @@ -/** -@module ember -*/ -import { get } from '@ember/-internals/metal'; -import type { AnyFn } from '@ember/-internals/utility-types'; -import { assert, deprecate } from '@ember/debug'; -import { flaggedInstrument } from '@ember/instrumentation'; -import { join } from '@ember/runloop'; -import { DEBUG } from '@glimmer/env'; -import type { CapturedArguments } from '@glimmer/interfaces'; -import type { Reference } from '@glimmer/reference'; -import { createUnboundRef, isInvokableRef, updateRef, valueForRef } from '@glimmer/reference'; -import { internalHelper } from './internal-helper'; - -export const ACTIONS = new WeakSet(); - -/** - The `{{action}}` helper provides a way to pass triggers for behavior (usually - just a function) between components, and into components from controllers. - - ### Passing functions with the action helper - - There are three contexts an action helper can be used in. The first two - contexts to discuss are attribute context, and Handlebars value context. - - ```handlebars - {{! An example of attribute context }} -
- {{! Examples of Handlebars value context }} - {{input on-input=(action "save")}} - {{yield (action "refreshData") andAnotherParam}} - ``` - - In these contexts, - the helper is called a "closure action" helper. Its behavior is simple: - If passed a function name, read that function off the `actions` property - of the current context. Once that function is read, or immediately if a function was - passed, create a closure over that function and any arguments. - The resulting value of an action helper used this way is simply a function. - - For example, in the attribute context: - - ```handlebars - {{! An example of attribute context }} -
- ``` - - The resulting template render logic would be: - - ```js - var div = document.createElement('div'); - var actionFunction = (function(context){ - return function() { - return context.actions.save.apply(context, arguments); - }; - })(context); - div.onclick = actionFunction; - ``` - - Thus when the div is clicked, the action on that context is called. - Because the `actionFunction` is just a function, closure actions can be - passed between components and still execute in the correct context. - - Here is an example action handler on a component: - - ```app/components/my-component.js - import Component from '@glimmer/component'; - import { action } from '@ember/object'; - - export default class extends Component { - @action - save() { - this.model.save(); - } - } - ``` - - Actions are always looked up on the `actions` property of the current context. - This avoids collisions in the naming of common actions, such as `destroy`. - Two options can be passed to the `action` helper when it is used in this way. - - * `target=someProperty` will look to `someProperty` instead of the current - context for the `actions` hash. This can be useful when targeting a - service for actions. - * `value="target.value"` will read the path `target.value` off the first - argument to the action when it is called and rewrite the first argument - to be that value. This is useful when attaching actions to event listeners. - - ### Invoking an action - - Closure actions curry both their scope and any arguments. When invoked, any - additional arguments are added to the already curried list. - Actions are presented in JavaScript as callbacks, and are - invoked like any other JavaScript function. - - For example - - ```app/components/update-name.js - import Component from '@glimmer/component'; - import { action } from '@ember/object'; - - export default class extends Component { - @action - setName(model, name) { - model.set('name', name); - } - } - ``` - - ```app/components/update-name.hbs - {{input on-input=(action (action 'setName' @model) value="target.value")}} - ``` - - The first argument (`@model`) was curried over, and the run-time argument (`event`) - becomes a second argument. Action calls can be nested this way because each simply - returns a function. Any function can be passed to the `{{action}}` helper, including - other actions. - - Actions invoked with `sendAction` have the same currying behavior as demonstrated - with `on-input` above. For example: - - ```app/components/my-input.js - import Component from '@glimmer/component'; - import { action } from '@ember/object'; - - export default class extends Component { - @action - setName(model, name) { - model.set('name', name); - } - } - ``` - - ```handlebars - - ``` - - or - - ```handlebars - {{my-input submit=(action 'setName' @model)}} - ``` - - ```app/components/my-component.js - import Component from '@ember/component'; - - export default Component.extend({ - click() { - // Note that model is not passed, it was curried in the template - this.submit('bob'); - } - }); - ``` - - ### Attaching actions to DOM elements - - The third context of the `{{action}}` helper can be called "element space". - For example: - - ```handlebars - {{! An example of element space }} -
- ``` - - Used this way, the `{{action}}` helper provides a useful shortcut for - registering an HTML element in a template for a single DOM event and - forwarding that interaction to the template's context (controller or component). - If the context of a template is a controller, actions used this way will - bubble to routes when the controller does not implement the specified action. - Once an action hits a route, it will bubble through the route hierarchy. - - ### Event Propagation - - `{{action}}` helpers called in element space can control event bubbling. Note - that the closure style actions cannot. - - Events triggered through the action helper will automatically have - `.preventDefault()` called on them. You do not need to do so in your event - handlers. If you need to allow event propagation (to handle file inputs for - example) you can supply the `preventDefault=false` option to the `{{action}}` helper: - - ```handlebars -
- - -
- ``` - - To disable bubbling, pass `bubbles=false` to the helper: - - ```handlebars - - ``` - - To disable bubbling with closure style actions you must create your own - wrapper helper that makes use of `event.stopPropagation()`: - - ```handlebars -
Hello
- ``` - - ```app/helpers/disable-bubbling.js - import { helper } from '@ember/component/helper'; - - export function disableBubbling([action]) { - return function(event) { - event.stopPropagation(); - return action(event); - }; - } - export default helper(disableBubbling); - ``` - - If you need the default handler to trigger you should either register your - own event handler, or use event methods on your view class. See - ["Responding to Browser Events"](/ember/release/classes/Component) - in the documentation for `Component` for more information. - - ### Specifying DOM event type - - `{{action}}` helpers called in element space can specify an event type. - By default the `{{action}}` helper registers for DOM `click` events. You can - supply an `on` option to the helper to specify a different DOM event name: - - ```handlebars -
- click me -
- ``` - - See ["Event Names"](/ember/release/classes/Component) for a list of - acceptable DOM event names. - - ### Specifying whitelisted modifier keys - - `{{action}}` helpers called in element space can specify modifier keys. - By default the `{{action}}` helper will ignore click events with pressed modifier - keys. You can supply an `allowedKeys` option to specify which keys should not be ignored. - - ```handlebars -
- click me -
- ``` - - This way the action will fire when clicking with the alt key pressed down. - Alternatively, supply "any" to the `allowedKeys` option to accept any combination of modifier keys. - - ```handlebars -
- click me with any key pressed -
- ``` - - ### Specifying a Target - - A `target` option can be provided to the helper to change - which object will receive the method call. This option must be a path - to an object, accessible in the current context: - - ```app/templates/application.hbs -
- click me -
- ``` - - ```app/controllers/application.js - import Controller from '@ember/controller'; - import { service } from '@ember/service'; - - export default class extends Controller { - @service someService; - } - ``` - - @method action - @for Ember.Templates.helpers - @public -*/ -export default internalHelper((args: CapturedArguments): Reference => { - deprecate( - `Usage of the \`(action)\` helper is deprecated. Migrate to native functions and function invocation.`, - false, - { - id: 'template-action', - url: 'https://deprecations.emberjs.com/v5.x/#toc_template-action', - until: '6.0.0', - for: 'ember-source', - since: { - available: '5.10.0', - enabled: '5.10.0', - }, - } - ); - let { named, positional } = args; - // The first two argument slots are reserved. - // pos[0] is the context (or `this`) - // pos[1] is the action name or function - // Anything else is an action argument. - let [context, action, ...restArgs] = positional; - assert('hash position arguments', context && action); - - let debugKey: string = action.debugLabel!; - - let target = 'target' in named ? named['target'] : context; - let processArgs = makeArgsProcessor(('value' in named && named['value']) || false, restArgs); - - let fn: Function; - - if (isInvokableRef(action)) { - fn = makeClosureAction(action, action as MaybeActionHandler, invokeRef, processArgs, debugKey); - } else { - fn = makeDynamicClosureAction( - valueForRef(context) as object, - // SAFETY: glimmer-vm should expose narrowing utilities for references - // as is, `target` is still `Reference`. - // however, we never even tried to narrow `target`, so this is potentially risky code. - target!, - // SAFETY: glimmer-vm should expose narrowing utilities for references - // as is, `action` is still `Reference` - action, - processArgs, - debugKey - ); - } - - ACTIONS.add(fn); - - return createUnboundRef(fn, '(result of an `action` helper)'); -}); - -function NOOP(args: unknown[]) { - return args; -} - -function makeArgsProcessor(valuePathRef: Reference | false, actionArgsRef: Reference[]) { - let mergeArgs: ((args: unknown[]) => unknown[]) | undefined; - - if (actionArgsRef.length > 0) { - mergeArgs = (args: unknown[]) => { - return actionArgsRef.map(valueForRef).concat(args); - }; - } - - let readValue: ((args: unknown[]) => unknown[]) | undefined; - - if (valuePathRef) { - readValue = (args: unknown[]) => { - let valuePath = valueForRef(valuePathRef); - - if (valuePath && args.length > 0) { - args[0] = get(args[0] as object, valuePath as string); - } - - return args; - }; - } - - if (mergeArgs && readValue) { - return (args: unknown[]) => { - return readValue!(mergeArgs!(args)); - }; - } else { - return mergeArgs || readValue || NOOP; - } -} - -function makeDynamicClosureAction( - context: object, - targetRef: Reference, - actionRef: Reference, - processArgs: (args: unknown[]) => unknown[], - debugKey: string -) { - const action = valueForRef(actionRef); - - // We don't allow undefined/null values, so this creates a throw-away action to trigger the assertions - if (DEBUG) { - makeClosureAction(context, valueForRef(targetRef), action, processArgs, debugKey); - } - - return (...args: any[]) => { - return makeClosureAction( - context, - valueForRef(targetRef), - action, - processArgs, - debugKey - )(...args); - }; -} - -interface MaybeActionHandler { - actions?: Record; -} - -function makeClosureAction( - context: object, - target: unknown, - action: unknown | null | undefined | string | Function, - processArgs: (args: unknown[]) => unknown[], - debugKey: string -) { - let self: object; - let fn: Function; - - assert( - `Action passed is null or undefined in (action) from ${target}.`, - action !== undefined && action !== null - ); - - if (typeof action === 'string') { - assert('target must be an object', target !== null && typeof target === 'object'); - self = target; - let value = (target as { actions?: Record }).actions?.[action]; - assert(`An action named '${action}' was not found in ${target}`, Boolean(value)); - assert( - `An action named '${action}' was found in ${target}, but is not a function`, - typeof value === 'function' - ); - fn = value; - } else if (typeof action === 'function') { - self = context; - fn = action; - } else { - assert( - `An action could not be made for \`${ - debugKey || action - }\` in ${target}. Please confirm that you are using either a quoted action name (i.e. \`(action '${ - debugKey || 'myAction' - }')\`) or a function available in ${target}.`, - false - ); - } - - return (...args: any[]) => { - let payload = { target: self, args, label: '@glimmer/closure-action' }; - return flaggedInstrument('interaction.ember-action', payload, () => { - return join(self, fn as AnyFn, ...processArgs(args)); - }); - }; -} - -// The code above: - -// 1. Finds an action function, usually on the `actions` hash -// 2. Calls it with the target as the correct `this` context - -// Previously, `UPDATE_REFERENCED_VALUE` was a method on the reference itself, -// so this made a bit more sense. Now, it isn't, and so we need to create a -// function that can have `this` bound to it when called. This allows us to use -// the same codepath to call `updateRef` on the reference. -function invokeRef(this: Reference, value: unknown) { - updateRef(this, value); -} diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts deleted file mode 100644 index 633f43aabd5..00000000000 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ /dev/null @@ -1,299 +0,0 @@ -import type { InternalOwner } from '@ember/-internals/owner'; -import { uuid } from '@ember/-internals/utils'; -import { ActionManager, EventDispatcher, isSimpleClick } from '@ember/-internals/views'; -import { assert, deprecate } from '@ember/debug'; -import { flaggedInstrument } from '@ember/instrumentation'; -import { join } from '@ember/runloop'; -import { registerDestructor } from '@glimmer/destroyable'; -import { DEBUG } from '@glimmer/env'; -import type { - CapturedArguments, - CapturedNamedArguments, - CapturedPositionalArguments, - InternalModifierManager, -} from '@glimmer/interfaces'; -import { setInternalModifierManager } from '@glimmer/manager'; -import { isInvokableRef, updateRef, valueForRef } from '@glimmer/reference'; -import type { UpdatableTag } from '@glimmer/validator'; -import { createUpdatableTag } from '@glimmer/validator'; -import type { SimpleElement } from '@simple-dom/interface'; - -const MODIFIERS = ['alt', 'shift', 'meta', 'ctrl']; -const POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/; - -function isAllowedEvent(event: Event, allowedKeys: any) { - if (allowedKeys === null || allowedKeys === undefined) { - if (POINTER_EVENT_TYPE_REGEX.test(event.type)) { - return isSimpleClick(event); - } else { - allowedKeys = ''; - } - } - - if (allowedKeys.indexOf('any') >= 0) { - return true; - } - - for (let i = 0; i < MODIFIERS.length; i++) { - if ((event as any)[MODIFIERS[i] + 'Key'] && allowedKeys.indexOf(MODIFIERS[i]) === -1) { - return false; - } - } - - return true; -} - -export let ActionHelper = { - // registeredActions is re-exported for compatibility with older plugins - // that were using this undocumented API. - registeredActions: ActionManager.registeredActions, - - registerAction(actionState: ActionState) { - let { actionId } = actionState; - - ActionManager.registeredActions[actionId] = actionState; - - return actionId; - }, - - unregisterAction(actionState: ActionState) { - let { actionId } = actionState; - - delete ActionManager.registeredActions[actionId]; - }, -}; - -export class ActionState { - public element: SimpleElement; - public owner: InternalOwner; - public actionId: number; - public actionName: any; - public actionArgs: any; - public namedArgs: CapturedNamedArguments; - public positional: CapturedPositionalArguments; - public implicitTarget: any; - public eventName: any; - public tag = createUpdatableTag(); - - constructor( - element: SimpleElement, - owner: InternalOwner, - actionId: number, - actionArgs: any[], - namedArgs: CapturedNamedArguments, - positionalArgs: CapturedPositionalArguments - ) { - this.element = element; - this.owner = owner; - this.actionId = actionId; - this.actionArgs = actionArgs; - this.namedArgs = namedArgs; - this.positional = positionalArgs; - this.eventName = this.getEventName(); - - registerDestructor(this, () => ActionHelper.unregisterAction(this)); - } - - getEventName() { - let { on } = this.namedArgs; - - return on !== undefined ? valueForRef(on) : 'click'; - } - - getActionArgs() { - let result = new Array(this.actionArgs.length); - - for (let i = 0; i < this.actionArgs.length; i++) { - result[i] = valueForRef(this.actionArgs[i]); - } - - return result; - } - - getTarget(): any { - let { implicitTarget, namedArgs } = this; - let { target } = namedArgs; - - return target !== undefined ? valueForRef(target) : valueForRef(implicitTarget); - } - - handler(event: Event): boolean { - let { actionName, namedArgs } = this; - let { bubbles, preventDefault, allowedKeys } = namedArgs; - - let bubblesVal = bubbles !== undefined ? valueForRef(bubbles) : undefined; - let preventDefaultVal = preventDefault !== undefined ? valueForRef(preventDefault) : undefined; - let allowedKeysVal = allowedKeys !== undefined ? valueForRef(allowedKeys) : undefined; - - let target = this.getTarget(); - - let shouldBubble = bubblesVal !== false; - - if (!isAllowedEvent(event, allowedKeysVal)) { - return true; - } - - if (preventDefaultVal !== false) { - event.preventDefault(); - } - - if (!shouldBubble) { - event.stopPropagation(); - } - - join(() => { - let args = this.getActionArgs(); - let payload = { - args, - target, - name: null, - }; - if (isInvokableRef(actionName)) { - flaggedInstrument('interaction.ember-action', payload, () => { - updateRef(actionName, args[0]); - }); - return; - } - if (typeof actionName === 'function') { - flaggedInstrument('interaction.ember-action', payload, () => { - actionName.apply(target, args); - }); - return; - } - payload.name = actionName; - if (target.send) { - flaggedInstrument('interaction.ember-action', payload, () => { - target.send.apply(target, [actionName, ...args]); - }); - } else { - assert( - `The action '${actionName}' did not exist on ${target}`, - typeof target[actionName] === 'function' - ); - flaggedInstrument('interaction.ember-action', payload, () => { - target[actionName].apply(target, args); - }); - } - }); - - return shouldBubble; - } -} - -class ActionModifierManager implements InternalModifierManager { - create( - owner: InternalOwner, - element: SimpleElement, - _state: object, - { named, positional }: CapturedArguments - ): ActionState { - let actionArgs: any[] = []; - // The first two arguments are (1) `this` and (2) the action name. - // Everything else is a param. - for (let i = 2; i < positional.length; i++) { - actionArgs.push(positional[i]); - } - - let actionId = uuid(); - - return new ActionState(element, owner, actionId, actionArgs, named, positional); - } - - getDebugName(): string { - return 'action'; - } - - install(actionState: ActionState): void { - deprecate( - `Usage of the \`{{action}}\` modifier is deprecated. Migrate to native functions and function invocation.`, - false, - { - id: 'template-action', - url: 'https://deprecations.emberjs.com/v5.x/#toc_template-action', - until: '6.0.0', - for: 'ember-source', - since: { - available: '5.10.0', - enabled: '5.10.0', - }, - } - ); - let { element, actionId, positional } = actionState; - - let actionName; - let actionNameRef: any; - let implicitTarget; - - if (positional.length > 1) { - implicitTarget = positional[0]; - actionNameRef = positional[1]; - - if (isInvokableRef(actionNameRef)) { - actionName = actionNameRef; - } else { - actionName = valueForRef(actionNameRef); - - if (DEBUG) { - let actionPath = actionNameRef.debugLabel; - let actionPathParts = actionPath.split('.'); - let actionLabel = actionPathParts[actionPathParts.length - 1]; - - assert( - 'You specified a quoteless path, `' + - actionPath + - '`, to the ' + - '{{action}} helper which did not resolve to an action name (a ' + - 'string). Perhaps you meant to use a quoted actionName? (e.g. ' + - '{{action "' + - actionLabel + - '"}}).', - typeof actionName === 'string' || typeof actionName === 'function' - ); - } - } - } - - actionState.actionName = actionName; - actionState.implicitTarget = implicitTarget; - - this.ensureEventSetup(actionState); - ActionHelper.registerAction(actionState); - - element.setAttribute('data-ember-action', ''); - element.setAttribute(`data-ember-action-${actionId}`, String(actionId)); - } - - update(actionState: ActionState): void { - let { positional } = actionState; - let actionNameRef = positional[1]; - assert('Expected at least one positional arg', actionNameRef); - - if (!isInvokableRef(actionNameRef)) { - actionState.actionName = valueForRef(actionNameRef); - } - - let newEventName = actionState.getEventName(); - if (newEventName !== actionState.eventName) { - this.ensureEventSetup(actionState); - actionState.eventName = actionState.getEventName(); - } - } - - ensureEventSetup(actionState: ActionState): void { - let dispatcher = actionState.owner.lookup('event_dispatcher:main'); - assert('Expected dispatcher to be an EventDispatcher', dispatcher instanceof EventDispatcher); - dispatcher?.setupHandlerForEmberEvent(actionState.eventName); - } - - getTag(actionState: ActionState): UpdatableTag { - return actionState.tag; - } - - getDestroyable(actionState: ActionState): object { - return actionState; - } -} - -const ACTION_MODIFIER_MANAGER = new ActionModifierManager(); - -export default setInternalModifierManager(ACTION_MODIFIER_MANAGER, {}); diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 5ad07efc0c4..3c4953a5246 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -37,14 +37,12 @@ import { default as inElementNullCheckHelper } from './helpers/-in-element-null- import { default as normalizeClassHelper } from './helpers/-normalize-class'; import { default as resolve } from './helpers/-resolve'; import { default as trackArray } from './helpers/-track-array'; -import { default as action } from './helpers/action'; import { default as eachIn } from './helpers/each-in'; import { default as mut } from './helpers/mut'; import { default as readonly } from './helpers/readonly'; import { default as unbound } from './helpers/unbound'; import { default as uniqueId } from './helpers/unique-id'; -import actionModifier from './modifiers/action'; import { mountHelper } from './syntax/mount'; import { outletHelper } from './syntax/outlet'; @@ -109,7 +107,6 @@ function lookupComponentPair( } const BUILTIN_KEYWORD_HELPERS: Record = { - action, mut, readonly, unbound, @@ -147,12 +144,7 @@ if (DEBUG) { BUILTIN_HELPERS['-disallow-dynamic-resolution'] = disallowDynamicResolution; } -const BUILTIN_KEYWORD_MODIFIERS: Record = { - action: actionModifier, -}; - const BUILTIN_MODIFIERS: Record = { - ...BUILTIN_KEYWORD_MODIFIERS, on, }; diff --git a/packages/@ember/-internals/glimmer/lib/utils/process-args.ts b/packages/@ember/-internals/glimmer/lib/utils/process-args.ts index 51e79131dc5..27014c8ab11 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/process-args.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/process-args.ts @@ -4,7 +4,6 @@ import type { Reference } from '@glimmer/reference'; import { isUpdatableRef, updateRef, valueForRef } from '@glimmer/reference'; import { assert } from '@ember/debug'; import { ARGS } from '../component-managers/curly'; -import { ACTIONS } from '../helpers/action'; // ComponentArgs takes EvaluatedNamedArgs and converts them into the // inputs needed by CurlyComponents (attrs and props, with mutable @@ -20,9 +19,7 @@ export function processComponentArgs(namedArgs: CapturedNamedArguments) { assert('expected ref', ref); let value = valueForRef(ref); - let isAction = typeof value === 'function' && ACTIONS.has(value); - - if (isUpdatableRef(ref) && !isAction) { + if (isUpdatableRef(ref)) { attrs[name] = new MutableCell(ref, value); } else { attrs[name] = value; diff --git a/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js b/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js deleted file mode 100644 index b31436f630e..00000000000 --- a/packages/@ember/-internals/glimmer/tests/integration/application/actions-test.js +++ /dev/null @@ -1,111 +0,0 @@ -import { moduleFor, ApplicationTestCase, RenderingTestCase, runTask } from 'internal-test-helpers'; - -import Controller from '@ember/controller'; -import { getDebugFunction, setDebugFunction } from '@ember/debug'; - -import { Component } from '../../utils/helpers'; - -const originalDebug = getDebugFunction('debug'); -const noop = function () {}; - -moduleFor( - 'Application test: actions', - class extends ApplicationTestCase { - constructor() { - setDebugFunction('debug', noop); - super(...arguments); - - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - } - - teardown() { - setDebugFunction('debug', originalDebug); - } - - ['@test actions in top level template application template target application controller']( - assert - ) { - assert.expect(2); - - this.add( - 'controller:application', - Controller.extend({ - actions: { - handleIt() { - assert.ok(true, 'controller received action properly'); - }, - }, - }) - ); - - this.addTemplate( - 'application', - '' - ); - - return this.visit('/').then(() => { - runTask(() => this.$('#handle-it').click()); - }); - } - - ['@test actions in nested outlet template target their controller'](assert) { - assert.expect(2); - - this.add( - 'controller:application', - Controller.extend({ - actions: { - handleIt() { - assert.ok(false, 'application controller should not have received action!'); - }, - }, - }) - ); - - this.add( - 'controller:index', - Controller.extend({ - actions: { - handleIt() { - assert.ok(true, 'controller received action properly'); - }, - }, - }) - ); - - this.addTemplate('index', ''); - - return this.visit('/').then(() => { - runTask(() => this.$('#handle-it').click()); - }); - } - } -); - -moduleFor( - 'Rendering test: non-interactive actions', - class extends RenderingTestCase { - getBootOptions() { - return { isInteractive: false }; - } - - [`@test doesn't attatch actions`](assert) { - this.registerComponent('foo-bar', { - ComponentClass: Component.extend({ - actions: { - fire() { - assert.ok(false); - }, - }, - }), - template: ``, - }); - - this.render('{{foo-bar tagName=""}}'); - - this.assertHTML(''); - - this.$('button').click(); - } - } -); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js index f18ff4a1733..42703390c27 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js @@ -1428,8 +1428,6 @@ moduleFor( ) { let componentInstance = null; - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.registerComponent('non-block', { ComponentClass: Component.extend({ counter: computed({ @@ -1461,7 +1459,7 @@ moduleFor( }, }), template: ` - + `, }); @@ -3151,19 +3149,15 @@ moduleFor( ['@test returning `true` from an action does not bubble if `target` is not specified (GH#14275)']( assert ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.registerComponent('display-toggle', { ComponentClass: Component.extend({ - actions: { - show() { - assert.ok(true, 'display-toggle show action was called'); - return true; - }, + show() { + assert.ok(true, 'display-toggle show action was called'); + return true; }, }), - template: ``, + template: ``, }); this.render(`{{display-toggle}}`, { @@ -3177,36 +3171,6 @@ moduleFor( runTask(() => this.$('button').click()); } - ['@test returning `true` from an action bubbles to the `target` if specified'](assert) { - assert.expect(5); - - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - this.registerComponent('display-toggle', { - ComponentClass: Component.extend({ - actions: { - show() { - assert.ok(true, 'display-toggle show action was called'); - return true; - }, - }, - }), - - template: ``, - }); - - this.render(`{{display-toggle target=this}}`, { - send(actionName) { - assert.ok(true, 'send should be called when action is "subscribed" to'); - assert.equal(actionName, 'show'); - }, - }); - - this.assertText('Show'); - - runTask(() => this.$('button').click()); - } - ['@test triggering an event only attempts to invoke an identically named method, if it actually is a function (GH#15228)']( assert ) { diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js index 6973b400980..e0055584fdf 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js @@ -449,19 +449,15 @@ moduleFor( }), }); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - let actionTriggered = 0; this.registerComponent('outer-component', { template: - '{{#component this.componentName somethingClicked=(action "mappedAction")}}arepas!{{/component}}', + '{{#component this.componentName somethingClicked=this.mappedAction}}arepas!{{/component}}', ComponentClass: Component.extend({ classNames: 'outer-component', componentName: 'inner-component', - actions: { - mappedAction() { - actionTriggered++; - }, + mappedAction() { + actionTriggered++; }, }), }); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js index edd10998d31..6e31685e8af 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js @@ -283,15 +283,12 @@ moduleFor( ['@test sends an action with `` when is pressed']( assert ) { - assert.expect(3); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + assert.expect(2); - this.render(``, { - actions: { - foo(value, event) { - assert.ok(true, 'action was triggered'); - assert.ok(event instanceof Event, 'Native event was passed'); - }, + this.render(``, { + foo(value, event) { + assert.ok(true, 'action was triggered'); + assert.ok(event instanceof Event, 'Native event was passed'); }, }); @@ -321,15 +318,12 @@ moduleFor( ['@test sends an action with `` when is pressed']( assert ) { - assert.expect(3); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); + assert.expect(2); - this.render(``, { - actions: { - foo(value, event) { - assert.ok(true, 'action was triggered'); - assert.ok(event instanceof Event, 'Native event was passed'); - }, + this.render(``, { + foo(value, event) { + assert.ok(true, 'action was triggered'); + assert.ok(event instanceof Event, 'Native event was passed'); }, }); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js index f0c54952deb..ea0b55727a0 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js @@ -152,15 +152,12 @@ moduleFor( ['@test sends an action with `{{input enter=(action "foo")}}` when is pressed']( assert ) { - assert.expect(3); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - this.render(`{{input enter=(action 'foo')}}`, { - actions: { - foo(value, event) { - assert.ok(true, 'action was triggered'); - assert.ok(event instanceof Event, 'Native event was passed'); - }, + assert.expect(2); + + this.render(`{{input enter=this.foo}}`, { + foo(value, event) { + assert.ok(true, 'action was triggered'); + assert.ok(event instanceof Event, 'Native event was passed'); }, }); @@ -170,15 +167,12 @@ moduleFor( } ['@test sends `insert-newline` when is pressed'](assert) { - assert.expect(3); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - this.render(`{{input insert-newline=(action 'foo')}}`, { - actions: { - foo(value, event) { - assert.ok(true, 'action was triggered'); - assert.ok(event instanceof Event, 'Native event was passed'); - }, + assert.expect(2); + + this.render(`{{input insert-newline=this.foo}}`, { + foo(value, event) { + assert.ok(true, 'action was triggered'); + assert.ok(event instanceof Event, 'Native event was passed'); }, }); @@ -187,18 +181,15 @@ moduleFor( }); } - ['@test sends an action with `{{input escape-press=(action "foo")}}` when is pressed']( + ['@test sends an action with `{{input escape-press=this.foo}}` when is pressed']( assert ) { - assert.expect(3); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - this.render(`{{input escape-press=(action 'foo')}}`, { - actions: { - foo(value, event) { - assert.ok(true, 'action was triggered'); - assert.ok(event instanceof Event, 'Native event was passed'); - }, + assert.expect(2); + + this.render(`{{input escape-press=this.foo}}`, { + foo(value, event) { + assert.ok(true, 'action was triggered'); + assert.ok(event instanceof Event, 'Native event was passed'); }, }); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js deleted file mode 100644 index 542ff4c2646..00000000000 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js +++ /dev/null @@ -1,1065 +0,0 @@ -import { RenderingTestCase, moduleFor, strip, runTask } from 'internal-test-helpers'; - -import { _getCurrentRunLoop } from '@ember/runloop'; -import { set, computed } from '@ember/object'; - -import { Component } from '../../utils/helpers'; - -moduleFor( - 'Helpers test: closure {{action}}', - class extends RenderingTestCase { - ['@test action should be called']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let outerActionCalled = false; - let component; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - outerSubmit() { - outerActionCalled = true; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: '{{inner-component submit=(action this.outerSubmit)}}', - }); - - this.render('{{outer-component}}'); - - runTask(() => { - component.fireAction(); - }); - - this.assert.ok(outerActionCalled, 'the action was called'); - } - - ['@test an error is triggered when bound action function is undefined']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - this.registerComponent('inner-component', { - template: 'inner', - }); - this.registerComponent('outer-component', { - template: '{{inner-component submit=(action this.somethingThatIsUndefined)}}', - }); - - expectAssertion(() => { - this.render('{{outer-component}}'); - }, /Action passed is null or undefined in \(action[^)]*\) from .*\./); - } - - ['@test an error is triggered when bound action being passed in is a non-function']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - this.registerComponent('inner-component', { - template: 'inner', - }); - this.registerComponent('outer-component', { - ComponentClass: Component.extend({ - nonFunctionThing: {}, - }), - template: '{{inner-component submit=(action this.nonFunctionThing)}}', - }); - - expectAssertion(() => { - this.render('{{outer-component}}'); - }, /An action could not be made for `.*` in .*\. Please confirm that you are using either a quoted action name \(i\.e\. `\(action '.*'\)`\) or a function available in .*\./); - } - - ['@test [#12718] a nice error is shown when a bound action function is undefined and it is passed as @foo']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - this.registerComponent('inner-component', { - template: - '', - }); - - this.registerComponent('outer-component', { - template: '{{inner-component}}', - }); - - expectAssertion(() => { - this.render('{{outer-component}}'); - }, /Action passed is null or undefined in \(action[^)]*\) from .*\./); - } - - ['@test action value is returned']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let expectedValue = 'terrible tom'; - let returnedValue; - let innerComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - returnedValue = this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - outerSubmit() { - return expectedValue; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: '{{inner-component submit=(action this.outerSubmit)}}', - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(returnedValue, expectedValue, 'action can return to caller'); - } - - ['@test action should be called on the correct scope']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let innerComponent; - let outerComponent; - let actualComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - init() { - this._super(...arguments); - outerComponent = this; - }, - isOuterComponent: true, - outerSubmit() { - actualComponent = this; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: '{{inner-component submit=(action this.outerSubmit)}}', - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(actualComponent, outerComponent, 'action has the correct context'); - this.assert.ok(actualComponent.isOuterComponent, 'action has the correct context'); - } - - ['@test arguments to action are passed, curry']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let first = 'mitch'; - let second = 'martin'; - let third = 'matt'; - let fourth = 'wacky wycats'; - - let innerComponent; - let actualArgs; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(fourth); - }, - }); - - let OuterComponent = Component.extend({ - third, - outerSubmit() { - actualArgs = [...arguments]; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action (action this.outerSubmit "${first}") "${second}" this.third)}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.deepEqual( - actualArgs, - [first, second, third, fourth], - 'action has the correct args' - ); - } - - ['@test `this` can be passed as an argument']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let value = {}; - let component; - let innerComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - actions: { - outerAction(incomingValue) { - value = incomingValue; - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: '{{inner-component submit=(action "outerAction" this)}}', - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.strictEqual(value, component, 'the component is passed at `this`'); - } - - ['@test arguments to action are bound']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let value = 'lazy leah'; - - let innerComponent; - let outerComponent; - let actualArg; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - init() { - this._super(...arguments); - outerComponent = this; - }, - value: '', - outerSubmit(incomingValue) { - actualArg = incomingValue; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action this.outerSubmit this.value)}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.strictEqual(actualArg, '', 'action has the correct first arg'); - - runTask(() => { - outerComponent.set('value', value); - }); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.strictEqual(actualArg, value, 'action has the correct first arg'); - } - - ['@test array arguments are passed correctly to action']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let first = 'foo'; - let second = [3, 5]; - let third = [4, 9]; - - let actualFirst; - let actualSecond; - let actualThird; - - let innerComponent; - let outerComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(second, third); - }, - }); - - let OuterComponent = Component.extend({ - init() { - this._super(...arguments); - outerComponent = this; - }, - outerSubmit(incomingFirst, incomingSecond, incomingThird) { - actualFirst = incomingFirst; - actualSecond = incomingSecond; - actualThird = incomingThird; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action this.outerSubmit this.first)}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - outerComponent.set('first', first); - outerComponent.set('second', second); - }); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(actualFirst, first, 'action has the correct first arg'); - this.assert.equal(actualSecond, second, 'action has the correct second arg'); - this.assert.equal(actualThird, third, 'action has the correct third arg'); - } - - ['@test mut values can be wrapped in actions, are settable']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let newValue = 'trollin trek'; - - let innerComponent; - let outerComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(newValue); - }, - }); - - let OuterComponent = Component.extend({ - init() { - this._super(...arguments); - outerComponent = this; - }, - outerMut: 'patient peter', - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action (mut this.outerMut))}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(outerComponent.get('outerMut'), newValue, 'mut value is set'); - } - - ['@test mut values can be wrapped in actions, are settable with a curry']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let newValue = 'trollin trek'; - - let innerComponent; - let outerComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - init() { - this._super(...arguments); - outerComponent = this; - }, - outerMut: 'patient peter', - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action (mut this.outerMut) '${newValue}')}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(outerComponent.get('outerMut'), newValue, 'mut value is set'); - } - - ['@test action can create closures over actions']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let first = 'raging robert'; - let second = 'mild machty'; - let returnValue = 'butch brian'; - - let actualFirst; - let actualSecond; - let actualReturnedValue; - - let innerComponent; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - actualReturnedValue = this.attrs.submit(second); - }, - }); - - let OuterComponent = Component.extend({ - actions: { - outerAction(incomingFirst, incomingSecond) { - actualFirst = incomingFirst; - actualSecond = incomingSecond; - return returnValue; - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action 'outerAction' '${first}')}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(actualReturnedValue, returnValue, 'return value is present'); - this.assert.equal(actualFirst, first, 'first argument is correct'); - this.assert.equal(actualSecond, second, 'second argument is correct'); - } - - ['@test provides a helpful error if an action is not present']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let InnerComponent = Component.extend({}); - - let OuterComponent = Component.extend({ - actions: { - something() { - // this is present to ensure `actions` hash is present - // a different error is triggered if `actions` is missing - // completely - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action 'doesNotExist')}}`, - }); - - expectAssertion(() => { - this.render('{{outer-component}}'); - }, /An action named 'doesNotExist' was not found in /); - } - - ['@test provides a helpful error if actions hash is not present']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let InnerComponent = Component.extend({}); - - let OuterComponent = Component.extend({}); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action 'doesNotExist')}}`, - }); - - expectAssertion(() => { - this.render('{{outer-component}}'); - }, /An action named 'doesNotExist' was not found in /); - } - - ['@test action can create closures over actions with target']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let innerComponent; - let actionCalled = false; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - otherComponent: computed(function () { - return { - actions: { - outerAction() { - actionCalled = true; - }, - }, - }; - }), - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action 'outerAction' target=this.otherComponent)}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.ok(actionCalled, 'action called on otherComponent'); - } - - ['@test value can be used with action over actions']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let newValue = 'yelping yehuda'; - - let innerComponent; - let actualValue; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit({ - readProp: newValue, - }); - }, - }); - - let OuterComponent = Component.extend({ - outerContent: { - readProp: newValue, - }, - actions: { - outerAction(incomingValue) { - actualValue = incomingValue; - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action 'outerAction' value="readProp")}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(actualValue, newValue, 'value is read'); - } - - ['@test action will read the value of a first property']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let newValue = 'irate igor'; - - let innerComponent; - let actualValue; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit({ - readProp: newValue, - }); - }, - }); - - let OuterComponent = Component.extend({ - outerAction(incomingValue) { - actualValue = incomingValue; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action this.outerAction value="readProp")}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(actualValue, newValue, 'property is read'); - } - - ['@test action will read the value of a curried first argument property']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let newValue = 'kissing kris'; - - let innerComponent; - let actualValue; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - objectArgument: { - readProp: newValue, - }, - outerAction(incomingValue) { - actualValue = incomingValue; - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action this.outerAction this.objectArgument value="readProp")}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.equal(actualValue, newValue, 'property is read'); - } - - ['@test action closure does not get auto-mut wrapped'](assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let first = 'raging robert'; - let second = 'mild machty'; - let returnValue = 'butch brian'; - - let innerComponent; - let actualFirst; - let actualSecond; - let actualReturnedValue; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.get('submit')(second); - this.get('attrs-submit')(second); - let attrsSubmitReturnValue = this.attrs['attrs-submit'](second); - let submitReturnValue = this.attrs.submit(second); - - assert.equal( - attrsSubmitReturnValue, - submitReturnValue, - 'both attrs.foo and foo should behave the same' - ); - - return submitReturnValue; - }, - }); - - let MiddleComponent = Component.extend({}); - - let OuterComponent = Component.extend({ - actions: { - outerAction(incomingFirst, incomingSecond) { - actualFirst = incomingFirst; - actualSecond = incomingSecond; - return returnValue; - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('middle-component', { - ComponentClass: MiddleComponent, - template: `{{inner-component attrs-submit=@submit submit=this.submit}}`, - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{middle-component submit=(action 'outerAction' '${first}')}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - actualReturnedValue = innerComponent.fireAction(); - }); - - this.assert.equal(actualFirst, first, 'first argument is correct'); - this.assert.equal(actualSecond, second, 'second argument is correct'); - this.assert.equal(actualReturnedValue, returnValue, 'return value is present'); - } - - ['@test action should be called within a run loop']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let innerComponent; - let capturedRunLoop; - - let InnerComponent = Component.extend({ - init() { - this._super(...arguments); - innerComponent = this; - }, - fireAction() { - this.attrs.submit(); - }, - }); - - let OuterComponent = Component.extend({ - actions: { - submit() { - capturedRunLoop = _getCurrentRunLoop(); - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: 'inner', - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: `{{inner-component submit=(action 'submit')}}`, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - innerComponent.fireAction(); - }); - - this.assert.ok(capturedRunLoop, 'action is called within a run loop'); - } - - ['@test closure action with `(mut undefinedThing)` works properly [GH#13959]']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let component; - - let ExampleComponent = Component.extend({ - label: undefined, - init() { - this._super(...arguments); - component = this; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - '', - }); - - this.render('{{example-component}}'); - - this.assertText('Click me'); - - this.assertStableRerender(); - - runTask(() => { - this.$('button').click(); - }); - - this.assertText('Clicked!'); - - runTask(() => { - component.set('label', 'Dun clicked'); - }); - - this.assertText('Dun clicked'); - - runTask(() => { - this.$('button').click(); - }); - - this.assertText('Clicked!'); - - runTask(() => { - component.set('label', undefined); - }); - - this.assertText('Click me'); - } - - ['@test closure actions does not cause component hooks to fire unnecessarily [GH#14305] [GH#14654]']( - assert - ) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let clicked = 0; - let didReceiveAttrsFired = 0; - - let ClickMeComponent = Component.extend({ - tagName: 'button', - - click() { - this.get('onClick').call(undefined, ++clicked); - }, - - didReceiveAttrs() { - didReceiveAttrsFired++; - }, - }); - - this.registerComponent('click-me', { - ComponentClass: ClickMeComponent, - }); - - let outer; - - let OuterComponent = Component.extend({ - clicked: 0, - - actions: { - 'on-click': function () { - this.incrementProperty('clicked'); - }, - }, - - init() { - this._super(); - outer = this; - this.set('onClick', () => this.incrementProperty('clicked')); - }, - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: strip` -
clicked: {{this.clicked}}; foo: {{this.foo}}
- - {{click-me id="string-action" onClick=(action "on-click")}} - {{click-me id="function-action" onClick=(action this.onClick)}} - {{click-me id="mut-action" onClick=(action (mut this.clicked))}} - `, - }); - - this.render('{{outer-component foo=this.foo}}', { foo: 1 }); - - this.assertText('clicked: 0; foo: 1'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => this.rerender()); - - this.assertText('clicked: 0; foo: 1'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => set(this.context, 'foo', 2)); - - this.assertText('clicked: 0; foo: 2'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => this.$('#string-action').click()); - - this.assertText('clicked: 1; foo: 2'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => this.$('#function-action').click()); - - this.assertText('clicked: 2; foo: 2'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => - set(outer, 'onClick', function () { - outer.incrementProperty('clicked'); - }) - ); - - this.assertText('clicked: 2; foo: 2'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => this.$('#function-action').click()); - - this.assertText('clicked: 3; foo: 2'); - - assert.equal(didReceiveAttrsFired, 3); - - runTask(() => this.$('#mut-action').click()); - - this.assertText('clicked: 4; foo: 2'); - - assert.equal(didReceiveAttrsFired, 3); - } - } -); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js deleted file mode 100644 index 6a4d60bc2b6..00000000000 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js +++ /dev/null @@ -1,1670 +0,0 @@ -import { RenderingTestCase, moduleFor, strip, runTask } from 'internal-test-helpers'; - -import EmberObject, { set } from '@ember/object'; -import { A as emberA } from '@ember/array'; -import { ActionManager } from '@ember/-internals/views'; - -import { Component } from '../../utils/helpers'; - -function getActionAttributes(element) { - let attributes = element.attributes; - let actionAttrs = []; - - for (let i = 0; i < attributes.length; i++) { - let attr = attributes.item(i); - - if (attr.name.indexOf('data-ember-action-') === 0) { - actionAttrs.push(attr.name); - } - } - - return actionAttrs; -} - -function getActionIds(element) { - return getActionAttributes(element).map((attribute) => - attribute.slice('data-ember-action-'.length) - ); -} - -moduleFor( - 'Helpers test: element action', - class extends RenderingTestCase { - ['@test it can call an action on its enclosing component']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let fooCallCount = 0; - - let ExampleComponent = Component.extend({ - actions: { - foo() { - fooCallCount++; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '', - }); - - this.render('{{example-component}}'); - - this.assert.equal(fooCallCount, 0, 'foo has not been called'); - - runTask(() => this.rerender()); - - this.assert.equal(fooCallCount, 0, 'foo has not been called'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.equal(fooCallCount, 1, 'foo has been called 1 time'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.equal(fooCallCount, 2, 'foo has been called 2 times'); - } - - ['@test it can call an action with parameters']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let fooArgs = []; - let component; - - let ExampleComponent = Component.extend({ - member: 'a', - init() { - this._super(...arguments); - component = this; - }, - actions: { - foo(thing) { - fooArgs.push(thing); - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '', - }); - - this.render('{{example-component}}'); - - this.assert.deepEqual(fooArgs, [], 'foo has not been called'); - - runTask(() => this.rerender()); - - this.assert.deepEqual(fooArgs, [], 'foo has not been called'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.deepEqual(fooArgs, ['a'], 'foo has not been called'); - - runTask(() => { - component.set('member', 'b'); - }); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.deepEqual(fooArgs, ['a', 'b'], 'foo has been called with an updated value'); - } - - ['@test it should output a marker attribute with a guid']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - this.render(''); - - let button = this.$('button'); - - let attributes = getActionAttributes(button[0]); - - this.assert.ok( - button.attr('data-ember-action').match(''), - 'An empty data-ember-action attribute was added' - ); - this.assert.ok( - attributes[0].match(/data-ember-action-\d+/), - 'A data-ember-action-xyz attribute with a guid was added' - ); - } - - ['@test it should allow alternative events to be handled']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let showCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '
', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('#show').trigger('mouseup'); - }); - - this.assert.ok(showCalled, 'show action was called on mouseUp'); - } - - ['@test inside a yield, the target points at the original target']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let targetWatted = false; - let innerWatted = false; - - let TargetComponent = Component.extend({ - actions: { - wat() { - targetWatted = true; - }, - }, - }); - - let InnerComponent = Component.extend({ - actions: { - wat() { - innerWatted = true; - }, - }, - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: '{{yield}}', - }); - - this.registerComponent('target-component', { - ComponentClass: TargetComponent, - template: strip` - {{#inner-component}} - - {{/inner-component}} - `, - }); - - this.render('{{target-component}}'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.ok(targetWatted, 'the correct target was watted'); - this.assert.notOk(innerWatted, 'the inner target was not watted'); - } - - ['@test it should allow a target to be specified']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let targetWatted = false; - - let TargetComponent = Component.extend({ - actions: { - wat() { - targetWatted = true; - }, - }, - }); - - let OtherComponent = Component.extend({}); - - this.registerComponent('target-component', { - ComponentClass: TargetComponent, - template: '{{yield this}}', - }); - - this.registerComponent('other-component', { - ComponentClass: OtherComponent, - template: 'Wat?', - }); - - this.render(strip` - {{#target-component as |parent|}} - {{other-component anotherTarget=parent}} - {{/target-component}} - `); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.equal(targetWatted, true, 'the specified target was watted'); - } - - ['@test it should lazily evaluate the target']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let firstEdit = 0; - let secondEdit = 0; - let component; - - let first = { - edit() { - firstEdit++; - }, - }; - - let second = { - edit() { - secondEdit++; - }, - }; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - theTarget: first, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'Edit', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.equal(firstEdit, 1); - - runTask(() => { - set(component, 'theTarget', second); - }); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.equal(firstEdit, 1); - this.assert.equal(secondEdit, 1); - } - - ['@test it should register an event handler']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let shortcutHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - edit() { - editHandlerWasCalled = true; - }, - shortcut() { - shortcutHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - 'click me
click me too
', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a[data-ember-action]').trigger('click', { altKey: true }); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the event handler was called'); - - runTask(() => { - this.$('div[data-ember-action]').trigger('click', { ctrlKey: true }); - }); - - this.assert.equal( - shortcutHandlerWasCalled, - true, - 'the "any" shortcut\'s event handler was called' - ); - } - - ['@test it handles whitelisted bound modifier keys']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let shortcutHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - altKey: 'alt', - anyKey: 'any', - actions: { - edit() { - editHandlerWasCalled = true; - }, - shortcut() { - shortcutHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - 'click me
click me too
', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a[data-ember-action]').trigger('click', { altKey: true }); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the event handler was called'); - - runTask(() => { - this.$('div[data-ember-action]').trigger('click', { ctrlKey: true }); - }); - - this.assert.equal( - shortcutHandlerWasCalled, - true, - 'the "any" shortcut\'s event handler was called' - ); - } - - ['@test it handles whitelisted bound modifier keys with current value']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - acceptedKeys: 'alt', - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'click me', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a[data-ember-action]').trigger('click', { altKey: true }); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the event handler was called'); - - editHandlerWasCalled = false; - - runTask(() => { - component.set('acceptedKeys', ''); - }); - - runTask(() => { - this.$('div[data-ember-action]').click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the event handler was not called'); - } - - ['@test should be able to use action more than once for the same event within a view']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let deleteHandlerWasCalled = false; - let originalHandlerWasCalled = false; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - actions: { - edit() { - editHandlerWasCalled = true; - }, - delete() { - deleteHandlerWasCalled = true; - }, - }, - click() { - originalHandlerWasCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - 'editdelete', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('#edit').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the edit action was called'); - this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called'); - this.assert.equal( - originalHandlerWasCalled, - true, - 'the click handler was called (due to bubbling)' - ); - - editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - this.$('#delete').click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called'); - this.assert.equal(deleteHandlerWasCalled, true, 'the delete action was called'); - this.assert.equal( - originalHandlerWasCalled, - true, - 'the click handler was called (due to bubbling)' - ); - - editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - this.wrap(component.element).click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called'); - this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called'); - this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called'); - } - - ['@test the event should not bubble if `bubbles=false` is passed']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let deleteHandlerWasCalled = false; - let originalHandlerWasCalled = false; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - actions: { - edit() { - editHandlerWasCalled = true; - }, - delete() { - deleteHandlerWasCalled = true; - }, - }, - click() { - originalHandlerWasCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - 'editdelete', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('#edit').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the edit action was called'); - this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called'); - this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called'); - - editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - this.$('#delete').click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called'); - this.assert.equal(deleteHandlerWasCalled, true, 'the delete action was called'); - this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called'); - - editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - this.wrap(component.element).click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called'); - this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called'); - this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called'); - } - - ['@test the event should not bubble if `bubbles=false` is passed bound']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let deleteHandlerWasCalled = false; - let originalHandlerWasCalled = false; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - isFalse: false, - actions: { - edit() { - editHandlerWasCalled = true; - }, - delete() { - deleteHandlerWasCalled = true; - }, - }, - click() { - originalHandlerWasCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - 'editdelete', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('#edit').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the edit action was called'); - this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called'); - this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called'); - - editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - this.$('#delete').click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called'); - this.assert.equal(deleteHandlerWasCalled, true, 'the delete action was called'); - this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called'); - - editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - this.wrap(component.element).click(); - }); - - this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called'); - this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called'); - this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called'); - } - - ['@test the bubbling depends on the bound parameter']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let originalHandlerWasCalled = false; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - shouldBubble: false, - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - click() { - originalHandlerWasCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'edit', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('#edit').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the edit action was called'); - this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called'); - - editHandlerWasCalled = originalHandlerWasCalled = false; - - runTask(() => { - component.set('shouldBubble', true); - }); - - runTask(() => { - this.$('#edit').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the edit action was called'); - this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called'); - } - - ['@test multiple actions with bubbles=false for same event are called but prevent bubbling']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let clickAction1WasCalled = false; - let clickAction2WasCalled = false; - let eventHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - clicked1() { - clickAction1WasCalled = true; - }, - clicked2() { - clickAction2WasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: strip` - click me`, - click() { - eventHandlerWasCalled = true; - }, - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').trigger('click'); - }); - - this.assert.ok(clickAction1WasCalled, 'the first clicked action was called'); - this.assert.ok(clickAction2WasCalled, 'the second clicked action was called'); - this.assert.notOk(eventHandlerWasCalled, 'event did not bubble up'); - } - - ['@test it should work properly in an #each block']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - items: emberA([1, 2, 3, 4]), - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - '{{#each this.items as |item|}}click me{{/each}}', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the event handler was called'); - } - - ['@test it should work properly in a {{#let foo as |bar|}} block']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - something: { ohai: 'there' }, - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - '{{#let this.something as |somethingElse|}}click me{{/let}}', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.equal(editHandlerWasCalled, true, 'the event handler was called'); - } - - ['@test it should unregister event handlers when an element action is removed'](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let ExampleComponent = Component.extend({ - actions: { - edit() {}, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '{{#if this.isActive}}click me{{/if}}', - }); - - this.render('{{example-component isActive=this.isActive}}', { - isActive: true, - }); - - assert.equal(this.$('a[data-ember-action]').length, 1, 'The element is rendered'); - - let actionId; - - actionId = getActionIds(this.$('a[data-ember-action]')[0])[0]; - - assert.ok(ActionManager.registeredActions[actionId], 'An action is registered'); - - runTask(() => this.rerender()); - - assert.equal(this.$('a[data-ember-action]').length, 1, 'The element is still present'); - - assert.ok(ActionManager.registeredActions[actionId], 'The action is still registered'); - - runTask(() => set(this.context, 'isActive', false)); - - assert.strictEqual(this.$('a[data-ember-action]').length, 0, 'The element is removed'); - - assert.ok(!ActionManager.registeredActions[actionId], 'The action is unregistered'); - - runTask(() => set(this.context, 'isActive', true)); - - assert.equal(this.$('a[data-ember-action]').length, 1, 'The element is rendered'); - - actionId = getActionIds(this.$('a[data-ember-action]')[0])[0]; - - assert.ok(ActionManager.registeredActions[actionId], 'A new action is registered'); - } - - ['@test it should capture events from child elements and allow them to trigger the action']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '
', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.ok( - editHandlerWasCalled, - 'event on a child target triggered the action of its parent' - ); - } - - ['@test it should allow bubbling of events from action helper to original parent event']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let originalHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - click() { - originalHandlerWasCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'click me', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.ok( - editHandlerWasCalled && originalHandlerWasCalled, - 'both event handlers were called' - ); - } - - ['@test it should not bubble an event from action helper to original parent event if `bubbles=false` is passed']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - let originalHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - click() { - originalHandlerWasCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'click me', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.ok(editHandlerWasCalled, 'the child event handler was called'); - this.assert.notOk(originalHandlerWasCalled, 'the parent handler was not called'); - } - - ['@test it should allow "send" as the action name (#594)']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let sendHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - send() { - sendHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'click me', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.ok(sendHandlerWasCalled, 'the event handler was called'); - } - - ['@test it should send the view, event, and current context to the action']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let passedTarget; - let passedContext; - let targetThis; - - let TargetComponent = Component.extend({ - init() { - this._super(...arguments); - targetThis = this; - }, - actions: { - edit(context) { - passedTarget = this === targetThis; - passedContext = context; - }, - }, - }); - - let aContext; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - aContext = this; - }, - }); - - this.registerComponent('target-component', { - ComponentClass: TargetComponent, - template: '{{yield this}}', - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: strip` - {{#target-component as |aTarget|}} - click me - {{/target-component}} - `, - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('#edit').click(); - }); - - this.assert.ok(passedTarget, 'the action is called with the target as this'); - this.assert.strictEqual(passedContext, aContext, 'the parameter is passed along'); - } - - ['@test it should only trigger actions for the event they were registered on']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let editHandlerWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - edit() { - editHandlerWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'click me', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.ok(editHandlerWasCalled, 'the event handler was called on click'); - - editHandlerWasCalled = false; - - runTask(() => { - this.$('a').trigger('mouseover'); - }); - - this.assert.notOk(editHandlerWasCalled, 'the event handler was not called on mouseover'); - } - - ['@test it should allow multiple contexts to be specified']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let passedContexts; - let models = [EmberObject.create(), EmberObject.create()]; - - let ExampleComponent = Component.extend({ - modelA: models[0], - modelB: models[1], - actions: { - edit(...args) { - passedContexts = args; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.deepEqual( - passedContexts, - models, - 'the action was called with the passed contexts' - ); - } - - ['@test it should allow multiple contexts to be specified mixed with string args']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let passedContexts; - let model = EmberObject.create(); - - let ExampleComponent = Component.extend({ - model: model, - actions: { - edit(...args) { - passedContexts = args; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.deepEqual( - passedContexts, - ['herp', model], - 'the action was called with the passed contexts' - ); - } - - ['@test it should not trigger action with special clicks']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let showCalled = false; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '', - }); - - this.render('{{example-component}}'); - - let assert = this.assert; - - let checkClick = (prop, value, expected) => { - showCalled = false; - let event = this.wrap(component.element) - .findAll('button') - .trigger('click', { [prop]: value })[0]; - if (expected) { - assert.ok(showCalled, `should call action with ${prop}:${value}`); - assert.ok(event.defaultPrevented, 'should prevent default'); - } else { - assert.notOk(showCalled, `should not call action with ${prop}:${value}`); - assert.notOk(event.defaultPrevented, 'should not prevent default'); - } - }; - - checkClick('ctrlKey', true, false); - checkClick('altKey', true, false); - checkClick('metaKey', true, false); - checkClick('shiftKey', true, false); - - checkClick('button', 0, true); - checkClick('button', 1, false); - checkClick('button', 2, false); - checkClick('button', 3, false); - checkClick('button', 4, false); - } - - ['@test it can trigger actions for keyboard events']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let showCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('input').trigger('keyup', { char: 'a', which: 65 }); - }); - - this.assert.ok(showCalled, 'the action was called with keyup'); - } - - ['@test a quoteless parameter should allow dynamic lookup of the actionName']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let lastAction; - let actionOrder = []; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - hookMeUp: 'rock', - actions: { - rock() { - lastAction = 'rock'; - actionOrder.push('rock'); - }, - paper() { - lastAction = 'paper'; - actionOrder.push('paper'); - }, - scissors() { - lastAction = 'scissors'; - actionOrder.push('scissors'); - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'Whistle tips go woop woooop', - }); - - this.render('{{example-component}}'); - - let test = this; - - let testBoundAction = (propertyValue) => { - runTask(() => { - component.set('hookMeUp', propertyValue); - }); - - runTask(() => { - this.wrap(component.element).findAll('#bound-param').click(); - }); - - test.assert.ok(lastAction, propertyValue, `lastAction set to ${propertyValue}`); - }; - - testBoundAction('rock'); - testBoundAction('paper'); - testBoundAction('scissors'); - - this.assert.deepEqual( - actionOrder, - ['rock', 'paper', 'scissors'], - 'action name was looked up properly' - ); - } - - ['@test a quoteless string parameter should resolve actionName, including path']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let lastAction; - let actionOrder = []; - let component; - - let ExampleComponent = Component.extend({ - init() { - this._super(...arguments); - component = this; - }, - allactions: emberA([ - { title: 'Rock', name: 'rock' }, - { title: 'Paper', name: 'paper' }, - { title: 'Scissors', name: 'scissors' }, - ]), - actions: { - rock() { - lastAction = 'rock'; - actionOrder.push('rock'); - }, - paper() { - lastAction = 'paper'; - actionOrder.push('paper'); - }, - scissors() { - lastAction = 'scissors'; - actionOrder.push('scissors'); - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - '{{#each this.allactions as |allaction|}}{{allaction.title}}{{/each}}', - }); - - this.render('{{example-component}}'); - - let test = this; - - let testBoundAction = (propertyValue) => { - runTask(() => { - this.wrap(component.element).findAll(`#${propertyValue}`).click(); - }); - - test.assert.ok(lastAction, propertyValue, `lastAction set to ${propertyValue}`); - }; - - testBoundAction('rock'); - testBoundAction('paper'); - testBoundAction('scissors'); - - this.assert.deepEqual( - actionOrder, - ['rock', 'paper', 'scissors'], - 'action name was looked up properly' - ); - } - - ['@test a quoteless function parameter should be called, including arguments']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let submitCalled = false; - let incomingArg; - - let arg = 'rough ray'; - - let ExampleComponent = Component.extend({ - submit(actualArg) { - incomingArg = actualArg; - submitCalled = true; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: `Hi`, - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').click(); - }); - - this.assert.ok(submitCalled, 'submit function called'); - this.assert.equal(incomingArg, arg, 'argument passed'); - } - - ['@test a quoteless parameter that does not resolve to a value asserts']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let ExampleComponent = Component.extend({ - actions: { - ohNoeNotValid() {}, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'Hi', - }); - - expectAssertion(() => { - this.render('{{example-component}}'); - }, 'You specified a quoteless path, `this.ohNoeNotValid`, to the {{action}} helper ' + 'which did not resolve to an action name (a string). ' + 'Perhaps you meant to use a quoted actionName? (e.g. {{action "ohNoeNotValid"}}).'); - } - - ['@test allows multiple actions on a single element']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let clickActionWasCalled = false; - let doubleClickActionWasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - clicked() { - clickActionWasCalled = true; - }, - doubleClicked() { - doubleClickActionWasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: strip` - click me`, - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').trigger('click'); - }); - - this.assert.ok(clickActionWasCalled, 'the clicked action was called'); - - runTask(() => { - this.$('a').trigger('dblclick'); - }); - - this.assert.ok(doubleClickActionWasCalled, 'the doubleClicked action was called'); - } - - ['@test allows multiple actions for same event on a single element']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let clickAction1WasCalled = false; - let clickAction2WasCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - clicked1() { - clickAction1WasCalled = true; - }, - clicked2() { - clickAction2WasCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: strip` - click me`, - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('a').trigger('click'); - }); - - this.assert.ok(clickAction1WasCalled, 'the first clicked action was called'); - this.assert.ok(clickAction2WasCalled, 'the second clicked action was called'); - } - - ['@test it should respect preventDefault option if provided']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let ExampleComponent = Component.extend({ - actions: { - show() {}, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'Hi', - }); - - this.render('{{example-component}}'); - - let event; - - runTask(() => { - event = this.$('a').click()[0]; - }); - - this.assert.equal(event.defaultPrevented, false, 'should not preventDefault'); - } - - ['@test it should respect preventDefault option if provided bound']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let component; - - let ExampleComponent = Component.extend({ - shouldPreventDefault: false, - init() { - this._super(...arguments); - component = this; - }, - actions: { - show() {}, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: 'Hi', - }); - - this.render('{{example-component}}'); - - let event; - - runTask(() => { - event = this.$('a').trigger(event)[0]; - }); - - this.assert.equal(event.defaultPrevented, false, 'should not preventDefault'); - - runTask(() => { - component.set('shouldPreventDefault', true); - event = this.$('a').trigger('click')[0]; - }); - - this.assert.equal(event.defaultPrevented, true, 'should preventDefault'); - } - - ['@test it should target the proper component when `action` is in yielded block [GH #12409]']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - let outerActionCalled = false; - let innerClickCalled = false; - - let OuterComponent = Component.extend({ - actions: { - hey() { - outerActionCalled = true; - }, - }, - }); - - let MiddleComponent = Component.extend({}); - - let InnerComponent = Component.extend({ - click() { - innerClickCalled = true; - this.action(); - }, - }); - - this.registerComponent('outer-component', { - ComponentClass: OuterComponent, - template: strip` - {{#middle-component}} - {{inner-component action=(action "hey")}} - {{/middle-component}} - `, - }); - - this.registerComponent('middle-component', { - ComponentClass: MiddleComponent, - template: '{{yield}}', - }); - - this.registerComponent('inner-component', { - ComponentClass: InnerComponent, - template: strip` - - {{yield}} - `, - }); - - this.render('{{outer-component}}'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.ok(outerActionCalled, 'the action fired on the proper target'); - this.assert.ok(innerClickCalled, 'the click was triggered'); - } - - ['@test element action with (mut undefinedThing) works properly']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let component; - - let ExampleComponent = Component.extend({ - label: undefined, - init() { - this._super(...arguments); - component = this; - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - '', - }); - - this.render('{{example-component}}'); - - this.assertText('Click me'); - - this.assertStableRerender(); - - runTask(() => { - this.$('button').click(); - }); - - this.assertText('Clicked!'); - - runTask(() => { - component.set('label', 'Dun clicked'); - }); - - this.assertText('Dun clicked'); - - runTask(() => { - this.$('button').click(); - }); - - this.assertText('Clicked!'); - - runTask(() => { - component.set('label', undefined); - }); - - this.assertText('Click me'); - } - - ['@test it supports non-registered actions [GH#14888]']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - this.render( - ` - {{#if this.show}} - - {{/if}} - `, - { show: true } - ); - - this.assert.equal(this.$('button').text().trim(), 'Show (true)'); - // We need to focus in to simulate an actual click. - runTask(() => { - document.getElementById('ddButton').focus(); - document.getElementById('ddButton').click(); - }); - } - - ["@test action handler that shifts element attributes doesn't trigger multiple invocations"]() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - - let actionCount = 0; - let ExampleComponent = Component.extend({ - selected: false, - actions: { - toggleSelected() { - actionCount++; - this.toggleProperty('selected'); - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: - '', - }); - - this.render('{{example-component}}'); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.equal(actionCount, 1, 'Click action only fired once.'); - this.assert.ok( - this.$('button').hasClass('selected'), - "Element with action handler has properly updated it's conditional class" - ); - - runTask(() => { - this.$('button').click(); - }); - - this.assert.equal(actionCount, 2, 'Second click action only fired once.'); - this.assert.ok( - !this.$('button').hasClass('selected'), - "Element with action handler has properly updated it's conditional class" - ); - } - } -); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js index 7c132026a98..f0c77893cdc 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js @@ -36,52 +36,6 @@ moduleFor( // No U-R } - '@test passing an action to {{readonly}} avoids mutable cell wrapping'(assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - assert.expect(5); - let outer, inner; - - this.registerComponent('x-inner', { - ComponentClass: Component.extend({ - init() { - this._super(...arguments); - inner = this; - }, - }), - }); - - this.registerComponent('x-outer', { - ComponentClass: Component.extend({ - init() { - this._super(...arguments); - outer = this; - }, - }), - template: '{{x-inner onClick=(readonly this.onClick)}}', - }); - - this.render('{{x-outer onClick=(action this.doIt)}}', { - doIt() { - assert.ok(true, 'action was called'); - }, - }); - - assert.equal( - typeof outer.attrs.onClick, - 'function', - 'function itself is present in outer component attrs' - ); - outer.attrs.onClick(); - - assert.equal( - typeof inner.attrs.onClick, - 'function', - 'function itself is present in inner component attrs' - ); - inner.attrs.onClick(); - } - '@test updating a {{readonly}} property from above works'(assert) { let component; diff --git a/packages/@ember/-internals/glimmer/tests/integration/input-test.js b/packages/@ember/-internals/glimmer/tests/integration/input-test.js index 2ca32fe77ee..c0efd27c47f 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/input-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/input-test.js @@ -201,34 +201,16 @@ moduleFor( this.assertValue('hola', 'Value is used'); } - ['@test GH18211 input checked attribute, without a value, works with the action helper']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.render(``, { - actions: { someAction() {} }, - }); - this.assertPropertyHasValue('checked', true); - } - - ['@test GH18211 input checked attribute, with a value, works with the action helper']() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.render(``, { - actions: { someAction() {} }, - }); - this.assertPropertyHasValue('checked', true); - } - ['@test GH18211 input checked attribute, without a value, works with attributes with values']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - this.render(``, { - actions: { someAction() {} }, + this.render(``, { + someAction() {}, }); this.assertPropertyHasValue('checked', true); } ['@test GH18211 input checked attribute, without a value, works with event attributes']() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - this.render(``, { - actions: { someAction() {} }, + this.render(``, { + someAction() {}, }); this.assertPropertyHasValue('checked', true); } diff --git a/packages/@ember/-internals/views/index.ts b/packages/@ember/-internals/views/index.ts index b103f9f0550..bd82ffc6897 100644 --- a/packages/@ember/-internals/views/index.ts +++ b/packages/@ember/-internals/views/index.ts @@ -24,4 +24,3 @@ export { default as ViewStateSupport } from './lib/mixins/view_state_support'; export { default as ViewMixin } from './lib/mixins/view_support'; export { default as ActionSupport } from './lib/mixins/action_support'; export { MUTABLE_CELL } from './lib/compat/attrs'; -export { default as ActionManager } from './lib/system/action_manager'; diff --git a/packages/@ember/-internals/views/lib/system/action_manager.ts b/packages/@ember/-internals/views/lib/system/action_manager.ts deleted file mode 100644 index 430701cbcb0..00000000000 --- a/packages/@ember/-internals/views/lib/system/action_manager.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { ActionState } from '@ember/-internals/glimmer/lib/modifiers/action'; - -/** -@module ember -*/ - -export default function ActionManager() {} - -/** - Global action id hash. - - @private - @property registeredActions - @type Object -*/ -ActionManager.registeredActions = {} as Record; diff --git a/packages/@ember/-internals/views/lib/system/event_dispatcher.ts b/packages/@ember/-internals/views/lib/system/event_dispatcher.ts index 1e281c9bcaf..4d328839d1e 100644 --- a/packages/@ember/-internals/views/lib/system/event_dispatcher.ts +++ b/packages/@ember/-internals/views/lib/system/event_dispatcher.ts @@ -2,11 +2,7 @@ import { getOwner } from '@ember/-internals/owner'; import { assert } from '@ember/debug'; import { get, set } from '@ember/-internals/metal'; import EmberObject from '@ember/object'; -import { getElementView } from '@ember/-internals/views'; -import ActionManager from './action_manager'; import type { BootEnvironment } from '@ember/-internals/glimmer/lib/views/outlet'; -import type Component from '@ember/component'; -import type { ActionState } from '@ember/-internals/glimmer/lib/modifiers/action'; /** @module ember @@ -253,66 +249,6 @@ export default class EventDispatcher extends EmberObject { return; // nothing to do } - let viewHandler = (target: Element, event: Event) => { - let view = getElementView(target); - let result = true; - - if (view) { - // SAFETY: As currently written, this is not safe. Though it seems to always be true. - result = (view as Component).handleEvent(eventName, event); - } - - return result; - }; - - let actionHandler = (target: Element, event: Event) => { - let actionId = target.getAttribute('data-ember-action'); - let actions: Array | undefined; - - // In Glimmer2 this attribute is set to an empty string and an additional - // attribute it set for each action on a given element. In this case, the - // attributes need to be read so that a proper set of action handlers can - // be coalesced. - if (actionId === '') { - actions = []; - - for (let attr of target.attributes) { - let attrName = attr.name; - - if (attrName.indexOf('data-ember-action-') === 0) { - let action = ActionManager.registeredActions[attr.value]; - assert('[BUG] Missing action', action); - actions.push(action); - } - } - } else if (actionId) { - // FIXME: This branch is never called in tests. Improve tests or remove - let actionState = ActionManager.registeredActions[actionId]; - if (actionState) { - actions = [actionState]; - } - } - - // We have to check for actions here since in some cases, jQuery will trigger - // an event on `removeChild` (i.e. focusout) after we've already torn down the - // action handlers for the view. - if (!actions) { - // FIXME: This branch is never called in tests. Improve tests or remove - return; - } - - let result = true; - for (let index = 0; index < actions.length; index++) { - let action = actions[index]; - - if (action && action.eventName === eventName) { - // return false if any of the action handlers returns false - result = action.handler(event) && result; - } - } - return result; - }; - let handleEvent = (this._eventHandlers[event] = (event: Event) => { let target = event.target; @@ -320,27 +256,6 @@ export default class EventDispatcher extends EmberObject { `[BUG] Received event without an Element target: ${event.type}, ${target}`, target instanceof Element ); - - do { - if (getElementView(target)) { - if (viewHandler(target, event) === false) { - event.preventDefault(); - event.stopPropagation(); - break; - } else if (event.cancelBubble === true) { - break; - } - } else if ( - typeof target.hasAttribute === 'function' && - target.hasAttribute('data-ember-action') - ) { - if (actionHandler(target, event) === false) { - break; - } - } - - target = target.parentNode; - } while (target instanceof Element); }); rootElement.addEventListener(event, handleEvent); diff --git a/packages/@ember/object/tests/action_test.js b/packages/@ember/object/tests/action_test.js index c246585ea18..806893c06f0 100644 --- a/packages/@ember/object/tests/action_test.js +++ b/packages/@ember/object/tests/action_test.js @@ -6,8 +6,6 @@ moduleFor( '@action decorator', class extends RenderingTestCase { '@test action decorator works with ES6 class'(assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - class FooComponent extends Component { @action foo() { @@ -17,7 +15,7 @@ moduleFor( this.registerComponent('foo-bar', { ComponentClass: FooComponent, - template: "", + template: "", }); this.render('{{foo-bar}}'); @@ -51,14 +49,11 @@ moduleFor( } '@test actions are properly merged through traditional and ES6 prototype hierarchy'(assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - assert.expect(5); + assert.expect(4); let FooComponent = Component.extend({ - actions: { - foo() { - assert.ok(true, 'foo called!'); - }, + foo() { + assert.ok(true, 'foo called!'); }, }); @@ -70,10 +65,8 @@ moduleFor( } let BazComponent = BarComponent.extend({ - actions: { - baz() { - assert.ok(true, 'baz called!'); - }, + baz() { + assert.ok(true, 'baz called!'); }, }); @@ -87,10 +80,10 @@ moduleFor( this.registerComponent('qux-component', { ComponentClass: QuxComponent, template: strip` - - - - + + + + `, }); @@ -100,8 +93,6 @@ moduleFor( } '@test action decorator super works with native class methods'(assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - class FooComponent extends Component { foo() { assert.ok(true, 'called!'); @@ -117,7 +108,7 @@ moduleFor( this.registerComponent('bar-bar', { ComponentClass: BarComponent, - template: "", + template: "", }); this.render('{{bar-bar}}'); @@ -126,8 +117,6 @@ moduleFor( } '@test action decorator super works with traditional class methods'(assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let FooComponent = Component.extend({ foo() { assert.ok(true, 'called!'); @@ -143,7 +132,7 @@ moduleFor( this.registerComponent('bar-bar', { ComponentClass: BarComponent, - template: "", + template: "", }); this.render('{{bar-bar}}'); @@ -169,7 +158,7 @@ moduleFor( this.registerComponent('bar-bar', { ComponentClass: BarComponent, - template: "", + template: "", }); this.render('{{bar-bar}}'); @@ -246,8 +235,6 @@ moduleFor( } '@test action decorator can be used as a classic decorator with strings'(assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let FooComponent = Component.extend({ foo: action(function () { assert.ok(true, 'called!'); @@ -256,7 +243,7 @@ moduleFor( this.registerComponent('foo-bar', { ComponentClass: FooComponent, - template: "", + template: "", }); this.render('{{foo-bar}}'); diff --git a/packages/ember/tests/component_context_test.js b/packages/ember/tests/component_context_test.js index 884c3370449..cfa87f5bc10 100644 --- a/packages/ember/tests/component_context_test.js +++ b/packages/ember/tests/component_context_test.js @@ -186,13 +186,12 @@ moduleFor( ['@test Components trigger actions in the parents context when called from within a block']( assert ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'application', `
{{#my-component}} - Fizzbuzz + Fizzbuzz {{/my-component}}
` @@ -201,10 +200,8 @@ moduleFor( this.add( 'controller:application', Controller.extend({ - actions: { - fizzbuzz() { - assert.ok(true, 'action triggered on parent'); - }, + fizzbuzz() { + assert.ok(true, 'action triggered on parent'); }, }) ); @@ -220,7 +217,6 @@ moduleFor( ['@test Components trigger actions in the components context when called from within its template']( assert ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'application', ` @@ -231,22 +227,18 @@ moduleFor( this.add( 'controller:application', Controller.extend({ - actions: { - fizzbuzz() { - assert.ok(false, 'action on the wrong context'); - }, + fizzbuzz() { + assert.ok(false, 'action on the wrong context'); }, }) ); this.addComponent('my-component', { ComponentClass: Component.extend({ - actions: { - fizzbuzz() { - assert.ok(true, 'action triggered on component'); - }, + fizzbuzz() { + assert.ok(true, 'action triggered on component'); }, }), - template: `Fizzbuzz`, + template: `Fizzbuzz`, }); return this.visit('/').then(() => { diff --git a/packages/ember/tests/controller_test.js b/packages/ember/tests/controller_test.js deleted file mode 100644 index 1b8ea9c02f6..00000000000 --- a/packages/ember/tests/controller_test.js +++ /dev/null @@ -1,45 +0,0 @@ -import Controller from '@ember/controller'; -import { moduleFor, ApplicationTestCase, runTask } from 'internal-test-helpers'; -import { Component } from '@ember/-internals/glimmer'; - -/* - In Ember 1.x, controllers subtly affect things like template scope - and action targets in exciting and often inscrutable ways. This test - file contains integration tests that verify the correct behavior of - the many parts of the system that change and rely upon controller scope, - from the runtime up to the templating layer. -*/ - -moduleFor( - 'Template scoping examples', - class extends ApplicationTestCase { - ['@test Actions inside an outlet go to the associated controller'](assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - this.add( - 'controller:index', - Controller.extend({ - actions: { - componentAction() { - assert.ok(true, 'controller received the action'); - }, - }, - }) - ); - - this.addComponent('component-with-action', { - ComponentClass: Component.extend({ - classNames: ['component-with-action'], - click() { - this.action(); - }, - }), - }); - - this.addTemplate('index', '{{component-with-action action=(action "componentAction")}}'); - - return this.visit('/').then(() => { - runTask(() => this.$('.component-with-action').click()); - }); - } - } -); diff --git a/packages/ember/tests/routing/decoupled_basic_test.js b/packages/ember/tests/routing/decoupled_basic_test.js index 6827b87c429..55a05c928ab 100644 --- a/packages/ember/tests/routing/decoupled_basic_test.js +++ b/packages/ember/tests/routing/decoupled_basic_test.js @@ -305,7 +305,6 @@ moduleFor( async ['@test Events are triggered on the controller if a matching action name is implemented']( assert ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let done = assert.async(); this.router.map(function () { @@ -322,24 +321,20 @@ moduleFor( return model; }, - actions: { - showStuff() { - stateIsNotCalled = false; - }, + showStuff() { + stateIsNotCalled = false; }, }) ); - this.addTemplate('home', '{{this.name}}'); + this.addTemplate('home', '{{this.name}}'); this.add( 'controller:home', Controller.extend({ - actions: { - showStuff(context) { - assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); - assert.deepEqual(context, { name: 'Tom Dale' }, 'an event with context is passed'); - done(); - }, + showStuff(context) { + assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); + assert.deepEqual(context, { name: 'Tom Dale' }, 'an event with context is passed'); + done(); }, }) ); From 64a839e9493a00cd97a461e1c19a4328b7085653 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 9 Mar 2024 16:08:22 -0500 Subject: [PATCH 5/6] lints --- .../tests/routing/decoupled_basic_test.js | 283 ------------------ 1 file changed, 283 deletions(-) diff --git a/packages/ember/tests/routing/decoupled_basic_test.js b/packages/ember/tests/routing/decoupled_basic_test.js index 55a05c928ab..cd5a6783fc5 100644 --- a/packages/ember/tests/routing/decoupled_basic_test.js +++ b/packages/ember/tests/routing/decoupled_basic_test.js @@ -17,7 +17,6 @@ import { } from 'internal-test-helpers'; import { run } from '@ember/runloop'; import { addObserver } from '@ember/-internals/metal'; -import Mixin from '@ember/object/mixin'; import { service } from '@ember/service'; import Engine from '@ember/engine'; import { InternalTransition as Transition } from 'router_js'; @@ -344,236 +343,6 @@ moduleFor( document.getElementById('qunit-fixture').querySelector('a').click(); } - async ['@test Events are triggered on the current state when defined in `actions` object']( - assert - ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let done = assert.async(); - - this.router.map(function () { - this.route('home', { path: '/' }); - }); - - let model = { name: 'Tom Dale' }; - let HomeRoute = Route.extend({ - model() { - return model; - }, - - actions: { - showStuff(obj) { - assert.ok(this instanceof HomeRoute, 'the handler is an App.HomeRoute'); - assert.deepEqual( - Object.assign({}, obj), - { name: 'Tom Dale' }, - 'the context is correct' - ); - done(); - }, - }, - }); - - this.add('route:home', HomeRoute); - this.addTemplate('home', '{{@model.name}}'); - - await this.visit('/'); - - document.getElementById('qunit-fixture').querySelector('a').click(); - } - - async ['@test Events defined in `actions` object are triggered on the current state when routes are nested']( - assert - ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let done = assert.async(); - - this.router.map(function () { - this.route('root', { path: '/' }, function () { - this.route('index', { path: '/' }); - }); - }); - - let model = { name: 'Tom Dale' }; - - let RootRoute = Route.extend({ - actions: { - showStuff(obj) { - assert.ok(this instanceof RootRoute, 'the handler is an App.HomeRoute'); - assert.deepEqual( - Object.assign({}, obj), - { name: 'Tom Dale' }, - 'the context is correct' - ); - done(); - }, - }, - }); - this.add('route:root', RootRoute); - this.add( - 'route:root.index', - Route.extend({ - model() { - return model; - }, - }) - ); - - this.addTemplate('root.index', '{{@model.name}}'); - - await this.visit('/'); - - document.getElementById('qunit-fixture').querySelector('a').click(); - } - - ['@test Events can be handled by inherited event handlers'](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - assert.expect(5); - - let SuperRoute = Route.extend({ - actions: { - foo() { - assert.ok(true, 'foo'); - }, - bar(msg) { - assert.equal(msg, 'HELLO', 'bar hander in super route'); - }, - }, - }); - - let RouteMixin = Mixin.create({ - actions: { - bar(msg) { - assert.equal(msg, 'HELLO', 'bar handler in mixin'); - this._super(msg); - }, - }, - }); - - this.add( - 'route:home', - SuperRoute.extend(RouteMixin, { - actions: { - baz() { - assert.ok(true, 'baz', 'baz hander in route'); - }, - }, - }) - ); - this.addTemplate( - 'home', - ` - Do foo - Do bar with arg - Do bar - ` - ); - - return this.visit('/').then(() => { - let rootElement = document.getElementById('qunit-fixture'); - rootElement.querySelector('.do-foo').click(); - rootElement.querySelector('.do-bar-with-arg').click(); - rootElement.querySelector('.do-baz').click(); - }); - } - - async ['@test Actions are not triggered on the controller if a matching action name is implemented as a method']( - assert - ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let done = assert.async(); - - this.router.map(function () { - this.route('home', { path: '/' }); - }); - - let model = { name: 'Tom Dale' }; - let stateIsNotCalled = true; - - this.add( - 'route:home', - Route.extend({ - model() { - return model; - }, - - actions: { - showStuff(context) { - assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); - assert.deepEqual(context, { name: 'Tom Dale' }, 'an event with context is passed'); - done(); - }, - }, - }) - ); - - this.addTemplate('home', '{{this.name}}'); - - this.add( - 'controller:home', - Controller.extend({ - showStuff() { - stateIsNotCalled = false; - assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); - }, - }) - ); - - await this.visit('/'); - - document.getElementById('qunit-fixture').querySelector('a').click(); - } - - async ['@test actions can be triggered with multiple arguments'](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let done = assert.async(); - this.router.map(function () { - this.route('root', { path: '/' }, function () { - this.route('index', { path: '/' }); - }); - }); - - let model1 = { name: 'Tilde' }; - let model2 = { name: 'Tom Dale' }; - - let RootRoute = Route.extend({ - actions: { - showStuff(obj1, obj2) { - assert.ok(this instanceof RootRoute, 'the handler is an App.HomeRoute'); - assert.deepEqual( - Object.assign({}, obj1), - { name: 'Tilde' }, - 'the first context is correct' - ); - assert.deepEqual( - Object.assign({}, obj2), - { name: 'Tom Dale' }, - 'the second context is correct' - ); - done(); - }, - }, - }); - - this.add('route:root', RootRoute); - - this.add( - 'controller:root.index', - Controller.extend({ - model1: model1, - model2: model2, - }) - ); - - this.addTemplate( - 'root.index', - '{{this.model1.name}}' - ); - - await this.visit('/'); - - document.getElementById('qunit-fixture').querySelector('a').click(); - } - ['@test transitioning multiple times in a single run loop only sets the URL once'](assert) { this.router.map(function () { this.route('root', { path: '/' }); @@ -1222,58 +991,6 @@ moduleFor( return this.visit('/nork').then(() => this.visit('/dork')); } - ['@test Actions can be handled by inherited action handlers'](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - assert.expect(5); - - let SuperRoute = Route.extend({ - actions: { - foo() { - assert.ok(true, 'foo'); - }, - bar(msg) { - assert.equal(msg, 'HELLO'); - }, - }, - }); - - let RouteMixin = Mixin.create({ - actions: { - bar(msg) { - assert.equal(msg, 'HELLO'); - this._super(msg); - }, - }, - }); - - this.add( - 'route:home', - SuperRoute.extend(RouteMixin, { - actions: { - baz() { - assert.ok(true, 'baz'); - }, - }, - }) - ); - - this.addTemplate( - 'home', - ` - Do foo - Do bar with arg - Do bar - ` - ); - - return this.visit('/').then(() => { - let rootElement = document.getElementById('qunit-fixture'); - rootElement.querySelector('.do-foo').click(); - rootElement.querySelector('.do-bar-with-arg').click(); - rootElement.querySelector('.do-baz').click(); - }); - } - ['@test transitionTo returns Transition when passed a route name'](assert) { assert.expect(1); From 76bdcb62c5e3a56bd6421f3165ac32342050cf59 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:41:57 -0500 Subject: [PATCH 6/6] updates --- .../components/contextual-components-test.js | 28 ++++------- .../components/input-angle-test.js | 15 +++--- .../components/link-to/routing-angle-test.js | 3 +- .../components/link-to/routing-curly-test.js | 4 +- .../integration/components/tracked-test.js | 48 +++++-------------- .../integration/components/utils-test.js | 12 ++--- .../integration/event-dispatcher-test.js | 7 +-- .../tests/integration/helpers/fn-test.js | 3 +- .../tests/integration/helpers/tracked-test.js | 12 ++--- .../@ember/application/tests/visit_test.js | 9 ++-- .../tests/integration/multiple-app-test.js | 11 ++--- .../ember/tests/routing/query_params_test.js | 11 ++--- 12 files changed, 50 insertions(+), 113 deletions(-) diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js index 6ebc290b8c4..2b3dc653ee3 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js @@ -757,8 +757,6 @@ moduleFor( } ['@test renders with dot path and updates attributes'](assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - this.registerComponent('my-nested-component', { ComponentClass: Component.extend({ didReceiveAttrs() { @@ -775,10 +773,8 @@ moduleFor( this.registerComponent('my-action-component', { ComponentClass: Component.extend({ - actions: { - changeValue() { - this.incrementProperty('myProp'); - }, + changeValue() { + this.incrementProperty('myProp'); }, }), template: strip` @@ -786,7 +782,7 @@ moduleFor( {{api.my-nested-component}} {{/my-component}}
- `, + `, }); this.render('{{my-action-component myProp=this.model.myProp}}', { @@ -841,15 +837,12 @@ moduleFor( ['@test parameters in a contextual component are mutable when value is a param'](assert) { // This checks that a `(mut)` is added to parameters and attributes to // contextual components when it is a param. - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.registerComponent('change-button', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['val'], }), template: strip` - `, }); @@ -893,19 +886,16 @@ moduleFor( } ['@test GH#13494 tagless blockless component with property binding'](assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); this.registerComponent('outer-component', { ComponentClass: Component.extend({ message: 'hello', - actions: { - change() { - this.set('message', 'goodbye'); - }, + change() { + this.set('message', 'goodbye'); }, }), template: strip` message: {{this.message}}{{inner-component message=this.message}} - `, }); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js index 6e31685e8af..08041ea29e5 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js @@ -299,14 +299,11 @@ moduleFor( ['@test sends `insert-newline` when is pressed'](assert) { assert.expect(3); - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - - this.render(``, { - actions: { - foo(value, event) { - assert.ok(true, 'action was triggered'); - assert.ok(event instanceof Event, 'Native event was passed'); - }, + + this.render(``, { + foo(value, event) { + assert.ok(true, 'action was triggered'); + assert.ok(event instanceof Event, 'Native event was passed'); }, }); @@ -315,7 +312,7 @@ moduleFor( }); } - ['@test sends an action with `` when is pressed']( + ['@test sends an action with `` when is pressed']( assert ) { assert.expect(2); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js index 687a2175187..e0b50279cb3 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js @@ -1027,11 +1027,10 @@ moduleFor( } async ['@test it defaults to bubbling'](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'about', ` -
+
About
{{outlet}} diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js index 9a966144be3..ab1d8e0a9e1 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js @@ -1097,12 +1097,10 @@ moduleFor( } async ['@test it defaults to bubbling'](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.addTemplate( 'about', ` -
+
{{#link-to route='about.contact'}}About{{/link-to}}
{{outlet}} diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js index ec0784cf567..1975a167925 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js @@ -136,8 +136,6 @@ moduleFor( } '@test tracked properties that are uninitialized do not throw an error'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let CountComponent = Component.extend({ count: tracked(), @@ -151,7 +149,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -164,8 +162,6 @@ moduleFor( } '@test tracked properties rerender when updated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let CountComponent = Component.extend({ count: tracked({ value: 0 }), @@ -176,7 +172,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -189,8 +185,6 @@ moduleFor( } '@test tracked properties rerender when updated outside of a runloop'(assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let done = assert.async(); let CountComponent = Component.extend({ @@ -205,7 +199,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -222,8 +216,6 @@ moduleFor( } '@test nested tracked properties rerender when updated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let Counter = EmberObject.extend({ count: tracked({ value: 0 }), }); @@ -238,7 +230,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -251,8 +243,6 @@ moduleFor( } '@test array properties rerender when updated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let NumListComponent = Component.extend({ numbers: tracked({ initializer: () => A([1, 2, 3]) }), @@ -264,7 +254,7 @@ moduleFor( this.registerComponent('num-list', { ComponentClass: NumListComponent, template: strip` - `, @@ -280,8 +270,6 @@ moduleFor( } '@test getters update when dependent properties are invalidated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let CountComponent = Component.extend({ count: tracked({ value: 0 }), @@ -298,7 +286,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -311,8 +299,6 @@ moduleFor( } '@test getters update when dependent computeds are invalidated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let CountComponent = Component.extend({ _count: 0, @@ -337,7 +323,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -354,8 +340,6 @@ moduleFor( } '@test nested getters update when dependent properties are invalidated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let Counter = EmberObject.extend({ count: tracked({ value: 0 }), @@ -376,7 +360,7 @@ moduleFor( this.registerComponent('counter', { ComponentClass: CountComponent, - template: '', + template: '', }); this.render(''); @@ -389,8 +373,6 @@ moduleFor( } '@test tracked object passed down through components updates correctly'(assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - let Person = EmberObject.extend({ first: tracked({ value: 'Rob' }), last: tracked({ value: 'Jackson' }), @@ -425,7 +407,7 @@ moduleFor( ComponentClass: ChildComponent, template: strip`
{{this.person.full}}
- + `, }); @@ -441,8 +423,6 @@ moduleFor( } '@test yielded getters update correctly'() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - let PersonComponent = Component.extend({ first: tracked({ value: 'Rob' }), last: tracked({ value: 'Jackson' }), @@ -462,7 +442,7 @@ moduleFor( this.registerComponent('person', { ComponentClass: PersonComponent, template: strip` - {{yield this.full (action this.updatePerson)}} + {{yield this.full this.updatePerson}} `, }); @@ -482,8 +462,6 @@ moduleFor( } '@test yielded nested getters update correctly'() { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - let Person = EmberObject.extend({ first: tracked({ value: 'Rob' }), last: tracked({ value: 'Jackson' }), @@ -507,7 +485,7 @@ moduleFor( this.registerComponent('person', { ComponentClass: PersonComponent, template: strip` - {{yield this.person (action this.updatePerson)}} + {{yield this.person this.updatePerson}} `, }); @@ -609,8 +587,6 @@ moduleFor( '@test downstream property changes do not invalidate upstream component getters/arguments'( assert ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - let outerRenderCount = 0; let innerRenderCount = 0; @@ -641,7 +617,7 @@ moduleFor( this.registerComponent('inner', { ComponentClass: InnerComponent, - template: '', + template: '', }); this.render('', { diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js index b9626ad58a9..37039f85534 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js @@ -42,15 +42,11 @@ moduleFor( let ToggleController = Controller.extend({ isExpanded: true, - actions: { - toggle: function () { - this.toggleProperty('isExpanded'); - }, + toggle: function () { + this.toggleProperty('isExpanded'); }, }); - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); - this.add('controller:application', ToggleController); this.addTemplate( @@ -66,7 +62,7 @@ moduleFor( {{/x-toggle}} {{/x-toggle}} - + {{#if this.isExpanded}} {{x-toggle id="root-3"}} @@ -96,7 +92,7 @@ moduleFor( {{/x-toggle}} {{/x-toggle}} - + {{#if this.isExpanded}} {{x-toggle id="root-6"}} diff --git a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js index cac044c9504..02a9263b2d1 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js @@ -134,8 +134,6 @@ moduleFor( } ['@test case insensitive events'](assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - let receivedEvent; this.registerComponent('x-bar', { @@ -144,7 +142,7 @@ moduleFor( receivedEvent = event; }, }), - template: ``, + template: ``, }); this.render(`{{x-bar}}`); @@ -155,7 +153,6 @@ moduleFor( } ['@test case sensitive events'](assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); let receivedEvent; this.registerComponent('x-bar', { @@ -164,7 +161,7 @@ moduleFor( receivedEvent = event; }, }), - template: ``, + template: ``, }); this.render(`{{x-bar}}`); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js index 67118b5a1e9..759b3ebb80f 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/fn-test.js @@ -135,8 +135,7 @@ moduleFor( } '@test can use `this` if bound prior to passing to fn'(assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); - this.render(`{{stash stashedFn=(fn (action this.myFunc) this.arg1)}}`, { + this.render(`{{stash stashedFn=(fn (fn this.myFunc) this.arg1)}}`, { myFunc(arg1) { return `arg1: ${arg1}, arg2: ${this.arg2}`; }, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js index 7d97a452c25..ba59a4dbbde 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js @@ -15,7 +15,6 @@ moduleFor( 'Helper Tracked Properties', class extends RenderingTestCase { '@test tracked properties rerender when updated'(assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); let computeCount = 0; let PersonComponent = Component.extend({ @@ -29,7 +28,7 @@ moduleFor( this.registerComponent('person', { ComponentClass: PersonComponent, template: strip` - `, @@ -93,7 +92,6 @@ moduleFor( } '@test getters update when dependent properties are invalidated'(assert) { - expectDeprecation(/Usage of the `\(action\)` helper is deprecated./); let computeCount = 0; let PersonComponent = Component.extend({ @@ -115,7 +113,7 @@ moduleFor( this.registerComponent('person', { ComponentClass: PersonComponent, template: strip` - `, @@ -146,7 +144,6 @@ moduleFor( } '@test array properties rerender when updated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let NumListComponent = Component.extend({ numbers: tracked({ initializer: () => A([1, 2, 3]) }), @@ -158,7 +155,7 @@ moduleFor( this.registerComponent('num-list', { ComponentClass: NumListComponent, template: strip` - `, @@ -178,7 +175,6 @@ moduleFor( } '@test custom ember array properties rerender when updated'() { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let CustomArray = EmberObject.extend(MutableArray, { init() { this._super(...arguments); @@ -214,7 +210,7 @@ moduleFor( this.registerComponent('num-list', { ComponentClass: NumListComponent, template: strip` - `, diff --git a/packages/@ember/application/tests/visit_test.js b/packages/@ember/application/tests/visit_test.js index 4b45d706dc9..411df556794 100644 --- a/packages/@ember/application/tests/visit_test.js +++ b/packages/@ember/application/tests/visit_test.js @@ -625,7 +625,6 @@ moduleFor( } [`@test Ember Islands-style setup`](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let xFooInitCalled = false; let xFooDidInsertElementCalled = false; @@ -704,7 +703,7 @@ moduleFor( 'components/x-bar', `

X-Bar

- + ` ); @@ -713,10 +712,8 @@ moduleFor( Component.extend({ counter: service('sharedCounter'), - actions: { - incrementCounter() { - this.get('counter').increment(); - }, + incrementCounter() { + this.get('counter').increment(); }, init() { diff --git a/packages/ember/tests/integration/multiple-app-test.js b/packages/ember/tests/integration/multiple-app-test.js index ab2c4bbb37f..34c9440eb01 100644 --- a/packages/ember/tests/integration/multiple-app-test.js +++ b/packages/ember/tests/integration/multiple-app-test.js @@ -48,11 +48,9 @@ moduleFor( resolver.add( 'component:special-button', Component.extend({ - actions: { - doStuff() { - let rootElement = getOwner(this).application.rootElement; - actions.push(rootElement); - }, + doStuff() { + let rootElement = getOwner(this).application.rootElement; + actions.push(rootElement); }, }) ); @@ -72,7 +70,7 @@ moduleFor( 'template:components/special-button', this.compile( ` - + `, { moduleName: 'my-app/templates/components/special-button.hbs', @@ -82,7 +80,6 @@ moduleFor( } [`@test booting multiple applications can properly handle events`](assert) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); let actions = []; this.addFactoriesToResolver(actions, this.resolver); this.addFactoriesToResolver(actions, this.secondResolver); diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js index 32368b37b09..dc4ced410ab 100644 --- a/packages/ember/tests/routing/query_params_test.js +++ b/packages/ember/tests/routing/query_params_test.js @@ -743,18 +743,15 @@ moduleFor( async ['@test queryParams are updated when a controller property is set and the route is refreshed. Issue #13263 ']( assert ) { - expectDeprecation(/Usage of the `\{\{action\}\}` modifier is deprecated./); this.addTemplate( 'application', - '{{this.foo}}{{outlet}}' + '{{this.foo}}{{outlet}}' ); this.setSingleQPController('application', 'foo', 1, { - actions: { - increment() { - this.incrementProperty('foo'); - this.send('refreshRoute'); - }, + increment() { + this.incrementProperty('foo'); + this.send('refreshRoute'); }, });