222 lines
9.1 KiB
JavaScript
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']);
|
|
});
|
|
});
|