From 9da1fb820ec3a67565eec8323bfa9118217f8b1b Mon Sep 17 00:00:00 2001 From: johba Date: Mon, 23 Mar 2026 18:03:28 +0000 Subject: [PATCH] fix: detect local swap widget by container class, not wallet-gated input In CI (VITE_ENABLE_LOCAL_SWAP=true), the LocalSwapWidget renders a "Connect your wallet" message when no wallet is connected. The previous check looked for [data-testid="swap-amount-input"] which only appears with an active wallet, causing the test to fall through to the Uniswap link check (which also doesn't exist in local mode). Fix: detect local swap mode via the .local-swap-widget container class which is always rendered. Also add force:true for mobile CTA click. Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/e2e/07-conversion-funnel.spec.ts | 59 +++++++++++++++++--------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/tests/e2e/07-conversion-funnel.spec.ts b/tests/e2e/07-conversion-funnel.spec.ts index 8322fe8..db5e58a 100644 --- a/tests/e2e/07-conversion-funnel.spec.ts +++ b/tests/e2e/07-conversion-funnel.spec.ts @@ -80,21 +80,30 @@ test.describe('Conversion Funnel: Landing → Swap → Stake', () => { await page.screenshot({ path: 'test-results/funnel-02-get-krk-desktop.png' }); - // ── Step 3: Verify Uniswap deep link ── - console.log('[FUNNEL] Verifying Uniswap deep link...'); - const swapLink = page.locator('a.swap-button'); + // ── Step 3: Verify swap page content ── + console.log('[FUNNEL] Verifying swap page...'); - // In local dev, the inline swap widget is shown instead of the Uniswap link. - // Verify whichever variant is active. - const localSwapWidget = page.locator('[data-testid="swap-amount-input"]'); - const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 3_000 }).catch(() => false); + // In local dev (VITE_ENABLE_LOCAL_SWAP=true), the LocalSwapWidget is shown. + // Without a wallet, it renders a "Connect your wallet" message instead of + // the swap input. Check for the widget container class to detect local mode. + const localSwapWidget = page.locator('.local-swap-widget'); + const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 5_000 }).catch(() => false); if (hasLocalSwap) { - console.log('[FUNNEL] Local swap widget detected (dev environment) — skipping Uniswap link check'); - // Verify the local swap widget is functional - await expect(localSwapWidget).toBeVisible(); + console.log('[FUNNEL] Local swap widget detected (dev environment)'); + // Without wallet, the widget shows a connect prompt + const swapWarning = page.locator('.swap-warning'); + const hasWarning = await swapWarning.isVisible({ timeout: 3_000 }).catch(() => false); + if (hasWarning) { + console.log('[FUNNEL] Wallet not connected — swap widget shows connect prompt'); + } else { + // With wallet, the swap input is shown + await expect(page.locator('[data-testid="swap-amount-input"]')).toBeVisible({ timeout: 5_000 }); + console.log('[FUNNEL] Swap input visible'); + } } else { // Production path: verify the Uniswap deep link + const swapLink = page.locator('a.swap-button'); await expect(swapLink).toBeVisible({ timeout: 10_000 }); const href = await swapLink.getAttribute('href'); expect(href).toBeTruthy(); @@ -173,13 +182,16 @@ test.describe('Conversion Funnel: Landing → Swap → Stake', () => { await page.screenshot({ path: 'test-results/funnel-01-landing-mobile.png' }); - // ── Step 2: Click CTA ── + // ── Step 2: Click CTA → navigates to /app/get-krk ── const heroCta = page.locator('.header-cta button, .header-cta .k-button').first(); await expect(heroCta).toBeVisible({ timeout: 15_000 }); console.log('[FUNNEL-MOBILE] Clicking hero CTA...'); + // On mobile, the CTA click triggers window.location.href which starts a + // full-page navigation. Use waitForURL with domcontentloaded to avoid + // waiting for all resources to load on slower mobile emulation. await Promise.all([ - page.waitForURL('**/app/get-krk**', { timeout: 30_000 }), - heroCta.click(), + page.waitForURL('**/app/get-krk**', { timeout: 30_000, waitUntil: 'domcontentloaded' }), + heroCta.click({ force: true }), ]); console.log('[FUNNEL-MOBILE] Navigated to get-krk page'); @@ -188,11 +200,13 @@ test.describe('Conversion Funnel: Landing → Swap → Stake', () => { await page.screenshot({ path: 'test-results/funnel-02-get-krk-mobile.png' }); - // ── Step 3: Verify Uniswap link or local swap on mobile ── - const localSwapWidget = page.locator('[data-testid="swap-amount-input"]'); - const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 3_000 }).catch(() => false); + // ── Step 3: Verify swap page on mobile ── + const localSwapWidget = page.locator('.local-swap-widget'); + const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 5_000 }).catch(() => false); - if (!hasLocalSwap) { + if (hasLocalSwap) { + console.log('[FUNNEL-MOBILE] Local swap widget detected'); + } else { const swapLink = page.locator('a.swap-button'); await expect(swapLink).toBeVisible({ timeout: 10_000 }); const href = await swapLink.getAttribute('href'); @@ -297,13 +311,16 @@ test.describe('Conversion Funnel: Landing → Swap → Stake', () => { await page.goto(`${STACK_WEBAPP_URL}/app/get-krk`, { waitUntil: 'domcontentloaded' }); await expect(page.getByRole('heading', { name: 'Get $KRK Tokens' })).toBeVisible({ timeout: 15_000 }); - // Check if we're in local swap mode or production link mode - const localSwapWidget = page.locator('[data-testid="swap-amount-input"]'); - const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 3_000 }).catch(() => false); + // Check if we're in local swap mode or production link mode. + // The LocalSwapWidget container is always rendered when enableLocalSwap=true, + // but the swap input only appears when a wallet is connected. + const localSwapWidget = page.locator('.local-swap-widget'); + const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 5_000 }).catch(() => false); if (hasLocalSwap) { console.log('[DEEPLINK] Local swap mode — verifying swap widget is functional'); - await expect(localSwapWidget).toBeVisible(); + // With wallet context, the swap input and buy button should be visible + await expect(page.locator('[data-testid="swap-amount-input"]')).toBeVisible({ timeout: 5_000 }); await expect(page.getByTestId('swap-buy-button')).toBeVisible(); console.log('[DEEPLINK] ✅ Local swap widget verified'); } else {