Skip to content

Commit dde534e

Browse files
committed
feat: updated tests
1 parent 04ab1de commit dde534e

1 file changed

Lines changed: 129 additions & 30 deletions

File tree

packages/earn-controller/src/EarnController.test.ts

Lines changed: 129 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ function getEarnControllerMessenger(
132132
events: [
133133
'NetworkController:networkDidChange',
134134
'AccountTreeController:selectedAccountGroupChange',
135+
'AccountTreeController:stateChange',
135136
'TransactionController:transactionConfirmed',
136137
],
137138
});
@@ -869,6 +870,108 @@ describe('EarnController', () => {
869870
mockedEarnApiService?.pooledStaking?.getPooledStakes,
870871
).toHaveBeenCalledTimes(2); // 2 chains (ETH + HOODI) from the first init()
871872
});
873+
874+
describe('when no EVM account is available at init time', () => {
875+
// Minimal AccountTreeControllerState shape used to trigger the stateChange event
876+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
877+
const mockAccountTreeStateWithGroup: any = {
878+
selectedAccountGroup: 'keyring:test/0',
879+
accountTree: { wallets: {} },
880+
isAccountTreeSyncingInProgress: false,
881+
hasAccountTreeSyncingSyncedAtLeastOnce: false,
882+
accountGroupsMetadata: {},
883+
accountWalletsMetadata: {},
884+
};
885+
886+
it('defers portfolio refresh until AccountTreeController:stateChange fires with a non-empty selectedAccountGroup', async () => {
887+
const mockGetAccounts = jest
888+
.fn()
889+
.mockReturnValueOnce([]) // No account during init
890+
.mockReturnValue([mockInternalAccount1]); // Account available after stateChange
891+
892+
const { messenger } = await setupController({
893+
mockGetAccountsFromSelectedAccountGroup: mockGetAccounts,
894+
});
895+
896+
// No eligibility or staking refresh should have happened during init
897+
expect(
898+
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
899+
).not.toHaveBeenCalled();
900+
expect(
901+
mockedEarnApiService?.pooledStaking?.getPooledStakes,
902+
).not.toHaveBeenCalled();
903+
904+
messenger.publish(
905+
'AccountTreeController:stateChange',
906+
mockAccountTreeStateWithGroup,
907+
[],
908+
);
909+
await new Promise((resolve) => setTimeout(resolve, 0));
910+
911+
expect(
912+
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
913+
).toHaveBeenCalledWith([mockAccount1Address]);
914+
expect(
915+
mockedEarnApiService?.pooledStaking?.getPooledStakes,
916+
).toHaveBeenCalled();
917+
});
918+
919+
it('does not trigger portfolio refresh when selectedAccountGroup is empty', async () => {
920+
const { messenger } = await setupController({
921+
mockGetAccountsFromSelectedAccountGroup: jest.fn(() => []),
922+
});
923+
924+
messenger.publish(
925+
'AccountTreeController:stateChange',
926+
{
927+
...mockAccountTreeStateWithGroup,
928+
selectedAccountGroup: '',
929+
},
930+
[],
931+
);
932+
await new Promise((resolve) => setTimeout(resolve, 0));
933+
934+
expect(
935+
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
936+
).not.toHaveBeenCalled();
937+
});
938+
939+
it('unsubscribes after the first non-empty selectedAccountGroup event', async () => {
940+
const mockGetAccounts = jest
941+
.fn()
942+
.mockReturnValueOnce([]) // No account during init
943+
.mockReturnValue([mockInternalAccount1]); // Account available after stateChange
944+
945+
const { messenger } = await setupController({
946+
mockGetAccountsFromSelectedAccountGroup: mockGetAccounts,
947+
});
948+
949+
// First publish triggers the deferred refresh
950+
messenger.publish(
951+
'AccountTreeController:stateChange',
952+
mockAccountTreeStateWithGroup,
953+
[],
954+
);
955+
await new Promise((resolve) => setTimeout(resolve, 0));
956+
957+
const eligibilityCallCount = (
958+
mockedEarnApiService?.pooledStaking
959+
?.getPooledStakingEligibility as jest.Mock
960+
).mock.calls.length;
961+
962+
// Second publish should be ignored – handler was already unsubscribed
963+
messenger.publish(
964+
'AccountTreeController:stateChange',
965+
mockAccountTreeStateWithGroup,
966+
[],
967+
);
968+
await new Promise((resolve) => setTimeout(resolve, 0));
969+
970+
expect(
971+
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
972+
).toHaveBeenCalledTimes(eligibilityCallCount);
973+
});
974+
});
872975
});
873976

