cd74497de6
fix: restore ScoringConfig improvements lost in refactor commit docs: rewrite README and CLAUDE.md to reflect current architecture code-format code fixes
93 lines
2.8 KiB
JavaScript
93 lines
2.8 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mapToStandardFormat } from '../src/screener/DataMapper.js';
|
|
|
|
const base = {
|
|
price: { quoteType: 'EQUITY', regularMarketPrice: 150 },
|
|
assetProfile: { sector: 'Technology', industry: 'Software', category: '' },
|
|
financialData: {
|
|
quickRatio: 1.2,
|
|
debtToEquity: 150,
|
|
freeCashflow: 5e9,
|
|
revenueGrowth: 0.15,
|
|
profitMargins: 0.25,
|
|
operatingMargins: 0.3,
|
|
returnOnEquity: 0.2,
|
|
earningsGrowth: 0.12,
|
|
operatingCashflow: 8e9,
|
|
},
|
|
defaultKeyStatistics: { pegRatio: null, forwardPE: 28, sharesOutstanding: 1e9, priceToBook: 12 },
|
|
summaryDetail: {
|
|
trailingAnnualDividendYield: 0.005,
|
|
trailingPE: 30,
|
|
beta: 1.2,
|
|
fiftyTwoWeekHigh: 200,
|
|
fiftyTwoWeekLow: 120,
|
|
},
|
|
};
|
|
|
|
test('maps EQUITY quote type to STOCK', () => {
|
|
const result = mapToStandardFormat('AAPL', base);
|
|
assert.equal(result.type, 'STOCK');
|
|
assert.equal(result.ticker, 'AAPL');
|
|
});
|
|
|
|
test('computes PEG from trailingPE / earningsGrowth when Yahoo returns null', () => {
|
|
const result = mapToStandardFormat('AAPL', base);
|
|
const expected = +(30 / (0.12 * 100)).toFixed(2); // trailingPE=30, earningsGrowth=12%
|
|
assert.equal(result.pegRatio, expected);
|
|
});
|
|
|
|
test('uses Yahoo pegRatio when available', () => {
|
|
const summary = {
|
|
...base,
|
|
defaultKeyStatistics: { ...base.defaultKeyStatistics, pegRatio: 1.5 },
|
|
};
|
|
const result = mapToStandardFormat('AAPL', summary);
|
|
assert.equal(result.pegRatio, 1.5);
|
|
});
|
|
|
|
test('debtToEquity is divided by 100', () => {
|
|
const result = mapToStandardFormat('AAPL', base);
|
|
assert.equal(result.debtToEquity, 1.5); // 150 / 100
|
|
});
|
|
|
|
test('maps ETF quoteType to ETF', () => {
|
|
const etfSummary = {
|
|
...base,
|
|
price: { ...base.price, quoteType: 'ETF' },
|
|
assetProfile: { category: 'Large Blend' },
|
|
};
|
|
const result = mapToStandardFormat('VOO', etfSummary);
|
|
assert.equal(result.type, 'ETF');
|
|
});
|
|
|
|
test('classifies bond ETF from category keyword', () => {
|
|
const bondSummary = {
|
|
...base,
|
|
price: { ...base.price, quoteType: 'ETF' },
|
|
assetProfile: { category: 'Intermediate-Term Bond' },
|
|
};
|
|
const result = mapToStandardFormat('BND', bondSummary);
|
|
assert.equal(result.type, 'BOND');
|
|
});
|
|
|
|
test('FCF yield is computed when data available', () => {
|
|
const result = mapToStandardFormat('AAPL', base);
|
|
assert.notEqual(result.fcfYield, null);
|
|
assert(result.fcfYield > 0);
|
|
});
|
|
|
|
test('metrics are null (not 0) when data missing', () => {
|
|
const sparse = {
|
|
price: { quoteType: 'EQUITY', regularMarketPrice: 100 },
|
|
financialData: {},
|
|
defaultKeyStatistics: {},
|
|
summaryDetail: {},
|
|
assetProfile: {},
|
|
};
|
|
const result = mapToStandardFormat('X', sparse);
|
|
assert.equal(result.pegRatio, null);
|
|
assert.equal(result.quickRatio, null);
|
|
});
|