recreate project
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Tests\App\Controllers\Api;
|
||||
|
||||
use App\Controllers\Api\AdministratorController;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\Services;
|
||||
|
||||
class AdministratorControllerTest extends CIUnitTestCase
|
||||
{
|
||||
protected $controller;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// ✅ Create a fake database connection object
|
||||
$fakeDb = $this->createMock(\CodeIgniter\Database\BaseConnection::class);
|
||||
|
||||
// ✅ Stub Config\Database::connect() globally using class_alias
|
||||
// so CodeIgniter's static Database::connect() returns our fake DB
|
||||
if (!class_exists('Config\\FakeDatabase')) {
|
||||
eval('namespace Config; class FakeDatabase extends \\Config\\Database {
|
||||
public static function connect($group = null, bool $getShared = true) {
|
||||
return $GLOBALS["__fakeDb__"];
|
||||
}
|
||||
}');
|
||||
}
|
||||
$GLOBALS['__fakeDb__'] = $fakeDb;
|
||||
|
||||
// Temporarily alias Config\Database to our FakeDatabase
|
||||
class_alias('Config\\FakeDatabase', 'Config\\Database');
|
||||
|
||||
// ✅ Mock all required models/services
|
||||
foreach ([
|
||||
\App\Models\UserModel::class,
|
||||
\App\Models\StudentModel::class,
|
||||
\App\Models\ConfigurationModel::class,
|
||||
\App\Models\LoginActivityModel::class,
|
||||
\App\Models\EnrollmentModel::class,
|
||||
\App\Models\RefundModel::class,
|
||||
\App\Models\InvoiceModel::class,
|
||||
\App\Models\ClassSectionModel::class,
|
||||
\App\Models\UserRoleModel::class,
|
||||
\App\Models\StudentClassModel::class,
|
||||
\App\Models\StaffAttendanceModel::class,
|
||||
\App\Services\FeeCalculationService::class,
|
||||
] as $class) {
|
||||
$this->mockModel($class);
|
||||
}
|
||||
|
||||
// ✅ Configuration mock
|
||||
$configMock = $this->mockModel(\App\Models\ConfigurationModel::class);
|
||||
$configMock->method('getConfig')->willReturnMap([
|
||||
['school_year', '2024-2025'],
|
||||
['semester', 'Fall'],
|
||||
]);
|
||||
|
||||
// ✅ Instantiate controller safely (no DB hit)
|
||||
$this->controller = new AdministratorController();
|
||||
}
|
||||
|
||||
protected function mockModel(string $class)
|
||||
{
|
||||
$mock = $this->createMock($class);
|
||||
Services::injectMock($class, $mock);
|
||||
return $mock;
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function testDashboardSuccess()
|
||||
{
|
||||
$result = $this->controller->dashboard();
|
||||
$this->assertNotNull($result);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* absenceInfo()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testAbsenceInfoWithValidUser()
|
||||
{
|
||||
helper('date');
|
||||
$this->controller->setSession(['user_id' => 7]);
|
||||
|
||||
$userMock = model(UserModel::class);
|
||||
$staffMock = model(StaffAttendanceModel::class);
|
||||
|
||||
$userMock->method('find')->willReturn(['firstname' => 'Jane', 'lastname' => 'Admin']);
|
||||
$staffMock->method('where')->willReturnSelf();
|
||||
$staffMock->method('orderBy')->willReturnSelf();
|
||||
$staffMock->method('findAll')->willReturn([
|
||||
['date' => '2025-09-14', 'status' => 'present'],
|
||||
]);
|
||||
|
||||
$response = $this->controller->absenceInfo();
|
||||
$this->assertTrue($response['status']);
|
||||
$this->assertArrayHasKey('available_dates', $response['data']);
|
||||
}
|
||||
|
||||
public function testAbsenceInfoUnauthorized()
|
||||
{
|
||||
$this->controller->setSession([]); // no user
|
||||
$response = $this->controller->absenceInfo();
|
||||
$this->assertFalse($response['status']);
|
||||
$this->assertEquals(401, $response['code']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* submitAbsence()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testSubmitAbsenceRejectsMissingReason()
|
||||
{
|
||||
$this->controller->setSession(['user_id' => 2]);
|
||||
$req = $this->makeRequest('POST', '/api/v1/administrator/absence', [
|
||||
'dates' => ['2025-10-05'],
|
||||
'reason' => '',
|
||||
]);
|
||||
$this->controller->setRequest($req);
|
||||
$resp = $this->controller->submitAbsence();
|
||||
$this->assertFalse($resp['status']);
|
||||
$this->assertEquals('Reason is required', $resp['message']);
|
||||
}
|
||||
|
||||
public function testSubmitAbsenceValidDateAndReason()
|
||||
{
|
||||
$this->controller->setSession(['user_id' => 5]);
|
||||
|
||||
$req = $this->makeRequest('POST', '/api/v1/administrator/absence', [
|
||||
'dates' => ['2025-09-07'],
|
||||
'reason_type' => 'Personal',
|
||||
'reason' => 'Travel',
|
||||
]);
|
||||
$this->controller->setRequest($req);
|
||||
|
||||
$staffMock = model(StaffAttendanceModel::class);
|
||||
$userMock = model(UserModel::class);
|
||||
|
||||
$userMock->method('getUserRole')->willReturn('admin');
|
||||
$staffMock->method('upsertOne')->willReturn(true);
|
||||
$userMock->method('find')->willReturn(['firstname' => 'Sarah', 'lastname' => 'Ali', 'email' => 's@a.com']);
|
||||
|
||||
$email = Services::email();
|
||||
$email->clear();
|
||||
|
||||
$resp = $this->controller->submitAbsence();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertArrayHasKey('saved_dates', $resp['data']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* search()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testSearchRequiresQueryParam()
|
||||
{
|
||||
$this->controller->setRequest($this->makeRequest('GET', '/api/v1/administrator/search?q='));
|
||||
$resp = $this->controller->search();
|
||||
$this->assertFalse($resp['status']);
|
||||
$this->assertEquals('Search query is required', $resp['message']);
|
||||
}
|
||||
|
||||
public function testSearchReturnsStructuredResults()
|
||||
{
|
||||
$this->controller->setRequest($this->makeRequest('GET', '/api/v1/administrator/search?q=john'));
|
||||
|
||||
$db = $this->createMock(\CodeIgniter\Database\BaseConnection::class);
|
||||
$builder = $this->createMock(\CodeIgniter\Database\BaseBuilder::class);
|
||||
$builder->method('select')->willReturnSelf();
|
||||
$builder->method('limit')->willReturnSelf();
|
||||
$builder->method('get')->willReturnSelf();
|
||||
$builder->method('getResultArray')->willReturn([
|
||||
['id' => 1, 'firstname' => 'John', 'lastname' => 'Doe'],
|
||||
]);
|
||||
$db->method('table')->willReturn($builder);
|
||||
service('database')->shouldReceive('connect')->andReturn($db);
|
||||
|
||||
$resp = $this->controller->search();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertArrayHasKey('users', $resp['data']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* enrollmentWithdrawal()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testEnrollmentWithdrawalPagination()
|
||||
{
|
||||
$mock = model(EnrollmentModel::class);
|
||||
$mock->method('where')->willReturnSelf();
|
||||
$mock->method('orderBy')->willReturnSelf();
|
||||
$mock->method('findAll')->willReturn([
|
||||
['student_id' => 1, 'status' => 'enrolled'],
|
||||
]);
|
||||
|
||||
$resp = $this->controller->enrollmentWithdrawal();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertEquals('Enrollment/withdrawal data retrieved successfully', $resp['message']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* enrollmentWithdrawalData()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testEnrollmentWithdrawalDataBuildsStudentList()
|
||||
{
|
||||
$stuMock = model(StudentModel::class);
|
||||
$stuMock->method('getStudentsWithClassAndEnrollment')->willReturn([
|
||||
['id' => 1, 'firstname' => 'A', 'lastname' => 'Z', 'parent_id' => 10],
|
||||
]);
|
||||
|
||||
$clsMock = model(ClassSectionModel::class);
|
||||
$clsMock->method('select')->willReturnSelf();
|
||||
$clsMock->method('where')->willReturnSelf();
|
||||
$clsMock->method('orderBy')->willReturnSelf();
|
||||
$clsMock->method('findAll')->willReturn([
|
||||
['id' => 1, 'class_section_name' => 'KG1'],
|
||||
]);
|
||||
|
||||
$enrollMock = model(EnrollmentModel::class);
|
||||
$enrollMock->method('getEnrollmentStatus')->willReturn('enrolled');
|
||||
|
||||
$resp = $this->controller->enrollmentWithdrawalData();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertArrayHasKey('students', $resp['data']);
|
||||
$this->assertArrayHasKey('classes', $resp['data']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* updateEnrollmentStatuses()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testUpdateEnrollmentStatusesRejectsEmptyPayload()
|
||||
{
|
||||
$req = $this->makeRequest('POST', '/api/v1/administrator/enrollment-withdrawal/update', []);
|
||||
$this->controller->setRequest($req);
|
||||
$resp = $this->controller->updateEnrollmentStatuses();
|
||||
$this->assertFalse($resp['status']);
|
||||
$this->assertEquals('No enrollment statuses were submitted.', $resp['message']);
|
||||
}
|
||||
|
||||
public function testUpdateEnrollmentStatusesWithValidStatus()
|
||||
{
|
||||
$req = $this->makeRequest('POST', '/api/v1/administrator/enrollment-withdrawal/update', [
|
||||
'enrollment_status' => [1 => 'enrolled']
|
||||
]);
|
||||
$this->controller->setRequest($req);
|
||||
|
||||
$stuMock = model(StudentModel::class);
|
||||
$stuMock->method('find')->willReturn(['id' => 1, 'parent_id' => 2]);
|
||||
|
||||
$enrollMock = model(EnrollmentModel::class);
|
||||
$enrollMock->method('where')->willReturnSelf();
|
||||
$enrollMock->method('get')->willReturnSelf();
|
||||
$enrollMock->method('getRowArray')->willReturn(['enrollment_status' => 'payment pending', 'parent_id' => 2]);
|
||||
|
||||
$invoiceMock = model(InvoiceModel::class);
|
||||
$invoiceMock->method('where')->willReturnSelf();
|
||||
$invoiceMock->method('orderBy')->willReturnSelf();
|
||||
$invoiceMock->method('first')->willReturn(['id' => 10, 'school_year' => '2024-2025']);
|
||||
|
||||
$refundMock = model(RefundModel::class);
|
||||
$refundMock->method('where')->willReturnSelf();
|
||||
$refundMock->method('first')->willReturn(null);
|
||||
|
||||
$resp = $this->controller->updateEnrollmentStatuses();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertArrayHasKey('groupsByParentStatus', $resp['data']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* studentProfiles()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testStudentProfilesReturnsList()
|
||||
{
|
||||
$studClassMock = model(StudentClassModel::class);
|
||||
$studClassMock->method('getClassSectionNameByStudentId')->willReturn('KG2');
|
||||
|
||||
$resp = $this->controller->studentProfiles();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertArrayHasKey('students', $resp['data']);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* parentProfiles()
|
||||
* -------------------------------------------------------------------------- */
|
||||
public function testParentProfilesWithParentRole()
|
||||
{
|
||||
$userMock = model(UserModel::class);
|
||||
$userMock->method('findAll')->willReturn([
|
||||
['id' => 20, 'firstname' => 'Layla', 'lastname' => 'Yusuf', 'email' => 'layla@test.com', 'cellphone' => '123', 'school_id' => 'P1'],
|
||||
]);
|
||||
|
||||
$roleMock = model(UserRoleModel::class);
|
||||
$roleMock->method('getRolesByUserId')->willReturn([
|
||||
['role_name' => 'parent'],
|
||||
]);
|
||||
|
||||
$invMock = model(InvoiceModel::class);
|
||||
$invMock->method('getLatestInvoicePaidAmount')->willReturn(150.00);
|
||||
$invMock->method('getLatestInvoiceBalance')->willReturn(50.00);
|
||||
|
||||
$resp = $this->controller->parentProfiles();
|
||||
$this->assertTrue($resp['status']);
|
||||
$this->assertArrayHasKey('parents', $resp['data']);
|
||||
$this->assertEquals('Layla', $resp['data']['parents'][0]['firstname']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user