From 9a7393b6ecc67eb30f8f4f6b5d929523bab7abf2 Mon Sep 17 00:00:00 2001 From: Kanthesha Devaramane Date: Wed, 23 Oct 2024 23:08:26 +0100 Subject: [PATCH 1/2] upgrade alert controller to base controller v2 --- .../controllers/alert-controller.test.ts | 162 +++++++++--------- app/scripts/controllers/alert-controller.ts | 119 +++++++------ app/scripts/metamask-controller.js | 6 +- 3 files changed, 152 insertions(+), 135 deletions(-) diff --git a/app/scripts/controllers/alert-controller.test.ts b/app/scripts/controllers/alert-controller.test.ts index a8aee606e02d..2d70ecd78912 100644 --- a/app/scripts/controllers/alert-controller.test.ts +++ b/app/scripts/controllers/alert-controller.test.ts @@ -2,16 +2,15 @@ * @jest-environment node */ import { ControllerMessenger } from '@metamask/base-controller'; -import { KeyringControllerStateChangeEvent } from '@metamask/keyring-controller'; -import { SnapControllerStateChangeEvent } from '@metamask/snaps-controllers'; import { EthAccountType } from '@metamask/keyring-api'; import { - AlertControllerActions, - AlertControllerEvents, AlertController, AllowedActions, AllowedEvents, AlertControllerState, + AlertControllerMessenger, + AlertControllerGetStateAction, + AlertControllerStateChangeEvent, } from './alert-controller'; const EMPTY_ACCOUNT = { @@ -28,48 +27,54 @@ const EMPTY_ACCOUNT = { importTime: 0, }, }; -describe('AlertController', () => { - let controllerMessenger: ControllerMessenger< - AlertControllerActions | AllowedActions, - | AlertControllerEvents - | KeyringControllerStateChangeEvent - | SnapControllerStateChangeEvent - | AllowedEvents - >; - let alertController: AlertController; - - beforeEach(() => { - controllerMessenger = new ControllerMessenger< - AllowedActions, - AllowedEvents - >(); - controllerMessenger.registerActionHandler( - 'AccountsController:getSelectedAccount', - () => EMPTY_ACCOUNT, - ); - const alertMessenger = controllerMessenger.getRestricted({ +const setupController = ({ + state, +}: { + state?: Partial; +}) => { + const controllerMessenger = new ControllerMessenger< + AllowedActions | AlertControllerGetStateAction, + AllowedEvents | AlertControllerStateChangeEvent + >(); + const alertControllerMessenger: AlertControllerMessenger = + controllerMessenger.getRestricted({ name: 'AlertController', - allowedActions: [`AccountsController:getSelectedAccount`], - allowedEvents: [`AccountsController:selectedAccountChange`], + allowedActions: ['AccountsController:getSelectedAccount'], + allowedEvents: ['AccountsController:selectedAccountChange'], }); - alertController = new AlertController({ - state: { - unconnectedAccountAlertShownOrigins: { - testUnconnectedOrigin: false, - }, - web3ShimUsageOrigins: { - testWeb3ShimUsageOrigin: 0, - }, - }, - controllerMessenger: alertMessenger, - }); + controllerMessenger.registerActionHandler( + 'AccountsController:getSelectedAccount', + jest.fn().mockReturnValue(EMPTY_ACCOUNT), + ); + const initialState = { + unconnectedAccountAlertShownOrigins: { + testUnconnectedOrigin: false, + }, + web3ShimUsageOrigins: { + testWeb3ShimUsageOrigin: 0, + }, + }; + const controller = new AlertController({ + messenger: alertControllerMessenger, + state: { + ...initialState, + ...state, + }, }); + return { + controller, + messenger: controllerMessenger, + }; +}; + +describe('AlertController', () => { describe('default state', () => { it('should be same as AlertControllerState initialized', () => { - expect(alertController.store.getState()).toStrictEqual({ + const { controller } = setupController({}); + expect(controller.state).toStrictEqual({ alertEnabledness: { unconnectedAccount: true, web3ShimUsage: true, @@ -85,33 +90,35 @@ describe('AlertController', () => { }); describe('alertEnabledness', () => { + const { controller, messenger } = setupController({}); it('should default unconnectedAccount of alertEnabledness to true', () => { expect( - alertController.store.getState().alertEnabledness.unconnectedAccount, + controller.state.alertEnabledness.unconnectedAccount, ).toStrictEqual(true); }); it('should set unconnectedAccount of alertEnabledness to false', () => { - alertController.setAlertEnabledness('unconnectedAccount', false); + controller.setAlertEnabledness('unconnectedAccount', false); expect( - alertController.store.getState().alertEnabledness.unconnectedAccount, + controller.state.alertEnabledness.unconnectedAccount, ).toStrictEqual(false); expect( - controllerMessenger.call('AlertController:getState').alertEnabledness + messenger.call('AlertController:getState').alertEnabledness .unconnectedAccount, ).toStrictEqual(false); }); }); describe('unconnectedAccountAlertShownOrigins', () => { + const { controller, messenger } = setupController({}); it('should default unconnectedAccountAlertShownOrigins', () => { expect( - alertController.store.getState().unconnectedAccountAlertShownOrigins, + controller.state.unconnectedAccountAlertShownOrigins, ).toStrictEqual({ testUnconnectedOrigin: false, }); expect( - controllerMessenger.call('AlertController:getState') + messenger.call('AlertController:getState') .unconnectedAccountAlertShownOrigins, ).toStrictEqual({ testUnconnectedOrigin: false, @@ -119,14 +126,14 @@ describe('AlertController', () => { }); it('should set unconnectedAccountAlertShownOrigins', () => { - alertController.setUnconnectedAccountAlertShown('testUnconnectedOrigin'); + controller.setUnconnectedAccountAlertShown('testUnconnectedOrigin'); expect( - alertController.store.getState().unconnectedAccountAlertShownOrigins, + controller.state.unconnectedAccountAlertShownOrigins, ).toStrictEqual({ testUnconnectedOrigin: true, }); expect( - controllerMessenger.call('AlertController:getState') + messenger.call('AlertController:getState') .unconnectedAccountAlertShownOrigins, ).toStrictEqual({ testUnconnectedOrigin: true, @@ -135,44 +142,36 @@ describe('AlertController', () => { }); describe('web3ShimUsageOrigins', () => { + const { controller, messenger } = setupController({}); it('should default web3ShimUsageOrigins', () => { - expect( - alertController.store.getState().web3ShimUsageOrigins, - ).toStrictEqual({ + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ testWeb3ShimUsageOrigin: 0, }); expect( - controllerMessenger.call('AlertController:getState') - .web3ShimUsageOrigins, + messenger.call('AlertController:getState').web3ShimUsageOrigins, ).toStrictEqual({ testWeb3ShimUsageOrigin: 0, }); }); it('should set origin of web3ShimUsageOrigins to recorded', () => { - alertController.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); - expect( - alertController.store.getState().web3ShimUsageOrigins, - ).toStrictEqual({ + controller.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ testWeb3ShimUsageOrigin: 1, }); expect( - controllerMessenger.call('AlertController:getState') - .web3ShimUsageOrigins, + messenger.call('AlertController:getState').web3ShimUsageOrigins, ).toStrictEqual({ testWeb3ShimUsageOrigin: 1, }); }); it('should set origin of web3ShimUsageOrigins to dismissed', () => { - alertController.setWeb3ShimUsageAlertDismissed('testWeb3ShimUsageOrigin'); - expect( - alertController.store.getState().web3ShimUsageOrigins, - ).toStrictEqual({ + controller.setWeb3ShimUsageAlertDismissed('testWeb3ShimUsageOrigin'); + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ testWeb3ShimUsageOrigin: 2, }); expect( - controllerMessenger.call('AlertController:getState') - .web3ShimUsageOrigins, + messenger.call('AlertController:getState').web3ShimUsageOrigins, ).toStrictEqual({ testWeb3ShimUsageOrigin: 2, }); @@ -180,8 +179,9 @@ describe('AlertController', () => { }); describe('selectedAccount change', () => { + const { controller, messenger } = setupController({}); it('should set unconnectedAccountAlertShownOrigins to {}', () => { - controllerMessenger.publish('AccountsController:selectedAccountChange', { + messenger.publish('AccountsController:selectedAccountChange', { id: '', address: '0x1234567', options: {}, @@ -196,39 +196,38 @@ describe('AlertController', () => { }, }); expect( - alertController.store.getState().unconnectedAccountAlertShownOrigins, + controller.state.unconnectedAccountAlertShownOrigins, ).toStrictEqual({}); expect( - controllerMessenger.call('AlertController:getState') + messenger.call('AlertController:getState') .unconnectedAccountAlertShownOrigins, ).toStrictEqual({}); }); }); describe('AlertController:getState', () => { + const { controller, messenger } = setupController({}); it('should return the current state of the property', () => { const defaultWeb3ShimUsageOrigins = { testWeb3ShimUsageOrigin: 0, }; + expect(controller.state.web3ShimUsageOrigins).toStrictEqual( + defaultWeb3ShimUsageOrigins, + ); expect( - alertController.store.getState().web3ShimUsageOrigins, - ).toStrictEqual(defaultWeb3ShimUsageOrigins); - expect( - controllerMessenger.call('AlertController:getState') - .web3ShimUsageOrigins, + messenger.call('AlertController:getState').web3ShimUsageOrigins, ).toStrictEqual(defaultWeb3ShimUsageOrigins); }); }); describe('AlertController:stateChange', () => { + const { controller, messenger } = setupController({}); it('state will be published when there is state change', () => { - expect( - alertController.store.getState().web3ShimUsageOrigins, - ).toStrictEqual({ + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ testWeb3ShimUsageOrigin: 0, }); - controllerMessenger.subscribe( + messenger.subscribe( 'AlertController:stateChange', (state: Partial) => { expect(state.web3ShimUsageOrigins).toStrictEqual({ @@ -237,19 +236,16 @@ describe('AlertController', () => { }, ); - alertController.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); + controller.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); - expect( - alertController.store.getState().web3ShimUsageOrigins, - ).toStrictEqual({ + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ testWeb3ShimUsageOrigin: 1, }); expect( - alertController.getWeb3ShimUsageState('testWeb3ShimUsageOrigin'), + controller.getWeb3ShimUsageState('testWeb3ShimUsageOrigin'), ).toStrictEqual(1); expect( - controllerMessenger.call('AlertController:getState') - .web3ShimUsageOrigins, + messenger.call('AlertController:getState').web3ShimUsageOrigins, ).toStrictEqual({ testWeb3ShimUsageOrigin: 1, }); diff --git a/app/scripts/controllers/alert-controller.ts b/app/scripts/controllers/alert-controller.ts index 9e1882035e02..544f430ad272 100644 --- a/app/scripts/controllers/alert-controller.ts +++ b/app/scripts/controllers/alert-controller.ts @@ -1,9 +1,13 @@ -import { ObservableStore } from '@metamask/obs-store'; import { AccountsControllerGetSelectedAccountAction, AccountsControllerSelectedAccountChangeEvent, } from '@metamask/accounts-controller'; -import { RestrictedControllerMessenger } from '@metamask/base-controller'; +import { + BaseController, + ControllerGetStateAction, + ControllerStateChangeEvent, + RestrictedControllerMessenger, +} from '@metamask/base-controller'; import { TOGGLEABLE_ALERT_TYPES, Web3ShimUsageAlertStates, @@ -14,10 +18,10 @@ const controllerName = 'AlertController'; /** * Returns the state of the {@link AlertController}. */ -export type AlertControllerGetStateAction = { - type: 'AlertController:getState'; - handler: () => AlertControllerState; -}; +export type AlertControllerGetStateAction = ControllerGetStateAction< + typeof controllerName, + AlertControllerState +>; /** * Actions exposed by the {@link AlertController}. @@ -27,10 +31,10 @@ export type AlertControllerActions = AlertControllerGetStateAction; /** * Event emitted when the state of the {@link AlertController} changes. */ -export type AlertControllerStateChangeEvent = { - type: 'AlertController:stateChange'; - payload: [AlertControllerState, []]; -}; +export type AlertControllerStateChangeEvent = ControllerStateChangeEvent< + typeof controllerName, + AlertControllerState +>; /** * Events emitted by {@link AlertController}. @@ -77,11 +81,11 @@ export type AlertControllerState = { * @property controllerMessenger - The controller messenger */ type AlertControllerOptions = { - state?: Partial; - controllerMessenger: AlertControllerMessenger; + state: Partial; + messenger: AlertControllerMessenger; }; -const defaultState: AlertControllerState = { +export const getDefaultAlertControllerState = (): AlertControllerState => ({ alertEnabledness: TOGGLEABLE_ALERT_TYPES.reduce( (alertEnabledness: Record, alertType: string) => { alertEnabledness[alertType] = true; @@ -91,61 +95,76 @@ const defaultState: AlertControllerState = { ), unconnectedAccountAlertShownOrigins: {}, web3ShimUsageOrigins: {}, +}); + +/** + * {@link AlertController}'s metadata. + * + * This allows us to choose if fields of the state should be persisted or not + * using the `persist` flag; and if they can be sent to Sentry or not, using + * the `anonymous` flag. + */ +const controllerMetadata = { + alertEnabledness: { + persist: true, + anonymous: true, + }, + unconnectedAccountAlertShownOrigins: { + persist: true, + anonymous: false, + }, + web3ShimUsageOrigins: { + persist: true, + anonymous: false, + }, }; /** * Controller responsible for maintaining alert-related state. */ -export class AlertController { - store: ObservableStore; - - readonly #controllerMessenger: AlertControllerMessenger; - +export class AlertController extends BaseController< + typeof controllerName, + AlertControllerState, + AlertControllerMessenger +> { #selectedAddress: string; constructor(opts: AlertControllerOptions) { - const state: AlertControllerState = { - ...defaultState, - ...opts.state, - }; - - this.store = new ObservableStore(state); - this.#controllerMessenger = opts.controllerMessenger; - this.#controllerMessenger.registerActionHandler( - 'AlertController:getState', - () => this.store.getState(), - ); - this.store.subscribe((alertState: AlertControllerState) => { - this.#controllerMessenger.publish( - 'AlertController:stateChange', - alertState, - [], - ); + super({ + messenger: opts.messenger, + metadata: controllerMetadata, + name: controllerName, + state: { + ...getDefaultAlertControllerState(), + ...opts.state, + }, }); - this.#selectedAddress = this.#controllerMessenger.call( + this.#selectedAddress = this.messagingSystem.call( 'AccountsController:getSelectedAccount', ).address; - this.#controllerMessenger.subscribe( + this.messagingSystem.subscribe( 'AccountsController:selectedAccountChange', (account: { address: string }) => { - const currentState = this.store.getState(); + const currentState = this.state; if ( currentState.unconnectedAccountAlertShownOrigins && this.#selectedAddress !== account.address ) { this.#selectedAddress = account.address; - this.store.updateState({ unconnectedAccountAlertShownOrigins: {} }); + this.update((state) => { + state.unconnectedAccountAlertShownOrigins = {}; + }); } }, ); } setAlertEnabledness(alertId: string, enabledness: boolean): void { - const { alertEnabledness } = this.store.getState(); - alertEnabledness[alertId] = enabledness; - this.store.updateState({ alertEnabledness }); + this.update((state) => { + state.alertEnabledness[alertId] = enabledness; + }); } /** @@ -154,9 +173,9 @@ export class AlertController { * @param origin - The origin the alert has been shown for */ setUnconnectedAccountAlertShown(origin: string): void { - const { unconnectedAccountAlertShownOrigins } = this.store.getState(); - unconnectedAccountAlertShownOrigins[origin] = true; - this.store.updateState({ unconnectedAccountAlertShownOrigins }); + this.update((state) => { + state.unconnectedAccountAlertShownOrigins[origin] = true; + }); } /** @@ -167,7 +186,7 @@ export class AlertController { * origin, or undefined. */ getWeb3ShimUsageState(origin: string): number | undefined { - return this.store.getState().web3ShimUsageOrigins?.[origin]; + return this.state.web3ShimUsageOrigins?.[origin]; } /** @@ -194,10 +213,12 @@ export class AlertController { * @param value - The state value to set. */ #setWeb3ShimUsageState(origin: string, value: number): void { - const { web3ShimUsageOrigins } = this.store.getState(); + const { web3ShimUsageOrigins } = this.state; if (web3ShimUsageOrigins) { - web3ShimUsageOrigins[origin] = value; - this.store.updateState({ web3ShimUsageOrigins }); + this.update((state) => { + state.web3ShimUsageOrigins = state.web3ShimUsageOrigins || {}; + state.web3ShimUsageOrigins[origin] = value; + }); } } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c33485f665b7..47ce1a351baf 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1794,7 +1794,7 @@ export default class MetamaskController extends EventEmitter { this.alertController = new AlertController({ state: initState.AlertController, - controllerMessenger: this.controllerMessenger.getRestricted({ + messenger: this.controllerMessenger.getRestricted({ name: 'AlertController', allowedEvents: ['AccountsController:selectedAccountChange'], allowedActions: ['AccountsController:getSelectedAccount'], @@ -2382,7 +2382,7 @@ export default class MetamaskController extends EventEmitter { AddressBookController: this.addressBookController, CurrencyController: this.currencyRateController, NetworkController: this.networkController, - AlertController: this.alertController.store, + AlertController: this.alertController, OnboardingController: this.onboardingController, PermissionController: this.permissionController, PermissionLogController: this.permissionLogController, @@ -2437,7 +2437,7 @@ export default class MetamaskController extends EventEmitter { this.metaMetricsDataDeletionController, AddressBookController: this.addressBookController, CurrencyController: this.currencyRateController, - AlertController: this.alertController.store, + AlertController: this.alertController, OnboardingController: this.onboardingController, PermissionController: this.permissionController, PermissionLogController: this.permissionLogController, From 7c3949e169a066b49ede7dcd591d52737546800b Mon Sep 17 00:00:00 2001 From: Kanthesha Devaramane Date: Fri, 25 Oct 2024 13:43:47 +0100 Subject: [PATCH 2/2] add jsdoc to getDefaultState and add withController in tests --- .../controllers/alert-controller.test.ts | 376 ++++++++++-------- app/scripts/controllers/alert-controller.ts | 5 +- 2 files changed, 223 insertions(+), 158 deletions(-) diff --git a/app/scripts/controllers/alert-controller.test.ts b/app/scripts/controllers/alert-controller.test.ts index 2d70ecd78912..17d071b18efc 100644 --- a/app/scripts/controllers/alert-controller.test.ts +++ b/app/scripts/controllers/alert-controller.test.ts @@ -11,6 +11,8 @@ import { AlertControllerMessenger, AlertControllerGetStateAction, AlertControllerStateChangeEvent, + AlertControllerOptions, + getDefaultAlertControllerState, } from './alert-controller'; const EMPTY_ACCOUNT = { @@ -28,15 +30,42 @@ const EMPTY_ACCOUNT = { }, }; -const setupController = ({ - state, +const initialState = { + unconnectedAccountAlertShownOrigins: { + testUnconnectedOrigin: false, + }, + web3ShimUsageOrigins: { + testWeb3ShimUsageOrigin: 0, + }, +}; + +type WithControllerOptions = Partial; + +type WithControllerCallback = ({ + controller, }: { - state?: Partial; -}) => { + controller: AlertController; + messenger: ControllerMessenger< + AllowedActions | AlertControllerGetStateAction, + AllowedEvents | AlertControllerStateChangeEvent + >; +}) => ReturnValue; + +type WithControllerArgs = + | [WithControllerCallback] + | [WithControllerOptions, WithControllerCallback]; + +async function withController( + ...args: WithControllerArgs +): Promise { + const [{ ...rest }, fn] = args.length === 2 ? args : [{}, args[0]]; + const { ...alertControllerOptions } = rest; + const controllerMessenger = new ControllerMessenger< AllowedActions | AlertControllerGetStateAction, AllowedEvents | AlertControllerStateChangeEvent >(); + const alertControllerMessenger: AlertControllerMessenger = controllerMessenger.getRestricted({ name: 'AlertController', @@ -48,207 +77,240 @@ const setupController = ({ 'AccountsController:getSelectedAccount', jest.fn().mockReturnValue(EMPTY_ACCOUNT), ); - const initialState = { - unconnectedAccountAlertShownOrigins: { - testUnconnectedOrigin: false, - }, - web3ShimUsageOrigins: { - testWeb3ShimUsageOrigin: 0, - }, - }; + const controller = new AlertController({ messenger: alertControllerMessenger, - state: { - ...initialState, - ...state, - }, + state: getDefaultAlertControllerState(), + ...alertControllerOptions, }); - return { + return await fn({ controller, messenger: controllerMessenger, - }; -}; + }); +} describe('AlertController', () => { describe('default state', () => { - it('should be same as AlertControllerState initialized', () => { - const { controller } = setupController({}); - expect(controller.state).toStrictEqual({ - alertEnabledness: { - unconnectedAccount: true, - web3ShimUsage: true, - }, - unconnectedAccountAlertShownOrigins: { - testUnconnectedOrigin: false, - }, - web3ShimUsageOrigins: { - testWeb3ShimUsageOrigin: 0, - }, + it('should be same as AlertControllerState initialized', async () => { + await withController({ state: initialState }, ({ controller }) => { + expect(controller.state).toStrictEqual({ + alertEnabledness: { + unconnectedAccount: true, + web3ShimUsage: true, + }, + unconnectedAccountAlertShownOrigins: { + testUnconnectedOrigin: false, + }, + web3ShimUsageOrigins: { + testWeb3ShimUsageOrigin: 0, + }, + }); }); }); }); describe('alertEnabledness', () => { - const { controller, messenger } = setupController({}); - it('should default unconnectedAccount of alertEnabledness to true', () => { - expect( - controller.state.alertEnabledness.unconnectedAccount, - ).toStrictEqual(true); + it('should default unconnectedAccount of alertEnabledness to true', async () => { + await withController({ state: initialState }, ({ controller }) => { + expect( + controller.state.alertEnabledness.unconnectedAccount, + ).toStrictEqual(true); + }); }); - it('should set unconnectedAccount of alertEnabledness to false', () => { - controller.setAlertEnabledness('unconnectedAccount', false); - expect( - controller.state.alertEnabledness.unconnectedAccount, - ).toStrictEqual(false); - expect( - messenger.call('AlertController:getState').alertEnabledness - .unconnectedAccount, - ).toStrictEqual(false); + it('should set unconnectedAccount of alertEnabledness to false', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + controller.setAlertEnabledness('unconnectedAccount', false); + expect( + controller.state.alertEnabledness.unconnectedAccount, + ).toStrictEqual(false); + expect( + messenger.call('AlertController:getState').alertEnabledness + .unconnectedAccount, + ).toStrictEqual(false); + }, + ); }); }); describe('unconnectedAccountAlertShownOrigins', () => { - const { controller, messenger } = setupController({}); - it('should default unconnectedAccountAlertShownOrigins', () => { - expect( - controller.state.unconnectedAccountAlertShownOrigins, - ).toStrictEqual({ - testUnconnectedOrigin: false, - }); - expect( - messenger.call('AlertController:getState') - .unconnectedAccountAlertShownOrigins, - ).toStrictEqual({ - testUnconnectedOrigin: false, - }); + it('should default unconnectedAccountAlertShownOrigins', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + expect( + controller.state.unconnectedAccountAlertShownOrigins, + ).toStrictEqual({ + testUnconnectedOrigin: false, + }); + expect( + messenger.call('AlertController:getState') + .unconnectedAccountAlertShownOrigins, + ).toStrictEqual({ + testUnconnectedOrigin: false, + }); + }, + ); }); - it('should set unconnectedAccountAlertShownOrigins', () => { - controller.setUnconnectedAccountAlertShown('testUnconnectedOrigin'); - expect( - controller.state.unconnectedAccountAlertShownOrigins, - ).toStrictEqual({ - testUnconnectedOrigin: true, - }); - expect( - messenger.call('AlertController:getState') - .unconnectedAccountAlertShownOrigins, - ).toStrictEqual({ - testUnconnectedOrigin: true, - }); + it('should set unconnectedAccountAlertShownOrigins', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + controller.setUnconnectedAccountAlertShown('testUnconnectedOrigin'); + expect( + controller.state.unconnectedAccountAlertShownOrigins, + ).toStrictEqual({ + testUnconnectedOrigin: true, + }); + expect( + messenger.call('AlertController:getState') + .unconnectedAccountAlertShownOrigins, + ).toStrictEqual({ + testUnconnectedOrigin: true, + }); + }, + ); }); }); describe('web3ShimUsageOrigins', () => { - const { controller, messenger } = setupController({}); - it('should default web3ShimUsageOrigins', () => { - expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ - testWeb3ShimUsageOrigin: 0, - }); - expect( - messenger.call('AlertController:getState').web3ShimUsageOrigins, - ).toStrictEqual({ - testWeb3ShimUsageOrigin: 0, - }); + it('should default web3ShimUsageOrigins', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ + testWeb3ShimUsageOrigin: 0, + }); + expect( + messenger.call('AlertController:getState').web3ShimUsageOrigins, + ).toStrictEqual({ + testWeb3ShimUsageOrigin: 0, + }); + }, + ); }); - it('should set origin of web3ShimUsageOrigins to recorded', () => { - controller.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); - expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ - testWeb3ShimUsageOrigin: 1, - }); - expect( - messenger.call('AlertController:getState').web3ShimUsageOrigins, - ).toStrictEqual({ - testWeb3ShimUsageOrigin: 1, - }); + it('should set origin of web3ShimUsageOrigins to recorded', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + controller.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ + testWeb3ShimUsageOrigin: 1, + }); + expect( + messenger.call('AlertController:getState').web3ShimUsageOrigins, + ).toStrictEqual({ + testWeb3ShimUsageOrigin: 1, + }); + }, + ); }); - it('should set origin of web3ShimUsageOrigins to dismissed', () => { - controller.setWeb3ShimUsageAlertDismissed('testWeb3ShimUsageOrigin'); - expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ - testWeb3ShimUsageOrigin: 2, - }); - expect( - messenger.call('AlertController:getState').web3ShimUsageOrigins, - ).toStrictEqual({ - testWeb3ShimUsageOrigin: 2, - }); + it('should set origin of web3ShimUsageOrigins to dismissed', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + controller.setWeb3ShimUsageAlertDismissed('testWeb3ShimUsageOrigin'); + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ + testWeb3ShimUsageOrigin: 2, + }); + expect( + messenger.call('AlertController:getState').web3ShimUsageOrigins, + ).toStrictEqual({ + testWeb3ShimUsageOrigin: 2, + }); + }, + ); }); }); describe('selectedAccount change', () => { - const { controller, messenger } = setupController({}); - it('should set unconnectedAccountAlertShownOrigins to {}', () => { - messenger.publish('AccountsController:selectedAccountChange', { - id: '', - address: '0x1234567', - options: {}, - methods: [], - type: 'eip155:eoa', - metadata: { - name: '', - keyring: { - type: '', - }, - importTime: 0, + it('should set unconnectedAccountAlertShownOrigins to {}', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + messenger.publish('AccountsController:selectedAccountChange', { + id: '', + address: '0x1234567', + options: {}, + methods: [], + type: 'eip155:eoa', + metadata: { + name: '', + keyring: { + type: '', + }, + importTime: 0, + }, + }); + expect( + controller.state.unconnectedAccountAlertShownOrigins, + ).toStrictEqual({}); + expect( + messenger.call('AlertController:getState') + .unconnectedAccountAlertShownOrigins, + ).toStrictEqual({}); }, - }); - expect( - controller.state.unconnectedAccountAlertShownOrigins, - ).toStrictEqual({}); - expect( - messenger.call('AlertController:getState') - .unconnectedAccountAlertShownOrigins, - ).toStrictEqual({}); + ); }); }); describe('AlertController:getState', () => { - const { controller, messenger } = setupController({}); - it('should return the current state of the property', () => { - const defaultWeb3ShimUsageOrigins = { - testWeb3ShimUsageOrigin: 0, - }; - expect(controller.state.web3ShimUsageOrigins).toStrictEqual( - defaultWeb3ShimUsageOrigins, + it('should return the current state of the property', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + const defaultWeb3ShimUsageOrigins = { + testWeb3ShimUsageOrigin: 0, + }; + expect(controller.state.web3ShimUsageOrigins).toStrictEqual( + defaultWeb3ShimUsageOrigins, + ); + expect( + messenger.call('AlertController:getState').web3ShimUsageOrigins, + ).toStrictEqual(defaultWeb3ShimUsageOrigins); + }, ); - expect( - messenger.call('AlertController:getState').web3ShimUsageOrigins, - ).toStrictEqual(defaultWeb3ShimUsageOrigins); }); }); describe('AlertController:stateChange', () => { - const { controller, messenger } = setupController({}); - it('state will be published when there is state change', () => { - expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ - testWeb3ShimUsageOrigin: 0, - }); + it('state will be published when there is state change', async () => { + await withController( + { state: initialState }, + ({ controller, messenger }) => { + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ + testWeb3ShimUsageOrigin: 0, + }); + + messenger.subscribe( + 'AlertController:stateChange', + (state: Partial) => { + expect(state.web3ShimUsageOrigins).toStrictEqual({ + testWeb3ShimUsageOrigin: 1, + }); + }, + ); + + controller.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); - messenger.subscribe( - 'AlertController:stateChange', - (state: Partial) => { - expect(state.web3ShimUsageOrigins).toStrictEqual({ + expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ + testWeb3ShimUsageOrigin: 1, + }); + expect( + controller.getWeb3ShimUsageState('testWeb3ShimUsageOrigin'), + ).toStrictEqual(1); + expect( + messenger.call('AlertController:getState').web3ShimUsageOrigins, + ).toStrictEqual({ testWeb3ShimUsageOrigin: 1, }); }, ); - - controller.setWeb3ShimUsageRecorded('testWeb3ShimUsageOrigin'); - - expect(controller.state.web3ShimUsageOrigins).toStrictEqual({ - testWeb3ShimUsageOrigin: 1, - }); - expect( - controller.getWeb3ShimUsageState('testWeb3ShimUsageOrigin'), - ).toStrictEqual(1); - expect( - messenger.call('AlertController:getState').web3ShimUsageOrigins, - ).toStrictEqual({ - testWeb3ShimUsageOrigin: 1, - }); }); }); }); diff --git a/app/scripts/controllers/alert-controller.ts b/app/scripts/controllers/alert-controller.ts index 544f430ad272..46308e1ba3a7 100644 --- a/app/scripts/controllers/alert-controller.ts +++ b/app/scripts/controllers/alert-controller.ts @@ -80,11 +80,14 @@ export type AlertControllerState = { * @property state - The initial controller state * @property controllerMessenger - The controller messenger */ -type AlertControllerOptions = { +export type AlertControllerOptions = { state: Partial; messenger: AlertControllerMessenger; }; +/** + * Function to get default state of the {@link AlertController}. + */ export const getDefaultAlertControllerState = (): AlertControllerState => ({ alertEnabledness: TOGGLEABLE_ALERT_TYPES.reduce( (alertEnabledness: Record, alertType: string) => {