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

198 lines
5.5 KiB
PHP

<?php
namespace Tests\App\Controllers\Api;
use App\Controllers\Api\NotificationController;
use CodeIgniter\HTTP\URI;
use CodeIgniter\HTTP\UserAgent;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Mock\MockIncomingRequest;
use Config\App;
class StubUserNotificationModel
{
public array $whereHistory = [];
private ?array $firstResult = null;
public ?array $lastUpdate = null;
public function select(string $columns): self
{
return $this;
}
public function join(string $table, string $cond): self
{
return $this;
}
public function where(string $column, $value = null): self
{
$this->whereHistory[] = ['column' => $column, 'value' => $value];
return $this;
}
public function first(): ?array
{
return $this->firstResult;
}
public function update(int $id, array $data): bool
{
$this->lastUpdate = ['id' => $id, 'data' => $data];
return true;
}
public function setFirstResult(?array $result): void
{
$this->firstResult = $result;
}
}
class FakeNotificationRequest extends MockIncomingRequest
{
public function __construct(private readonly array $params = [])
{
parent::__construct(config(App::class), new URI('https://test.alrahmaisgl.org'), null, new UserAgent());
}
public function getGet($key = null, $filter = null, $default = null)
{
if ($key === null) {
return $this->params;
}
return $this->params[$key] ?? $default;
}
}
class TestableNotificationController extends NotificationController
{
private array $overridePagination = [];
private ?object $currentUser = null;
public function __construct()
{
// Skip normal boot to keep dependencies under test control.
}
public function setModels(StubUserNotificationModel $model): void
{
$this->userNotificationModel = $model;
}
public function setCurrentUser(object $user): void
{
$this->currentUser = $user;
}
public function setPaginatedResult(array $result): void
{
$this->overridePagination = $result;
}
protected function paginate($source, int $page = 1, int $perPage = 20): array
{
if (!empty($this->overridePagination)) {
return $this->overridePagination;
}
return parent::paginate($source, $page, $perPage);
}
protected function getCurrentUser(): ?object
{
return $this->currentUser;
}
}
class NotificationControllerTest extends CIUnitTestCase
{
private TestableNotificationController $controller;
private StubUserNotificationModel $model;
protected function setUp(): void
{
parent::setUp();
$this->controller = new TestableNotificationController();
$this->model = new StubUserNotificationModel();
$this->controller->setModels($this->model);
$this->controller->setCurrentUser((object) ['id' => 42]);
}
public function testIndexReturnsPaginatedNotifications()
{
$payload = ['data' => [['id' => 1]], 'pagination' => ['total' => 1]];
$this->controller->setPaginatedResult($payload);
$request = new FakeNotificationRequest();
$this->controller->setRequest($request);
$response = $this->controller->index();
$this->assertTrue($response['status']);
$this->assertSame($payload, $response['data']);
$this->assertSame('Notifications retrieved successfully', $response['message']);
}
public function testIndexRespectsReadFilter()
{
$payload = ['data' => [], 'pagination' => ['total' => 0]];
$this->controller->setPaginatedResult($payload);
$request = new FakeNotificationRequest(['read' => 'false']);
$this->controller->setRequest($request);
$this->controller->index();
$readWhere = array_filter(
$this->model->whereHistory,
static fn ($entry) => $entry['column'] === 'user_notifications.is_read'
);
$this->assertNotEmpty($readWhere);
$this->assertSame(0, $readWhere[array_key_last($readWhere)]['value']);
}
public function testShowReturnsNotification()
{
$this->model->setFirstResult(['id' => 99, 'notification_id' => 99]);
$response = $this->controller->show(99);
$this->assertTrue($response['status']);
$this->assertSame('Notification retrieved successfully', $response['message']);
}
public function testShowReturns404WhenMissing()
{
$this->model->setFirstResult(null);
$response = $this->controller->show(9);
$this->assertFalse($response['status']);
$this->assertSame(404, $response['code']);
}
public function testMarkReadUpdatesNotification()
{
$this->model->setFirstResult(['id' => 50, 'notification_id' => 500]);
$response = $this->controller->markRead(500);
$this->assertTrue($response['status']);
$this->assertSame('Notification marked as read', $response['message']);
$this->assertSame(50, $this->model->lastUpdate['id']);
$this->assertSame(1, $this->model->lastUpdate['data']['is_read']);
$this->assertNotEmpty($this->model->lastUpdate['data']['read_at']);
}
public function testMarkReadReturns404WhenNotFound()
{
$this->model->setFirstResult(null);
$response = $this->controller->markRead(77);
$this->assertFalse($response['status']);
$this->assertSame(404, $response['code']);
}
}