Versie 0.2.0

This commit is contained in:
Atreides Assets committed 2026-10-29 11:57:29 +01:00
commit e77d8fd373
495 files changed
+81026

No files matched your search

+264
View File
@@ -0,0 +1,264 @@
// Generated, do not edit. sha256:615ef8a5d598742e85ea7f2f5b84abfb3e5a2087d59fe201265eaa5faea109f0
import { describe, it, mock } from 'node:test';
import assert from 'node:assert/strict';
import { vasteRekenvaluta } from '../helpers/rekenvaluta.mjs';
await vasteRekenvaluta(mock, 'EUR');
const { fmtUnit, fmtAmount, fmtPct, pctTone, fmtBaseSigned, colouredSigns, fmtPrice, fmtMoney, currencyName, isBaseAsset, subline, toBaseByFactor } = await import('../../client/ui/format.js');
const { setAppSetting } = await import('../../client/app-settings.js');
import { CONFIG } from '../../shared/config.js';
const EUR = { symbol: 'EUR', kind: 'fiat', decimals: 2, unit: 'EUR', subunit: 'cent', displayUnit: 'unit' };
const BTC = { kind: 'crypto', decimals: 8, unit: 'BTC', subunit: 'sat', displayUnit: 'unit' };
const GOUD = { kind: 'metal', unit: 'ozt', subunit: 'g', displayUnit: 'unit' };
describe('fmtUnit bij geld', () => {
it('houdt de decimalen van het asset vast, ook als het nullen zijn', () => {
assert.equal(fmtUnit(130_000, EUR), '1.300,00 EUR');
assert.equal(fmtUnit(100_530, EUR), '1.005,30 EUR');
assert.equal(fmtUnit(0, EUR), '0,00 EUR');
});
it('laat een negatief bedrag heel (een boeking mag omlaag)', () => {
assert.equal(fmtUnit(-2_882_490, EUR), '-28.824,90 EUR');
});
it('volgt het asset en niet de aanname dat geld twee decimalen heeft', () => {
const zonderCenten = { kind: 'fiat', decimals: 0, unit: 'JPY', subunit: null, displayUnit: 'unit' };
assert.equal(fmtUnit(1_300, zonderCenten), '1.300 JPY');
});
it('telt in de ondereenheid gewoon hele centen', () => {
assert.equal(fmtUnit(100_530, { ...EUR, displayUnit: 'subunit' }), '100.530 cent');
});
});
describe('fmtUnit bij crypto en metaal blijft ongewijzigd', () => {
it('laat overtollige nullen bij crypto juist wél weg', () => {
assert.equal(fmtUnit(50_000_000, BTC), '0,5 BTC');
assert.equal(fmtUnit(100_000_000, BTC), '1 BTC');
assert.equal(fmtUnit(1, BTC), '0,00000001 BTC');
});
it('laat het metaal-pad ongemoeid (dat rekent met factoren, niet met 10^decimals)', () => {
assert.equal(fmtUnit(toBaseByFactor(1, 'ozt'), GOUD), '1 ozt');
assert.equal(fmtUnit(toBaseByFactor(2.5, 'ozt'), GOUD), '2,5 ozt');
});
});
describe('fmtAmount volgt dezelfde regel', () => {
it('geeft bij geld een hoofdbedrag met vaste decimalen en de centen ernaast', () => {
assert.deepEqual(fmtAmount(130_000, EUR), { primary: '1.300,00 EUR', secondary: '130.000 cent' });
});
it('en bij crypto niet', () => {
assert.deepEqual(fmtAmount(50_000_000, BTC), { primary: '0,5 BTC', secondary: '50.000.000 sat' });
});
});
describe('isBaseAsset: is dit de eenheid waarin de app rekent', () => {
it('herkent het reken-asset op zijn symbool', () => {
assert.equal(isBaseAsset(EUR), true);
assert.equal(isBaseAsset(BTC), false);
});
it('kijkt NIET naar de asset-soort', () => {
const USD = { symbol: 'USD', kind: 'fiat', decimals: 2, unit: 'USD', subunit: 'cent', displayUnit: 'unit' };
assert.equal(isBaseAsset(USD), false);
});
it('is onwaar zonder asset', () => {
assert.equal(isBaseAsset(undefined), false);
assert.equal(isBaseAsset(null), false);
});
});
describe('subline: de tweede regel onder een waarde', () => {
it('rendert niets als er niets te tonen is', () => {
assert.equal(subline(''), '');
assert.equal(subline(null), '');
assert.equal(subline(undefined), '');
});
it('rendert de regel wél als er inhoud is', () => {
assert.equal(subline('<span class="val">€ 1,00</span>'),
'<div class="t-muted-cell t-subline"><span class="val">€ 1,00</span></div>');
});
});
describe('fmtPrice: de decimalen volgen de grootte', () => {
it('houdt een grote prijs op twee decimalen', () => {
assert.equal(fmtPrice(74884.62115428, 'eur'), '€ 74.884,62');
});
it('houdt twee decimalen vast als er niets achter de komma staat', () => {
assert.equal(fmtPrice(40000, 'eur'), '€ 40.000,00');
});
it('geeft een kleine prijs zijn cijfers', () => {
assert.equal(fmtPrice(0.00012345, 'eur'), '€ 0,00012345');
assert.equal(fmtPrice(1.23456789, 'eur'), '€ 1,2346');
});
it('weigert een onbekende munt in plaats van iets te verzinnen', () => {
assert.throws(() => fmtPrice(1, 'xyz'), /Unknown currency/);
});
});
describe('fmtMoney: symbool en decimalen per munt', () => {
it('laat euro en dollar ongewijzigd', () => {
assert.equal(fmtMoney(1234.5, 'eur'), '€ 1.234,50');
assert.equal(fmtMoney(1234.5, 'USD'), '$ 1.234,50');
assert.equal(fmtMoney(0.001, 'eur'), '€ 0,001', 'onder een halve cent komen er cijfers bij');
});
it('volgt de decimalen van de munt: een yen heeft er geen', () => {
assert.equal(fmtMoney(1234.5, 'JPY'), '¥ 1.235');
assert.equal(fmtPrice(1234.5, 'JPY'), '¥ 1.234,5');
});
it('kent elke munt uit de lijst, en weigert een code daarbuiten', () => {
for (const code of CONFIG.PORTFOLIO.BASE_CURRENCIES) assert.doesNotThrow(() => fmtMoney(1, code), code);
assert.throws(() => fmtMoney(1, 'XYZ'), /Unknown currency/);
});
});
describe('currencyName', () => {
it('geeft elke munt uit de lijst een Nederlandse naam met hoofdletter', () => {
assert.equal(currencyName('eur'), 'Euro');
for (const code of CONFIG.PORTFOLIO.BASE_CURRENCIES) {
const naam = currencyName(code);
assert.match(naam, /^[A-Z]/, `${code}: '${naam}'`);
assert.notEqual(naam, code, `${code} heeft geen naam van Intl gekregen`);
}
});
it('weigert een code buiten de lijst, net als fmtMoney', () => {
assert.throws(() => currencyName('XYZ'), /Unknown currency/);
});
});
describe('fmtPct', () => {
it('schrijft Nederlands: een komma en één decimaal', () => {
assert.equal(fmtPct(0.306), '+30,6%');
assert.equal(fmtPct(0.1), '+10,0%');
});
it('gebruikt het echte minteken en niet een koppelteken', () => {
assert.equal(fmtPct(-0.008), '−0,8%');
assert.ok(!fmtPct(-0.008).includes('-'), 'een koppelteken hoort er niet in te staan');
});
it('geeft een waarde die op nul afrondt GEEN teken, ook als hij echt negatief is', () => {
assert.equal(fmtPct(0), '0,0%');
assert.equal(fmtPct(-0.000167), '0,0%');
assert.equal(fmtPct(0.0004), '0,0%');
});
it('fine: twee decimalen alleen als één decimaal de beweging verbergt', () => {
assert.equal(fmtPct(0.0004, { fine: true }), '+0,04%');
assert.equal(fmtPct(-0.000167, { fine: true }), '−0,02%');
assert.equal(fmtPct(0.014, { fine: true }), '+1,4%', 'een gewone dagbeweging houdt één decimaal');
assert.equal(fmtPct(0.0006, { fine: true }), '+0,1%', 'wat op één decimaal te zien is, blijft zo');
assert.equal(fmtPct(0.00004, { fine: true }), '0,0%', 'ook op twee decimalen nul: dan blijft het 0,0%');
});
it('pctTone: rood bij −0,1%, geen kleur bij wat als 0,0% staat', () => {
assert.equal(pctTone(-0.001), 't-neg');
assert.equal(pctTone(0.001), 't-pos');
assert.equal(pctTone(-0.0004), '', 'staat als 0,0%');
assert.equal(pctTone(-0.0004, { fine: true }), 't-neg', 'met twee decimalen staat er −0,04%');
});
it('signs: geen, alleen negatief of allebei; de kleur blijft in elke stand', () => {
assert.equal(fmtPct(0.306), '+30,6%', 'zonder kleur beide tekens');
assert.equal(fmtPct(0.306, { signs: 'negative' }), '30,6%');
assert.equal(fmtPct(-0.008, { signs: 'negative' }), '−0,8%');
assert.equal(fmtPct(-0.008, { signs: 'none' }), '0,8%');
assert.equal(fmtPct(0.306, { signs: 'both' }), '+30,6%');
assert.equal(fmtPct(0.0004, { fine: true, signs: 'negative' }), '0,04%');
assert.equal(pctTone(-0.001, { signs: 'none' }), 't-neg');
assert.equal(pctTone(0.001, { signs: 'none' }), 't-pos');
});
it('fmtBaseSigned: euroteken, spatie, teken, bedrag; onder een cent geen teken', () => {
assert.equal(fmtBaseSigned(-4.77, 'negative'), '€ −4,77');
assert.equal(fmtBaseSigned(31.51, 'negative'), '€ 31,51');
assert.equal(fmtBaseSigned(31.51, 'both'), '€ +31,51');
assert.equal(fmtBaseSigned(-4.77, 'none'), '€ 4,77');
assert.equal(fmtBaseSigned(-1234.5, 'both'), '€ −1.234,50');
assert.equal(fmtBaseSigned(-0.004, 'both'), '€ 0,00');
});
it('colouredSigns leest de instelling', async () => {
await setAppSetting('result_signs', 'none');
assert.equal(colouredSigns(), 'none');
await setAppSetting('result_signs', 'both');
assert.equal(colouredSigns(), 'both');
});
it('houdt het teken zodra er wél iets te zien is', () => {
assert.equal(fmtPct(0.0006), '+0,1%');
assert.equal(fmtPct(-0.0006), '−0,1%');
});
it('rondt af op één decimaal en niet meer', () => {
assert.equal(fmtPct(0.12345), '+12,3%');
assert.equal(fmtPct(0.12678), '+12,7%');
});
it('geeft een lege tekst als er geen getal is, want dat is iets anders dan nul', () => {
assert.equal(fmtPct(null), '');
assert.equal(fmtPct(undefined), '');
assert.equal(fmtPct(NaN), '');
assert.equal(fmtPct(Infinity), '');
});
it('valt niet over een groot percentage met een duizendtalscheiding', () => {
assert.equal(fmtPct(10), '+1.000,0%');
assert.equal(fmtPct(20000), '+2.000.000,0%');
});
});
const { parseLocaleNumber } = await import('../../client/ui/format.js');
const { setLocale } = await import('../../client/i18n/index.js');
describe('opmaak en invoer volgen de taal', () => {
const inTaal = (code, fn) => { setLocale(code); try { fn(); } finally { setLocale('nl'); } };
it('leest de eigen opmaak terug, in het Nederlands en in het Engels', () => {
assert.equal(parseLocaleNumber('1.000,50'), 1000.5);
assert.equal(parseLocaleNumber('100.000.000'), 1e8);
inTaal('en', () => {
assert.equal(parseLocaleNumber('1,000.50'), 1000.5);
assert.equal(parseLocaleNumber('100,000,000'), 1e8);
});
});
it('neemt één scheidingsteken zonder drie cijfers erachter als decimaalteken, in elke taal', () => {
assert.equal(parseLocaleNumber('3.5'), 3.5);
assert.equal(parseLocaleNumber('0.500'), 0.5, 'na een kale nul is het geen duizendtal');
assert.equal(parseLocaleNumber('3,5'), 3.5);
inTaal('en', () => {
assert.equal(parseLocaleNumber('3,5'), 3.5);
assert.equal(parseLocaleNumber('1,000'), 1000);
});
});
it('geeft NaN zonder cijfers, zodat de aanroeper zelf kiest', () => {
assert.ok(Number.isNaN(parseLocaleNumber('')));
assert.ok(Number.isNaN(parseLocaleNumber('€ -')));
assert.equal(parseLocaleNumber('-1.234,5'), -1234.5);
});
it('formatteert in de actieve taal, ook na een wissel terug', () => {
inTaal('en', () => {
assert.equal(fmtMoney(1234.5, 'EUR'), '€ 1,234.50');
assert.equal(fmtPct(10), '+1,000.0%');
assert.equal(currencyName('USD'), 'US Dollar');
});
assert.equal(fmtMoney(1234.5, 'EUR'), '€ 1.234,50');
assert.equal(currencyName('USD'), 'Amerikaanse dollar');
});
});