Files
bin/finance/tests/js/doppelzaehlung.dom.test.js
T
2026-09-29 07:35:16 +02:00

76 lines
3.2 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/doppelzaehlung.js'), 'utf8');
const HTML = `
<form id="f" hx-post="/api/recurring"><input name="name" value="Rate Auto"></form>
<dialog id="doppelzaehlung-dialog">
<p class="dz-meldung"></p><ul class="dz-konflikte"></ul>
<button type="button" id="dz-abbrechen">Abbrechen</button>
<button type="button" id="dz-bestaetigen">Trotzdem speichern</button>
</dialog>`;
const BODY = JSON.stringify({ detail: { code: 'doppelzaehlung_kredit', meldung: 'Erklärung',
konflikte: [{ posten: 'Rate Auto', posten_betrag: '-100.00', kredit: 'Auto', kredit_rate: '100.00' }] } });
function load() {
const dom = new JSDOM(`<!doctype html><body>${HTML}</body>`, { runScripts: 'outside-only' });
const w = dom.window;
const calls = [];
w.htmx = { trigger: (el, name) => calls.push([el.id, name]) };
const dlg = w.document.getElementById('doppelzaehlung-dialog');
dlg.showModal = function () { this.setAttribute('open', ''); };
dlg.close = function () { this.removeAttribute('open'); };
w.eval(SRC);
w.FBDoppel.init(w.document);
const form = w.document.getElementById('f');
const evt = { detail: { xhr: { status: 409, responseText: BODY }, elt: form } };
return { w, dlg, form, evt, calls };
}
test('409 öffnet Dialog mit Erklärung und Konfliktliste', { skip: !JSDOM }, () => {
const { w, dlg, evt } = load();
assert.equal(w.FBDoppel.handle(evt), true);
assert.ok(dlg.hasAttribute('open'));
assert.equal(dlg.querySelector('.dz-meldung').textContent, 'Erklärung');
assert.equal(dlg.querySelectorAll('.dz-konflikte li').length, 1);
});
test('andere Fehler werden nicht abgefangen', { skip: !JSDOM }, () => {
const { w, form } = load();
assert.equal(w.FBDoppel.handle({ detail: { xhr: { status: 422, responseText: '{}' }, elt: form } }), false);
});
test('Abbrechen speichert nicht', { skip: !JSDOM }, () => {
const { w, dlg, form, evt, calls } = load();
w.FBDoppel.handle(evt);
w.document.getElementById('dz-abbrechen').click();
assert.ok(!dlg.hasAttribute('open'));
assert.equal(calls.length, 0);
assert.ok(!form.hasAttribute('data-doppelzaehlung-bestaetigt'));
assert.equal(form.querySelector('input').value, 'Rate Auto');
});
test('Trotzdem speichern sendet erneut mit Flag', { skip: !JSDOM }, () => {
const { w, dlg, form, evt, calls } = load();
w.FBDoppel.handle(evt);
w.document.getElementById('dz-bestaetigen').click();
assert.ok(!dlg.hasAttribute('open'));
assert.equal(form.getAttribute('data-doppelzaehlung-bestaetigt'), '1');
assert.deepEqual(calls, [['f', 'submit']]);
});
test('Flag nach Request entfernt', { skip: !JSDOM }, () => {
const { w, form, evt } = load();
w.FBDoppel.handle(evt);
w.document.getElementById('dz-bestaetigen').click();
const e = new w.CustomEvent('htmx:afterRequest', { bubbles: true, detail: { elt: form } });
form.dispatchEvent(e);
assert.ok(!form.hasAttribute('data-doppelzaehlung-bestaetigt'));
});