2026-02-18 00:19:05 +01:00
import { expect , 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 ,
logCopyFeedback ,
logTokenomicsQuestion ,
recordPageVisit ,
recordAction ,
writeReport ,
attemptStake ,
resetChainState ,
} from './helpers' ;
// Alex uses Anvil account #0 (same as original test, different persona)
const ACCOUNT_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' ;
const ACCOUNT_ADDRESS = new Wallet ( ACCOUNT_PRIVATE_KEY ) . address . toLowerCase ( ) ;
const STACK_CONFIG = getStackConfig ( ) ;
const STACK_RPC_URL = STACK_CONFIG . rpcUrl ;
const STACK_WEBAPP_URL = STACK_CONFIG . webAppUrl ;
test . describe ( 'Alex Rivera - Crypto-Curious Newcomer' , ( ) = > {
test . beforeAll ( async ( ) = > {
await resetChainState ( STACK_RPC_URL ) ;
await validateStackHealthy ( STACK_CONFIG ) ;
} ) ;
test ( 'Alex learns about DeFi through Kraiken' , async ( { browser } ) = > {
const report = createReport ( 'Alex Rivera' ) ;
const personaName = 'Alex' ;
console . log ( ` [ ${ personaName } ] Starting test - Newcomer trying to understand DeFi... ` ) ;
const context = await createWalletContext ( browser , {
privateKey : ACCOUNT_PRIVATE_KEY ,
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 {
// --- Landing Page (Reads Carefully) ---
let pageStart = Date . now ( ) ;
await page . goto ( ` ${ STACK_WEBAPP_URL } /app/ ` , { waitUntil : 'domcontentloaded' } ) ;
await page . waitForTimeout ( 3 _000 ) ;
await takeScreenshot ( page , personaName , 'landing-page' , report ) ;
logObservation ( personaName , 'This looks professional but I have no idea what I\'m looking at...' , report ) ;
logCopyFeedback ( personaName , 'Landing page should have a "New to DeFi?" section that explains basics' , report ) ;
logTokenomicsQuestion ( personaName , 'What is staking? How do I make money from this?' , report ) ;
recordPageVisit ( 'Landing' , page . url ( ) , pageStart , report ) ;
// --- Look for Help/Tutorial ---
logObservation ( personaName , 'Looking for a "How it Works" or tutorial before I do anything...' , report ) ;
const tutorialVisible = await page . getByText ( /how it works|tutorial|getting started|learn/i ) . isVisible ( ) . catch ( ( ) = > false ) ;
if ( ! tutorialVisible ) {
logCopyFeedback ( personaName , 'CRITICAL: No "Getting Started" guide visible. I\'m intimidated and don\'t know where to begin.' , report ) ;
logObservation ( personaName , 'Feeling overwhelmed - too much jargon without explanation' , report ) ;
}
await takeScreenshot ( page , personaName , 'looking-for-help' , report ) ;
// --- Nervous About Connecting Wallet ---
logObservation ( personaName , 'I\'ve heard about wallet scams... is this safe to connect?' , report ) ;
logCopyFeedback ( personaName , 'Need trust signals: "Audited", "Secure", "Non-custodial" badges to reassure newcomers' , report ) ;
const securityInfo = await page . getByText ( /secure|safe|audited|trusted/i ) . isVisible ( ) . catch ( ( ) = > false ) ;
if ( ! securityInfo ) {
logObservation ( personaName , 'No security information visible - makes me nervous to connect wallet' , report ) ;
}
await page . waitForTimeout ( 2 _000 ) ;
// --- Decides to Connect Wallet (Cautiously) ---
logObservation ( personaName , 'Okay, deep breath... connecting wallet for the first time on this app' , report ) ;
try {
await connectWallet ( page ) ;
await takeScreenshot ( page , personaName , 'wallet-connected' , report ) ;
recordAction ( 'Connect wallet (first time)' , true , undefined , report ) ;
logObservation ( personaName , 'Wallet connected! That was easier than I thought. Now what?' , report ) ;
} catch ( error : any ) {
logObservation ( personaName , ` Wallet connection failed: ${ error . message } . This is too complicated, giving up. ` , report ) ;
logCopyFeedback ( personaName , 'Wallet connection errors need beginner-friendly explanations' , report ) ;
recordAction ( 'Connect wallet' , false , error . message , report ) ;
throw error ;
}
// --- Navigate to Stake Page to Learn ---
pageStart = Date . now ( ) ;
2026-02-20 17:28:59 +01:00
await page . goto ( ` ${ STACK_WEBAPP_URL } /app/stake ` ) ;
2026-02-18 00:19:05 +01:00
await page . waitForTimeout ( 3 _000 ) ;
recordPageVisit ( 'Stake (learning)' , page . url ( ) , pageStart , report ) ;
await takeScreenshot ( page , personaName , 'stake-page-first-look' , report ) ;
logObservation ( personaName , 'Lots of numbers and charts... what does it all mean?' , report ) ;
logTokenomicsQuestion ( personaName , 'What is a "Harberger Tax"? Never heard of this before.' , report ) ;
logTokenomicsQuestion ( personaName , 'What are "owner slots"? Is that like shares?' , report ) ;
// --- Reads Info Icon ---
const infoIcon = page . locator ( 'svg' ) . filter ( { hasText : /info/i } ) . first ( ) ;
const infoVisible = await infoIcon . isVisible ( ) . catch ( ( ) = > false ) ;
if ( infoVisible ) {
logObservation ( personaName , 'Found info icon - let me read this...' , report ) ;
// Try to hover to see tooltip
await infoIcon . hover ( ) . catch ( ( ) = > { } ) ;
await page . waitForTimeout ( 1 _000 ) ;
await takeScreenshot ( page , personaName , 'reading-info-tooltip' , report ) ;
logCopyFeedback ( personaName , 'Info tooltips help, but still too technical for total beginners' , report ) ;
} else {
logCopyFeedback ( personaName , 'Need more info icons and tooltips to explain every element' , report ) ;
}
// --- Confused by Terminology ---
logObservation ( personaName , 'Words I don\'t understand: VWAP, tax rate, snatching, claimed slots...' , report ) ;
logCopyFeedback ( personaName , 'ESSENTIAL: Need a glossary or hover definitions for all DeFi terms' , report ) ;
// --- Tries to Find FAQ ---
logObservation ( personaName , 'Looking for FAQ or help section...' , report ) ;
const faqVisible = await page . getByText ( /faq|frequently asked|help/i ) . isVisible ( ) . catch ( ( ) = > false ) ;
if ( ! faqVisible ) {
logCopyFeedback ( personaName , 'No FAQ visible! Common questions like "Can I lose money?" need answers up front.' , report ) ;
logTokenomicsQuestion ( personaName , 'Can I lose my money if I stake? What are the risks?' , report ) ;
}
// --- Mint ETH (Following Instructions) ---
logObservation ( personaName , 'I need to get some tokens first... let me figure out how' , report ) ;
pageStart = Date . now ( ) ;
2026-02-20 17:28:59 +01:00
await page . goto ( ` ${ STACK_WEBAPP_URL } /app/cheats ` ) ;
2026-02-18 00:19:05 +01:00
await page . waitForTimeout ( 2 _000 ) ;
recordPageVisit ( 'Cheats (confused)' , page . url ( ) , pageStart , report ) ;
await takeScreenshot ( page , personaName , 'cheats-page' , report ) ;
logObservation ( personaName , '"Cheat Console"? Is this for testing? I\'m confused but will try it...' , report ) ;
try {
await mintEth ( page , STACK_RPC_URL , ACCOUNT_ADDRESS , '5' ) ;
recordAction ( 'Mint 5 ETH (following guide)' , true , undefined , report ) ;
logObservation ( personaName , 'Got some ETH! Still not sure what I\'m doing though...' , report ) ;
} catch ( error : any ) {
logObservation ( personaName , ` Mint failed: ${ error . message } . These errors are scary! ` , report ) ;
logCopyFeedback ( personaName , 'Error messages should be encouraging, not scary. Add "Need help?" links.' , report ) ;
recordAction ( 'Mint ETH' , false , error . message , report ) ;
}
// --- Buy Small Amount (Cautiously) ---
logObservation ( personaName , 'Buying the smallest amount possible to test - don\'t want to lose much if this is a scam' , report ) ;
try {
await buyKrk ( page , '0.8' ) ;
recordAction ( 'Buy KRK with 0.05 ETH (minimal test)' , true , undefined , report ) ;
await takeScreenshot ( page , personaName , 'small-purchase' , report ) ;
logObservation ( personaName , 'Purchase went through! That was actually pretty smooth.' , report ) ;
logCopyFeedback ( personaName , 'Good: Transaction was straightforward. Bad: No confirmation message explaining what happened.' , report ) ;
} catch ( error : any ) {
logObservation ( personaName , ` Buy failed: ${ error . message } . Maybe I should just stick to Coinbase... ` , report ) ;
recordAction ( 'Buy KRK' , false , error . message , report ) ;
}
await page . waitForTimeout ( 2 _000 ) ;
// --- Navigate to Stake (Intimidated) ---
pageStart = Date . now ( ) ;
2026-02-20 17:28:59 +01:00
await page . goto ( ` ${ STACK_WEBAPP_URL } /app/stake ` ) ;
2026-02-18 00:19:05 +01:00
await page . waitForTimeout ( 2 _000 ) ;
recordPageVisit ( 'Stake (attempting)' , page . url ( ) , pageStart , report ) ;
await takeScreenshot ( page , personaName , 'stake-form-confused' , report ) ;
logObservation ( personaName , 'Staring at the stake form... what tax rate should I pick???' , report ) ;
logTokenomicsQuestion ( personaName , 'Higher tax = more money or less money? This is backwards from normal taxes!' , report ) ;
logCopyFeedback ( personaName , 'CRITICAL: Tax rate needs "Recommended for beginners: 10-15%" guidance' , report ) ;
// --- Looks for Recommendation ---
const recommendationVisible = await page . getByText ( /recommended|suggested|beginner/i ) . isVisible ( ) . catch ( ( ) = > false ) ;
if ( ! recommendationVisible ) {
logCopyFeedback ( personaName , 'Please add a "What should I choose?" helper or wizard mode for newcomers!' , report ) ;
}
// --- Attempt Conservative Stake ---
logObservation ( personaName , 'Going with 15% because it sounds safe... I think? Really not sure about this.' , report ) ;
try {
await attemptStake ( page , '25' , '15' , personaName , report ) ;
await takeScreenshot ( page , personaName , 'stake-success' , report ) ;
logObservation ( personaName , 'IT WORKED! I just staked my first crypto! But... what happens now?' , report ) ;
recordAction ( 'Stake 25 KRK at 15% tax (nervous)' , true , undefined , report ) ;
logTokenomicsQuestion ( personaName , 'When do I get paid? How much will I earn? Where do I see my rewards?' , report ) ;
} catch ( error : any ) {
logObservation ( personaName , ` Stake failed: ${ error . message } . I give up, this is too hard. ` , report ) ;
logCopyFeedback ( personaName , 'Failed stakes need recovery guidance: "Here\'s what to try next..."' , report ) ;
await takeScreenshot ( page , personaName , 'stake-failed' , report ) ;
}
await page . waitForTimeout ( 3 _000 ) ;
// --- Check for Progress Indicators ---
2026-02-20 17:28:59 +01:00
await page . goto ( ` ${ STACK_WEBAPP_URL } /app/stake ` ) ;
2026-02-18 00:19:05 +01:00
await page . waitForTimeout ( 2 _000 ) ;
await takeScreenshot ( page , personaName , 'looking-for-my-position' , report ) ;
logObservation ( personaName , 'Where is my position? How do I see what I earned?' , report ) ;
logCopyFeedback ( personaName , 'Need a big "Your Position" dashboard showing: amount staked, daily earnings, time held' , report ) ;
// --- Worried About Snatching ---
logObservation ( personaName , 'I see something about "snatching"... can someone steal my stake???' , report ) ;
logTokenomicsQuestion ( personaName , 'What does snatching mean? Will I lose my money? This is scary!' , report ) ;
logCopyFeedback ( personaName , 'Snatching concept is TERRIFYING for newcomers. Need clear "You don\'t lose principal" message.' , report ) ;
await takeScreenshot ( page , personaName , 'worried-about-snatching' , report ) ;
// --- Compare to Coinbase ---
logObservation ( personaName , 'On Coinbase I just click "Stake ETH" and get 4% APY. This is way more complicated...' , report ) ;
logTokenomicsQuestion ( personaName , 'Why should I use this instead of just staking ETH on Coinbase?' , report ) ;
logCopyFeedback ( personaName , 'Need comparison: "Coinbase: 4% simple. Kraiken: 8-15% but you choose your own risk level"' , report ) ;
// --- Final Feelings ---
await page . waitForTimeout ( 2 _000 ) ;
await takeScreenshot ( page , personaName , 'final-state' , report ) ;
report . overallSentiment = 'Mixed feelings - excited that I did my first DeFi stake, but confused and nervous about many things. GOOD: The actual transaction process was smooth once I figured it out. UI looks professional and trustworthy. CONFUSING: Harberger tax concept is completely foreign to me. Don\'t understand how tax rates affect my earnings. Scared about "snatching" - sounds like I could lose money. No clear guidance on what to do next or how to track earnings. NEEDED: (1) "Getting Started" tutorial with video walkthrough, (2) Glossary of terms in plain English, (3) Tax rate wizard that asks questions and recommends a rate, (4) Big clear "Your Daily Earnings: $X" display, (5) FAQ addressing "Can I lose money?" and "What is snatching?", (6) Comparison to Coinbase/simple staking to show why this is better. VERDICT: Would monitor my tiny stake for a week to see what happens. If I actually earn money and nothing bad happens, I might add more. But if I get "snatched" without understanding why, I\'m selling everything and never coming back. This needs to be MUCH more beginner-friendly to compete with centralized platforms.' ;
logObservation ( personaName , report . overallSentiment , report ) ;
} finally {
writeReport ( 'alex-rivera' , report ) ;
await context . close ( ) ;
}
} ) ;
} ) ;