64 lines
3.1 KiB
TypeScript
64 lines
3.1 KiB
TypeScript
import { describe, expect, it } from 'bun:test';
|
|
import {
|
|
classifyStatementRole,
|
|
parseLabelLinkbase,
|
|
parsePresentationLinkbase
|
|
} from '@/lib/server/taxonomy/linkbase-parser';
|
|
|
|
const SAMPLE_LABEL_LINKBASE = `
|
|
<link:linkbase xmlns:link="http://www.xbrl.org/2003/linkbase"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
xmlns:us-gaap="http://fasb.org/us-gaap/2024">
|
|
<link:labelLink xlink:type="extended">
|
|
<link:loc xlink:type="locator" xlink:label="loc_rev" xlink:href="test.xsd#us-gaap_Revenues" />
|
|
<link:label xlink:type="resource" xlink:label="lab_terse" xlink:role="http://www.xbrl.org/2003/role/terseLabel">Rev.</link:label>
|
|
<link:label xlink:type="resource" xlink:label="lab_label" xlink:role="http://www.xbrl.org/2003/role/label">Revenues</link:label>
|
|
<link:labelArc xlink:type="arc" xlink:from="loc_rev" xlink:to="lab_terse" />
|
|
<link:labelArc xlink:type="arc" xlink:from="loc_rev" xlink:to="lab_label" />
|
|
</link:labelLink>
|
|
</link:linkbase>
|
|
`;
|
|
|
|
const SAMPLE_PRESENTATION_LINKBASE = `
|
|
<link:linkbase xmlns:link="http://www.xbrl.org/2003/linkbase"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
xmlns:us-gaap="http://fasb.org/us-gaap/2024">
|
|
<link:presentationLink xlink:type="extended" xlink:role="http://www.xbrl.org/2003/role/StatementOfOperations">
|
|
<link:loc xlink:type="locator" xlink:label="root" xlink:href="test.xsd#us-gaap_StatementLineItems" />
|
|
<link:loc xlink:type="locator" xlink:label="rev" xlink:href="test.xsd#us-gaap_Revenues" />
|
|
<link:loc xlink:type="locator" xlink:label="cogs" xlink:href="test.xsd#us-gaap_CostOfGoodsSold" />
|
|
<link:presentationArc xlink:type="arc" xlink:from="root" xlink:to="rev" order="1" />
|
|
<link:presentationArc xlink:type="arc" xlink:from="root" xlink:to="cogs" order="2" />
|
|
</link:presentationLink>
|
|
</link:linkbase>
|
|
`;
|
|
|
|
describe('linkbase parser', () => {
|
|
it('builds preferred labels from label linkbase', () => {
|
|
const labels = parseLabelLinkbase(SAMPLE_LABEL_LINKBASE);
|
|
expect(labels.get('http://fasb.org/us-gaap/2024#Revenues')).toBe('Revenues');
|
|
});
|
|
|
|
it('builds role trees with depth/order/parent metadata', () => {
|
|
const rows = parsePresentationLinkbase(SAMPLE_PRESENTATION_LINKBASE);
|
|
expect(rows.length).toBe(3);
|
|
|
|
const root = rows.find((row) => row.qname === 'us-gaap:StatementLineItems');
|
|
const revenue = rows.find((row) => row.qname === 'us-gaap:Revenues');
|
|
const cogs = rows.find((row) => row.qname === 'us-gaap:CostOfGoodsSold');
|
|
|
|
expect(root?.depth).toBe(0);
|
|
expect(root?.parentConceptKey).toBeNull();
|
|
expect(revenue?.depth).toBe(1);
|
|
expect(cogs?.depth).toBe(1);
|
|
expect(revenue?.parentConceptKey).toBe(root?.conceptKey ?? null);
|
|
expect(revenue?.order).toBeLessThan(cogs?.order ?? Number.POSITIVE_INFINITY);
|
|
});
|
|
|
|
it('classifies statement roles into canonical statement kinds', () => {
|
|
expect(classifyStatementRole('http://www.xbrl.org/2003/role/StatementOfOperations')).toBe('income');
|
|
expect(classifyStatementRole('http://www.xbrl.org/2003/role/StatementOfFinancialPosition')).toBe('balance');
|
|
expect(classifyStatementRole('http://www.xbrl.org/2003/role/StatementOfCashFlows')).toBe('cash_flow');
|
|
});
|
|
});
|