283 lines
8.0 KiB
PHP
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']);
|
|
}
|
|
}
|