128 lines
4.5 KiB
TypeScript
128 lines
4.5 KiB
TypeScript
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();
|
|
});
|