Add research workspace and graphing flows
This commit is contained in:
@@ -17,14 +17,59 @@ function toSlug(value: string) {
|
||||
|
||||
async function signUp(page: Page, testInfo: TestInfo) {
|
||||
const email = `playwright-research-${testInfo.workerIndex}-${toSlug(testInfo.title)}-${Date.now()}@example.com`;
|
||||
const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://127.0.0.1:3400';
|
||||
const output = execFileSync('bun', [
|
||||
'-e',
|
||||
`
|
||||
const [email, password] = process.argv.slice(1);
|
||||
const { auth } = await import('./lib/auth');
|
||||
const response = await auth.api.signUpEmail({
|
||||
body: {
|
||||
name: 'Playwright Research User',
|
||||
email,
|
||||
password,
|
||||
callbackURL: '/'
|
||||
},
|
||||
asResponse: true
|
||||
});
|
||||
|
||||
await page.goto('/auth/signup');
|
||||
await page.locator('input[autocomplete="name"]').fill('Playwright Research 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();
|
||||
console.log(JSON.stringify({
|
||||
status: response.status,
|
||||
sessionCookie: response.headers.get('set-cookie')
|
||||
}));
|
||||
`,
|
||||
email,
|
||||
PASSWORD
|
||||
], {
|
||||
cwd: process.cwd(),
|
||||
env: {
|
||||
...process.env,
|
||||
DATABASE_URL: `file:${E2E_DATABASE_PATH}`,
|
||||
BETTER_AUTH_BASE_URL: baseURL,
|
||||
BETTER_AUTH_SECRET: 'playwright-e2e-secret-playwright-e2e-secret',
|
||||
BETTER_AUTH_TRUSTED_ORIGINS: baseURL
|
||||
},
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
const { status, sessionCookie } = JSON.parse(output) as { status: number; sessionCookie: string | null };
|
||||
expect(status).toBe(200);
|
||||
expect(sessionCookie).toBeTruthy();
|
||||
|
||||
const [cookieNameValue] = sessionCookie!.split(';');
|
||||
const separatorIndex = cookieNameValue!.indexOf('=');
|
||||
const cookieName = cookieNameValue!.slice(0, separatorIndex);
|
||||
const cookieValue = cookieNameValue!.slice(separatorIndex + 1);
|
||||
|
||||
await page.context().addCookies([{
|
||||
name: cookieName,
|
||||
value: cookieValue,
|
||||
url: baseURL,
|
||||
httpOnly: true,
|
||||
sameSite: 'Lax'
|
||||
}]);
|
||||
|
||||
await page.goto('/');
|
||||
await expect(page).toHaveURL(/\/$/);
|
||||
return email;
|
||||
}
|
||||
@@ -109,7 +154,9 @@ finally:
|
||||
}
|
||||
|
||||
test('supports the core coverage-to-research workflow', async ({ page }, testInfo) => {
|
||||
test.slow();
|
||||
const accessionNumber = `0001045810-26-${String(Date.now()).slice(-6)}`;
|
||||
const uploadFixture = join(process.cwd(), 'e2e', 'fixtures', 'sample-research.txt');
|
||||
await signUp(page, testInfo);
|
||||
|
||||
seedFiling({
|
||||
@@ -139,30 +186,61 @@ test('supports the core coverage-to-research workflow', async ({ page }, testInf
|
||||
await expect(page).toHaveURL(/\/analysis\?ticker=NVDA/);
|
||||
await expect(page.getByText('Coverage Workflow')).toBeVisible();
|
||||
|
||||
await page.getByLabel('Journal title').fill('Own-the-stack moat check');
|
||||
await page.getByLabel('Journal body').fill('Monitor hyperscaler concentration, gross margin durability, and Blackwell shipment cadence.');
|
||||
await page.getByRole('link', { name: 'Open research' }).click();
|
||||
await expect(page).toHaveURL(/\/research\?ticker=NVDA/);
|
||||
await page.getByLabel('Research note title').fill('Own-the-stack moat check');
|
||||
await page.getByLabel('Research note summary').fill('Initial moat checkpoint');
|
||||
await page.getByLabel('Research note body').fill('Monitor hyperscaler concentration, gross margin durability, and Blackwell shipment cadence.');
|
||||
await page.getByLabel('Research note tags').fill('moat, thesis');
|
||||
await page.getByRole('button', { name: 'Save note' }).click();
|
||||
await expect(page.getByText('Own-the-stack moat check')).toBeVisible();
|
||||
await expect(page.getByText('Saved note to the research library.')).toBeVisible();
|
||||
|
||||
await page.getByLabel('Upload title').fill('Supply-chain diligence');
|
||||
await page.getByLabel('Upload summary').fill('Vendor and channel-check notes');
|
||||
await page.getByLabel('Upload tags').fill('diligence, channel-check');
|
||||
await page.getByLabel('Upload file').setInputFiles(uploadFixture);
|
||||
await page.locator('button', { hasText: 'Upload file' }).click();
|
||||
await expect(page.getByText('Uploaded research file.')).toBeVisible();
|
||||
|
||||
await page.goto(`/analysis?ticker=NVDA`);
|
||||
await page.getByRole('link', { name: 'Open summary' }).first().click();
|
||||
await expect(page).toHaveURL(/\/analysis\/reports\/NVDA\//);
|
||||
await page.getByRole('button', { name: 'Add to journal' }).click();
|
||||
await expect(page.getByText('Saved to the company research journal.')).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Save to library' }).click();
|
||||
await expect(page.getByText('Saved to the company research library.')).toBeVisible();
|
||||
|
||||
await page.getByRole('link', { name: 'Back to analysis' }).click();
|
||||
await page.goto('/research?ticker=NVDA');
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page).toHaveURL(/\/research\?ticker=NVDA/);
|
||||
await expect(page.getByRole('heading', { name: '10-K AI memo' }).first()).toBeVisible();
|
||||
|
||||
await page.getByLabel('Memo rating').selectOption('buy');
|
||||
await page.getByLabel('Memo conviction').selectOption('high');
|
||||
await page.getByLabel('Memo time horizon').fill('24');
|
||||
await page.getByLabel('Packet title').fill('NVIDIA buy-side packet');
|
||||
await page.getByLabel('Packet subtitle').fill('AI infrastructure compounder');
|
||||
await page.getByLabel('Memo Thesis').fill('Maintain a constructive stance as datacenter demand and platform depth widen the moat.');
|
||||
await page.getByLabel('Memo Catalysts').fill('Blackwell ramp, enterprise inference demand, and sustained operating leverage.');
|
||||
await page.getByLabel('Memo Risks').fill('Customer concentration, competition, and execution on supply.');
|
||||
await page.getByRole('button', { name: 'Save memo' }).click();
|
||||
await expect(page.getByText('Saved investment memo.')).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Attach' }).first().click();
|
||||
await expect(page.getByText('Attached evidence to Thesis.')).toBeVisible();
|
||||
|
||||
await page.goto('/analysis?ticker=NVDA');
|
||||
await expect(page).toHaveURL(/\/analysis\?ticker=NVDA/);
|
||||
await expect(page.getByText('10-K AI memo')).toBeVisible();
|
||||
|
||||
await page.getByRole('link', { name: 'Open financials' }).click();
|
||||
await page.goto('/financials?ticker=NVDA');
|
||||
await expect(page).toHaveURL(/\/financials\?ticker=NVDA/);
|
||||
|
||||
await page.getByRole('link', { name: 'Filings' }).first().click();
|
||||
await page.goto('/filings?ticker=NVDA');
|
||||
await expect(page).toHaveURL(/\/filings\?ticker=NVDA/);
|
||||
await expect(page.getByRole('cell', { name: 'NVIDIA Corporation' })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: /journal/i }).first()).toBeVisible();
|
||||
await expect(page.getByRole('link', { name: 'Summary' }).first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('supports add, edit, and delete holding flows with summary refresh', async ({ page }, testInfo) => {
|
||||
test.slow();
|
||||
await signUp(page, testInfo);
|
||||
|
||||
await page.goto('/portfolio');
|
||||
|
||||
Reference in New Issue
Block a user