Files
2026-02-10 22:11:06 -05:00

283 lines
8.0 KiB
PHP

<?php
namespace Tests\App\Controllers\Api;
use App\Controllers\Api\AssignmentController;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\HTTP\URI;
use CodeIgniter\HTTP\UserAgent;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Mock\MockIncomingRequest;
use Config\App;
class FakeJsonRequest extends MockIncomingRequest
{
public function __construct(private readonly ?array $payload)
{
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->payload;
}
}
class FakeGetRequest extends MockIncomingRequest
{
public function __construct(private readonly array $gets = [])
{
parent::__construct(config(App::class), new URI('https://test.alrahmaisgl.org'), 'php://input', new UserAgent());
}
public function getGet($key = null, $filter = null, $default = null)
{
if ($key === null) {
return $this->gets;
}
return $this->gets[$key] ?? $default;
}
}
class StubPager
{
public function __construct(private readonly int $current, private readonly int $perPage, private readonly int $total)
{
}
public function getCurrentPage()
{
return $this->current;
}
public function getPerPage()
{
return $this->perPage;
}
public function getTotal()
{
return $this->total;
}
public function getPageCount()
{
return (int) ceil($this->total / max(1, $this->perPage));
}
}
class StubAssignmentModel
{
public array $whereHistory = [];
public array $saved = [];
public int $nextId = 10;
public array $findAllResult = [];
public array $findResult = [];
public array $pagerData = ['current' => 1, 'perPage' => 20, 'total' => 0];
public function where(string $column, $value = null): self
{
$this->whereHistory[] = [$column => $value];
return $this;
}
public function paginate(int $perPage, string $group, int $page)
{
$this->pager = new StubPager($this->pagerData['current'], $this->pagerData['perPage'], $this->pagerData['total']);
return $this->findAllResult;
}
public function find($id)
{
return $this->findResult[$id] ?? null;
}
public function insert(array $data)
{
$this->nextId++;
$this->saved[$this->nextId] = $data;
$this->findResult[$this->nextId] = ['id' => $this->nextId] + $data;
return $this->nextId;
}
public function getInsertID()
{
return $this->nextId;
}
public function update($id, array $data)
{
$this->saved[$id] = $data;
$this->findResult[$id] = ['id' => $id] + $data;
return true;
}
public function delete($id)
{
unset($this->findResult[$id]);
return true;
}
public function findAll()
{
return $this->findAllResult;
}
}
class TestableAssignmentController extends AssignmentController
{
public bool $validationResult = true;
public array $validationErrors = [];
public $validator;
public function __construct()
{
// skip real initialization
}
public function setAssignmentModel(StubAssignmentModel $model): void
{
$this->assignmentModel = $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 AssignmentControllerTest extends CIUnitTestCase
{
private TestableAssignmentController $controller;
private StubAssignmentModel $model;
protected function setUp(): void
{
parent::setUp();
$this->controller = new TestableAssignmentController();
$this->model = new StubAssignmentModel();
$this->controller->setAssignmentModel($this->model);
}
public function testIndexAppliesFilters()
{
$request = new FakeGetRequest(['page' => '2', 'per_page' => '5', 'class_id' => '12', 'teacher_id' => '3', 'student_id' => '7']);
$this->controller->setRequest($request);
$this->model->findAllResult = [['id' => 1]];
$this->model->pagerData = ['current' => 2, 'perPage' => 5, 'total' => 11];
$response = $this->controller->index();
$this->assertSame('Assignments retrieved successfully', $response['message']);
$this->assertSame(['id' => 1], $response['data']['data'][0]);
$this->assertSame(2, $response['data']['pagination']['current_page']);
$this->assertCount(3, $this->model->whereHistory);
}
public function testShowNotFound()
{
$response = $this->controller->show(99);
$this->assertSame(ResponseInterface::HTTP_NOT_FOUND, $response['code']);
}
public function testShowSuccess()
{
$this->model->findResult[5] = ['id' => 5];
$response = $this->controller->show(5);
$this->assertSame('Assignment retrieved successfully', $response['message']);
$this->assertSame(['id' => 5], $response['data']);
}
public function testStoreValidationFails()
{
$this->controller->setValidationResult(false, ['title' => 'required']);
$request = new FakeJsonRequest(['title' => '']);
$this->controller->setRequest($request);
$response = $this->controller->store();
$this->assertSame(422, $response['code']);
$this->assertArrayHasKey('title', $response['errors']);
}
public function testStoreCreatesAssignment()
{
$request = new FakeJsonRequest([
'title' => 'Test',
'description' => '',
'due_date' => '2025-01-01',
'class_id' => 1,
'teacher_id' => 2,
]);
$this->controller->setRequest($request);
$this->controller->setValidationResult(true);
$response = $this->controller->store();
$this->assertSame('Assignment created successfully', $response['message']);
$this->assertSame('Test', $this->model->saved[$this->model->getInsertID()]['title']);
}
public function testUpdateNotFound()
{
$response = $this->controller->update(11);
$this->assertSame(ResponseInterface::HTTP_NOT_FOUND, $response['code']);
}
public function testUpdateModifiesAssignment()
{
$this->model->findResult[15] = ['id' => 15, 'title' => 'Old'];
$request = new FakeJsonRequest(['title' => 'New']);
$this->controller->setRequest($request);
$this->controller->setValidationResult(true);
$response = $this->controller->update(15);
$this->assertSame('Assignment updated successfully', $response['message']);
$this->assertSame('New', $this->model->findResult[15]['title']);
}
public function testDeleteFlow()
{
$this->model->findResult[20] = ['id' => 20];
$response = $this->controller->delete(20);
$this->assertSame('Assignment deleted successfully', $response['message']);
$this->assertArrayNotHasKey(20, $this->model->findResult);
}
public function testStudentReturnsList()
{
$this->model->findAllResult = [['id' => 1]];
$response = $this->controller->student(4);
$this->assertSame('Assignments retrieved successfully for student', $response['message']);
$this->assertNotEmpty($response['data']);
}
}