import { expect, test } from '@playwright/test' const EXPLORER_URL = process.env.EXPLORER_URL || 'https://explorer.d-bis.org' const CANONICAL_CUSDT = '0x93E66202A11B1772E55407B32B44e5Cd8eda7f22' test.describe('Explorer sprint smoke', () => { test('homepage dashboard loads', async ({ page }) => { await page.goto(`${EXPLORER_URL}/`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByText(/Network overview/i)).toBeVisible({ timeout: 10000 }) await expect(page.getByRole('heading', { name: /Recent Transactions/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Freshness Interpretation/i).first()).toBeVisible({ timeout: 10000 }) }) test('wallet page loads', async ({ page }) => { await page.goto(`${EXPLORER_URL}/wallet`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByRole('heading', { name: /Wallet Tools/i })).toBeVisible({ timeout: 10000 }) }) test('wallet page shows WalletConnect posture note', async ({ page }) => { await page.goto(`${EXPLORER_URL}/wallet`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByText(/WalletConnect v2 posture/i)).toBeVisible({ timeout: 10000 }) }) test('tokens page loads', async ({ page }) => { await page.goto(`${EXPLORER_URL}/tokens`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByRole('heading', { name: /^Tokens$/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Canonical Chain 138 trading set/i).first()).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Indexed tokens \(Blockscout\)/i).first()).toBeVisible({ timeout: 10000 }) }) test('canonical cUSDT token detail loads', async ({ page }) => { await page.goto(`${EXPLORER_URL}/tokens/${CANONICAL_CUSDT}`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByText(/cUSDT|Tether/i).first()).toBeVisible({ timeout: 10000 }) }) test('operations hub loads extended token list note', async ({ page }) => { await page.goto(`${EXPLORER_URL}/operations`, { waitUntil: 'networkidle', timeout: 30000 }) await expect(page.getByRole('heading', { name: /Operations hub/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Extended Metamask dual-chain catalog/i).first()).toBeVisible({ timeout: 10000 }) }) test('bridge page loads CCIP route catalog', async ({ page }) => { await page.goto(`${EXPLORER_URL}/bridge`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('heading', { name: /Bridge & Relay Monitoring/i })).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/CCIP route catalog/i).first()).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/Wemix/i).first()).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/Bridge Freshness Context/i).first()).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Config-ready lane health/i).first()).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/unfunded|funded/i).first()).toBeVisible({ timeout: 10000 }) }) test('posture glossary doc page loads', async ({ page }) => { await page.goto(`${EXPLORER_URL}/docs/posture-glossary`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('heading', { name: /Posture glossary/i })).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/x402 readiness/i).first()).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/transportActive/i).first()).toBeVisible({ timeout: 10000 }) }) test('posture glossary drawer opens from docs badges', async ({ page }) => { await page.goto(`${EXPLORER_URL}/docs/posture-glossary`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await page.getByRole('button', { name: /^GRU$/i }).click() await expect(page.getByRole('dialog')).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Methodology/i).first()).toBeVisible({ timeout: 10000 }) }) test('public API access doc page loads', async ({ page }) => { await page.goto(`${EXPLORER_URL}/docs/public-api-access`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('heading', { name: /Public API access/i })).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/Decision summary/i).first()).toBeVisible({ timeout: 10000 }) }) test('wallet page exposes WalletConnect action', async ({ page }) => { await page.goto(`${EXPLORER_URL}/wallet`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('button', { name: /^WalletConnect$/i })).toBeVisible({ timeout: 15000 }) }) test('operations hub shows WETH in surface navigation', async ({ page }) => { await page.setViewportSize({ width: 1280, height: 720 }) await page.goto(`${EXPLORER_URL}/operations`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('navigation', { name: /Operations surfaces/i }).getByRole('link', { name: /^WETH$/i })).toBeVisible({ timeout: 10000 }) }) test('footer lists public API endpoints and explorer surfaces', async ({ page }) => { await page.goto(`${EXPLORER_URL}/`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByRole('contentinfo').getByText(/Public APIs/i)).toBeVisible({ timeout: 10000 }) await expect(page.getByRole('contentinfo').getByRole('link', { name: /Blockscout stats/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByRole('contentinfo').getByRole('link', { name: /Wallet tools/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByRole('contentinfo').getByRole('button', { name: /Copy URL for Blockscout stats/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByRole('contentinfo').getByRole('link', { name: /Account access/i })).toBeVisible({ timeout: 10000 }) }) test('homepage quick links include account access', async ({ page }) => { await page.goto(`${EXPLORER_URL}/`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByRole('link', { name: /Account access/i }).first()).toBeVisible({ timeout: 10000 }) }) test('tablet viewport exposes mobile navigation menu', async ({ page }) => { await page.setViewportSize({ width: 1100, height: 800 }) await page.goto(`${EXPLORER_URL}/`, { waitUntil: 'domcontentloaded', timeout: 20000 }) await expect(page.getByRole('button', { name: /Open navigation menu/i })).toBeVisible({ timeout: 10000 }) await page.getByRole('button', { name: /Open navigation menu/i }).click() await expect(page.getByRole('link', { name: /Operations hub/i }).first()).toBeVisible({ timeout: 10000 }) }) test('analytics page shows track 3 surface note', async ({ page }) => { await page.goto(`${EXPLORER_URL}/analytics`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('heading', { name: /Analytics & Network Activity/i })).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/Track 3 public surface/i).first()).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Analytics Freshness Context/i).first()).toBeVisible({ timeout: 10000 }) }) test('operator page shows track 4 surface note', async ({ page }) => { await page.goto(`${EXPLORER_URL}/operator`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page.getByRole('heading', { name: /^Operator$/i })).toBeVisible({ timeout: 15000 }) await expect(page.getByText(/Track 4 public surface/i).first()).toBeVisible({ timeout: 10000 }) }) test('legacy SPA fallback loads with deprecation banner', async ({ page }) => { await page.goto(`${EXPLORER_URL}/legacy/index.html`, { waitUntil: 'domcontentloaded', timeout: 30000 }) await expect(page).toHaveTitle(/DBIS Explorer/i) await expect(page.getByText(/Deprecated legacy explorer UI/i)).toBeVisible({ timeout: 10000 }) await expect(page.getByRole('heading', { name: /Latest Blocks/i })).toBeVisible({ timeout: 15000 }) }) test('wallet connect config exposes browser-auth fallback', async ({ request }) => { const response = await request.get(`${EXPLORER_URL}/explorer-api/v1/walletconnect/config`) expect(response.ok()).toBeTruthy() const payload = await response.json() expect(payload.fallbackAuth).toBe('/api/v1/auth/wallet') expect(String(payload.message || '')).toMatch(/auth\/wallet|WalletConnect/i) }) })