import { test, after } from 'node:test' import assert from 'node:assert/strict' import { startAppwriteMock } from './support/appwriteMock.js' import { startFakeStripe } from './support/fakeStripe.js' import { useTestEnv } from './support/testEnv.js' const aw = await startAppwriteMock({ schema: {} }) const st = await startFakeStripe() useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url }) const { getStripe } = await import('../server/services/stripeBilling.js') after(() => Promise.all([aw.close(), st.close()])) const refused = (promise, pattern) => assert.rejects(promise, (err) => err.statusCode === 400 && pattern.test(err.message)) const create = (extra = {}) => getStripe().invoices.create({ customer: 'cus_x', collection_method: 'send_invoice', days_until_due: 14, ...extra }) const item = (invoice, extra) => getStripe().invoiceItems.create({ customer: 'cus_x', invoice, description: 'Posten', currency: 'eur', ...extra }) test('Stripe-Nachbau: custom_fields und rendering werden gespeichert und mit der Rechnung geliefert', async () => { const felder = [{ name: 'Projekt', value: 'Website anelia-wolf.com' }, { name: 'Auftrag', value: 'AB-2026-0002 vom 06.10.2026' }] const invoice = await create({ custom_fields: felder, rendering: { pdf: { page_size: 'a4' } } }) assert.deepEqual(st.invoices.get(invoice.id).custom_fields, felder) assert.deepEqual(st.invoices.get(invoice.id).rendering, { pdf: { page_size: 'a4' } }) const gelesen = await getStripe().invoices.retrieve(invoice.id) assert.deepEqual(gelesen.custom_fields, felder) assert.deepEqual(gelesen.rendering, { pdf: { page_size: 'a4' } }) await item(invoice.id, { quantity: 1, unit_amount_decimal: '1000' }) assert.deepEqual(st.invoices.get(invoice.id).custom_fields, felder, 'Posten ändern die Zusatzfelder nicht') const schlicht = await create() assert.equal(st.invoices.get(schlicht.id).custom_fields, null) assert.equal(st.invoices.get(schlicht.id).rendering, null) }) test('Stripe-Nachbau: Grenzen der Zusatzfelder (4, Name 40, Wert 140) und der Seitengröße wie bei Stripe', async () => { const viele = Array.from({ length: 5 }, (_, i) => ({ name: `Feld ${i}`, value: 'x' })) await refused(create({ custom_fields: viele }), /up to 4 custom fields/) await refused(create({ custom_fields: [{ name: 'n'.repeat(41), value: 'x' }] }), /names must be between 1 and 40/) await refused(create({ custom_fields: [{ name: 'n', value: 'v'.repeat(141) }] }), /values must be between 1 and 140/) await refused(create({ rendering: { pdf: { page_size: 'din-a4' } } }), /page_size/) const vier = await create({ custom_fields: viele.slice(0, 4).map((f) => ({ ...f, value: 'v'.repeat(140) })), rendering: { pdf: { page_size: 'letter' } } }) assert.equal(st.invoices.get(vier.id).custom_fields.length, 4) }) test('Stripe-Nachbau: Posten mit negativem amount (ohne quantity) mindern die Summe; amount mit quantity oder Einzelpreis wird abgelehnt', async () => { const invoice = await create() await item(invoice.id, { description: 'Leistung', quantity: 1, unit_amount_decimal: '40000' }) await item(invoice.id, { description: 'abzüglich Anzahlung', amount: -15000 }) const gespeichert = st.invoices.get(invoice.id) assert.deepEqual(gespeichert.lines.data.map((l) => [l.description, l.quantity, l.amount]), [['Leistung', 1, 40000], ['abzüglich Anzahlung', 1, -15000]]) assert.deepEqual([gespeichert.total, gespeichert.amount_due], [25000, 25000]) await refused(item(invoice.id, { amount: -100, quantity: 2 }), /only specify one of these parameters/) await refused(item(invoice.id, { amount: -100, unit_amount_decimal: '100' }), /only specify one of these parameters/) assert.equal(st.invoices.get(invoice.id).total, 25000) })