import { test, after } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { startAppwriteMock } from './support/appwriteMock.js' import { useTestEnv } from './support/testEnv.js' import { schemaKeys } from './support/schema.js' import { KUNDENANSICHT_ATTRIBUTE, main } from '../scripts/kundenansicht-setup.mjs' // Setup-Skript der Kundenansicht neu (Paket P5): Kundenart im Nachweis, Einrichtungs-Marker an Ticket und Funktion. // Das Skript laeuft hier nur gegen Mock-Clients, nie gegen Produktion. const aw = await startAppwriteMock({ schema: {} }) after(() => aw.close()) useTestEnv({ appwriteUrl: aw.url, stripeUrl: 'http://127.0.0.1:1' }) const { config } = await import('../server/config.js') const client = (vorhanden = {}) => { const calls = { attrs: [], waits: [] } return { calls, collectionExists: async () => true, listAttributes: async (id) => (vorhanden[id] ?? []).map((key) => ({ key })), createAttribute: async (id, a) => calls.attrs.push(`${id}.${a.key}`), waitForAttribute: async (id, k) => calls.waits.push(`${id}.${k}`), } } const ID = () => config.collections const ALLE = () => [ `${ID().featureConsents}.kundenart`, `${ID().portalFeatures}.einrichtungAbrechnung`, `${ID().portalFeatures}.unlockedBy`, `${ID().workorders}.einrichtungAbrechnung`, `${ID().workorders}.einrichtungFuer`, ] test('Schema: Schlüssel, Größen, nur optionale Strings; längste Werte passen hinein', () => { const kurz = Object.fromEntries(Object.entries(KUNDENANSICHT_ATTRIBUTE).map(([c, l]) => [c, l.map((a) => `${a.key}:${a.size}`)])) assert.deepEqual(kurz, { featureConsents: ['kundenart:12'], workorders: ['einrichtungFuer:16', 'einrichtungAbrechnung:8'], portalFeatures: ['unlockedBy:8', 'einrichtungAbrechnung:8'], }) assert.ok(Object.values(KUNDENANSICHT_ATTRIBUTE).flat().every((a) => a.type === 'string' && a.required === false)) assert.ok('unternehmen'.length <= 12 && 'projekt'.length <= 8 && 'unterkunft'.length <= 16) }) test('--pruefen meldet alle fünf Lücken und legt nichts an', async () => { const c = client() const log = [] const r = await main({ pruefen: true, client: c, log: (z) => log.push(z) }) assert.deepEqual(r.missing.map((a) => `${a.collection}.${a.key}`).sort(), ALLE()) assert.deepEqual(c.calls, { attrs: [], waits: [] }) assert.ok(log.some((z) => z === `- ${ID().featureConsents}.kundenart FEHLT`)) }) test('ohne --pruefen: legt an und wartet; der zweite Lauf ist idempotent', async () => { const c = client() await main({ client: c, log: () => {} }) assert.deepEqual([...c.calls.attrs].sort(), ALLE()) assert.deepEqual([...c.calls.waits].sort(), ALLE()) const voll = client({ [ID().featureConsents]: ['kundenart'], [ID().workorders]: ['einrichtungFuer', 'einrichtungAbrechnung'], [ID().portalFeatures]: ['unlockedBy', 'einrichtungAbrechnung'], }) assert.deepEqual((await main({ client: voll, log: () => {} })).missing, []) assert.deepEqual(voll.calls.attrs, []) }) test('schemaKeys liest das Skript; das Skript löscht nichts', () => { assert.equal(schemaKeys('featureConsents').at(-1), 'kundenart') const f = schemaKeys('portalFeatures') assert.ok(f.includes('einrichtungAbrechnung')) assert.equal(new Set(f).size, f.length) assert.doesNotMatch(readFileSync(new URL('../scripts/kundenansicht-setup.mjs', import.meta.url), 'utf8'), /delete/i) })