recreate project
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\App\Controllers\Api;
|
||||
|
||||
use App\Controllers\Api\AttendanceTrackingController;
|
||||
use CodeIgniter\HTTP\URI;
|
||||
use CodeIgniter\HTTP\UserAgent;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\Mock\MockIncomingRequest;
|
||||
use Config\App;
|
||||
|
||||
class FakeTrackingRequest extends MockIncomingRequest
|
||||
{
|
||||
public function __construct(private readonly ?array $json = null, private readonly array $gets = [])
|
||||
{
|
||||
parent::__construct(config(App::class), new URI('https://test.alrahmaisgl.org'), 'php://input', new UserAgent());
|
||||
}
|
||||
|
||||
public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0): ?array
|
||||
{
|
||||
return $this->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']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user