Files
2026-10-29 11:57:29 +01:00

222 lines
9.1 KiB
JavaScript

// Generated, do not edit. sha256:f1e6b320617af57c85b4584dfef9c069d414816f5a7ef1ec466834b230e30b89
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import {
ringData, dim, segmentIndices, uitsteek, nadrukKleuren, glansStops, outerEdge,
} from '../../client/wealth/chart.js';
describe('ringData', () => {
let volgendId = 1;
const kaart = (symbol, kind, value) => ({ asset: { id: volgendId++, symbol, kind }, m: { value } });
it('sorteert de assets aflopend op waarde', () => {
const d = ringData([kaart('XAU', 'metal', 500), kaart('BTC', 'crypto', 2000), kaart('EUR', 'fiat', 100)]);
assert.deepEqual(d.assets.map(a => a.label), ['BTC', 'XAU', 'EUR']);
});
it('telt de soorten op en houdt de volgorde van de enum aan', () => {
const d = ringData([kaart('XAU', 'metal', 900), kaart('BTC', 'crypto', 100), kaart('XAG', 'metal', 100)]);
assert.deepEqual(d.soorten.map(s => s.value), [100, 1000], 'crypto vóór metaal, ook al is metaal groter');
});
it('geeft een soortsegment de id\'s van zijn assets mee', () => {
const xau = kaart('XAU', 'metal', 900);
const xag = kaart('XAG', 'metal', 100);
const d = ringData([xau, kaart('BTC', 'crypto', 500), xag]);
const metaal = d.soorten.find(s => s.kind === 'metal');
assert.deepEqual(metaal.ids, [xau.asset.id, xag.asset.id]);
assert.deepEqual(metaal.kinds, ['metal'], 'en zijn eigen soort, zodat één matcher beide ringen dient');
});
it('laat een asset zonder koers uit de grafiek', () => {
const d = ringData([kaart('BTC', 'crypto', 100), kaart('XAU', 'metal', null)]);
assert.deepEqual(d.assets.map(a => a.label), ['BTC']);
assert.equal(d.soorten.length, 1);
});
it('laat nul en negatief er ook uit', () => {
const d = ringData([kaart('BTC', 'crypto', 100), kaart('XAG', 'metal', 0), kaart('XAU', 'metal', -5)]);
assert.deepEqual(d.assets.map(a => a.label), ['BTC']);
});
it('geeft twee lege ringen als er niets bruikbaars is', () => {
assert.deepEqual(ringData([kaart('BTC', 'crypto', null)]), { soorten: [], assets: [] });
assert.deepEqual(ringData([]), { soorten: [], assets: [] });
});
describe('kleine posten', () => {
it('bundelt alles onder de drempel in één post, met het aantal erbij', () => {
const d = ringData([
kaart('BTC', 'crypto', 9000), kaart('XAU', 'metal', 700),
kaart('XAG', 'metal', 100), kaart('EUR', 'fiat', 100), kaart('DOGE', 'crypto', 100),
]);
assert.deepEqual(d.assets.map(a => a.label), ['BTC', 'XAU', 'Overig (3)']);
assert.equal(d.assets.at(-1).value, 300, 'de rest is de som van de kleintjes');
});
it('draagt de id\'s van álle gebundelde assets mee', () => {
const klein = [kaart('XAG', 'metal', 100), kaart('EUR', 'fiat', 100)];
const d = ringData([kaart('BTC', 'crypto', 9800), ...klein]);
assert.deepEqual(d.assets.at(-1).ids, klein.map(k => k.asset.id));
});
it('bundelt NIET als er maar één kleine post is', () => {
const d = ringData([kaart('BTC', 'crypto', 9900), kaart('XAG', 'metal', 100)]);
assert.deepEqual(d.assets.map(a => a.label), ['BTC', 'XAG']);
});
it('laat de soortengrafiek ongemoeid: een soort verliest zijn aandeel niet', () => {
const d = ringData([
kaart('BTC', 'crypto', 9000), kaart('XAU', 'metal', 700),
kaart('XAG', 'metal', 100), kaart('DOGE', 'crypto', 200),
]);
const metaal = d.soorten.find(s => s.kind === 'metal');
assert.equal(metaal.value, 800, 'inclusief het zilver dat in Overig zit');
});
it('neemt de drempel als parameter aan', () => {
const kaarten = [kaart('BTC', 'crypto', 9000), kaart('XAU', 'metal', 600),
kaart('XAG', 'metal', 200), kaart('EUR', 'fiat', 200)];
assert.equal(ringData(kaarten, { restVanaf: 0 }).assets.length, 4, 'nul: nooit bundelen');
assert.equal(ringData(kaarten, { restVanaf: 0.5 }).assets.length, 2, 'de helft: bijna alles bundelen');
});
});
});
describe('segmentIndices', () => {
const ASSETS = [
{ label: 'BTC', ids: [7], kinds: ['crypto'] },
{ label: 'XAU', ids: [3], kinds: ['metal'] },
{ label: 'Overig (2)', ids: [9, 11], kinds: ['metal', 'fiat'] },
];
const SOORTEN = [
{ label: 'Crypto', ids: [7], kinds: ['crypto'] },
{ label: 'Metaal', ids: [3, 9], kinds: ['metal'] },
{ label: 'Fiat', ids: [11], kinds: ['fiat'] },
];
it('wijst het segment van één asset aan', () => {
assert.deepEqual(segmentIndices(ASSETS, { assetIds: [3] }), [1]);
});
it('wijst het restsegment aan voor een asset dat daarin gebundeld is', () => {
assert.deepEqual(segmentIndices(ASSETS, { assetIds: [9] }), [2]);
assert.deepEqual(segmentIndices(ASSETS, { assetIds: [11] }), [2]);
});
it('wijst álle segmenten van een soort aan, het restsegment incluis', () => {
assert.deepEqual(segmentIndices(ASSETS, { kind: 'metal' }), [1, 2]);
});
it('vertaalt dezelfde aanwijzing ook in de SOORTENRING', () => {
assert.deepEqual(segmentIndices(SOORTEN, { assetIds: [9] }), [1], 'een metaal-asset wijst metaal aan');
assert.deepEqual(segmentIndices(SOORTEN, { kind: 'fiat' }), [2]);
});
it('levert niets op bij null, bij een leeg segment of bij een onbekend asset', () => {
assert.deepEqual(segmentIndices(ASSETS, null), []);
assert.deepEqual(segmentIndices(ASSETS, { assetIds: [] }), []);
assert.deepEqual(segmentIndices(ASSETS, { assetIds: [999] }), []);
assert.deepEqual(segmentIndices(undefined, { kind: 'metal' }), []);
});
});
describe('uitsteek', () => {
it('schuift een kleine post bijna volledig uit', () => {
assert.equal(uitsteek(0.05, 14), 13);
});
it('laat een dominante post vrijwel stilstaan', () => {
assert.equal(uitsteek(0.8, 14), 3);
});
it('is continu en heeft dus geen sprong rond de helft', () => {
assert.equal(uitsteek(0.49, 100), 51);
assert.equal(uitsteek(0.51, 100), 49);
});
it('klemt buiten het bereik in plaats van negatief te worden', () => {
assert.equal(uitsteek(1.4, 14), 0);
assert.equal(uitsteek(-1, 14), 14);
assert.equal(uitsteek(undefined, 14), 14);
});
});
describe('nadrukKleuren', () => {
const KLEUREN = ['rgba(1,1,1,1)', 'rgba(1,1,1,0.6)', 'rgba(1,1,1,0.28)'];
it('houdt het aangewezen segment vol en dimt de rest', () => {
assert.deepEqual(nadrukKleuren(KLEUREN, new Set([1])),
['rgba(1,1,1,0.35)', 'rgba(1,1,1,0.6)', 'rgba(1,1,1,0.098)']);
});
it('laat alles vol staan als er niets is aangewezen', () => {
assert.deepEqual(nadrukKleuren(KLEUREN, new Set()), KLEUREN);
});
it('kan meerdere segmenten tegelijk vol houden', () => {
const uit = nadrukKleuren(KLEUREN, new Set([0, 2]));
assert.deepEqual([uit[0], uit[2]], [KLEUREN[0], KLEUREN[2]]);
assert.equal(uit[1], 'rgba(1,1,1,0.21)');
});
});
describe('dim', () => {
it('verlaagt alleen de alfa en houdt de tint', () => {
assert.equal(dim('rgba(255,107,0,1)'), 'rgba(255,107,0,0.35)');
assert.equal(dim('rgba(255,107,0,0.5)', 0.5), 'rgba(255,107,0,0.25)');
});
it('laat iets dat geen rgba is met rust in plaats van onzin te maken', () => {
assert.equal(dim('#FF6B00'), '#FF6B00');
assert.equal(dim(undefined), undefined);
});
});
describe('outerEdge', () => {
const boog = { x: 100, y: 100, startAngle: 0, endAngle: Math.PI / 2, innerRadius: 40, outerRadius: 80 };
it('valt zonder uitschuiven en zonder naad samen met de boog zelf', () => {
const r = outerEdge(boog);
assert.deepEqual([r.cx, r.cy, r.r], [100, 100, 80]);
assert.ok(Math.abs(r.start - 0) < 1e-3 && Math.abs(r.end - Math.PI / 2) < 1e-3);
});
it('schuift een aangewezen segment een KWART van zijn offset op, niet de hele offset', () => {
const r = outerEdge(boog, { offset: 16 });
const mid = Math.PI / 4;
assert.ok(Math.abs(r.cx - (100 + Math.cos(mid) * 4)) < 1e-9, `cx ${r.cx}`);
assert.ok(Math.abs(r.cy - (100 + Math.sin(mid) * 4)) < 1e-9, `cy ${r.cy}`);
assert.ok(Math.abs(r.r - 80) < 1e-9, `r ${r.r}`);
});
it('laat de naad buiten de lijn: de uiteinden schuiven naar binnen', () => {
const r = outerEdge(boog, { spacing: 2 });
assert.equal(r.r, 81);
assert.ok(r.start > 0 && r.end < Math.PI / 2);
});
});
describe('glansStops', () => {
it('maakt de binnenkant dieper en de buitenrand lichter', () => {
assert.deepEqual(glansStops('rgba(100,50,0,0.5)'), ['rgba(100,50,0,0.36)', 'rgba(128,87,46,0.55)']);
});
it('houdt de volgorde van de tinten intact, want de alfa draagt de rangorde', () => {
const reeks = ['rgba(59,130,246,1)', 'rgba(59,130,246,0.64)', 'rgba(59,130,246,0.28)'];
const alfa = s => Number(/,([\d.]+)\)$/.exec(s)[1]);
const binnen = reeks.map(k => alfa(glansStops(k)[0]));
const buiten = reeks.map(k => alfa(glansStops(k)[1]));
assert.ok(binnen[0] > binnen[1] && binnen[1] > binnen[2], `binnen: ${binnen}`);
assert.ok(buiten[0] >= buiten[1] && buiten[1] > buiten[2], `buiten: ${buiten}`);
});
it('komt nooit boven een alfa van 1 uit', () => {
assert.equal(glansStops('rgba(59,130,246,1)')[1], 'rgba(94,153,248,1)');
});
it('laat iets dat geen rgba is ongemoeid, op beide stops', () => {
assert.deepEqual(glansStops('#3B82F6'), ['#3B82F6', '#3B82F6']);
});
});