feat(financials): add compact surface UI and graphing states
This commit is contained in:
@@ -29,6 +29,12 @@ function createFinancialsPayload(input: {
|
||||
cadence: 'annual' | 'quarterly' | 'ltm';
|
||||
surface: string;
|
||||
}) {
|
||||
const fiscalPack = input.ticker === 'JPM'
|
||||
? 'bank_lender'
|
||||
: input.ticker === 'BLK'
|
||||
? 'broker_asset_manager'
|
||||
: 'core';
|
||||
|
||||
return {
|
||||
financials: {
|
||||
company: {
|
||||
@@ -83,7 +89,50 @@ function createFinancialsPayload(input: {
|
||||
resolvedSourceRowKeys: {
|
||||
[`${input.ticker}-p1`]: 'revenue',
|
||||
[`${input.ticker}-p2`]: 'revenue'
|
||||
}
|
||||
},
|
||||
resolutionMethod: 'direct'
|
||||
},
|
||||
{
|
||||
key: 'gross_profit',
|
||||
label: 'Gross Profit',
|
||||
category: 'profit',
|
||||
order: 15,
|
||||
unit: 'currency',
|
||||
values: {
|
||||
[`${input.ticker}-p1`]: input.ticker === 'JPM' ? null : input.ticker === 'AAPL' ? 138 : 112,
|
||||
[`${input.ticker}-p2`]: input.ticker === 'JPM' ? null : input.ticker === 'AAPL' ? 156 : 128
|
||||
},
|
||||
sourceConcepts: ['gross_profit'],
|
||||
sourceRowKeys: ['gross_profit'],
|
||||
sourceFactIds: [11],
|
||||
formulaKey: input.ticker === 'JPM' ? null : 'revenue_less_cost_of_revenue',
|
||||
hasDimensions: false,
|
||||
resolvedSourceRowKeys: {
|
||||
[`${input.ticker}-p1`]: 'gross_profit',
|
||||
[`${input.ticker}-p2`]: 'gross_profit'
|
||||
},
|
||||
resolutionMethod: input.ticker === 'JPM' ? 'not_meaningful' : 'formula_derived'
|
||||
},
|
||||
{
|
||||
key: 'other_operating_expense',
|
||||
label: 'Other Expense',
|
||||
category: 'opex',
|
||||
order: 16,
|
||||
unit: 'currency',
|
||||
values: {
|
||||
[`${input.ticker}-p1`]: input.ticker === 'BLK' ? null : input.ticker === 'AAPL' ? 12 : 8,
|
||||
[`${input.ticker}-p2`]: input.ticker === 'BLK' ? null : input.ticker === 'AAPL' ? 14 : 10
|
||||
},
|
||||
sourceConcepts: ['other_operating_expense'],
|
||||
sourceRowKeys: ['other_operating_expense'],
|
||||
sourceFactIds: [12],
|
||||
formulaKey: input.ticker === 'BLK' ? null : 'operating_expenses_residual',
|
||||
hasDimensions: false,
|
||||
resolvedSourceRowKeys: {
|
||||
[`${input.ticker}-p1`]: 'other_operating_expense',
|
||||
[`${input.ticker}-p2`]: 'other_operating_expense'
|
||||
},
|
||||
resolutionMethod: input.ticker === 'BLK' ? 'not_meaningful' : 'formula_derived'
|
||||
},
|
||||
{
|
||||
key: 'total_assets',
|
||||
@@ -103,7 +152,8 @@ function createFinancialsPayload(input: {
|
||||
resolvedSourceRowKeys: {
|
||||
[`${input.ticker}-p1`]: 'total_assets',
|
||||
[`${input.ticker}-p2`]: 'total_assets'
|
||||
}
|
||||
},
|
||||
resolutionMethod: 'direct'
|
||||
},
|
||||
{
|
||||
key: 'free_cash_flow',
|
||||
@@ -123,10 +173,12 @@ function createFinancialsPayload(input: {
|
||||
resolvedSourceRowKeys: {
|
||||
[`${input.ticker}-p1`]: 'free_cash_flow',
|
||||
[`${input.ticker}-p2`]: 'free_cash_flow'
|
||||
}
|
||||
},
|
||||
resolutionMethod: 'direct'
|
||||
}
|
||||
]
|
||||
},
|
||||
statementDetails: null,
|
||||
ratioRows: [
|
||||
{
|
||||
key: 'gross_margin',
|
||||
@@ -177,6 +229,13 @@ function createFinancialsPayload(input: {
|
||||
taxonomy: null,
|
||||
validation: null
|
||||
},
|
||||
normalization: {
|
||||
regime: 'unknown',
|
||||
fiscalPack,
|
||||
parserVersion: '0.0.0',
|
||||
unmappedRowCount: 0,
|
||||
materialUnmappedRowCount: 0
|
||||
},
|
||||
dimensionBreakdown: null
|
||||
}
|
||||
};
|
||||
@@ -204,6 +263,10 @@ async function mockGraphingFinancials(page: Page) {
|
||||
? 'NVIDIA Corporation'
|
||||
: ticker === 'AMD'
|
||||
? 'Advanced Micro Devices, Inc.'
|
||||
: ticker === 'BLK'
|
||||
? 'BlackRock, Inc.'
|
||||
: ticker === 'JPM'
|
||||
? 'JPMorgan Chase & Co.'
|
||||
: 'Microsoft Corporation';
|
||||
|
||||
await route.fulfill({
|
||||
@@ -227,7 +290,7 @@ test('supports graphing compare controls and partial failures', async ({ page },
|
||||
|
||||
await expect(page).toHaveURL(/tickers=MSFT%2CAAPL%2CNVDA/);
|
||||
await expect(page.getByRole('heading', { name: 'Graphing' })).toBeVisible();
|
||||
await expect(page.getByText('Microsoft Corporation')).toBeVisible();
|
||||
await expect(page.getByText('Microsoft Corporation').first()).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Graph surface Balance Sheet' }).click();
|
||||
await expect(page).toHaveURL(/surface=balance_sheet/);
|
||||
@@ -245,11 +308,25 @@ test('supports graphing compare controls and partial failures', async ({ page },
|
||||
await page.getByLabel('Compare tickers').fill('MSFT, NVDA, AMD');
|
||||
await page.getByRole('button', { name: 'Update Compare Set' }).click();
|
||||
await expect(page).toHaveURL(/tickers=MSFT%2CNVDA%2CAMD/);
|
||||
await expect(page.getByText('Advanced Micro Devices, Inc.')).toBeVisible();
|
||||
await expect(page.getByText('Advanced Micro Devices, Inc.').first()).toBeVisible();
|
||||
|
||||
await page.goto('/graphing?tickers=MSFT,BAD&surface=income_statement&metric=revenue&cadence=annual&chart=line&scale=millions');
|
||||
await expect(page.getByText('Partial coverage detected.')).toBeVisible();
|
||||
await expect(page.getByRole('cell', { name: /BAD/ })).toBeVisible();
|
||||
await expect(page.getByText('Ticker not found')).toBeVisible();
|
||||
await expect(page.getByText('Microsoft Corporation')).toBeVisible();
|
||||
await expect(page.getByText('Microsoft Corporation').first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('distinguishes not meaningful metrics from missing data in the latest values table', async ({ page }, testInfo) => {
|
||||
await signUp(page, testInfo);
|
||||
await mockGraphingFinancials(page);
|
||||
|
||||
await page.goto('/graphing?tickers=MSFT,BLK&surface=income_statement&metric=other_operating_expense&cadence=annual&chart=line&scale=millions');
|
||||
await expect(page.getByRole('combobox', { name: 'Metric selector' })).toHaveValue('other_operating_expense');
|
||||
await expect(page.getByRole('cell', { name: 'broker_asset_manager' })).toBeVisible();
|
||||
await expect(page.getByText('Not meaningful for this pack')).toBeVisible();
|
||||
|
||||
await page.goto('/graphing?tickers=JPM,MSFT&surface=income_statement&metric=gross_profit&cadence=annual&chart=line&scale=millions');
|
||||
await expect(page.getByText('not meaningful for the selected pack', { exact: false })).toBeVisible();
|
||||
await expect(page.getByRole('cell', { name: 'bank_lender' })).toBeVisible();
|
||||
await expect(page.getByText('Ready')).toBeVisible();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user