## Example Database

- Model find all
- Soft delete leaves row

## Attendance Flow (Tests\Integration\AttendanceFlow)

- Student attendance entry flow success
- Student attendance entry prevents duplicate
- Student attendance complete entry and exit
- Student attendance exit without entry
- Teacher attendance entry flow success
- Attendance with invalid unique code
- Attendance with invalid waktu
- Student can attend consecutive days

## Example Session

- Session simple

## Health

- Is defined app path
- Base url has been set

## Common Helpers (Tests\Unit\Helpers\CommonHelpers)

- Clean str removes special characters
- Clean str removes forbidden characters
- Clean str trims whitespace
- Clean number converts string to int
- Clean number returns zero for empty string
- Clean number returns zero for non numeric
- Clean number trims whitespace
- Clean number handles negative numbers
- Clr quotes removes double quotes
- Clr quotes removes single quotes
- Clr quotes removes both quote types
- Str trim removes leading whitespace
- Str trim removes trailing whitespace
- Str trim handles empty string
- Str trim handles null
- Str replace replaces string
- Str replace handles empty string
- Str replace handles null
- Remove forbidden characters removes semicolon
- Remove forbidden characters removes angular brackets
- Remove forbidden characters removes multiple characters
- Remove forbidden characters removes slash
- Remove special characters removes hash
- Remove special characters removes exclamation
- Remove special characters removes parentheses
- Remove special characters with quotes removal
- Remove special characters without quotes removal
- Generate token returns string
- Generate token generates unique tokens
- Generate token short version shorter
- Generate token contains no dots only dashes
- Count items returns correct count
- Count items returns zero for empty array
- Count items returns zero for null
- Count items returns zero for non array
- Get c s v input value returns value
- Get c s v input value returns empty string for missing key
- Get c s v input value returns zero for missing key int
- Get c s v input value returns empty for empty array
- Get c s v input value handles null array
- Clean str handles x s s attempt
- Clean str handles s q l injection attempt
- Remove forbidden characters handles path traversal
- Generate token is reasonably long

## Kelas Model

- Format kelas label uses desa kelompok and dapuan

## Guru Model (Tests\Unit\Models\GuruModel)

- Create guru successfully
- Create guru with rfid
- Create guru generates unique code
- Cek guru by unique code
- Cek guru by rfid code
- Get all guru
- Get guru by id
- Update guru
- Update guru with rfid
- Cek guru with invalid code
- Get guru by id with invalid id
- Get all guru when empty
- Create guru generates different unique codes
- Update guru does not change unique code
- Get all guru ordered by name
- Cek guru returns first match for or condition
- Generate c s v object successfully
- Generate c s v object with b o m
- Import c s v item successfully
- Import c s v item with multiple records
- Generate c s v object with empty file

## Jurusan Model (Tests\Unit\Models\JurusanModel)

- Generate c s v object successfully
- Generate c s v object with b o m
- Import c s v item successfully
- Import c s v item duplicate handling
- Import c s v item with multiple records
- Generate c s v object with empty file

## Kelas Model (Tests\Unit\Models\KelasModel)

- Generate c s v object successfully
- Generate c s v object with b o m
- Import c s v item successfully
- Import c s v item duplicate handling
- Import c s v item with multiple records
- Generate c s v object with empty file

## Presensi Guru Model (Tests\Unit\Models\PresensiGuruModel)

- Cek absen returns false when no attendance
- Cek absen returns id presensi when attendance exists
- Absen masuk creates new attendance record
- Absen keluar updates existing attendance
- Get presensi by id guru tanggal returns correct record
- Get presensi by id returns correct record
- Update presensi with new record
- Update presensi with existing record
- Get presensi by tanggal returns all teachers
- Cek absen with non existent teacher
- Cek absen with different date
- Get presensi by id guru tanggal returns null when no record
- Get presensi by id returns null for invalid id
- Absen keluar with invalid id
- Update presensi keeps existing keterangan when null
- Multiple absen masuk on same day
- Cek absen with time object
- Update presensi only updates jam masuk when provided
- Update presensi only updates jam keluar when provided
- Get presensi by kehadiran with hadir
- Get presensi by kehadiran with tanpa keterangan

## Presensi Siswa Model (Tests\Unit\Models\PresensiSiswaModel)

- Cek absen returns false when no attendance
- Cek absen returns id presensi when attendance exists
- Absen masuk creates new attendance record
- Absen keluar updates existing attendance
- Get presensi by id siswa tanggal returns correct record
- Get presensi by id returns correct record
- Update presensi with new record
- Update presensi with existing record
- Get presensi by kelas tanggal returns all students
- Cek absen with non existent student
- Cek absen with different date
- Get presensi by id siswa tanggal returns null when no record
- Get presensi by id returns null for invalid id
- Absen masuk without kelas id
- Absen keluar with invalid id
- Update presensi keeps existing keterangan when null
- Multiple absen masuk on same day
- Cek absen with time object
- Update presensi only updates jam masuk when provided
- Update presensi only updates jam keluar when provided
- Get presensi by kehadiran with hadir
- Get presensi by kehadiran with tanpa keterangan

## Siswa Model (Tests\Unit\Models\SiswaModel)

- Create siswa successfully
- Create siswa with rfid
- Cek siswa by unique code
- Cek siswa by rfid code
- Get siswa by id
- Get all siswa with kelas
- Get all siswa with kelas filter by tingkat
- Get all siswa with kelas filter by jurusan
- Get siswa by kelas
- Get siswa count by kelas
- Update siswa
- Update siswa with rfid
- Delete siswa
- Delete multi selected
- Cek siswa with invalid code
- Get siswa by id with invalid id
- Get siswa by kelas with no students
- Get siswa count by kelas with no students
- Delete siswa with invalid id
- Get siswa with invalid id
- Create siswa generates unique code
- Update siswa does not change unique code
- Get siswa count by kelas with invalid id
- Get all siswa with kelas ordered by name
- Delete multi selected with empty array
- Cek siswa returns first match for or condition

## QRGenerator

- Generate qr code

## RFIDRules (Tests\Unit\Validation\RFIDRules)

- Is rfid unique with empty string returns true
- Is rfid unique for new siswa with unique code
- Is rfid unique for new guru with unique code
- Is rfid unique returns false when code exists in siswa
- Is rfid unique returns false when code exists in guru
- Is rfid unique checks across both tables
- Is rfid unique excludes same student when updating
- Is rfid unique excludes same teacher when updating
- Is rfid unique does not exclude other students
- Is rfid unique without type parameter
- Is rfid unique with only exclude id no type
- Is rfid unique excludes correctly across types
- Is rfid unique with null rfid code
- Is rfid unique with whitespace rfid code
- Is rfid unique case sensitivity
- Is rfid unique with special characters
- Is rfid unique multiple students with null rfid