feat: add repayment discounts and interactive net worth trends
Support positive repayment discounts and negative surcharges with exact decimal conversion. Add independent trend toggles, pointer and keyboard date inspection, tests and Chinese documentation.
This commit is contained in:
1 parent
096f1577c2
commit
b2c22ca050
16 files changed
+505
-84
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { nearestTrendIndex, trendPath, NetWorthChart } from '../src/NetWorthChart';
|
||||
import { createElement } from 'react';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
const rows = [
|
||||
{
|
||||
date: '2026-09-01',
|
||||
assets: '100.86420975',
|
||||
liabilities: '20',
|
||||
net: '80.86420975',
|
||||
complete: true,
|
||||
missing: [],
|
||||
},
|
||||
{
|
||||
date: '2026-09-02',
|
||||
assets: '0',
|
||||
liabilities: '0',
|
||||
net: '0',
|
||||
complete: false,
|
||||
missing: ['USD'],
|
||||
},
|
||||
{ date: '2026-09-10', assets: '120', liabilities: '20', net: '100', complete: true, missing: [] },
|
||||
];
|
||||
test('hover dates use time distance across uneven dates and expose missing dates', () => {
|
||||
assert.equal(nearestTrendIndex(rows, Date.parse('2026-09-02T00:00:00Z')), 1);
|
||||
assert.equal(nearestTrendIndex(rows, Date.parse('2026-09-09T00:00:00Z')), 2);
|
||||
assert.equal(nearestTrendIndex(rows, Date.parse('2026-08-01T00:00:00Z')), 0);
|
||||
});
|
||||
test('trend paths keep a gap for incomplete dates rather than connecting misleading totals', () => {
|
||||
const path = trendPath(
|
||||
rows,
|
||||
'net',
|
||||
(d) => Number(d.slice(-2)),
|
||||
(v) => Number(v),
|
||||
);
|
||||
assert.equal(path, 'M1,80.86420975 M10,100');
|
||||
});
|
||||
test('trend legend offers three independent toggles and exact monetary data', () => {
|
||||
const html = renderToStaticMarkup(createElement(NetWorthChart, { rows, base: 'CNY' }));
|
||||
assert.equal((html.match(/aria-pressed="true"/g) || []).length, 3);
|
||||
assert.equal((html.match(/data-series=/g) || []).length, 3);
|
||||
assert.match(html, /80\.86420975/);
|
||||
assert.match(html, /tabindex="0"/);
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { repaymentFee } from '../src/repayment';
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
@@ -76,3 +77,11 @@ test('daily badges expire and filters combine month and day without mutating mar
|
||||
);
|
||||
assert.equal(p.lastBookedDate, '2026-10-04');
|
||||
});
|
||||
|
||||
test('repayment discount uses opposite fee sign without decimal precision loss', () => {
|
||||
assert.equal(repaymentFee('5.87654321'), '-5.87654321');
|
||||
assert.equal(repaymentFee('-1.86420975'), '1.86420975');
|
||||
assert.equal(repaymentFee('-0.00000000'), '0');
|
||||
assert.equal(repaymentFee('0'), '0');
|
||||
assert.throws(() => repaymentFee('1e3'));
|
||||
});
|
||||
Reference in new issue
Block a user