// 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']); }); });