163 lines
7.0 KiB
JavaScript
163 lines
7.0 KiB
JavaScript
// Generated, do not edit. sha256:f1d5e464bcd04ed7f483f797346cfeb34bcf1b0c9306b56821baa618e0b3ee5f
|
|
import { describe, it, before, mock } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import { createDbHarness } from '../helpers/db-node.mjs';
|
|
|
|
const harness = createDbHarness({ seedPreferences: true });
|
|
mock.module('../../server/db.js', { namedExports: harness.exports });
|
|
|
|
const { precisionSettings, precisionKey, shareDisclosure } = await import('../../server/ai/precision.js');
|
|
const { createTranslator } = await import('../../server/ai/translate.js');
|
|
const { setPref } = await import('../../server/data/preferences.js');
|
|
|
|
const TEST_GEHEIM = 'geheim-voor-de-precisietest-0123456789ab';
|
|
|
|
before(() => { harness.recreate(); });
|
|
|
|
describe('precisionSettings: de stand van dit moment', () => {
|
|
it('volgt de voorkeur, en leest hem per aanroep', async () => {
|
|
await setPref('ai', 'allow_raw', 0);
|
|
assert.equal(precisionSettings().rawValues, false);
|
|
|
|
await setPref('ai', 'allow_raw', 1);
|
|
assert.equal(precisionSettings().rawValues, true,
|
|
'zonder herlezen doet de schuif pas iets bij een nieuwe verbinding');
|
|
|
|
await setPref('ai', 'allow_raw', 0);
|
|
});
|
|
|
|
it('is bevroren, zodat een tool zijn eigen antwoord niet kan verbreden', () => {
|
|
const stand = precisionSettings();
|
|
assert.throws(() => { stand.rawValues = true; }, TypeError);
|
|
assert.equal(stand.rawValues, false);
|
|
});
|
|
});
|
|
|
|
describe('precisionKey: de stand als geheel in de sleutel', () => {
|
|
it('hangt niet aan de volgorde van de velden', () => {
|
|
assert.equal(precisionKey({ rawValues: false, totals: true }), precisionKey({ totals: true, rawValues: false }));
|
|
});
|
|
|
|
it('geeft twee verschillende standen twee verschillende sleutels', () => {
|
|
const a = precisionKey({ rawValues: false, totals: true });
|
|
const b = precisionKey({ rawValues: false, totals: false });
|
|
assert.notEqual(a, b, 'een verschil in welk veld dan ook hoort een andere sleutel op te leveren');
|
|
});
|
|
|
|
it('heeft een eigen vorm voor de lege stand, en verwart die niet met een ontbrekende', () => {
|
|
assert.equal(precisionKey({}), 'leeg');
|
|
assert.equal(precisionKey(undefined), 'leeg');
|
|
assert.equal(precisionKey(null), 'leeg');
|
|
});
|
|
});
|
|
|
|
describe('createTranslator: de stand komt binnen als geheel', () => {
|
|
it('valt zonder stand terug op VERTAALD en niet op onbewerkt', () => {
|
|
const t = createTranslator({ secret: TEST_GEHEIM });
|
|
assert.equal(t.precision.rawValues, false);
|
|
const uit = t.toAi({ id: 1, amount: 12345.678 }, { entity: 'account' });
|
|
assert.equal(typeof uit.amount, 'string');
|
|
});
|
|
|
|
it('draagt de stand die hij kreeg, en die is van buitenaf niet te verzetten', () => {
|
|
const t = createTranslator({ secret: TEST_GEHEIM, precision: { rawValues: true } });
|
|
assert.equal(t.precision.rawValues, true);
|
|
assert.throws(() => { t.precision.rawValues = false; }, TypeError);
|
|
});
|
|
|
|
it('laat een onbekend veld in de stand niet als raw gelden', () => {
|
|
const t = createTranslator({ secret: TEST_GEHEIM, precision: { rawWaarden: true } });
|
|
assert.equal(t.precision.rawValues, false);
|
|
const uit = t.toAi({ id: 1, amount: 12345.678 }, { entity: 'account' });
|
|
assert.equal(typeof uit.amount, 'string');
|
|
});
|
|
});
|
|
|
|
describe('de vier precisie-schuiven', () => {
|
|
const zet = async (sleutels) => {
|
|
for (const [k, v] of Object.entries(sleutels)) await setPref('ai', k, v ? 1 : 0);
|
|
};
|
|
|
|
it('zet de vier op false zodra onbewerkt delen aan staat, want dan valt er niets te emmeren', async () => {
|
|
await zet({ bucket_shares: 1, bucket_totals: 1, bucket_amounts: 1, bucket_quantities: 1 });
|
|
await setPref('ai', 'allow_raw', 1);
|
|
try {
|
|
const p = precisionSettings();
|
|
assert.equal(p.rawValues, true);
|
|
assert.deepEqual(
|
|
[p.bucketShares, p.bucketTotals, p.bucketAmounts, p.bucketQuantities],
|
|
[false, false, false, false],
|
|
'laag 3 hoort laag 1 te overrulen in de LAAG, niet bij elke aanroeper opnieuw');
|
|
} finally {
|
|
await setPref('ai', 'allow_raw', 0);
|
|
}
|
|
});
|
|
|
|
it('leest elke schuif apart, zodat er geen twee aan elkaar vastzitten', async () => {
|
|
await zet({ bucket_shares: 0, bucket_totals: 1, bucket_amounts: 0, bucket_quantities: 1 });
|
|
const p = precisionSettings();
|
|
assert.deepEqual(
|
|
[p.bucketShares, p.bucketTotals, p.bucketAmounts, p.bucketQuantities],
|
|
[false, true, false, true]);
|
|
await zet({ bucket_shares: 1, bucket_totals: 1, bucket_amounts: 1, bucket_quantities: 1 });
|
|
});
|
|
|
|
it('emmert een hoeveelheid alleen zolang ZIJN schuif aan staat', () => {
|
|
const aan = createTranslator({ secret: TEST_GEHEIM, precision: { bucketQuantities: true } });
|
|
const uit = createTranslator({ secret: TEST_GEHEIM, precision: { bucketQuantities: false } });
|
|
assert.equal(typeof aan.toAi({ amount: 12345.678 }, { entity: 'account' }).amount, 'string');
|
|
assert.equal(uit.toAi({ amount: 12345.678 }, { entity: 'account' }).amount, 12345.678);
|
|
});
|
|
|
|
it('KRUISPROEF: dezelfde klasse gaat anders naar buiten als TOTAAL dan als REGEL', () => {
|
|
const t = createTranslator({
|
|
secret: TEST_GEHEIM,
|
|
precision: { bucketTotals: false, bucketAmounts: true },
|
|
});
|
|
const alsTotaal = t.toAi({ fiatValue: 98765 }, { entity: 'wealth', role: 'total' }).fiatValue;
|
|
const alsRegel = t.toAi({ fiatValue: 98765 }, { entity: 'wealth' }).fiatValue;
|
|
assert.equal(alsTotaal, 98765, 'het totaal hoort exact te zijn: die schuif staat uit');
|
|
assert.equal(typeof alsRegel, 'string', 'het regelbedrag hoort een emmer te zijn: die staat aan');
|
|
});
|
|
|
|
it('leest een ontbrekende rol als REGEL, en dat is de striktste van de twee', () => {
|
|
const t = createTranslator({
|
|
secret: TEST_GEHEIM,
|
|
precision: { bucketTotals: false, bucketAmounts: true },
|
|
});
|
|
assert.equal(typeof t.toAi({ fiatValue: 98765 }, { entity: 'wealth' }).fiatValue, 'string');
|
|
});
|
|
});
|
|
|
|
describe('shareDisclosure: de invariant van §10c in de laag', () => {
|
|
const stand = (o) => ({ rawValues: false, bucketShares: true, bucketTotals: true,
|
|
bucketAmounts: true, bucketQuantities: true, ...o });
|
|
|
|
it('laat een geëmmerd aandeel naast een geëmmerd totaal toe: de gemeten uitzondering', () => {
|
|
assert.equal(shareDisclosure(stand({})), 'bucketed');
|
|
});
|
|
|
|
it('laat een exact aandeel toe zolang het TOTAAL geëmmerd is, want dat is één beeld', () => {
|
|
assert.equal(shareDisclosure(stand({ bucketShares: false })), 'exact');
|
|
});
|
|
|
|
it('LAAT DE VERDELING WEG als het totaal én het aandeel exact zijn', () => {
|
|
assert.equal(shareDisclosure(stand({ bucketShares: false, bucketTotals: false })), 'omit');
|
|
});
|
|
|
|
it('houdt de verdeling wél als de regelbedragen tóch al exact zijn', () => {
|
|
assert.equal(
|
|
shareDisclosure(stand({ bucketShares: false, bucketTotals: false, bucketAmounts: false })),
|
|
'exact');
|
|
});
|
|
|
|
it('geeft in de onbewerkte stand alles exact', () => {
|
|
assert.equal(shareDisclosure({ rawValues: true }), 'exact');
|
|
});
|
|
|
|
it('valt op een lege stand niet om', () => {
|
|
assert.equal(shareDisclosure(undefined), 'exact');
|
|
});
|
|
});
|