E2E tests + governance optimistic actions + proposal redirect#964
E2E tests + governance optimistic actions + proposal redirect#964
Conversation
…sal redirect - Add Playwright e2e test infrastructure with fully mocked network (API, subgraph, RPC) - Add governance e2e tests (8 tests: list rendering, proposal detail, navigation) - Replace setTimeout(10000) hacks in submit-proposal buttons with immediate redirect - Parse ProposalCreated event to navigate directly to proposal detail page - Add optimistic action atoms for vote/queue/execute (instant UI feedback) - Refactor proposal-detail-stats to use atom data instead of on-chain RPC call - Simplify proposal updater with deadline-aware polling (1s near deadline, 10s otherwise) - Add useProposalDetail polling with retry cap for just-created proposals - Add governance.ts unit tests (17 tests) and optimistic-actions tests (12 tests) - Add defensive basket/performance null guards in discover components - Add data-testid attributes for e2e selectors across UI components
Deploying register-app with
|
| Latest commit: |
4aa36ce
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a917e4c7.register-app.pages.dev |
| Branch Preview URL: | https://feature-e2e.register-app.pages.dev |
| }) | ||
|
|
||
| // Merkl campaign API — prevents real network calls from overview page | ||
| await page.route('**/api.merkl.xyz/**', (route) => { |
There was a problem hiding this comment.
Merkl? we no longer use it, pretty sure, this is stale code
| // Discover DTF list — only return data for Base (8453), empty for other chains. | ||
| if (pathname.includes('/discover/dtf')) { | ||
| const chainId = new URL(url).searchParams.get('chainId') | ||
| const data = chainId === '8453' ? discoverDtfData : [] |
There was a problem hiding this comment.
dont use magic numbers, we have the chainIDs stored on constants
There was a problem hiding this comment.
Also, pretty sure latest endpoint is chain independant and it returns all the indexDTFs
| export async function installTestWallet( | ||
| page: Page, | ||
| config: MockWalletConfig = { | ||
| address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', |
There was a problem hiding this comment.
wasnt this a constant?
| page: Page, | ||
| config: MockWalletConfig = { | ||
| address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', | ||
| chainId: 8453, |
| page: Page, | ||
| config: MockWalletConfig = { | ||
| address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', | ||
| chainId: 8453, |
There was a problem hiding this comment.
Also make sure to support multichain on our mock provider, we will want to test with ChainId.Mainnet, ChainId.Base and ChainId.BSC
| } from '../optimistic-actions' | ||
| import { Address } from 'viem' | ||
|
|
||
| const makeProposalDetail = ( |
There was a problem hiding this comment.
lets grab a REAL proposal detail data for this mock
|
|
||
| const { writeContract, isPending, data, error } = useWriteContract() | ||
| const { isSuccess } = useWaitForTransactionReceipt({ | ||
| const targets = useMemo(() => { |
There was a problem hiding this comment.
is this robust enough?
| targets, | ||
| calldatas: calldatas ?? [], | ||
| description: description ?? '', | ||
| govAddress: (govAddress ?? '0x') as Address, |
There was a problem hiding this comment.
govAddress and Proposer MUST be there, this is to fragile
| proposer: (wallet ?? '0x') as Address, | ||
| }) | ||
|
|
||
| const handleSubmit = () => { |
There was a problem hiding this comment.
I think handleSubmit is the spot where we need to save the state for the optimisticActions data, everything must be here, voter, gov address, targets, etc
There was a problem hiding this comment.
it may actually just be updating a ref
| receipt, | ||
| targets: proposalData?.targets ?? [], | ||
| calldatas: proposalData?.calldatas ?? [], | ||
| description: description ?? '', |
There was a problem hiding this comment.
same, this thing is fragile
Summary
ProposalCreatedevent is parsed from the receipt to get the proposal ID, and an optimisticProposalDetailis pre-seeded.useProposalDetailpolls the subgraph every 3s (capped at 10 retries) until real data arrives.proposal-detail-statsno longer makes an on-chainproposalVotes()RPC call — it reads from the atom (subgraph + optimistic data). The proposal updater was simplified: removed the key-based remount hack andproposalRefreshFnAtom, replaced with deadline-aware polling (1s in last 5 min, 10s otherwise).basket ?? []guards in discover components,governance.tsgets optionalcurrentTimeparam for testability,data-testidattributes for e2e selectors.Tests
getProposalState(governance.test.ts)