import { test } from 'node:test' import assert from 'node:assert/strict' // Vor dem Import von config.js setzen: Appwrite unerreichbar (Port 9), damit kein Test ins Netz geht process.env.APPWRITE_ENDPOINT = 'http://127.0.0.1:9/v1' process.env.APPWRITE_API_KEY = 'test' const { attemptState, newPasswordProblem, recordAttempt } = await import('../server/services/customerPassword.js') const { forgetPasswordVersion, isSessionPasswordCurrent, rememberPasswordVersion } = await import('../server/services/passwordVersion.js') test('Neues Passwort: Laenge in Zeichen, Grenze von Appwrite in Byte', () => { assert.equal(newPasswordProblem('alt-alt-alt', ''), 'Bitte gib ein neues Passwort ein.') assert.match(newPasswordProblem('alt-alt-alt', '1234567'), /mindestens 8 Zeichen/) assert.equal(newPasswordProblem('alt-alt-alt', '1234567ä'), '') // Emoji zaehlen als ein Zeichen (nicht als zwei UTF-16-Einheiten) assert.match(newPasswordProblem('alt-alt-alt', '😀'.repeat(7)), /mindestens 8 Zeichen/) assert.equal(newPasswordProblem('alt-alt-alt', '😀'.repeat(8)), '') assert.equal(newPasswordProblem('alt-alt-alt', 'x'.repeat(256)), '') assert.match(newPasswordProblem('alt-alt-alt', 'x'.repeat(257)), /zu lang/) assert.equal(newPasswordProblem('alt-alt-alt', 'ü'.repeat(128)), '') assert.match(newPasswordProblem('alt-alt-alt', 'ü'.repeat(129)), /zu lang/) }) test('Neues Passwort: nicht leer, nicht das alte, nicht die E-Mail', () => { assert.match(newPasswordProblem('alt-alt-alt', ' '.repeat(10)), /Leerzeichen/) assert.match(newPasswordProblem('Altes-Passwort', 'Altes-Passwort'), /unterscheiden/) assert.match(newPasswordProblem('alt-alt-alt', ' Kunde@Beispiel.de ', 'kunde@beispiel.de'), /E-Mail-Adresse/) assert.equal(newPasswordProblem('alt-alt-alt', 'kunde@beispiel.de!', 'kunde@beispiel.de'), '') assert.equal(newPasswordProblem('alt-alt-alt', 'Ein langer Satz, den nur ich kenne'), '') }) test('Versuche: 5 je Stunde und Kunde, danach Sperre bis der erste eine Stunde alt ist', () => { const t0 = Date.parse('2026-09-27T10:00:00Z') const min = 60 * 1000 assert.deepEqual(attemptState('k1', t0), { left: 5, blockedFor: 0 }) for (let i = 0; i < 4; i++) recordAttempt('k1', t0 + i * min) assert.deepEqual(attemptState('k1', t0 + 4 * min), { left: 1, blockedFor: 0 }) recordAttempt('k1', t0 + 4 * min) assert.deepEqual(attemptState('k1', t0 + 5 * min), { left: 0, blockedFor: 55 * 60 }) // Nach einer Stunde ist der erste Versuch verfallen: wieder einer frei assert.deepEqual(attemptState('k1', t0 + 60 * min), { left: 1, blockedFor: 0 }) assert.deepEqual(attemptState('k1', t0 + 65 * min), { left: 5, blockedFor: 0 }) // Andere Kunden sind nicht betroffen assert.deepEqual(attemptState('k2', t0 + 5 * min), { left: 5, blockedFor: 0 }) }) test('Sessions: nach Passwortaenderung ungueltig, alte ohne Stand und Admins bleiben', async () => { rememberPasswordVersion('u1', '2026-09-27T10:00:00.000+00:00') assert.equal(await isSessionPasswordCurrent({ appwriteUserId: 'u1', customerId: 'c1', pwv: '2026-09-27T10:00:00.000+00:00' }), true) assert.equal(await isSessionPasswordCurrent({ appwriteUserId: 'u1', customerId: 'c1', pwv: '2026-09-01T08:00:00.000+00:00' }), false) // Session von vor dieser Pruefung (ohne pwv) laeuft normal aus assert.equal(await isSessionPasswordCurrent({ appwriteUserId: 'u1', customerId: 'c1' }), true) // Kundenansicht: appwriteUserId ist die des Mitarbeiters assert.equal(await isSessionPasswordCurrent({ role: 'admin', viewAs: true, appwriteUserId: 'u1', customerId: 'c1', pwv: 'x' }), true) // Konto ohne Passwort (geleert): keine Session gilt mehr rememberPasswordVersion('u2', '') assert.equal(await isSessionPasswordCurrent({ appwriteUserId: 'u2', customerId: 'c2', pwv: '2026-09-27T10:00:00.000+00:00' }), false) }) test('Sessions: ist Appwrite nicht erreichbar, bleibt man angemeldet', async () => { forgetPasswordVersion('u3') assert.equal(await isSessionPasswordCurrent({ appwriteUserId: 'u3', customerId: 'c3', pwv: 'irgendwas' }), true) })