874977
describe('SDK initialization', () => {
@@ -1051,7 +1154,7 @@ describe('EarnController', () => {
10511154
const { controller } = await setupController();
10521155

10531156
await expect(controller.refreshPooledStakingData()).rejects.toThrow(
1054-
'Failed to refresh some staking data: API Error getPooledStakingEligibility, API Error getPooledStakes, API Error getVaultData, API Error getVaultDailyApys, API Error getVaultApyAverages, API Error getPooledStakes, API Error getVaultData, API Error getVaultDailyApys, API Error getVaultApyAverages',
1157+
'Failed to refresh some staking data: API Error getPooledStakes, API Error getVaultData, API Error getVaultDailyApys, API Error getVaultApyAverages, API Error getPooledStakes, API Error getVaultData, API Error getVaultDailyApys, API Error getVaultApyAverages',
10551158
);
10561159
expect(consoleErrorSpy).toHaveBeenCalled();
10571160
consoleErrorSpy.mockRestore();
@@ -1223,7 +1326,19 @@ describe('EarnController', () => {
12231326
// Assertion on second call since the first is part of controller setup.
12241327
expect(
12251328
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
1226-
).toHaveBeenNthCalledWith(3, [mockAccount2Address]);
1329+
).toHaveBeenNthCalledWith(2, [mockAccount2Address]);
1330+
});
1331+
1332+
it('returns early without fetching when no address is available', async () => {
1333+
const { controller } = await setupController({
1334+
mockGetAccountsFromSelectedAccountGroup: jest.fn(() => []),
1335+
});
1336+
1337+
await controller.refreshEarnEligibility();
1338+
1339+
expect(
1340+
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
1341+
).not.toHaveBeenCalled();
12271342
});
12281343
});
12291344

@@ -1624,31 +1739,6 @@ describe('EarnController', () => {
16241739
});
16251740

16261741
describe('Lending', () => {
1627-
describe('refreshLendingEligibility', () => {
1628-
it('fetches lending eligibility using active account (default)', async () => {
1629-
const { controller } = await setupController();
1630-
1631-
await controller.refreshLendingEligibility();
1632-
1633-
// Assertion on third call since the first and second calls are part of controller setup.
1634-
expect(
1635-
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
1636-
).toHaveBeenNthCalledWith(3, [mockAccount1Address]);
1637-
});
1638-
1639-
it('fetches lending eligibility using options.address override', async () => {
1640-
const { controller } = await setupController();
1641-
await controller.refreshLendingEligibility({
1642-
address: mockAccount2Address,
1643-
});
1644-
1645-
// Assertion on third call since the first and second calls are part of controller setup.
1646-
expect(
1647-
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
1648-
).toHaveBeenNthCalledWith(3, [mockAccount2Address]);
1649-
});
1650-
});
1651-
16521742
describe('refreshLendingPositions', () => {
16531743
it('fetches using active account (default)', async () => {
16541744
const { controller } = await setupController();
@@ -1671,6 +1761,18 @@ describe('EarnController', () => {
16711761
mockedEarnApiService?.lending?.getPositions,
16721762
).toHaveBeenNthCalledWith(2, mockAccount2Address);
16731763
});
1764+
1765+
it('returns early without fetching when no address is available', async () => {
1766+
const { controller } = await setupController({
1767+
mockGetAccountsFromSelectedAccountGroup: jest.fn(() => []),
1768+
});
1769+
1770+
await controller.refreshLendingPositions();
1771+
1772+
expect(
1773+
mockedEarnApiService?.lending?.getPositions,
1774+
).not.toHaveBeenCalled();
1775+
});
16741776
});
16751777

16761778
describe('refreshLendingMarkets', () => {
@@ -1697,9 +1799,6 @@ describe('EarnController', () => {
16971799
expect(
16981800
mockedEarnApiService?.lending?.getPositions,
16991801
).toHaveBeenCalledTimes(2);
1700-
expect(
1701-
mockedEarnApiService?.pooledStaking?.getPooledStakingEligibility,
1702-
).toHaveBeenCalledTimes(3); // Additionally called once in controller setup by refreshPooledStakingData
17031802
});
17041803
});
17051804

0 commit comments

Comments
 (0)