diff --git a/packages/base-controller/src/BaseControllerV2.test.ts b/packages/base-controller/src/BaseControllerV2.test.ts index f9a2e86c40d..e243b330227 100644 --- a/packages/base-controller/src/BaseControllerV2.test.ts +++ b/packages/base-controller/src/BaseControllerV2.test.ts @@ -296,6 +296,64 @@ describe('BaseController', () => { ]); }); + it('should notify a subscriber with a selector of state changes', () => { + const controllerMessenger = new ControllerMessenger< + never, + CountControllerEvent + >(); + const controller = new CountController({ + messenger: getCountMessenger(controllerMessenger), + name: 'CountController', + state: { count: 0 }, + metadata: countControllerStateMetadata, + }); + const listener = sinon.stub(); + controllerMessenger.subscribe( + 'CountController:stateChange', + listener, + ({ count }) => { + // Selector rounds down to nearest multiple of 10 + return Math.floor(count / 10); + }, + ); + + controller.update(() => { + return { count: 10 }; + }); + + expect(listener.callCount).toBe(1); + expect(listener.firstCall.args).toStrictEqual([1, 0]); + }); + + it('should not inform a subscriber of state changes if the selected value is unchanged', () => { + const controllerMessenger = new ControllerMessenger< + never, + CountControllerEvent + >(); + const controller = new CountController({ + messenger: getCountMessenger(controllerMessenger), + name: 'CountController', + state: { count: 0 }, + metadata: countControllerStateMetadata, + }); + const listener = sinon.stub(); + controllerMessenger.subscribe( + 'CountController:stateChange', + listener, + ({ count }) => { + // Selector rounds down to nearest multiple of 10 + return Math.floor(count / 10); + }, + ); + + controller.update(() => { + // Note that this rounds down to zero, so the selected value is still zero + return { count: 1 }; + }); + + expect(listener.callCount).toBe(0); + }); + it('should inform a subscriber of each state change once even after multiple subscriptions', () => { const controllerMessenger = new ControllerMessenger< never, diff --git a/packages/base-controller/src/BaseControllerV2.ts b/packages/base-controller/src/BaseControllerV2.ts index 92ea30f9adb..32467cf0d43 100644 --- a/packages/base-controller/src/BaseControllerV2.ts +++ b/packages/base-controller/src/BaseControllerV2.ts @@ -154,6 +154,11 @@ export class BaseController< `${name}:getState`, () => this.state, ); + + this.messagingSystem.registerInitialEventPayload({ + eventType: `${name}:stateChange`, + getPayload: () => [this.state, []], + }); } /** diff --git a/packages/signature-controller/src/SignatureController.test.ts b/packages/signature-controller/src/SignatureController.test.ts index 4f176a66a0f..240e93c85c8 100644 --- a/packages/signature-controller/src/SignatureController.test.ts +++ b/packages/signature-controller/src/SignatureController.test.ts @@ -94,6 +94,7 @@ const createMessengerMock = () => registerActionHandler: jest.fn(), publish: jest.fn(), call: jest.fn(), + registerInitialEventPayload: jest.fn(), // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any as jest.Mocked);