251 lines
7.6 KiB
PHP
251 lines
7.6 KiB
PHP
<?php
|
|
|
|
namespace Tests\App\Controllers\Api;
|
|
|
|
use App\Controllers\Api\PreferencesController;
|
|
use CodeIgniter\HTTP\URI;
|
|
use CodeIgniter\HTTP\UserAgent;
|
|
use CodeIgniter\Test\CIUnitTestCase;
|
|
use CodeIgniter\Test\Mock\MockIncomingRequest;
|
|
use Config\App;
|
|
use Config\Services;
|
|
|
|
class StubPreferencesModel
|
|
{
|
|
private ?array $firstResult = null;
|
|
private array $findResults = [];
|
|
private int $nextInsertId = 200;
|
|
public ?array $lastUpdate = null;
|
|
public ?array $lastInsertData = null;
|
|
|
|
public function where(string $column, $value): self
|
|
{
|
|
return $this;
|
|
}
|
|
|
|
public function first(): ?array
|
|
{
|
|
return $this->firstResult;
|
|
}
|
|
|
|
public function setFirstResult(?array $result): void
|
|
{
|
|
$this->firstResult = $result;
|
|
}
|
|
|
|
public function update(int $id, array $data): bool
|
|
{
|
|
$this->lastUpdate = ['id' => $id, 'data' => $data];
|
|
$this->findResults[$id] = ['id' => $id] + $data;
|
|
return true;
|
|
}
|
|
|
|
public function insert(array $data): int
|
|
{
|
|
$id = $this->nextInsertId++;
|
|
$this->lastInsertData = $data;
|
|
$this->findResults[$id] = ['id' => $id] + $data;
|
|
return $id;
|
|
}
|
|
|
|
public function find(int $id): ?array
|
|
{
|
|
return $this->findResults[$id] ?? null;
|
|
}
|
|
|
|
public function setFindResult(int $id, array $result): void
|
|
{
|
|
$this->findResults[$id] = $result;
|
|
}
|
|
}
|
|
|
|
class FakeJsonRequest extends MockIncomingRequest
|
|
{
|
|
public function __construct(private readonly ?array $payload)
|
|
{
|
|
parent::__construct(config(App::class), new URI('https://test.alrahmaisgl.org'), null, new UserAgent());
|
|
}
|
|
|
|
public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0): ?array
|
|
{
|
|
return $this->payload;
|
|
}
|
|
}
|
|
|
|
class TestablePreferencesController extends PreferencesController
|
|
{
|
|
private ?object $currentUser = null;
|
|
|
|
public function __construct()
|
|
{
|
|
// Skip the real constructor to avoid bootstrapping models.
|
|
}
|
|
|
|
public function setPreferencesModel(StubPreferencesModel $model): void
|
|
{
|
|
$this->preferencesModel = $model;
|
|
}
|
|
|
|
public function setCurrentUser(?object $user): void
|
|
{
|
|
$this->currentUser = $user;
|
|
}
|
|
|
|
protected function getCurrentUser(): ?object
|
|
{
|
|
return $this->currentUser;
|
|
}
|
|
}
|
|
|
|
class PreferencesControllerTest extends CIUnitTestCase
|
|
{
|
|
private TestablePreferencesController $controller;
|
|
private StubPreferencesModel $preferencesModel;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
Services::resetSingle('validation');
|
|
Services::resetSingle('session');
|
|
|
|
$this->preferencesModel = new StubPreferencesModel();
|
|
|
|
$this->controller = new TestablePreferencesController();
|
|
$this->controller->setPreferencesModel($this->preferencesModel);
|
|
}
|
|
|
|
public function testIndexRequiresAuthentication()
|
|
{
|
|
$this->controller->setCurrentUser(null);
|
|
|
|
$response = $this->controller->index();
|
|
|
|
$this->assertFalse($response['status']);
|
|
$this->assertSame(401, $response['code']);
|
|
$this->assertSame('Authentication required', $response['message']);
|
|
}
|
|
|
|
public function testIndexReturnsDefaultsIfNoPreferences()
|
|
{
|
|
$this->controller->setCurrentUser((object) ['id' => 7]);
|
|
$this->preferencesModel->setFirstResult(null);
|
|
|
|
$response = $this->controller->index();
|
|
|
|
$this->assertTrue($response['status']);
|
|
$this->assertSame('Preferences retrieved successfully', $response['message']);
|
|
$this->assertSame(1, $response['data']['notification_email']);
|
|
$this->assertSame('light', $response['data']['theme']);
|
|
$this->assertSame('blue', $response['data']['style_color']);
|
|
$this->assertSame('white', $response['data']['menu_color']);
|
|
}
|
|
|
|
public function testIndexPropagatesStoredPreferencesAndSessionStyles()
|
|
{
|
|
$this->controller->setCurrentUser((object) ['id' => 9]);
|
|
$this->preferencesModel->setFirstResult([
|
|
'id' => 11,
|
|
'user_id' => 9,
|
|
'notification_email' => 0,
|
|
'notification_sms' => 0,
|
|
'theme' => 'dark',
|
|
'language' => 'fr',
|
|
]);
|
|
|
|
session()->set('style_color', 'rose');
|
|
session()->set('menu_color', 'navy');
|
|
|
|
$response = $this->controller->index();
|
|
|
|
$this->assertTrue($response['status']);
|
|
$this->assertSame(0, $response['data']['notification_email']);
|
|
$this->assertSame('rose', $response['data']['style_color']);
|
|
$this->assertSame('navy', $response['data']['menu_color']);
|
|
}
|
|
|
|
public function testUpdateReturnsValidationErrors()
|
|
{
|
|
$this->controller->setCurrentUser((object) ['id' => 3]);
|
|
$this->setRequestPayload(['notification_email' => '2']);
|
|
|
|
$response = $this->controller->update();
|
|
|
|
$this->assertFalse($response['status']);
|
|
$this->assertSame(422, $response['code']);
|
|
$this->assertSame('Validation failed', $response['message']);
|
|
$this->assertArrayHasKey('errors', $response);
|
|
}
|
|
|
|
public function testUpdateInsertsWhenPreferencesAbsent()
|
|
{
|
|
$this->controller->setCurrentUser((object) ['id' => 12]);
|
|
$this->preferencesModel->setFirstResult(null);
|
|
|
|
$payload = [
|
|
'notification_email' => 0,
|
|
'notification_sms' => 1,
|
|
'theme' => 'dark',
|
|
'language' => 'es',
|
|
'style_color' => 'green',
|
|
'menu_color' => 'brand',
|
|
];
|
|
|
|
$this->setRequestPayload($payload);
|
|
|
|
$response = $this->controller->update();
|
|
|
|
$this->assertTrue($response['status']);
|
|
$this->assertSame('Preferences updated successfully', $response['message']);
|
|
$this->assertSame(0, $response['data']['notification_email']);
|
|
$this->assertSame('green', session()->get('style_color'));
|
|
$this->assertSame('brand', session()->get('menu_color'));
|
|
$this->assertSame($this->preferencesModel->lastInsertData, [
|
|
'user_id' => 12,
|
|
'notification_email' => 0,
|
|
'notification_sms' => 1,
|
|
'theme' => 'dark',
|
|
'language' => 'es',
|
|
]);
|
|
}
|
|
|
|
public function testUpdateModifiesExistingPreferences()
|
|
{
|
|
$this->controller->setCurrentUser((object) ['id' => 21]);
|
|
$this->preferencesModel->setFirstResult([
|
|
'id' => 18,
|
|
'user_id' => 21,
|
|
'notification_email' => 1,
|
|
'notification_sms' => 1,
|
|
'theme' => 'light',
|
|
'language' => 'en',
|
|
]);
|
|
$this->preferencesModel->setFindResult(18, [
|
|
'id' => 18,
|
|
'user_id' => 21,
|
|
'notification_email' => 1,
|
|
'notification_sms' => 1,
|
|
'theme' => 'light',
|
|
'language' => 'en',
|
|
]);
|
|
|
|
$payload = ['notification_email' => 1, 'notification_sms' => 0, 'language' => 'fr'];
|
|
$this->setRequestPayload($payload);
|
|
|
|
$response = $this->controller->update();
|
|
|
|
$this->assertTrue($response['status']);
|
|
$this->assertSame('Preferences updated successfully', $response['message']);
|
|
$this->assertSame(1, $this->preferencesModel->lastUpdate['data']['notification_email']);
|
|
$this->assertSame(0, $this->preferencesModel->lastUpdate['data']['notification_sms']);
|
|
$this->assertSame(18, $this->preferencesModel->lastUpdate['id']);
|
|
$this->assertSame('fr', $response['data']['language']);
|
|
}
|
|
|
|
private function setRequestPayload(?array $payload): void
|
|
{
|
|
$request = new FakeJsonRequest($payload);
|
|
$this->controller->setRequest($request);
|
|
}
|
|
}
|