88 lines
5.4 KiB
JavaScript
88 lines
5.4 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'
|
|
|
|
// Team-Routen fuers Ticketsystem: Portal-Status, Protokoll der Kundenansicht, Preview-Link fuer alle Mitarbeiter
|
|
const aw = await startAppwriteMock({ schema: { customerViewLog: schemaKeys('customerViewLog') } })
|
|
const st = await startFakeStripe()
|
|
useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url })
|
|
const { startTestApp, rawGet, post } = await import('./support/testApp.js')
|
|
const { seedFixtures } = await import('./support/fixtures.js')
|
|
const { default: teamRoutes } = await import('../server/routes/team/index.js')
|
|
const { consumeStaffPreviewToken } = await import('../server/services/staffPreviewTokens.js')
|
|
const app = await startTestApp({ '/api/team': teamRoutes })
|
|
after(() => Promise.all([app.close(), aw.close(), st.close()]))
|
|
|
|
seedFixtures(aw)
|
|
aw.seed('employees', { $id: 'e_staff2', userId: 'u_staff2', displayName: 'Andrej', email: 'andrej@webklar.com' })
|
|
aw.seed('customerPortalAccess', { $id: 'pa1', customerId: 'c1', enabled: true, lastLoginAt: '2026-09-30T10:00:00.000Z' })
|
|
aw.seed('customerViewLog', { $id: 'v1', customerId: 'c1', staffUserId: 'u_staff2', staffName: 'Andrej', action: 'geoeffnet', detail: '', createdAt: '2026-09-30T10:00:00.000Z' })
|
|
aw.seed('customerViewLog', { $id: 'v2', customerId: 'c1', staffUserId: 'u_staff2', staffName: 'Andrej', action: 'news_angelegt', detail: 'Hallo', createdAt: '2026-09-30T10:05:00.000Z' })
|
|
aw.seed('customerViewLog', { $id: 'v3', customerId: 'c2', staffUserId: 'u_staff2', staffName: 'Andrej', action: 'geoeffnet', detail: '', createdAt: '2026-09-30T11:00:00.000Z' })
|
|
aw.seed('websiteProjects', { $id: 'wp1', customerId: 'c1', projectName: 'Bäckerei', subdomain: 'baeckerei', status: 'ready' })
|
|
aw.seed('websiteProjects', { $id: 'wp2', customerId: 'c1', projectName: 'Café', subdomain: 'cafe', status: 'building' })
|
|
|
|
const auth = { headers: { authorization: 'Bearer jwt-staff' } }
|
|
|
|
test('portal: hasAccess und lastLoginAt; c2 ohne Zugang hasAccess false; unbekannt 404', async () => {
|
|
const c1 = await rawGet('/api/team/customers/c1/portal', auth)
|
|
assert.equal(c1.status, 200)
|
|
assert.deepEqual(c1.body, { hasAccess: true, lastLoginAt: '2026-09-30T10:00:00.000Z' })
|
|
assert.deepEqual((await rawGet('/api/team/customers/c2/portal', auth)).body, { hasAccess: false, lastLoginAt: null })
|
|
assert.equal((await rawGet('/api/team/customers/gibtsnicht/portal', auth)).status, 404)
|
|
})
|
|
|
|
test('protokoll: Eintraege des Kunden neueste zuerst', async () => {
|
|
const res = await rawGet('/api/team/customers/c1/protokoll', auth)
|
|
assert.equal(res.status, 200)
|
|
assert.deepEqual(res.body.entries.map((e) => e.id), ['v2', 'v1'])
|
|
assert.deepEqual(res.body.entries[0], { id: 'v2', at: '2026-09-30T10:05:00.000Z', staffName: 'Andrej', action: 'news_angelegt', detail: 'Hallo' })
|
|
})
|
|
|
|
test('preview-link fuer Mitarbeiter ohne Admin-Label -> openUrl auf staff-preview', async () => {
|
|
const res = await post('/api/team/preview-link', { subdomain: 'baeckerei', previewUrl: 'https://baeckerei.project.webklar.com/' }, auth)
|
|
assert.equal(res.status, 200)
|
|
assert.match(res.body.openUrl, /^https:\/\/project\.webklar\.com\/api\/auth\/staff-preview\?token=[0-9a-f]{64}$/)
|
|
const data = consumeStaffPreviewToken(new URL(res.body.openUrl).searchParams.get('token'))
|
|
assert.deepEqual([data.userId, data.name, data.previewUrl, data.customerId], ['u_staff2', 'Andrej', 'https://baeckerei.project.webklar.com/', 'c1'])
|
|
})
|
|
|
|
test('preview-link: nicht bereit 409, unbekannt 404, ohne Subdomain 400', async () => {
|
|
assert.equal((await post('/api/team/preview-link', { subdomain: 'cafe' }, auth)).status, 409)
|
|
assert.equal((await post('/api/team/preview-link', { subdomain: 'gibtsnicht' }, auth)).status, 404)
|
|
assert.equal((await post('/api/team/preview-link', {}, auth)).status, 400)
|
|
})
|
|
|
|
test('alle Team-Routen ohne JWT -> 401', async () => {
|
|
for (const [method, p] of [
|
|
['GET', '/api/team/customers/c1/portal'],
|
|
['GET', '/api/team/customers/c1/protokoll'],
|
|
['POST', '/api/team/customers/c1/kundenansicht'],
|
|
['POST', '/api/team/preview-link'],
|
|
]) {
|
|
const res = method === 'GET' ? await rawGet(p) : await post(p, {})
|
|
assert.equal(res.status, 401, `${method} ${p}`)
|
|
}
|
|
})
|
|
|
|
// Etappe 3: Abo-Status fuer alle Mitarbeiter (Kunden-Reiter "Abo & Angebote", Stunden-Pruefung am Ticket)
|
|
test('abo: Mitarbeiter ohne Admin-Label sieht den Abo-Status', async () => {
|
|
aw.seed('subscriptions', {
|
|
$id: 'sub_t', customerId: 'c3', status: 'active', productKey: 'wartung', storageUnits: 1,
|
|
startedAt: '2026-09-01T10:00:00.000Z', trialEnd: '2026-09-15T00:00:00.000Z', currentPeriodEnd: '2026-11-01T00:00:00.000Z', cancelAt: null,
|
|
})
|
|
const res = await rawGet('/api/team/customers/c3/abo', auth)
|
|
assert.equal(res.status, 200)
|
|
assert.deepEqual(res.body, {
|
|
productKey: 'wartung', active: true, status: 'active', storageUnits: 1, startedAt: '2026-09-01T10:00:00.000Z',
|
|
serviceStart: '2026-09-15T00:00:00.000Z', currentPeriodEnd: '2026-11-01T00:00:00.000Z', cancelAt: null,
|
|
})
|
|
assert.deepEqual((await rawGet('/api/team/customers/c4/abo', auth)).body, {
|
|
productKey: null, active: false, status: null, storageUnits: 0, startedAt: null, serviceStart: null, currentPeriodEnd: null, cancelAt: null,
|
|
})
|
|
assert.equal((await rawGet('/api/team/customers/c3/abo')).status, 401)
|
|
})
|