import { expect, test, type Page, type TestInfo } from '@playwright/test'; const PASSWORD = 'Sup3rSecure!123'; function toSlug(value: string) { return value .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, '') .slice(0, 48); } async function signUp(page: Page, testInfo: TestInfo) { const email = `playwright-analysis-${testInfo.workerIndex}-${toSlug(testInfo.title)}-${Date.now()}@example.com`; await page.goto('/auth/signup'); await page.locator('input[autocomplete="name"]').fill('Playwright Analysis User'); await page.locator('input[autocomplete="email"]').fill(email); await page.locator('input[autocomplete="new-password"]').first().fill(PASSWORD); await page.locator('input[autocomplete="new-password"]').nth(1).fill(PASSWORD); await page.getByRole('button', { name: 'Create account' }).click(); await expect(page.getByRole('heading', { name: 'Command Center' })).toBeVisible({ timeout: 30_000 }); await expect(page).toHaveURL(/\/$/, { timeout: 30_000 }); } test('shows the overview skeleton while analysis is loading', async ({ page }, testInfo) => { await signUp(page, testInfo); await page.route('**/api/analysis/company**', async (route) => { await new Promise((resolve) => setTimeout(resolve, 700)); await route.fulfill({ contentType: 'application/json', body: JSON.stringify({ analysis: { company: { ticker: 'MSFT', companyName: 'Microsoft Corporation', sector: 'Technology', category: null, tags: [], cik: '0000789019' }, quote: 425.12, position: null, priceHistory: [ { date: '2025-01-01T00:00:00.000Z', close: 380 }, { date: '2026-01-01T00:00:00.000Z', close: 425.12 } ], benchmarkHistory: [ { date: '2025-01-01T00:00:00.000Z', close: 5000 }, { date: '2026-01-01T00:00:00.000Z', close: 5400 } ], financials: [], filings: [], aiReports: [], coverage: null, journalPreview: [], recentAiReports: [], latestFilingSummary: null, keyMetrics: { referenceDate: null, revenue: null, netIncome: null, totalAssets: null, cash: null, debt: null, netMargin: null }, companyProfile: { description: 'Microsoft builds cloud and software products worldwide.', exchange: 'NASDAQ', industry: 'Software', country: 'United States', website: 'https://www.microsoft.com', fiscalYearEnd: '06/30', employeeCount: 220000, source: 'sec_derived' }, valuationSnapshot: { sharesOutstanding: 7430000000, marketCap: 3150000000000, enterpriseValue: 3200000000000, trailingPe: 35, evToRevenue: 12, evToEbitda: null, source: 'derived' }, bullBear: { source: 'memo_fallback', bull: ['Azure and Copilot demand remain durable.'], bear: ['Valuation leaves less room for execution misses.'], updatedAt: '2026-03-13T00:00:00.000Z' }, recentDevelopments: { status: 'ready', items: [{ id: 'msft-1', kind: '8-K', title: 'Microsoft filed an 8-K', url: 'https://www.sec.gov/Archives/test.htm', source: 'SEC filings', publishedAt: '2026-03-10', summary: 'The company disclosed a current report with updated commercial details.', accessionNumber: '0000000000-26-000001' }], weeklySnapshot: { summary: 'The week centered on filing-driven updates.', highlights: ['An 8-K added current commercial context.'], itemCount: 1, startDate: '2026-03-07', endDate: '2026-03-13', updatedAt: '2026-03-13T00:00:00.000Z', source: 'heuristic' } } } }) }); }); await page.goto('/analysis?ticker=MSFT'); await expect(page.getByTestId('analysis-overview-skeleton')).toBeVisible(); await expect(page.getByRole('heading', { name: 'Microsoft Corporation' })).toBeVisible(); await expect(page.getByText('Bull vs Bear')).toBeVisible(); });