Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die README; an keiner Stelle Bedeutung, nur Zeichensetzung.
125 lines
4.3 KiB
TypeScript
125 lines
4.3 KiB
TypeScript
// @vitest-environment node
|
|
import { afterAll, describe, expect, it } from 'vitest'
|
|
import { db } from '@/lib/db'
|
|
import { parseTemplateFields } from '@/lib/templates/schema'
|
|
import { dossierRows, dossierSpan, isInputField } from '@/lib/templates/fields'
|
|
|
|
/**
|
|
* Das Aktenblatt der Personalabteilung.
|
|
*
|
|
* Der erste Test ist der wichtigere: `parseTemplateFields` gibt bei einer
|
|
* ungültigen Vorlage eine **leere Liste** zurück, statt zu werfen. Ein Tippfehler
|
|
* im Seed würde das Blatt also lautlos leeren, statt aufzufallen.
|
|
*/
|
|
const url = process.env.DIRECT_DATABASE_URL ?? process.env.DATABASE_URL
|
|
const suite = url ? describe : describe.skip
|
|
|
|
suite('Vorlage des Aktenblatts', () => {
|
|
afterAll(async () => {
|
|
await db.$disconnect()
|
|
})
|
|
|
|
async function felder() {
|
|
const vorlage = await db.documentTemplate.findFirst({
|
|
where: { key: 'personalakte', isActive: true },
|
|
orderBy: { version: 'desc' },
|
|
select: { fields: true, layout: true, uses: true, sheetTitle: true, sheetSubtitle: true },
|
|
})
|
|
expect(vorlage).not.toBeNull()
|
|
return { vorlage: vorlage!, fields: parseTemplateFields(vorlage!.fields) }
|
|
}
|
|
|
|
it('übersteht die verbindliche Prüfung vollständig', async () => {
|
|
const { vorlage, fields } = await felder()
|
|
|
|
// Kein stilles Leerlaufen: die Zahl muss stimmen, nicht nur "grösser null".
|
|
expect(fields).toHaveLength(
|
|
(vorlage.fields as unknown[]).length,
|
|
)
|
|
expect(vorlage.layout).toBe('DOSSIER')
|
|
expect(vorlage.uses).toEqual(['PERSON_DOCUMENT'])
|
|
expect(vorlage.sheetSubtitle).toBeTruthy()
|
|
|
|
// Die Felder, die das Blatt ausmachen.
|
|
const schluessel = fields.map((f) => f.key)
|
|
for (const key of [
|
|
'lichtbild',
|
|
'name',
|
|
'vorname',
|
|
'alter',
|
|
'geschlecht',
|
|
'groesse',
|
|
'abteilung',
|
|
'dienstgrad',
|
|
'sicherheitsfreigabe',
|
|
'wissensfreigabe',
|
|
'konfession',
|
|
'adresse',
|
|
'anmerkungen',
|
|
'personalarbeiter',
|
|
'standortleiter',
|
|
]) {
|
|
expect(schluessel).toContain(key)
|
|
}
|
|
})
|
|
|
|
it('ergibt genau das Raster des Formulars', async () => {
|
|
const { fields } = await felder()
|
|
const { photo, photoRows, rows } = dossierRows(fields)
|
|
|
|
expect(photo?.key).toBe('lichtbild')
|
|
expect(photoRows).toBe(4)
|
|
|
|
// Neben dem Lichtbild vier Zeilen zu je vier Spalten, danach fünf.
|
|
const struktur = rows.map((row, index) =>
|
|
row.map((field) => `${field.key}:${dossierSpan(field, index < photoRows)}`),
|
|
)
|
|
expect(struktur).toEqual([
|
|
['name:2', 'vorname:2'],
|
|
['alter:2', 'geschlecht:2'],
|
|
['groesse:4'],
|
|
['abteilung:2', 'dienstgrad:2'],
|
|
['sicherheitsfreigabe:3', 'wissensfreigabe:2'],
|
|
['konfession:2', 'adresse:3'],
|
|
['anmerkungen:5'],
|
|
['personalarbeiter:3', 'standortleiter:2'],
|
|
])
|
|
})
|
|
|
|
it('lässt die Datumsfelder der Unterschriften aus dem Raster heraus', async () => {
|
|
const { fields } = await felder()
|
|
const { rows } = dossierRows(fields)
|
|
const imRaster = rows.flat().map((f) => f.key)
|
|
|
|
// Sie stehen unter der jeweiligen Unterschrift, nicht in einer eigenen
|
|
// Zelle - bearbeitbar bleiben sie trotzdem.
|
|
expect(imRaster).not.toContain('personalarbeiter_datum')
|
|
expect(imRaster).not.toContain('standortleiter_datum')
|
|
expect(fields.map((f) => f.key)).toContain('personalarbeiter_datum')
|
|
})
|
|
|
|
it('hält die Klassifikation aus dem Raster heraus, sie gehört in den Balken', async () => {
|
|
const { fields } = await felder()
|
|
const { rows } = dossierRows(fields)
|
|
expect(rows.flat().map((f) => f.key)).not.toContain('foundation_klassifikation')
|
|
|
|
const feld = fields.find((f) => f.key === 'foundation_klassifikation')
|
|
expect(feld && isInputField(feld) && feld.slot).toBe('classbar')
|
|
})
|
|
|
|
it('kennt für jede Klassifikationsstufe eine Farbe', async () => {
|
|
const { fields } = await felder()
|
|
const feld = fields.find((f) => f.key === 'foundation_klassifikation')
|
|
const stufen = await db.foundationClearance.findMany({ orderBy: { level: 'asc' } })
|
|
|
|
// Sonst bliebe der Balken bei einer gültigen Auswahl grau.
|
|
const optionen = feld && isInputField(feld) ? (feld.options ?? []) : []
|
|
for (const option of optionen) {
|
|
expect(stufen.map((s) => String(s.level))).toContain(option)
|
|
}
|
|
for (const stufe of stufen) {
|
|
expect(stufe.colorHex).toMatch(/^#[0-9a-f]{6}$/i)
|
|
}
|
|
})
|
|
})
|