feat/ponder-lm-indexing (#142)
This commit is contained in:
parent
de3c8eef94
commit
31063379a8
107 changed files with 12517 additions and 367 deletions
178
tests/e2e/usertest/all-personas.spec.ts
Normal file
178
tests/e2e/usertest/all-personas.spec.ts
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
import { test } from '@playwright/test';
|
||||
import { Wallet } from 'ethers';
|
||||
import { createWalletContext } from '../../setup/wallet-provider';
|
||||
import { getStackConfig, validateStackHealthy } from '../../setup/stack';
|
||||
import {
|
||||
createReport,
|
||||
connectWallet,
|
||||
mintEth,
|
||||
buyKrk,
|
||||
takeScreenshot,
|
||||
logObservation,
|
||||
recordAction,
|
||||
writeReport,
|
||||
attemptStake,
|
||||
resetChainState,
|
||||
} from './helpers';
|
||||
|
||||
const STACK_CONFIG = getStackConfig();
|
||||
const STACK_RPC_URL = STACK_CONFIG.rpcUrl;
|
||||
const STACK_WEBAPP_URL = STACK_CONFIG.webAppUrl;
|
||||
|
||||
// Persona accounts (Anvil #1-5)
|
||||
// Note: Pool has limited liquidity - 0.05 ETH buy yields ~3.99 KRK
|
||||
// Staking 3 KRK leaves enough for upfront tax payment
|
||||
const PERSONAS = [
|
||||
{
|
||||
name: 'Marcus Flash Chen',
|
||||
shortName: 'Marcus',
|
||||
privateKey: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',
|
||||
ethToMint: '10',
|
||||
ethToSpend: '0.05',
|
||||
stakeAmount: '3', // Conservative amount that fits within ~3.99 KRK balance
|
||||
taxRate: '2',
|
||||
},
|
||||
{
|
||||
name: 'Sarah Park',
|
||||
shortName: 'Sarah',
|
||||
privateKey: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a',
|
||||
ethToMint: '10',
|
||||
ethToSpend: '0.05',
|
||||
stakeAmount: '3',
|
||||
taxRate: '2',
|
||||
},
|
||||
{
|
||||
name: 'Tyler Brooks',
|
||||
shortName: 'Tyler',
|
||||
privateKey: '0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6',
|
||||
ethToMint: '10',
|
||||
ethToSpend: '0.05',
|
||||
stakeAmount: '3',
|
||||
taxRate: '2',
|
||||
},
|
||||
{
|
||||
name: 'Priya Sharma',
|
||||
shortName: 'Priya',
|
||||
privateKey: '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a',
|
||||
ethToMint: '10',
|
||||
ethToSpend: '0.05',
|
||||
stakeAmount: '3',
|
||||
taxRate: '2',
|
||||
},
|
||||
{
|
||||
name: 'Alex Rivera',
|
||||
shortName: 'Alex',
|
||||
privateKey: '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba',
|
||||
ethToMint: '10',
|
||||
ethToSpend: '0.05',
|
||||
stakeAmount: '3',
|
||||
taxRate: '2',
|
||||
},
|
||||
];
|
||||
|
||||
test.describe('All Personas - Fresh Pool State', () => {
|
||||
for (const persona of PERSONAS) {
|
||||
test(`${persona.name} completes full journey`, async ({ browser }) => {
|
||||
// Reset chain state before THIS persona
|
||||
// First call takes initial snapshot, subsequent calls revert to it
|
||||
console.log(`\n[ORCHESTRATOR] Resetting chain state for ${persona.name}...`);
|
||||
await resetChainState(STACK_RPC_URL);
|
||||
|
||||
// Validate stack health once at start
|
||||
if (persona === PERSONAS[0]) {
|
||||
console.log('[ORCHESTRATOR] Validating stack health...');
|
||||
await validateStackHealthy(STACK_CONFIG);
|
||||
}
|
||||
|
||||
const report = createReport(persona.name);
|
||||
const address = new Wallet(persona.privateKey).address.toLowerCase();
|
||||
|
||||
console.log(`[${persona.shortName}] Starting test - fresh pool state`);
|
||||
|
||||
const context = await createWalletContext(browser, {
|
||||
privateKey: persona.privateKey,
|
||||
rpcUrl: STACK_RPC_URL,
|
||||
});
|
||||
|
||||
const page = await context.newPage();
|
||||
page.on('console', msg => console.log(`[BROWSER] ${msg.type()}: ${msg.text()}`));
|
||||
page.on('pageerror', error => console.log(`[BROWSER ERROR] ${error.message}`));
|
||||
|
||||
try {
|
||||
// 1. Navigate to app
|
||||
await page.goto(`${STACK_WEBAPP_URL}/app/`, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(2_000);
|
||||
await takeScreenshot(page, persona.shortName, '1-landing', report);
|
||||
logObservation(persona.shortName, 'Arrived at app', report);
|
||||
|
||||
// 2. Connect wallet
|
||||
await connectWallet(page);
|
||||
await takeScreenshot(page, persona.shortName, '2-wallet-connected', report);
|
||||
recordAction('Connect wallet', true, undefined, report);
|
||||
console.log(`[${persona.shortName}] ✅ Wallet connected`);
|
||||
|
||||
// 3. Mint ETH
|
||||
await page.goto(`${STACK_WEBAPP_URL}/app/#/cheats`);
|
||||
await page.waitForTimeout(1_000);
|
||||
await mintEth(page, STACK_RPC_URL, address, persona.ethToMint);
|
||||
await takeScreenshot(page, persona.shortName, '3-eth-minted', report);
|
||||
recordAction(`Mint ${persona.ethToMint} ETH`, true, undefined, report);
|
||||
console.log(`[${persona.shortName}] ✅ Minted ${persona.ethToMint} ETH`);
|
||||
|
||||
// 4. Buy KRK
|
||||
await buyKrk(page, persona.ethToSpend);
|
||||
await takeScreenshot(page, persona.shortName, '4-krk-purchased', report);
|
||||
recordAction(`Buy KRK with ${persona.ethToSpend} ETH`, true, undefined, report);
|
||||
console.log(`[${persona.shortName}] ✅ Bought KRK with ${persona.ethToSpend} ETH`);
|
||||
|
||||
await page.waitForTimeout(2_000);
|
||||
|
||||
// 5. Navigate to stake page
|
||||
await page.goto(`${STACK_WEBAPP_URL}/app/#/stake`);
|
||||
await page.waitForTimeout(3_000);
|
||||
await takeScreenshot(page, persona.shortName, '5-stake-page', report);
|
||||
|
||||
// 6. Stake KRK with known working amount
|
||||
const stakeAmount = persona.stakeAmount;
|
||||
console.log(`[${persona.shortName}] Attempting to stake ${stakeAmount} KRK at ${persona.taxRate}% tax...`);
|
||||
await attemptStake(page, stakeAmount, persona.taxRate, persona.shortName, report);
|
||||
await takeScreenshot(page, persona.shortName, '6-stake-complete', report);
|
||||
console.log(`[${persona.shortName}] ✅ Staked ${stakeAmount} KRK at ${persona.taxRate}% tax`);
|
||||
|
||||
await page.waitForTimeout(2_000);
|
||||
|
||||
// 7. Verify position exists
|
||||
await page.goto(`${STACK_WEBAPP_URL}/app/#/stake`);
|
||||
await page.waitForTimeout(2_000);
|
||||
|
||||
const myPositionsSection = page.locator('.my-positions-list, [class*="my-position"], [class*="MyPosition"]').first();
|
||||
const hasPosition = await myPositionsSection.isVisible({ timeout: 5_000 }).catch(() => false);
|
||||
|
||||
if (hasPosition) {
|
||||
await takeScreenshot(page, persona.shortName, '7-position-verified', report);
|
||||
recordAction('Verify staked position exists', true, undefined, report);
|
||||
console.log(`[${persona.shortName}] ✅ Position verified in UI`);
|
||||
} else {
|
||||
await takeScreenshot(page, persona.shortName, '7-position-check-failed', report);
|
||||
recordAction('Verify staked position exists', false, 'Position not visible in UI', report);
|
||||
console.log(`[${persona.shortName}] ⚠️ Position not visible in UI - may still exist on-chain`);
|
||||
}
|
||||
|
||||
report.overallSentiment = `${persona.name} completed full journey: connected wallet → bought KRK → staked → ${hasPosition ? 'verified position' : 'stake attempted but position not visible'}`;
|
||||
logObservation(persona.shortName, report.overallSentiment, report);
|
||||
|
||||
console.log(`[${persona.shortName}] ✅ FULL JOURNEY COMPLETE`);
|
||||
|
||||
} catch (error: any) {
|
||||
const errorMsg = error.message || String(error);
|
||||
console.error(`[${persona.shortName}] ❌ Test failed: ${errorMsg}`);
|
||||
await takeScreenshot(page, persona.shortName, 'error-state', report).catch(() => {});
|
||||
report.overallSentiment = `Test failed: ${errorMsg}`;
|
||||
throw error;
|
||||
} finally {
|
||||
writeReport(persona.name.toLowerCase().replace(/\s+/g, '-'), report);
|
||||
await context.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue