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' });
// ── 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 {