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) <noreply@anthropic.com>
This commit is contained in:
johba 2026-03-23 18:03:28 +00:00
parent ea700b224e
commit 9da1fb820e

View file

@ -80,21 +80,30 @@ test.describe('Conversion Funnel: Landing → Swap → Stake', () => {
await page.screenshot({ path: 'test-results/funnel-02-get-krk-desktop.png' }); await page.screenshot({ path: 'test-results/funnel-02-get-krk-desktop.png' });
// ── Step 3: Verify Uniswap deep link ── // ── Step 3: Verify swap page content ──
console.log('[FUNNEL] Verifying Uniswap deep link...'); console.log('[FUNNEL] Verifying swap page...');
const swapLink = page.locator('a.swap-button');
// In local dev, the inline swap widget is shown instead of the Uniswap link. // In local dev (VITE_ENABLE_LOCAL_SWAP=true), the LocalSwapWidget is shown.
// Verify whichever variant is active. // Without a wallet, it renders a "Connect your wallet" message instead of
const localSwapWidget = page.locator('[data-testid="swap-amount-input"]'); // the swap input. Check for the widget container class to detect local mode.
const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 3_000 }).catch(() => false); const localSwapWidget = page.locator('.local-swap-widget');
const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 5_000 }).catch(() => false);
if (hasLocalSwap) { if (hasLocalSwap) {
console.log('[FUNNEL] Local swap widget detected (dev environment) — skipping Uniswap link check'); console.log('[FUNNEL] Local swap widget detected (dev environment)');
// Verify the local swap widget is functional // Without wallet, the widget shows a connect prompt
await expect(localSwapWidget).toBeVisible(); 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 { } else {
// Production path: verify the Uniswap deep link // Production path: verify the Uniswap deep link
const swapLink = page.locator('a.swap-button');
await expect(swapLink).toBeVisible({ timeout: 10_000 }); await expect(swapLink).toBeVisible({ timeout: 10_000 });
const href = await swapLink.getAttribute('href'); const href = await swapLink.getAttribute('href');
expect(href).toBeTruthy(); 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' }); 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(); const heroCta = page.locator('.header-cta button, .header-cta .k-button').first();
await expect(heroCta).toBeVisible({ timeout: 15_000 }); await expect(heroCta).toBeVisible({ timeout: 15_000 });
console.log('[FUNNEL-MOBILE] Clicking hero CTA...'); 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([ await Promise.all([
page.waitForURL('**/app/get-krk**', { timeout: 30_000 }), page.waitForURL('**/app/get-krk**', { timeout: 30_000, waitUntil: 'domcontentloaded' }),
heroCta.click(), heroCta.click({ force: true }),
]); ]);
console.log('[FUNNEL-MOBILE] Navigated to get-krk page'); 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' }); await page.screenshot({ path: 'test-results/funnel-02-get-krk-mobile.png' });
// ── Step 3: Verify Uniswap link or local swap on mobile ── // ── Step 3: Verify swap page on mobile ──
const localSwapWidget = page.locator('[data-testid="swap-amount-input"]'); const localSwapWidget = page.locator('.local-swap-widget');
const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 3_000 }).catch(() => false); 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'); const swapLink = page.locator('a.swap-button');
await expect(swapLink).toBeVisible({ timeout: 10_000 }); await expect(swapLink).toBeVisible({ timeout: 10_000 });
const href = await swapLink.getAttribute('href'); 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 page.goto(`${STACK_WEBAPP_URL}/app/get-krk`, { waitUntil: 'domcontentloaded' });
await expect(page.getByRole('heading', { name: 'Get $KRK Tokens' })).toBeVisible({ timeout: 15_000 }); 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 // Check if we're in local swap mode or production link mode.
const localSwapWidget = page.locator('[data-testid="swap-amount-input"]'); // The LocalSwapWidget container is always rendered when enableLocalSwap=true,
const hasLocalSwap = await localSwapWidget.isVisible({ timeout: 3_000 }).catch(() => false); // 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) { if (hasLocalSwap) {
console.log('[DEEPLINK] Local swap mode — verifying swap widget is functional'); 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(); await expect(page.getByTestId('swap-buy-button')).toBeVisible();
console.log('[DEEPLINK] ✅ Local swap widget verified'); console.log('[DEEPLINK] ✅ Local swap widget verified');
} else { } else {