@@ -1789,4 +1789,85 @@ describe('AssetsController', () => {
17891789 } ) ;
17901790 } ) ;
17911791 } ) ;
1792+
1793+ describe ( 'account tree state change' , ( ) => {
1794+ it ( 'triggers start when tree initializes after unlock with empty accounts' , async ( ) => {
1795+ const getAccountsMock = jest . fn ( ) . mockReturnValue ( [ ] ) ;
1796+
1797+ const messenger : RootMessenger = new Messenger ( {
1798+ namespace : MOCK_ANY_NAMESPACE ,
1799+ } ) ;
1800+ messenger . registerActionHandler (
1801+ 'AccountTreeController:getAccountsFromSelectedAccountGroup' ,
1802+ getAccountsMock ,
1803+ ) ;
1804+ messenger . registerActionHandler (
1805+ 'NetworkEnablementController:getState' ,
1806+ ( ) => ( {
1807+ enabledNetworkMap : { eip155 : { '1' : true } } ,
1808+ nativeAssetIdentifiers : {
1809+ 'eip155:1' : 'eip155:1/slip44:60' as `${string } :${string } /slip44:${number } `,
1810+ } ,
1811+ } ) ,
1812+ ) ;
1813+ (
1814+ messenger as {
1815+ registerActionHandler : ( a : string , h : ( ) => unknown ) => void ;
1816+ }
1817+ ) . registerActionHandler ( 'NetworkController:getState' , ( ) => ( {
1818+ networkConfigurationsByChainId : { } ,
1819+ networksMetadata : { } ,
1820+ } ) ) ;
1821+ (
1822+ messenger as {
1823+ registerActionHandler : ( a : string , h : ( ) => unknown ) => void ;
1824+ }
1825+ ) . registerActionHandler ( 'NetworkController:getNetworkClientById' , ( ) => ( {
1826+ provider : { } ,
1827+ } ) ) ;
1828+ (
1829+ messenger as {
1830+ registerActionHandler : ( a : string , h : ( ) => unknown ) => void ;
1831+ }
1832+ ) . registerActionHandler ( 'ClientController:getState' , ( ) => ( {
1833+ isUiOpen : true ,
1834+ } ) ) ;
1835+
1836+ const controller = new AssetsController ( {
1837+ messenger : messenger as unknown as AssetsControllerMessenger ,
1838+ queryApiClient : createMockQueryApiClient ( ) ,
1839+ subscribeToBasicFunctionalityChange : ( ) : void => {
1840+ /* no-op */
1841+ } ,
1842+ } ) ;
1843+
1844+ const getAssetsSpy = jest . spyOn ( controller , 'getAssets' ) ;
1845+
1846+ // Step 1: UI open + unlock — accounts empty, #start() is a no-op
1847+ (
1848+ messenger as unknown as {
1849+ publish : ( topic : string , payload ?: unknown ) => void ;
1850+ }
1851+ ) . publish ( 'ClientController:stateChange' , { isUiOpen : true } ) ;
1852+ messenger . publish ( 'KeyringController:unlock' ) ;
1853+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
1854+
1855+ expect ( getAssetsSpy ) . not . toHaveBeenCalled ( ) ;
1856+
1857+ // Step 2: AccountTreeController.init() completes — accounts now available
1858+ getAccountsMock . mockReturnValue ( [ createMockInternalAccount ( ) ] ) ;
1859+ ( messenger . publish as CallableFunction ) (
1860+ 'AccountTreeController:stateChange' ,
1861+ { } ,
1862+ [ ] ,
1863+ ) ;
1864+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
1865+
1866+ expect ( getAssetsSpy ) . toHaveBeenCalledTimes ( 1 ) ;
1867+ expect ( getAssetsSpy ) . toHaveBeenCalledWith (
1868+ [ expect . objectContaining ( { id : MOCK_ACCOUNT_ID } ) ] ,
1869+ expect . objectContaining ( { forceUpdate : true } ) ,
1870+ ) ;
1871+ } ) ;
1872+ } ) ;
17921873} ) ;
0 commit comments