89 lines
5.9 KiB
JavaScript
89 lines
5.9 KiB
JavaScript
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'
|
|
import { schemaKeys } from './support/schema.js'
|
|
|
|
// Einrichtungs-Ticket mit Abrechnung (V7) und unlockedBy in featureView fuer alle Funktionen.
|
|
// workorders, websiteProjects und customers legt das Setup-Skript nicht an: ohne Schema im Nachbau.
|
|
const aw = await startAppwriteMock({ schema: { portalFeatures: schemaKeys('portalFeatures') } })
|
|
const st = await startFakeStripe()
|
|
after(() => Promise.all([aw.close(), st.close()]))
|
|
useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url })
|
|
const { createFeatureTicket, ABRECHNUNGS_ZEILEN } = await import('../server/services/ticketAdmin.js')
|
|
const { featureView, ticketNachlegen } = await import('../server/services/siteFeatures.js')
|
|
|
|
aw.seed('customers', { $id: 'c1', name: 'Kunde Eins', location: 'Berlin', email: 'kunde1@example.test' })
|
|
|
|
const ALT = ['createdAt', 'customerId', 'customerLocation', 'customerName', 'details', 'priority', 'serviceType', 'status', 'systemType', 'topic', 'type', 'woid']
|
|
const base = { customerId: 'c1', project: { $id: 'p1', projectName: 'Bäckerei' }, featureKey: 'termine', siteKey: 'abcdefghijklmnop', topic: 'T', details: 'Zeile 1' }
|
|
const nutzer = (doc) => Object.keys(doc).filter((k) => !k.startsWith('$')).sort()
|
|
// aw.docs() liefert eine Kopie des Standes zum Aufruf: das Ticket erst anlegen, dann nachsehen
|
|
const ticketVon = async (args) => {
|
|
const { ticketId } = await createFeatureTicket(args)
|
|
return aw.docs('workorders').get(ticketId)
|
|
}
|
|
|
|
test('abrechnung abo und projekt: Felder und letzte Zeile', async () => {
|
|
assert.deepEqual(ABRECHNUNGS_ZEILEN, {
|
|
abo: 'Zeit im Arbeitsblatt erfassen und aufs Abo-Stundenkonto anrechnen (Einrichtung aus dem Abo, Vorschuss möglich).',
|
|
projekt: 'Zeit im Arbeitsblatt erfassen, nicht aufs Abo anrechnen (im Projekt enthalten).',
|
|
})
|
|
const t = await ticketVon({ ...base, abrechnung: 'abo' })
|
|
assert.deepEqual([t.einrichtungFuer, t.einrichtungAbrechnung], ['termine', 'abo'])
|
|
assert.equal(t.details, `Zeile 1\n${ABRECHNUNGS_ZEILEN.abo}`)
|
|
assert.ok((await ticketVon({ ...base, abrechnung: 'projekt' })).details.endsWith('\nZeit im Arbeitsblatt erfassen, nicht aufs Abo anrechnen (im Projekt enthalten).'))
|
|
})
|
|
|
|
test('ohne abrechnung: keine neuen Felder, Details unverändert (alte Ansicht)', async () => {
|
|
for (const abrechnung of [undefined, '']) {
|
|
const t = await ticketVon({ ...base, abrechnung })
|
|
assert.deepEqual(nutzer(t), ALT)
|
|
assert.equal(t.details, 'Zeile 1')
|
|
}
|
|
})
|
|
|
|
test('ungültiger Wert: TypeError, kein Ticket', async () => {
|
|
const n = aw.docs('workorders').size
|
|
for (const abrechnung of ['frei', 'Abo', null, 5]) await assert.rejects(() => createFeatureTicket({ ...base, abrechnung }), TypeError, String(abrechnung))
|
|
assert.equal(aw.docs('workorders').size, n)
|
|
})
|
|
|
|
test('lange Details: gekürzt auf 7000, die Schlusszeile bleibt; auch im Notfallweg nach 400', async () => {
|
|
const lang = Array.from({ length: 400 }, (_, i) => `Zeile ${i} ${'x'.repeat(30)}`).join('\n')
|
|
const t = await ticketVon({ ...base, details: lang, abrechnung: 'abo' })
|
|
assert.ok(t.details.length <= 7000 && t.details.endsWith(ABRECHNUNGS_ZEILEN.abo))
|
|
assert.ok(t.details.length > 6800, 'es wird nicht zu stark gekürzt')
|
|
aw.failNext({ collection: 'workorders', method: 'POST', status: 400, message: 'zu lang' })
|
|
const n = await ticketVon({ ...base, details: lang, fallbackDetails: 'Notfall', abrechnung: 'projekt' })
|
|
assert.ok(n.details.startsWith('Notfall') && n.details.endsWith(ABRECHNUNGS_ZEILEN.projekt))
|
|
})
|
|
|
|
test('featureView: unlockedBy für alle Funktionen, aboEndeAt/einbau nur bei Zeiten', async () => {
|
|
assert.equal((await featureView({ state: 'setup', unlockedBy: 'abo' }, 'news')).unlockedBy, 'abo')
|
|
assert.equal((await featureView({ state: 'setup', unlockedBy: 'projekt' }, 'shop')).unlockedBy, 'projekt')
|
|
assert.equal((await featureView({ state: 'active', unlockedByPurchase: true }, 'termine')).unlockedBy, 'kauf')
|
|
assert.equal((await featureView(undefined, 'news')).unlockedBy, null)
|
|
assert.equal((await featureView({ state: 'off', unlockedBy: 'abo' }, 'news')).unlockedBy, null)
|
|
assert.equal(Object.hasOwn(await featureView({ state: 'setup', unlockedBy: 'abo' }, 'news'), 'einbau'), false)
|
|
assert.equal(Object.hasOwn(await featureView({ state: 'setup', unlockedBy: 'abo' }, 'news'), 'aboEndeAt'), false)
|
|
const zeiten = await featureView({ state: 'setup', unlockedBy: 'abo', einbau: 'angestossen' }, 'zeiten')
|
|
assert.deepEqual([zeiten.unlockedBy, zeiten.einbau, Object.hasOwn(zeiten, 'aboEndeAt')], ['abo', 'angestossen', true])
|
|
})
|
|
|
|
test('ersetztes Ticket trägt die Abrechnung des Dokuments', async () => {
|
|
aw.seed('websiteProjects', { $id: 'p1', customerId: 'c1', projectName: 'Bäckerei' })
|
|
aw.seed('portalFeatures', { $id: 'f_p1_news', customerId: 'c1', projectId: 'p1', featureKey: 'news', siteKey: 'abcdefghijklmnop', state: 'setup', enabled: false, unlockedBy: 'abo', einrichtungAbrechnung: 'abo', ticketId: 'weg' })
|
|
const { doc } = await ticketNachlegen({ customerId: 'c1', projectId: 'p1', key: 'news', by: 'Kenso' })
|
|
const ticket = aw.docs('workorders').get(doc.ticketId)
|
|
assert.deepEqual([ticket.einrichtungAbrechnung, ticket.einrichtungFuer], ['abo', 'news'])
|
|
assert.ok(ticket.details.endsWith(ABRECHNUNGS_ZEILEN.abo))
|
|
})
|
|
|
|
test('ersetztes Ticket ohne Abrechnung am Dokument: wie bisher, keine neuen Felder', async () => {
|
|
aw.seed('portalFeatures', { $id: 'f_p1_termine', customerId: 'c1', projectId: 'p1', featureKey: 'termine', siteKey: 'bbcdefghijklmnop', state: 'setup', enabled: false, unlockedByPurchase: true, ticketId: 'weg2' })
|
|
const { doc } = await ticketNachlegen({ customerId: 'c1', projectId: 'p1', key: 'termine', by: 'Kenso' })
|
|
assert.deepEqual(nutzer(aw.docs('workorders').get(doc.ticketId)), ALT)
|
|
})
|