Files
bin/finance/tests/js/szenarien.dom.test.js
T

117 lines
5.5 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert');
const fs = require('node:fs');
const path = require('node:path');
let JSDOM = null;
try { ({ JSDOM } = require('jsdom')); } catch (e) { /* jsdom fehlt -> skip */ }
const SRC = fs.readFileSync(path.join(__dirname, '../../app/static/szenarien.js'), 'utf8');
const TIP = 'Für diese Eintragsart nicht relevant';
const HTML = `
<form id="a" class="entry-form aenderung-form" hx-post="/api/scenarios/1/modifiers">
<select name="kind"><option value="percent">Prozent</option><option value="absolute">Kürzung (€)</option>
<option value="set">Neuer Betrag</option><option value="remove">Entfällt</option><option value="ende">Ende</option></select>
<select name="target_type"><option value="category">Kategorie</option><option value="recurring">Wiederkehrender Posten</option></select>
<span class="mod-target-category"><select name="target_id"><option value="1">K</option></select></span>
<span class="mod-target-recurring" style="display:none"><select name="target_id" disabled><option value="2">P</option></select></span>
<label><span class="value-label">Prozentsatz (%)</span><input name="value"></label>
<input type="date" name="start_date">
<label><span class="bis-label">Gültig bis</span><input type="date" name="end_date"></label>
</form>
<form id="z" class="entry-form zahlung-form" hx-post="/api/scenarios/1/planned"
data-planned-url="/api/scenarios/1/planned" data-recurring-url="/api/scenarios/1/recurring">
<select class="zahlung-art"><option value="einmal">Einmalzahlung</option><option value="wiederkehrend">Wiederkehrend</option></select>
<input name="name"><input name="amount"><select name="category_id"><option value="">(keine)</option></select>
<input type="date" name="due">
<select name="rhythm"><option value="monthly">monatlich</option></select>
<input name="due_day"><input type="date" name="start_date"><input type="date" name="end_date">
</form>`;
function load() {
const dom = new JSDOM(`<!doctype html><body>${HTML}</body>`, { runScripts: 'outside-only' });
const w = dom.window;
const processed = [];
w.htmx = { process: (el) => processed.push(el.id) };
w.eval(SRC);
w.FBSzenario.init(w.document);
const d = w.document;
return { w, a: d.getElementById('a'), z: d.getElementById('z'), processed };
}
function f(form, name) { return form.querySelector(`[name="${name}"]`); }
function art(w, form, wert) {
const sel = form.querySelector('[name="kind"]');
sel.value = wert;
w.FBSzenario.aenderungArt(sel);
}
test('Prozent: Wert und Zeitraum aktiv', { skip: !JSDOM }, () => {
const { a } = load();
assert.equal(f(a, 'value').disabled, false);
assert.equal(a.querySelector('.value-label').textContent, 'Prozentsatz (%)');
assert.equal(f(a, 'start_date').disabled, false);
assert.equal(f(a, 'end_date').disabled, false);
assert.equal(a.querySelector('.bis-label').textContent, 'Gültig bis');
});
test('Kürzung: Label Kürzung (€)', { skip: !JSDOM }, () => {
const { w, a } = load();
art(w, a, 'absolute');
assert.equal(a.querySelector('.value-label').textContent, 'Kürzung (€)');
});
test('Neuer Betrag: Ziel-Typ fest auf Posten, Kategorie gesperrt', { skip: !JSDOM }, () => {
const { w, a } = load();
art(w, a, 'set');
const typ = f(a, 'target_type');
assert.equal(typ.value, 'recurring');
assert.equal(typ.querySelector('option[value="category"]').disabled, true);
assert.equal(a.querySelector('.mod-target-recurring select').disabled, false);
assert.equal(a.querySelector('.mod-target-category select').disabled, true);
assert.equal(a.querySelector('.value-label').textContent, 'Neuer Betrag (€)');
art(w, a, 'percent');
assert.equal(typ.querySelector('option[value="category"]').disabled, false);
});
test('Ende: Gültig ab und Wert gesperrt, Label Endet am', { skip: !JSDOM }, () => {
const { w, a } = load();
art(w, a, 'ende');
assert.equal(f(a, 'start_date').disabled, true);
assert.equal(f(a, 'start_date').title, TIP);
assert.equal(f(a, 'value').disabled, true);
assert.equal(f(a, 'end_date').disabled, false);
assert.equal(a.querySelector('.bis-label').textContent, 'Endet am');
});
test('Entfällt: Wert gesperrt, Zeitraum aktiv', { skip: !JSDOM }, () => {
const { w, a } = load();
art(w, a, 'remove');
assert.equal(f(a, 'value').disabled, true);
assert.equal(a.querySelector('.value-label').textContent, 'Wert');
assert.equal(f(a, 'start_date').disabled, false);
assert.equal(a.querySelector('.bis-label').textContent, 'Gültig bis');
});
test('Zahlung: Einmal → Wiederkehrend → Einmal', { skip: !JSDOM }, () => {
const { w, z, processed } = load();
const sel = z.querySelector('.zahlung-art');
const wiederkehrend = ['rhythm', 'due_day', 'start_date', 'end_date'];
assert.equal(z.getAttribute('hx-post'), '/api/scenarios/1/planned');
assert.equal(f(z, 'due').disabled, false);
wiederkehrend.forEach((n) => assert.equal(f(z, n).disabled, true, n));
sel.value = 'wiederkehrend';
w.FBSzenario.zahlungArt(sel);
assert.equal(z.getAttribute('hx-post'), '/api/scenarios/1/recurring');
assert.equal(f(z, 'due').disabled, true);
assert.equal(f(z, 'due').title, TIP);
wiederkehrend.forEach((n) => assert.equal(f(z, n).disabled, false, n));
sel.value = 'einmal';
w.FBSzenario.zahlungArt(sel);
assert.equal(z.getAttribute('hx-post'), '/api/scenarios/1/planned');
wiederkehrend.forEach((n) => assert.equal(f(z, n).disabled, true, n));
['name', 'amount', 'category_id'].forEach((n) => assert.equal(f(z, n).disabled, false, n));
assert.ok(processed.includes('z'));
});