292 lines
8.6 KiB
TypeScript
292 lines
8.6 KiB
TypeScript
import { describe, expect, it } from 'bun:test';
|
|
import { __filingTaxonomyInternals } from './filing-taxonomy';
|
|
|
|
describe('filing taxonomy snapshot normalization', () => {
|
|
it('normalizes legacy snake_case nested snapshot payloads in toSnapshotRecord', () => {
|
|
const record = __filingTaxonomyInternals.toSnapshotRecord({
|
|
id: 1,
|
|
filing_id: 10,
|
|
ticker: 'MSFT',
|
|
filing_date: '2026-01-28',
|
|
filing_type: '10-Q',
|
|
parse_status: 'ready',
|
|
parse_error: null,
|
|
source: 'xbrl_instance',
|
|
parser_engine: 'fiscal-xbrl',
|
|
parser_version: '0.1.0',
|
|
taxonomy_regime: 'us-gaap',
|
|
fiscal_pack: 'core',
|
|
periods: [{
|
|
id: 'fy-2025',
|
|
filing_id: 10,
|
|
accession_number: '0001',
|
|
filing_date: '2026-01-28',
|
|
period_start: '2025-01-01',
|
|
period_end: '2025-12-31',
|
|
filing_type: '10-Q',
|
|
period_label: 'FY 2025'
|
|
}],
|
|
faithful_rows: {
|
|
income: [{
|
|
key: 'revenue',
|
|
label: 'Revenue',
|
|
concept_key: 'us-gaap:Revenue',
|
|
qname: 'us-gaap:Revenue',
|
|
namespace_uri: 'http://fasb.org/us-gaap/2025',
|
|
local_name: 'Revenue',
|
|
is_extension: false,
|
|
statement: 'income',
|
|
role_uri: 'income',
|
|
order: 10,
|
|
depth: 0,
|
|
parent_key: null,
|
|
values: { 'fy-2025': 10 },
|
|
units: { 'fy-2025': 'iso4217:USD' },
|
|
has_dimensions: false,
|
|
source_fact_ids: [1]
|
|
}],
|
|
balance: [],
|
|
cash_flow: [],
|
|
equity: [],
|
|
comprehensive_income: []
|
|
},
|
|
statement_rows: null,
|
|
surface_rows: {
|
|
income: [{
|
|
key: 'revenue',
|
|
label: 'Revenue',
|
|
category: 'revenue',
|
|
template_section: 'revenue',
|
|
order: 10,
|
|
unit: 'currency',
|
|
values: { 'fy-2025': 10 },
|
|
source_concepts: ['us-gaap:Revenue'],
|
|
source_row_keys: ['revenue'],
|
|
source_fact_ids: [1],
|
|
formula_key: null,
|
|
has_dimensions: false,
|
|
resolved_source_row_keys: { 'fy-2025': 'revenue' },
|
|
statement: 'income',
|
|
detail_count: 1,
|
|
resolution_method: 'direct',
|
|
confidence: 'high',
|
|
warning_codes: ['legacy_surface']
|
|
}],
|
|
balance: [],
|
|
cash_flow: [],
|
|
equity: [],
|
|
comprehensive_income: []
|
|
},
|
|
detail_rows: {
|
|
income: {
|
|
revenue: [{
|
|
key: 'revenue_detail',
|
|
parent_surface_key: 'revenue',
|
|
label: 'Revenue Detail',
|
|
concept_key: 'us-gaap:RevenueDetail',
|
|
qname: 'us-gaap:RevenueDetail',
|
|
namespace_uri: 'http://fasb.org/us-gaap/2025',
|
|
local_name: 'RevenueDetail',
|
|
unit: 'iso4217:USD',
|
|
values: { 'fy-2025': 10 },
|
|
source_fact_ids: [2],
|
|
is_extension: false,
|
|
dimensions_summary: ['region:americas'],
|
|
residual_flag: false
|
|
}]
|
|
},
|
|
balance: {},
|
|
cash_flow: {},
|
|
equity: {},
|
|
comprehensive_income: {}
|
|
},
|
|
kpi_rows: [{
|
|
key: 'cloud_growth',
|
|
label: 'Cloud Growth',
|
|
category: 'operating_kpi',
|
|
unit: 'percent',
|
|
order: 10,
|
|
segment: null,
|
|
axis: null,
|
|
member: null,
|
|
values: { 'fy-2025': 0.25 },
|
|
source_concepts: ['msft:CloudGrowth'],
|
|
source_fact_ids: [3],
|
|
provenance_type: 'taxonomy',
|
|
has_dimensions: false
|
|
}],
|
|
derived_metrics: null,
|
|
validation_result: null,
|
|
normalization_summary: {
|
|
surface_row_count: 1,
|
|
detail_row_count: 1,
|
|
kpi_row_count: 1,
|
|
unmapped_row_count: 0,
|
|
material_unmapped_row_count: 0,
|
|
warnings: ['legacy_warning']
|
|
},
|
|
facts_count: 3,
|
|
concepts_count: 3,
|
|
dimensions_count: 1,
|
|
created_at: '2026-01-28T00:00:00.000Z',
|
|
updated_at: '2026-01-28T00:00:00.000Z'
|
|
} as never);
|
|
|
|
expect(record.periods[0]).toMatchObject({
|
|
filingId: 10,
|
|
accessionNumber: '0001',
|
|
filingDate: '2026-01-28',
|
|
periodStart: '2025-01-01',
|
|
periodEnd: '2025-12-31',
|
|
periodLabel: 'FY 2025'
|
|
});
|
|
expect(record.faithful_rows.income[0]).toMatchObject({
|
|
conceptKey: 'us-gaap:Revenue',
|
|
namespaceUri: 'http://fasb.org/us-gaap/2025',
|
|
localName: 'Revenue',
|
|
roleUri: 'income',
|
|
parentKey: null,
|
|
hasDimensions: false,
|
|
sourceFactIds: [1]
|
|
});
|
|
expect(record.surface_rows.income[0]).toMatchObject({
|
|
templateSection: 'revenue',
|
|
sourceConcepts: ['us-gaap:Revenue'],
|
|
sourceRowKeys: ['revenue'],
|
|
sourceFactIds: [1],
|
|
formulaKey: null,
|
|
hasDimensions: false,
|
|
resolvedSourceRowKeys: { 'fy-2025': 'revenue' },
|
|
detailCount: 1,
|
|
resolutionMethod: 'direct',
|
|
warningCodes: ['legacy_surface']
|
|
});
|
|
expect(record.detail_rows.income.revenue?.[0]).toMatchObject({
|
|
parentSurfaceKey: 'revenue',
|
|
conceptKey: 'us-gaap:RevenueDetail',
|
|
namespaceUri: 'http://fasb.org/us-gaap/2025',
|
|
sourceFactIds: [2],
|
|
dimensionsSummary: ['region:americas'],
|
|
residualFlag: false
|
|
});
|
|
expect(record.kpi_rows[0]).toMatchObject({
|
|
sourceConcepts: ['msft:CloudGrowth'],
|
|
sourceFactIds: [3],
|
|
provenanceType: 'taxonomy',
|
|
hasDimensions: false
|
|
});
|
|
expect(record.normalization_summary).toEqual({
|
|
surfaceRowCount: 1,
|
|
detailRowCount: 1,
|
|
kpiRowCount: 1,
|
|
unmappedRowCount: 0,
|
|
materialUnmappedRowCount: 0,
|
|
warnings: ['legacy_warning']
|
|
});
|
|
});
|
|
|
|
it('keeps mixed camelCase and snake_case payloads compatible', () => {
|
|
const normalized = __filingTaxonomyInternals.normalizeFilingTaxonomySnapshotPayload({
|
|
periods: [{
|
|
id: 'fy-2025',
|
|
filingId: 10,
|
|
accessionNumber: '0001',
|
|
filingDate: '2026-01-28',
|
|
periodStart: '2025-01-01',
|
|
periodEnd: '2025-12-31',
|
|
filingType: '10-K',
|
|
periodLabel: 'FY 2025'
|
|
}],
|
|
faithful_rows: {
|
|
income: [{
|
|
key: 'revenue',
|
|
label: 'Revenue',
|
|
conceptKey: 'us-gaap:Revenue',
|
|
qname: 'us-gaap:Revenue',
|
|
namespaceUri: 'http://fasb.org/us-gaap/2025',
|
|
localName: 'Revenue',
|
|
isExtension: false,
|
|
statement: 'income',
|
|
roleUri: 'income',
|
|
order: 10,
|
|
depth: 0,
|
|
parentKey: null,
|
|
values: { 'fy-2025': 10 },
|
|
units: { 'fy-2025': 'iso4217:USD' },
|
|
hasDimensions: false,
|
|
sourceFactIds: [1]
|
|
}],
|
|
balance: [],
|
|
cash_flow: [],
|
|
equity: [],
|
|
comprehensive_income: []
|
|
},
|
|
statement_rows: null,
|
|
surface_rows: {
|
|
income: [{
|
|
key: 'revenue',
|
|
label: 'Revenue',
|
|
category: 'revenue',
|
|
order: 10,
|
|
unit: 'currency',
|
|
values: { 'fy-2025': 10 },
|
|
source_concepts: ['us-gaap:Revenue'],
|
|
source_row_keys: ['revenue'],
|
|
source_fact_ids: [1],
|
|
formula_key: null,
|
|
has_dimensions: false,
|
|
resolved_source_row_keys: { 'fy-2025': 'revenue' }
|
|
}],
|
|
balance: [],
|
|
cash_flow: [],
|
|
equity: [],
|
|
comprehensive_income: []
|
|
},
|
|
detail_rows: {
|
|
income: {
|
|
revenue: [{
|
|
key: 'revenue_detail',
|
|
parentSurfaceKey: 'revenue',
|
|
label: 'Revenue Detail',
|
|
conceptKey: 'us-gaap:RevenueDetail',
|
|
qname: 'us-gaap:RevenueDetail',
|
|
namespaceUri: 'http://fasb.org/us-gaap/2025',
|
|
localName: 'RevenueDetail',
|
|
unit: 'iso4217:USD',
|
|
values: { 'fy-2025': 10 },
|
|
sourceFactIds: [2],
|
|
isExtension: false,
|
|
dimensionsSummary: [],
|
|
residualFlag: false
|
|
}]
|
|
},
|
|
balance: {},
|
|
cash_flow: {},
|
|
equity: {},
|
|
comprehensive_income: {}
|
|
},
|
|
kpi_rows: [],
|
|
normalization_summary: {
|
|
surfaceRowCount: 1,
|
|
detail_row_count: 1,
|
|
kpiRowCount: 0,
|
|
unmapped_row_count: 0,
|
|
materialUnmappedRowCount: 0,
|
|
warnings: []
|
|
}
|
|
});
|
|
|
|
expect(normalized.periods[0]?.filingId).toBe(10);
|
|
expect(normalized.surface_rows.income[0]?.sourceConcepts).toEqual(['us-gaap:Revenue']);
|
|
expect(normalized.detail_rows.income.revenue?.[0]?.parentSurfaceKey).toBe('revenue');
|
|
expect(normalized.normalization_summary).toEqual({
|
|
surfaceRowCount: 1,
|
|
detailRowCount: 1,
|
|
kpiRowCount: 0,
|
|
unmappedRowCount: 0,
|
|
materialUnmappedRowCount: 0,
|
|
warnings: []
|
|
});
|
|
});
|
|
});
|