Merge pull request 'fix: holdout scenario - use cheats page swap widget, match e2e wallet connection pattern' (#392) from fix/holdout-scenario-swap into master

This commit is contained in:
johba 2026-03-01 21:00:09 +01:00
commit e9abea2307

View file

@ -6,8 +6,9 @@
*
* Reuses tests/setup/ infrastructure no new wallet or navigation helpers.
*
* Account 5 from the Anvil test mnemonic is used so it never collides with
* the deploy scripts (which use accounts 01).
* Account 0 from the Anvil test mnemonic is used (same as e2e tests).
* Deploy scripts also use Account 0, but each test run gets a fresh Anvil stack,
* so no collision occurs.
*/
import { expect, test } from '@playwright/test';
import { Interface, Wallet } from 'ethers';
@ -15,8 +16,8 @@ import { createWalletContext } from '../../../../tests/setup/wallet-provider';
import { getStackConfig } from '../../../../tests/setup/stack';
import { navigateSPA } from '../../../../tests/setup/navigate';
// Anvil account 5 — never used by deploy or txnBot
const PK = '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba';
// Anvil account 0 — same as e2e tests (deploy uses it but state is reset per stack)
const PK = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
const ACCOUNT = new Wallet(PK);
const ACCOUNT_ADDRESS = ACCOUNT.address;
@ -91,56 +92,80 @@ test('I can always leave', async ({ browser }) => {
await page.evaluate(() => window.dispatchEvent(new Event('resize')));
await page.waitForTimeout(2_000);
// ── 2. Connect wallet via the UI ────────────────────────────────────
// ── 2. Connect wallet via the UI (matches e2e/01 pattern) ────────────
console.log('[TEST] Connecting wallet...');
let panelOpened = false;
const connectButton = page.locator('.connect-button--disconnected').first();
if (await connectButton.isVisible({ timeout: 5_000 })) {
console.log('[TEST] Found desktop Connect button, clicking...');
await connectButton.click();
await page.waitForTimeout(1_000);
const connector = page.locator('.connectors-element').first();
if (await connector.isVisible({ timeout: 5_000 })) {
await connector.click();
await page.waitForTimeout(2_000);
} else {
console.log('[TEST] WARNING: wallet connector panel not found after clicking Connect');
}
panelOpened = true;
} else {
console.log('[TEST] Connect button not found — wallet may already be connected or UI class changed');
const screenWidth = await page.evaluate(() => window.screen.width);
console.log(`[TEST] DEBUG: screen.width = ${screenWidth}`);
// Fallback to mobile login icon (dead code — wallet-provider always sets screen.width=1280, copied from e2e/01 for consistency)
const mobileLoginIcon = page.locator('.navbar-end svg').first();
if (await mobileLoginIcon.isVisible({ timeout: 2_000 })) {
console.log('[TEST] Found mobile login icon, clicking...');
await mobileLoginIcon.click();
panelOpened = true;
} else {
console.log('[TEST] No Connect button or mobile icon — wallet may already be connected');
}
}
// Confirm wallet address is displayed in the navbar (app shows first ~6 chars)
const addrPrefix = ACCOUNT_ADDRESS.slice(0, 8); // e.g. "0x996550"
if (panelOpened) {
await page.waitForTimeout(1_000);
console.log('[TEST] Looking for wallet connector in panel...');
const injectedConnector = page.locator('.connectors-element').first();
if (await injectedConnector.isVisible({ timeout: 5_000 })) {
console.log('[TEST] Clicking wallet connector...');
await injectedConnector.click();
await page.waitForTimeout(2_000);
} else {
console.log('[TEST] WARNING: No wallet connector found in panel');
}
}
// Confirm wallet address is displayed in the navbar
const addrPrefix = ACCOUNT_ADDRESS.slice(0, 8);
await expect(page.getByText(new RegExp(addrPrefix, 'i')).first()).toBeVisible({ timeout: 15_000 });
console.log('[TEST] Wallet connected');
// ── 3. Navigate to get-krk and buy KRK via the swap widget ──────────
console.log('[TEST] Navigating to get-krk...');
await navigateSPA(page, '/app/get-krk');
// ── 3. Navigate to cheats page (has swap widget, same as e2e tests) ──
console.log('[TEST] Navigating to cheats...');
await navigateSPA(page, '/app/cheats');
await expect(page.getByRole('heading', { name: 'Cheat Console' })).toBeVisible({ timeout: 10_000 });
// The LocalSwapWidget is rendered when VITE_ENABLE_LOCAL_SWAP=true
const swapInput = page.locator('#local-swap-amount');
// The cheats page has an inline FInput with label 'ETH to spend'
const swapInput = page.getByLabel('ETH to spend');
await expect(swapInput).toBeVisible({ timeout: 15_000 });
console.log('[TEST] Swap widget visible');
const krkBefore = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ACCOUNT_ADDRESS);
console.log(`[TEST] KRK balance before buy: ${krkBefore}`);
// Use fill() which triggers input events for Vue v-model binding
await swapInput.fill('0.1');
await page.waitForTimeout(500);
const buyButton = page.locator('.local-swap-widget .swap-button');
const buyButton = page.getByRole('button', { name: 'Buy' }).last();
await expect(buyButton).toBeVisible();
// Debug: screenshot before clicking
await page.screenshot({ path: 'test-results/holdout-before-buy.png' });
console.log('[TEST] Clicking Buy KRK...');
await buyButton.click();
await page.waitForTimeout(3_000);
await page.screenshot({ path: 'test-results/holdout-after-buy.png' });
// Wait for the swap to complete (button cycles through "Submitting…" → "Buy KRK")
// Wait for the swap to complete (button cycles through "Submitting…" → "Buy")
try {
await buyButton.filter({ hasText: /Submitting/i }).waitFor({ state: 'visible', timeout: 5_000 });
await page.getByRole('button', { name: /Submitting/i }).waitFor({ state: 'visible', timeout: 5_000 });
console.log('[TEST] Swap in progress...');
await buyButton.filter({ hasText: /Buy KRK/i }).waitFor({ state: 'visible', timeout: 60_000 });
await page.getByRole('button', { name: 'Buy' }).last().waitFor({ state: 'visible', timeout: 60_000 });
console.log('[TEST] Swap completed');
} catch (err) {
// On a fast Anvil node the button may cycle too quickly to observe.
// Log the caught value so the root cause is visible if a real error occurred.
console.log(`[TEST] Button state not observed (may be instant): ${err}`);
}
await page.waitForTimeout(2_000);