Files

158 lines
4.2 KiB
PHP

<?php
namespace {
if (!function_exists('site_url')) {
function site_url($uri = '')
{
return 'https://test.alrahmaisgl.org/' . ltrim((string) $uri, '/');
}
}
if (!function_exists('view')) {
function view($name, $data = [], $options = [])
{
return ['view' => $name, 'data' => $data, 'options' => $options];
}
}
}
namespace Tests\App\Controllers\View {
use App\Controllers\View\ExpenseController;
use CodeIgniter\Test\CIUnitTestCase;
use Config\Services;
class TestableExpenseController extends ExpenseController
{
public function __construct()
{
// Skip the real constructor so tests can inject fakes.
}
public function setExpenseModel(object $model): self
{
$this->expenseModel = $model;
return $this;
}
public function setConfigModel(object $model): self
{
$this->configModel = $model;
return $this;
}
}
class ExpenseIndexFakeModel
{
public array $whereCalls = [];
public function select(string $select): self
{
return $this;
}
public function join(string $table, string $condition, string $type = ''): self
{
return $this;
}
public function where(string $field, mixed $value): self
{
$this->whereCalls[] = [$field, $value];
return $this;
}
public function orderBy(string $field, string $direction = ''): self
{
return $this;
}
public function findAll(): array
{
return [
[
'id' => 10,
'category' => 'Expense',
'amount' => '12.50',
'receipt_path' => 'receipt.pdf',
'school_year' => '2025-2026',
],
];
}
}
class ExpenseIndexFakeConfig
{
public function getConfig(string $key): ?string
{
return $key === 'school_year' ? '2025-2026' : null;
}
}
class ExpenseFakeRenderer
{
private array $data = [];
private array $lastRender = [];
public function setData(?array $data = null): self
{
$this->data = $data ?? [];
return $this;
}
public function render(string $view, array $data = [], $options = null)
{
$this->lastRender = [
'view' => $view,
'data' => $data ?: $this->data,
'options' => $options,
];
return 'fake-rendered:' . $view;
}
public function getLastRender(): array
{
return $this->lastRender;
}
}
class ExpenseControllerTest extends CIUnitTestCase
{
protected function tearDown(): void
{
Services::resetSingle('renderer');
parent::tearDown();
}
public function testIndexScopesExpensesToActiveConfiguredSchoolYear(): void
{
$expenseModel = new ExpenseIndexFakeModel();
$renderer = new ExpenseFakeRenderer();
Services::injectMock('renderer', $renderer);
$controller = (new TestableExpenseController())
->setExpenseModel($expenseModel)
->setConfigModel(new ExpenseIndexFakeConfig());
$result = $controller->index();
if (is_array($result)) {
$rendered = $result;
} else {
$this->assertSame('fake-rendered:expenses/index', $result);
$rendered = $renderer->getLastRender();
}
$this->assertSame('expenses/index', $rendered['view']);
$this->assertSame('2025-2026', $rendered['data']['schoolYear']);
$this->assertSame([
['expenses.school_year', '2025-2026'],
], $expenseModel->whereCalls);
$this->assertSame(
site_url('receipts/receipt.pdf'),
$rendered['data']['expenses'][0]['receipt_url']
);
}
}
}