Skip to content

Commit 1e77bcb

Browse files
authored
test(beefy): Add unit tests for beefy positions hook (#638)
Focused on unit tests that hit `beefyAppTokenDefinition`, since that is what the earn positions are. Unit tests added for: - Confirming `getInfo` returns the expected fields for beefy - `getPositionDefinitions` returns positions with balance when supported networkId and address passed in - `getPositionDefinitions` returns all positions when supported networkId passed in but no address - `getPositionDefinitions` returns empty list for unsupported networkId
1 parent 5831dde commit 1e77bcb

File tree

1 file changed

+202
-7
lines changed

1 file changed

+202
-7
lines changed

src/apps/beefy/positions.test.ts

Lines changed: 202 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,164 @@
1-
import { BaseBeefyVault } from './api'
2-
import { getDailyYieldRatePercentage } from './positions'
1+
import { TFunction } from 'i18next'
2+
import {
3+
BaseBeefyVault,
4+
getApyBreakdown,
5+
getBeefyPrices,
6+
getBeefyVaults,
7+
getTvls,
8+
} from './api'
9+
import hook, { getDailyYieldRatePercentage } from './positions'
10+
import { NetworkId } from '../../types/networkId'
11+
import { Address } from 'viem'
12+
13+
const mockT = ((x: string) => x) as TFunction
14+
15+
const mockReadContract = jest.fn()
16+
jest.mock('../../runtime/client', () => ({
17+
getClient: jest.fn(() => ({
18+
readContract: mockReadContract,
19+
})),
20+
}))
21+
22+
jest.mock('./api.ts')
23+
24+
const mockBeefyVault: BaseBeefyVault = {
25+
id: 'defaultVault',
26+
name: 'Default Vault',
27+
type: 'auto',
28+
subType: 'concentrated',
29+
token: 'vaultToken',
30+
tokenAddress: '0x123456789' as Address,
31+
tokenDecimals: 8,
32+
tokenProviderId: '',
33+
earnedToken: '',
34+
earnContractAddress: '' as Address,
35+
status: '',
36+
platformId: '',
37+
assets: [],
38+
risks: [],
39+
strategyTypeId: '',
40+
network: 'arbitrum-one',
41+
chain: '',
42+
zaps: [],
43+
isGovVault: false,
44+
oracle: '',
45+
oracleId: '',
46+
createdAt: 12345,
47+
earnedTokenAddress: '0x987654321' as Address,
48+
depositTokenAddresses: [],
49+
strategy: '' as Address,
50+
pricePerFullShare: '120000000',
51+
}
52+
53+
const mockBeefyVault1: BaseBeefyVault = {
54+
...mockBeefyVault,
55+
id: 'vault1',
56+
name: 'Vault 1',
57+
}
58+
59+
const mockBeefyVault2: BaseBeefyVault = {
60+
...mockBeefyVault,
61+
id: 'vault2',
62+
name: 'Vault 2',
63+
tokenAddress: '0x111111111' as Address,
64+
createdAt: 135790,
65+
earnedTokenAddress: '0x999999999' as Address,
66+
pricePerFullShare: '100000',
67+
}
68+
69+
const mockBeefyVaults = {
70+
vaults: [mockBeefyVault1, mockBeefyVault2],
71+
govVaults: [],
72+
}
73+
const mockBeefyPrices = { vault1: 1.2, vault2: 1000 }
74+
const mockApyBreakdown = {
75+
vault1: { totalApy: 0.31 },
76+
vault2: { totalApy: 0.06 },
77+
}
78+
const mockTvls = { vault1: 98765, vault2: 1234567890 }
79+
const mockGetTokenBalancesResponse: readonly bigint[] = [0n, 10n]
80+
81+
jest.mocked(getBeefyVaults).mockResolvedValue(mockBeefyVaults)
82+
jest.mocked(getBeefyPrices).mockResolvedValue(mockBeefyPrices)
83+
jest.mocked(getApyBreakdown).mockResolvedValue(mockApyBreakdown)
84+
jest.mocked(getTvls).mockResolvedValue(mockTvls)
85+
86+
const vault: BaseBeefyVault = {
87+
type: 'gov',
88+
subType: 'cowcentrated',
89+
} as BaseBeefyVault
90+
91+
const expectedBeefyVault = {
92+
address: '0x987654321',
93+
availableShortcutIds: ['deposit', 'withdraw', 'swap-deposit'],
94+
dataProps: {
95+
cantSeparateCompoundedInterest: true,
96+
claimType: 'rewards',
97+
contractCreatedAt: '1970-01-01T03:25:45.000Z',
98+
dailyYieldRatePercentage: 0.07400740957195229,
99+
depositTokenId: 'arbitrum-one:0x123456789',
100+
earningItems: [],
101+
manageUrl: 'https://app.beefy.com/vault/defaultVault',
102+
safety: undefined,
103+
tvl: '98765',
104+
withdrawTokenId: 'arbitrum-one:0x987654321',
105+
yieldRates: [
106+
{
107+
label: 'yieldRates.earningsApy',
108+
percentage: 31,
109+
tokenId: 'arbitrum-one:0x123456789',
110+
},
111+
],
112+
},
113+
displayProps: expect.any(Function),
114+
networkId: 'arbitrum-one',
115+
pricePerShare: expect.any(Function),
116+
shortcutTriggerArgs: expect.any(Function),
117+
tokens: [
118+
{
119+
address: '0x123456789',
120+
fallbackPriceUsd: '1.2',
121+
networkId: 'arbitrum-one',
122+
},
123+
],
124+
type: 'app-token-definition',
125+
}
126+
127+
const expectedBeefyVault1 = {
128+
...expectedBeefyVault,
129+
dataProps: {
130+
...expectedBeefyVault.dataProps,
131+
manageUrl: 'https://app.beefy.com/vault/vault1',
132+
},
133+
}
134+
135+
const expectedBeefyVault2 = {
136+
...expectedBeefyVault,
137+
address: '0x999999999',
138+
dataProps: {
139+
...expectedBeefyVault.dataProps,
140+
contractCreatedAt: '1970-01-02T13:43:10.000Z',
141+
dailyYieldRatePercentage: 0.015965358745284597,
142+
depositTokenId: 'arbitrum-one:0x111111111',
143+
manageUrl: 'https://app.beefy.com/vault/vault2',
144+
tvl: '1234567890',
145+
withdrawTokenId: 'arbitrum-one:0x999999999',
146+
yieldRates: [
147+
{
148+
label: 'yieldRates.earningsApy',
149+
percentage: 6,
150+
tokenId: 'arbitrum-one:0x111111111',
151+
},
152+
],
153+
},
154+
tokens: [
155+
{
156+
address: '0x111111111',
157+
fallbackPriceUsd: '1000',
158+
networkId: 'arbitrum-one',
159+
},
160+
],
161+
}
3162

4163
const apyBreakdownWithCorrectComponents = {
5164
vaultApr: 0.1,
@@ -12,11 +171,6 @@ const apyBreakdownWithIncorrectComponents = {
12171
totalApy: 0.5,
13172
}
14173

15-
const vault: BaseBeefyVault = {
16-
type: 'gov',
17-
subType: 'cowcentrated',
18-
} as BaseBeefyVault
19-
20174
describe('getDailyYieldRatePercentage', () => {
21175
it('should return the correct daily yield rate percentage when there are components', () => {
22176
const dailyYieldRatePercentage = getDailyYieldRatePercentage(
@@ -54,3 +208,44 @@ describe('getDailyYieldRatePercentage', () => {
54208
expect(dailyYieldRatePercentage).toBeCloseTo(0.164)
55209
})
56210
})
211+
212+
describe('hook', () => {
213+
beforeEach(() => {
214+
jest.clearAllMocks()
215+
})
216+
it('should return the correct hook info', () => {
217+
expect(hook.getInfo()).toEqual({
218+
id: 'beefy',
219+
name: 'Beefy',
220+
description: 'Beefy vaults',
221+
})
222+
})
223+
it('should return expected positions with balances when getPositionDefinitions is called with supported networkId and address', async () => {
224+
mockReadContract.mockResolvedValue(mockGetTokenBalancesResponse)
225+
const beefyPositions = await hook.getPositionDefinitions({
226+
networkId: NetworkId['arbitrum-one'],
227+
address: '0x12345',
228+
t: mockT,
229+
})
230+
expect(beefyPositions.length).toBe(1)
231+
expect(beefyPositions[0]).toEqual(expectedBeefyVault2)
232+
})
233+
it('should return all expected positions when getPositionDefinitions is called with supported networkId and no address', async () => {
234+
const beefyPositions = await hook.getPositionDefinitions({
235+
networkId: NetworkId['arbitrum-one'],
236+
address: undefined,
237+
t: mockT,
238+
})
239+
expect(beefyPositions.length).toBe(2)
240+
expect(beefyPositions[0]).toEqual(expectedBeefyVault1)
241+
expect(beefyPositions[1]).toEqual(expectedBeefyVault2)
242+
})
243+
it('should return an empty array when getPositionDefinitions is called with an unsupported networkId', async () => {
244+
const beefyPositions = await hook.getPositionDefinitions({
245+
networkId: NetworkId['celo-alfajores'],
246+
address: '0x12345',
247+
t: mockT,
248+
})
249+
expect(beefyPositions).toEqual([])
250+
})
251+
})

0 commit comments

Comments
 (0)