json; } public function getGet($key = null, $filter = null, $default = null) { if ($key === null) { return $this->gets; } return $this->gets[$key] ?? $default; } } class StubTrackingModel { public array $findAllResult = []; public array $findResult = []; public array $updated = []; public array $inserted = []; public array $firstQueue = []; public function where($column, $value = null) { return $this; } public function select($columns) { return $this; } public function groupBy($column) { return $this; } public function having($column, $value) { return $this; } public function findAll(): array { return $this->findAllResult; } public function orderBy(...$args) { return $this; } public function first() { return array_shift($this->firstQueue) ?? null; } public function queueFirst(array $row): void { $this->firstQueue[] = $row; } public function insert(array $data) { $this->inserted[] = $data; return 1; } public function getInsertID() { return 1; } public function update(int $id, array $data) { $this->updated[$id] = $data; } public function find(int $id) { return $this->findResult[$id] ?? null; } } class TestableAttendanceTrackingController extends AttendanceTrackingController { public bool $validationResult = true; public array $validationErrors = []; public $validator; public function __construct() { // bypass real model instantiation } public function setTrackingModel(StubTrackingModel $model): void { $this->trackingModel = $model; } public function setValidationResult(bool $result, array $errors = []): void { $this->validationResult = $result; $this->validationErrors = $errors; } protected function validate($rules, array $messages = []): bool { $this->validator = new class($this->validationErrors) { private array $errors; public function __construct(array $errors) { $this->errors = $errors; } public function getErrors() { return $this->errors; } }; return $this->validationResult; } protected function respond($data = null, ?int $status = null, string $message = '') { return ['data' => $data, 'code' => $status, 'message' => $message]; } } class AttendanceTrackingControllerTest extends CIUnitTestCase { private TestableAttendanceTrackingController $controller; private StubTrackingModel $model; protected function setUp(): void { parent::setUp(); $this->controller = new TestableAttendanceTrackingController(); $this->model = new StubTrackingModel(); $this->controller->setTrackingModel($this->model); } public function testRecordValidationFails() { $this->controller->setValidationResult(false, ['student_id' => 'required']); $this->controller->setRequest(new FakeTrackingRequest(['student_id' => null])); $response = $this->controller->record(); $this->assertSame(422, $response['code']); $this->assertArrayHasKey('student_id', $response['errors']); } public function testRecordUpdatesExisting() { $this->model->queueFirst(['id' => 5]); $request = new FakeTrackingRequest(['student_id' => 1, 'date' => '2024-09-01', 'status' => 'present']); $this->controller->setRequest($request); $response = $this->controller->record(); $this->assertSame('Attendance tracking record updated successfully', $response['message']); $this->assertSame(['student_id' => 1, 'date' => '2024-09-01', 'status' => 'present'], $this->model->updated[5]); } public function testRecordCreatesNew() { $request = new FakeTrackingRequest(['student_id' => 2, 'date' => '2024-09-02', 'status' => 'late']); $this->controller->setRequest($request); $this->controller->setValidationResult(true); $response = $this->controller->record(); $this->assertSame('Attendance tracking record created successfully', $response['message']); $this->assertSame(1, $response['data']['id']); } public function testViolationsDefaultsThreshold() { $this->controller->setRequest(new FakeTrackingRequest(null, [])); $this->model->findAllResult = [['student_id' => 3, 'total_violations' => 5]]; $response = $this->controller->violations(); $this->assertSame('Attendance violations retrieved successfully', $response['message']); $this->assertSame(1, count($response['data'])); } public function testViolationsCustomThreshold() { $request = new FakeTrackingRequest(null, ['threshold' => '2']); $this->controller->setRequest($request); $this->model->findAllResult = [['student_id' => 4, 'total_violations' => 3]]; $response = $this->controller->violations(); $this->assertSame(1, count($response['data'])); } public function testStudentRecordsOrder() { $this->model->findAllResult = [['id' => 7]]; $response = $this->controller->student(7); $this->assertSame('Tracking records retrieved successfully for student', $response['message']); $this->assertSame(7, $response['data'][0]['id']); } }