From f6bd43d9fab03488c7a96fe26e21349015f0c03f Mon Sep 17 00:00:00 2001 From: bonkalol Date: Tue, 6 Aug 2024 12:47:05 +0300 Subject: [PATCH 1/2] off test --- src/components/super/i-block/event/index.ts | 4 +-- .../super/i-block/event/test/unit/api.ts | 33 +++++++++++++++++++ .../interface/component/component.ts | 29 +++++++++++++++- .../component/interface/component/types.ts | 4 ++- 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/components/super/i-block/event/index.ts b/src/components/super/i-block/event/index.ts index 4b099adf33..0529097472 100644 --- a/src/components/super/i-block/event/index.ts +++ b/src/components/super/i-block/event/index.ts @@ -97,10 +97,10 @@ export default abstract class iBlockEvent extends iBlockBase { off: (eventOrLink: string | EventId, handler: Function) => { if (Object.isString(eventOrLink)) { - return o.$off(normalizeEventName(eventOrLink), handler); + return o.$off(normalizeEventName(eventOrLink), handler, {rawEmitter: true}); } - return o.$off(eventOrLink); + return o.$off(eventOrLink, undefined, {rawEmitter: true}); }, emit: o.emit.bind(o), diff --git a/src/components/super/i-block/event/test/unit/api.ts b/src/components/super/i-block/event/test/unit/api.ts index d70a1b84b1..794213c569 100644 --- a/src/components/super/i-block/event/test/unit/api.ts +++ b/src/components/super/i-block/event/test/unit/api.ts @@ -11,6 +11,7 @@ import test from 'tests/config/unit/test'; import { renderDummy } from 'components/super/i-block/event/test/helpers'; import type bDummy from 'components/dummies/b-dummy/b-dummy'; +import { BOM, Component } from 'tests/helpers'; test.describe(' event API', () => { const componentName = 'b-dummy'; @@ -22,6 +23,38 @@ test.describe(' event API', () => { }, componentName); }); + test('the event handler should be removed by using off and providing cb', async ({page}) => { + const dummy = await Component.createComponent(page, 'b-dummy'); + + await dummy.evaluate((ctx) => { + ctx.testComponent = 'b-button-functional'; + }); + + const childComponent = await Component.waitForComponentByQuery(page, '.b-button'); + + await childComponent.evaluate((ctx) => { + const dummy = ctx.$normalParent; + + const handler = () => { + globalThis.testResult = true; + }; + + dummy?.once('hook:deactivated', handler); + + ctx.unsafe.async.worker(() => { + dummy?.off('hook:deactivated', handler); + }); + }); + + await BOM.waitForIdleCallback(page); + await childComponent.evaluate((ctx) => ctx.unsafe.$destroy()); + await BOM.waitForIdleCallback(page); + await dummy.evaluate((ctx) => ctx.deactivate()); + await BOM.waitForIdleCallback(page); + + await test.expect(page.evaluate(() => globalThis.testResult)).resolves.toBeUndefined(); + }); + test('the event passed to `emit` should be normalized to camelCase', async ({page}) => { const target = await renderDummy(page); diff --git a/src/core/component/interface/component/component.ts b/src/core/component/interface/component/component.ts index 99e81999b0..663f170d20 100644 --- a/src/core/component/interface/component/component.ts +++ b/src/core/component/interface/component/component.ts @@ -26,6 +26,7 @@ import type { RenderEngine } from 'core/component/interface/engine'; import type { ComponentApp, ComponentDestructorOptions, ComponentElement, ComponentEmitterOptions } from 'core/component/interface/component/types'; import type { WatchPath, WatchOptions, RawWatchHandler } from 'core/component/interface/watch'; import type { UnsafeGetter, UnsafeComponentInterface } from 'core/component/interface/component/unsafe'; +import type { ComponentEmitterCommonOptions } from 'components/super/i-data/i-data'; /** * An abstract class that encapsulates the Vue-compatible component API @@ -535,10 +536,19 @@ export abstract class ComponentInterface { /** * Detaches the specified event listeners from the component + * * @param [link] */ protected $off(link: CanArray): this; + /** + * Detaches the specified event listeners from the component + * + * @param [link] + * @param [opts] + */ + protected $off(link: CanArray, handler: undefined, opts?: ComponentEmitterCommonOptions): this; + /** * Detaches the specified event listeners from the component * @@ -547,7 +557,24 @@ export abstract class ComponentInterface { */ protected $off(event?: CanArray, handler?: Function): this; - protected $off(_event?: CanArray, _handler?: Function): this { + /** + * Detaches the specified event listeners from the component + * + * @param [event] + * @param [handler] + * @param [opts] + */ + protected $off( + event?: CanArray, + handler?: Function, + opts?: ComponentEmitterCommonOptions + ): this; + + protected $off( + _event?: CanArray, + _handler?: Function | ComponentEmitterCommonOptions, + _opts?: ComponentEmitterCommonOptions + ): this { return Object.throw(); } diff --git a/src/core/component/interface/component/types.ts b/src/core/component/interface/component/types.ts index 185fac6d2c..8201904284 100644 --- a/src/core/component/interface/component/types.ts +++ b/src/core/component/interface/component/types.ts @@ -32,13 +32,15 @@ export interface ComponentApp { state: State; } -export interface ComponentEmitterOptions { +export interface ComponentEmitterOptions extends ComponentEmitterCommonOptions { /** * If set to true, the handler will be added before all the other handlers * @default `false` */ prepend?: boolean; +} +export interface ComponentEmitterCommonOptions { /** * A flag indicating that the handler should be added directly to the component's event emitter. * Otherwise, the handler is always added to the emitter wrapped in an Async container. From af3dd23adc909581a785afbeffd3b29e30a7ae2e Mon Sep 17 00:00:00 2001 From: bonkalol Date: Tue, 6 Aug 2024 13:37:42 +0300 Subject: [PATCH 2/2] rollback --- src/components/super/i-block/event/index.ts | 4 +-- .../interface/component/component.ts | 29 +------------------ .../component/interface/component/types.ts | 4 +-- 3 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/components/super/i-block/event/index.ts b/src/components/super/i-block/event/index.ts index 0529097472..4b099adf33 100644 --- a/src/components/super/i-block/event/index.ts +++ b/src/components/super/i-block/event/index.ts @@ -97,10 +97,10 @@ export default abstract class iBlockEvent extends iBlockBase { off: (eventOrLink: string | EventId, handler: Function) => { if (Object.isString(eventOrLink)) { - return o.$off(normalizeEventName(eventOrLink), handler, {rawEmitter: true}); + return o.$off(normalizeEventName(eventOrLink), handler); } - return o.$off(eventOrLink, undefined, {rawEmitter: true}); + return o.$off(eventOrLink); }, emit: o.emit.bind(o), diff --git a/src/core/component/interface/component/component.ts b/src/core/component/interface/component/component.ts index 663f170d20..99e81999b0 100644 --- a/src/core/component/interface/component/component.ts +++ b/src/core/component/interface/component/component.ts @@ -26,7 +26,6 @@ import type { RenderEngine } from 'core/component/interface/engine'; import type { ComponentApp, ComponentDestructorOptions, ComponentElement, ComponentEmitterOptions } from 'core/component/interface/component/types'; import type { WatchPath, WatchOptions, RawWatchHandler } from 'core/component/interface/watch'; import type { UnsafeGetter, UnsafeComponentInterface } from 'core/component/interface/component/unsafe'; -import type { ComponentEmitterCommonOptions } from 'components/super/i-data/i-data'; /** * An abstract class that encapsulates the Vue-compatible component API @@ -536,19 +535,10 @@ export abstract class ComponentInterface { /** * Detaches the specified event listeners from the component - * * @param [link] */ protected $off(link: CanArray): this; - /** - * Detaches the specified event listeners from the component - * - * @param [link] - * @param [opts] - */ - protected $off(link: CanArray, handler: undefined, opts?: ComponentEmitterCommonOptions): this; - /** * Detaches the specified event listeners from the component * @@ -557,24 +547,7 @@ export abstract class ComponentInterface { */ protected $off(event?: CanArray, handler?: Function): this; - /** - * Detaches the specified event listeners from the component - * - * @param [event] - * @param [handler] - * @param [opts] - */ - protected $off( - event?: CanArray, - handler?: Function, - opts?: ComponentEmitterCommonOptions - ): this; - - protected $off( - _event?: CanArray, - _handler?: Function | ComponentEmitterCommonOptions, - _opts?: ComponentEmitterCommonOptions - ): this { + protected $off(_event?: CanArray, _handler?: Function): this { return Object.throw(); } diff --git a/src/core/component/interface/component/types.ts b/src/core/component/interface/component/types.ts index 8201904284..185fac6d2c 100644 --- a/src/core/component/interface/component/types.ts +++ b/src/core/component/interface/component/types.ts @@ -32,15 +32,13 @@ export interface ComponentApp { state: State; } -export interface ComponentEmitterOptions extends ComponentEmitterCommonOptions { +export interface ComponentEmitterOptions { /** * If set to true, the handler will be added before all the other handlers * @default `false` */ prepend?: boolean; -} -export interface ComponentEmitterCommonOptions { /** * A flag indicating that the handler should be added directly to the component's event emitter. * Otherwise, the handler is always added to the emitter wrapped in an Async container.