Files
perinco-Pulse/server/test/hrworks.test.mjs
T
schakal00783andClaude Opus 5.5 b6ba7860bf fix(kalender): Abwesenheiten jahresweise abfragen, Feiertagsnamen
- HRworks /absences erlaubt hoechstens ein Jahr je Aufruf; der Kalender
  reicht weiter und fragt jetzt in Abschnitten von 365 Tagen.
- HRworks liefert zu Feiertagen keinen Namen. Der Name kommt jetzt aus
  dem Datum (feste Feiertage, Ostern-abhaengige, Buss- und Bettag).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:41:49 +02:00

75 lines
3.6 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { chunks, matchUsers, ursache } from '../src/lib/hrworksSync.js';
import { ABSENCE_STATES, SICK_STATES } from '../src/lib/hrworks.js';
test('ein Feiertag gewinnt gegen Urlaub am selben Tag', () => {
assert.deepEqual(ursache({ holiday: true, absences: ['30_25'], sick_leaves: [] }), { art: 'holiday', ref: null });
assert.deepEqual(ursache({ holiday: false, absences: ['30_25'], sick_leaves: [] }), { art: 'absence', ref: '30_25' });
// Krankheit vor Urlaub: wer im Urlaub krank wird, ist krank.
assert.deepEqual(ursache({ holiday: false, absences: ['30_25'], sick_leaves: ['31_9'] }), { art: 'sick', ref: '31_9' });
assert.equal(ursache({ holiday: false, absences: [], sick_leaves: [] }), null);
});
test('Zuordnung: Mailadresse zuerst, dann Name', () => {
const users = [
{ id: 1, name: 'Kai Schwickert', email: 'kai.schwickert@icon-experts.de' },
{ id: 2, name: 'Nico Necknig', email: 'nico.necknig@perinco.de' },
{ id: 3, name: 'Renè Kleinau', email: 'rene.kleinau@perinco.de' },
];
const persons = [
// andere Domain in HRworks - greift ueber den Namen
{ person_id: 'KaiS', name: 'Kai Schwickert', email: 'kai.schwickert@perinco.de' },
// private Adresse in HRworks - greift ueber den Namen
{ person_id: 'NicoN', name: 'Nico Necknig', email: 'nico.necknig@web.de' },
// Akzent unterschiedlich geschrieben
{ person_id: 'ReneK', name: 'Rene Kleinau', email: 'andere@perinco.de' },
{ person_id: 'ServiceA', name: 'Service Account', email: 'sa.hrworks@perinco.de' },
];
const { matched, unmatched } = matchUsers(persons, users);
assert.equal(matched.get('KaiS').id, 1);
assert.equal(matched.get('NicoN').id, 2);
assert.equal(matched.get('ReneK').id, 3);
assert.deepEqual(unmatched.map((u) => u.person_id), ['ServiceA']);
});
test('doppelte Namen ergeben keinen Treffer', () => {
const users = [
{ id: 5, name: 'Luisa Sauerwald', email: 'lusia.sauerwald@perinco.de' },
{ id: 23, name: 'Luisa Sauerwald', email: 'luisa.sauerwald@perinco.de' },
];
// Mail passt: eindeutig.
let r = matchUsers([{ person_id: 'LuisaS', name: 'Luisa Sauerwald', email: 'luisa.sauerwald@perinco.de' }], users);
assert.equal(r.matched.get('LuisaS').id, 23);
// Mail passt nicht: der Name ist zweimal da, also lieber melden als raten.
r = matchUsers([{ person_id: 'LuisaS', name: 'Luisa Sauerwald', email: 'x@y.de' }], users);
assert.equal(r.matched.size, 0);
assert.equal(r.unmatched.length, 1);
});
test('Zeitraum wird in Abschnitte von hoechstens 31 Tagen zerlegt', () => {
assert.deepEqual(chunks('2026-09-01', '2026-09-05'), [['2026-09-01', '2026-09-05']]);
const lang = chunks('2026-07-23', '2026-09-21');
assert.equal(lang.length, 2);
assert.equal(lang[0][0], '2026-07-23');
assert.equal(lang[lang.length - 1][1], '2026-09-21');
for (const [von, bis] of lang) {
const tage = (new Date(bis) - new Date(von)) / 86400000 + 1;
assert.ok(tage <= 31, `${von}-${bis} hat ${tage} Tage`);
}
});
test('nur genehmigte Abwesenheiten, bei Krankheit auch offene Bescheinigungen', () => {
assert.deepEqual(ABSENCE_STATES, ['validatedOk']);
assert.ok(SICK_STATES.includes('certificatePending'));
assert.ok(SICK_STATES.includes('reported'));
assert.ok(!SICK_STATES.includes('cancelled'));
assert.ok(!ABSENCE_STATES.includes('requested'));
});
test('Abschnitte mit eigener Groesse (Abwesenheiten: hoechstens ein Jahr)', () => {
const teile = chunks('2025-10-01', '2027-11-01', 365);
assert.equal(teile.length, 3);
for (const [von, bis] of teile) assert.ok((new Date(bis) - new Date(von)) / 86400000 + 1 <= 365);
});