-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor: extract filters to composable and add tests (#4264)
* Refactor: extract filters to composable and add tests * Fix tests
- Loading branch information
Showing
3 changed files
with
200 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
src/components/contextual/pages/vebal/LMVoting/composables/useLMVotingFilters.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { mountComposableWithFakeTokensProvider as mountComposable } from '@tests/mount-helpers'; | ||
|
||
import { VotingPool } from '@/composables/queries/useVotingPoolsQuery'; | ||
import { Network } from '@/lib/config/types'; | ||
import { GqlChain } from '@/services/api/graphql/generated/api-types'; | ||
import { LocationQuery, createRouter, createWebHistory } from 'vue-router'; | ||
import { aVotingPool } from '../../MultiVoting/voting-pool.builders'; | ||
import { useLMVotingFilters } from './useLMVotingFilters'; | ||
|
||
function buildRouterMock() { | ||
const router = createRouter({ | ||
history: createWebHistory(), | ||
routes: [ | ||
{ | ||
path: '/blank', | ||
name: 'test route', | ||
component: {}, | ||
}, | ||
], | ||
}); | ||
|
||
// fake router params | ||
router.currentRoute.value.params = {}; | ||
router.push = vi.fn(); | ||
|
||
function setRouteQuery(chain: LocationQuery) { | ||
router.currentRoute.value.query = chain; | ||
} | ||
|
||
return { router, setRouteQuery }; | ||
} | ||
|
||
async function mountLmVotingFilters( | ||
votingPools: ComputedRef<VotingPool[]>, | ||
expiredGauges: Ref<readonly string[] | undefined>, | ||
routerMock = buildRouterMock().router | ||
) { | ||
const { result } = await mountComposable( | ||
() => useLMVotingFilters(votingPools, expiredGauges), | ||
{ routerMock } | ||
); | ||
return result; | ||
} | ||
|
||
const expiredGauges = ref([]); | ||
|
||
it('empty filters by default', async () => { | ||
const votingPools = computed(() => [aVotingPool()]); | ||
const { activeNetworkFilters } = await mountLmVotingFilters( | ||
votingPools, | ||
expiredGauges | ||
); | ||
expect(activeNetworkFilters.value).toEqual([]); | ||
}); | ||
|
||
it('when the url chain filter in the query string', async () => { | ||
const { router, setRouteQuery } = buildRouterMock(); | ||
setRouteQuery({ chain: 'arbitrum' }); | ||
|
||
const anArbitrumPool = aVotingPool({ | ||
network: Network.ARBITRUM, | ||
}); | ||
const anMainnetPool = aVotingPool({ chain: GqlChain.Mainnet }); | ||
|
||
const votingPools = computed(() => [anArbitrumPool, anMainnetPool]); | ||
|
||
const { activeNetworkFilters, filteredVotingPools } = | ||
await mountLmVotingFilters(votingPools, expiredGauges, router); | ||
|
||
expect(activeNetworkFilters.value).toEqual([42161]); | ||
expect(filteredVotingPools.value).toEqual([anArbitrumPool]); | ||
}); | ||
|
||
it('filters by token symbol', async () => { | ||
const { router, setRouteQuery } = buildRouterMock(); | ||
setRouteQuery({}); | ||
const aVotingPoolWithGoldToken = aVotingPool(); | ||
aVotingPoolWithGoldToken.tokens[0].symbol = 'Gold'; | ||
|
||
const votingPools = computed(() => [ | ||
aVotingPoolWithGoldToken, | ||
aVotingPool({ tokens: [] }), | ||
]); | ||
|
||
const { filteredVotingPools, tokenFilter, activeNetworkFilters } = | ||
await mountLmVotingFilters(votingPools, expiredGauges, router); | ||
|
||
tokenFilter.value = 'Gol'; | ||
|
||
expect(activeNetworkFilters.value).toEqual([]); | ||
|
||
expect(filteredVotingPools.value).toEqual([aVotingPoolWithGoldToken]); | ||
}); | ||
|
||
it('calculates networkFilters', async () => { | ||
const { networkFilters } = await mountLmVotingFilters( | ||
computed(() => []), | ||
expiredGauges | ||
); | ||
|
||
expect(networkFilters).toEqual([1, 10, 100, 137, 1101, 8453, 42161, 43114]); | ||
}); |
85 changes: 85 additions & 0 deletions
85
src/components/contextual/pages/vebal/LMVoting/composables/useLMVotingFilters.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { VotingPool } from '@/composables/queries/useVotingPoolsQuery'; | ||
import useDebouncedRef from '@/composables/useDebouncedRed'; | ||
import { isGaugeExpired } from '../../voting-utils'; | ||
import { Network } from '@/lib/config/types'; | ||
import configs from '@/lib/config'; | ||
|
||
export function useLMVotingFilters( | ||
votingPools: ComputedRef<VotingPool[]>, | ||
expiredGauges: Ref<readonly string[] | undefined> | ||
) { | ||
const router = useRouter(); | ||
|
||
const showExpiredGauges = useDebouncedRef<boolean>(false, 500); | ||
const tokenFilter = useDebouncedRef<string>('', 500); | ||
const activeNetworkFilters = useDebouncedRef<Network[]>( | ||
getDefaultActiveNetworkFilter(), | ||
500 | ||
); | ||
|
||
const poolsFilteredByExpiring = computed(() => { | ||
if (showExpiredGauges.value) { | ||
return votingPools.value; | ||
} | ||
|
||
return votingPools.value.filter(pool => { | ||
if (Number(pool.userVotes) > 0) { | ||
return true; | ||
} | ||
return !isGaugeExpired(expiredGauges.value, pool.gauge.address); | ||
}); | ||
}); | ||
|
||
function getDefaultActiveNetworkFilter() { | ||
const param = router.currentRoute.value.query.chain; | ||
|
||
if (!param || typeof param !== 'string') { | ||
return []; | ||
} | ||
|
||
const networkToFilter = Network[param.toUpperCase()]; | ||
if (!networkToFilter) { | ||
return []; | ||
} | ||
|
||
return [networkToFilter]; | ||
} | ||
|
||
const filteredVotingPools = computed(() => { | ||
// put filter by expiring in separate computed to maintain readability | ||
return poolsFilteredByExpiring.value.filter(pool => { | ||
let showByNetwork = true; | ||
if ( | ||
activeNetworkFilters.value.length > 0 && | ||
!activeNetworkFilters.value.includes(pool.network) | ||
) { | ||
showByNetwork = false; | ||
} | ||
|
||
return ( | ||
showByNetwork && | ||
pool.tokens.some(token => { | ||
return token.symbol | ||
?.toLowerCase() | ||
.includes(tokenFilter.value.toLowerCase()); | ||
}) | ||
); | ||
}); | ||
}); | ||
|
||
const networkFilters: Network[] = Object.entries(configs) | ||
.filter(details => { | ||
const config = details[1]; | ||
return ( | ||
!config.testNetwork && config.pools.Stakable.VotingGaugePools.length > 0 | ||
); | ||
}) | ||
.map(details => Number(details[0]) as Network); | ||
return { | ||
showExpiredGauges, | ||
activeNetworkFilters, | ||
filteredVotingPools, | ||
tokenFilter, | ||
networkFilters, | ||
}; | ||
} |
c2f144c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
beta-app-v2 – ./
beta-app-v2-balancer.vercel.app
beta-app-v2.vercel.app
beta-app-v2-git-develop-balancer.vercel.app
beta.balancer.fi