nhance/tests/unit/Api/ClaimHistoryTest.php
2026-03-31 12:04:35 +05:30

284 lines
10 KiB
PHP

<?php
namespace Tests\unit\Api;
use CodeIgniter\Test\CIUnitTestCase;
use App\Controllers\Api\NonEbClaimApiController;
/**
* Unit tests for NonEbClaimApiController::claimHistory()
*/
class ClaimHistoryTest extends CIUnitTestCase
{
// ─── Helpers ────────────────────────────────────────────────────────────
protected function makeController(?array $user = null): NonEbClaimApiController
{
$mockUser = $user;
$controller = new class($mockUser) extends NonEbClaimApiController {
private ?array $_mockUser;
public function __construct(?array $u) { $this->_mockUser = $u; }
protected function getAuthUser(): ?array { return $this->_mockUser; }
};
$request = \Config\Services::request();
$response = \Config\Services::response();
$logger = \Config\Services::logger();
$controller->initController($request, $response, $logger);
return $controller;
}
/**
* Build a fluent stub model.
* $firstReturn → returned by ->first()
* $allReturn → returned by ->findAll()
*/
protected function makeFluentStub(mixed $firstReturn, array $allReturn = []): object
{
return new class($firstReturn, $allReturn) {
private mixed $fr;
private array $ar;
public function __construct(mixed $fr, array $ar) { $this->fr = $fr; $this->ar = $ar; }
public function __call(string $name, array $args): mixed
{
if ($name === 'first') return $this->fr;
if ($name === 'findAll') return $this->ar;
return $this;
}
};
}
protected function inject(NonEbClaimApiController $ctrl, string $property, object $stub): void
{
$ref = new \ReflectionClass($ctrl);
$prop = $ref->getProperty($property);
$prop->setAccessible(true);
$prop->setValue($ctrl, $stub);
}
protected function body(\CodeIgniter\HTTP\ResponseInterface $resp): array
{
return json_decode($resp->getBody(), true);
}
// ─── Tests ──────────────────────────────────────────────────────────────
public function testReturns401WhenNoAuth(): void
{
$ctrl = $this->makeController(null);
$resp = $ctrl->claimHistory(1);
$this->assertSame(401, $resp->getStatusCode());
$body = $this->body($resp);
print_r($body);
$this->assertFalse($body['status']);
$this->assertSame(401, $body['code']);
}
public function testReturns404WhenClaimNotFound(): void
{
$ctrl = $this->makeController(['id' => 1, 'name' => 'U', 'email' => 'u@t.com', 'mobile' => '9']);
// nonEbTicketModel->first() returns null — claim not found
$this->inject($ctrl, 'nonEbTicketModel', $this->makeFluentStub(null));
$resp = $ctrl->claimHistory(999);
$this->assertSame(404, $resp->getStatusCode());
$body = $this->body($resp);
print_r($body);
$this->assertFalse($body['status']);
$this->assertSame(404, $body['code']);
$this->assertStringContainsString('not found', strtolower($body['message']));
}
public function testReturnsEmptyHistoryWhenNoHistoryRows(): void
{
$ctrl = $this->makeController(['id' => 1, 'name' => 'U', 'email' => 'u@t.com', 'mobile' => '9']);
$this->inject($ctrl, 'nonEbTicketModel', $this->makeFluentStub([
'id' => 10,
'client_id' => 5,
'policy_type_id' => 10,
]));
// ticketHistoryModel returns no rows
$this->inject($ctrl, 'ticketHistoryModel', $this->makeFluentStub(null, []));
$resp = $ctrl->claimHistory(10);
$this->assertSame(200, $resp->getStatusCode());
$body = $this->body($resp);
print_r($body);
$this->assertTrue($body['status']);
$this->assertSame(10, $body['claim_id']);
$this->assertIsArray($body['history']);
$this->assertEmpty($body['history']);
}
public function testFiltersOutStatusesWithNoDisplayName(): void
{
$ctrl = $this->makeController(['id' => 1, 'name' => 'U', 'email' => 'u@t.com', 'mobile' => '9']);
$this->inject($ctrl, 'nonEbTicketModel', $this->makeFluentStub([
'id' => 10,
'client_id' => 5,
'policy_type_id' => 10,
]));
// History rows: status IDs 1, 2, 3
$historyRows = [
['new_value' => '1', 'created_at' => '2026-03-22 10:00:00'],
['new_value' => '2', 'created_at' => '2026-03-23 11:00:00'],
['new_value' => '3', 'created_at' => '2026-03-24 12:00:00'],
];
// display_map: only status 1 and 3 have display_name; status 2 is internal
$statusRows = [
['id' => 1, 'claim_status' => 'Internal-A', 'display_name' => 'Claim Intimation'],
['id' => 3, 'claim_status' => 'Internal-C', 'display_name' => 'Under Process'],
];
// ticketHistoryModel findAll() returns history rows
$histStub = new class($historyRows) {
private array $rows;
public function __construct(array $rows) { $this->rows = $rows; }
public function __call(string $n, array $a): mixed
{
if ($n === 'findAll') return $this->rows;
if ($n === 'first') return $this->rows[0] ?? null;
return $this;
}
};
// claimStatusModel findAll() returns status rows
$statusStub = new class($statusRows) {
private array $rows;
public function __construct(array $rows) { $this->rows = $rows; }
public function __call(string $n, array $a): mixed
{
if ($n === 'findAll') return $this->rows;
if ($n === 'first') return $this->rows[0] ?? null;
return $this;
}
};
$this->inject($ctrl, 'ticketHistoryModel', $histStub);
$this->inject($ctrl, 'claimStatusModel', $statusStub);
$resp = $ctrl->claimHistory(10);
$this->assertSame(200, $resp->getStatusCode());
$body = $this->body($resp);
print_r($body);
$this->assertTrue($body['status']);
$this->assertCount(2, $body['history']);
// Status 2 (no display_name) must not appear
$statuses = array_column($body['history'], 'status');
$this->assertContains('Claim Intimation', $statuses);
$this->assertContains('Under Process', $statuses);
$this->assertNotContains('Internal-B', $statuses);
}
public function testHistoryIsReturnedOldestFirst(): void
{
$ctrl = $this->makeController(['id' => 1, 'name' => 'U', 'email' => 'u@t.com', 'mobile' => '9']);
$this->inject($ctrl, 'nonEbTicketModel', $this->makeFluentStub([
'id' => 10,
'client_id' => 5,
'policy_type_id' => 10,
]));
$historyRows = [
['new_value' => '1', 'created_at' => '2026-03-22 10:00:00'],
['new_value' => '2', 'created_at' => '2026-03-25 14:00:00'],
];
$statusRows = [
['id' => 1, 'claim_status' => 'A', 'display_name' => 'Claim Intimation'],
['id' => 2, 'claim_status' => 'B', 'display_name' => 'Under Process'],
];
$histStub = new class($historyRows) {
private array $rows;
public function __construct(array $rows) { $this->rows = $rows; }
public function __call(string $n, array $a): mixed
{
if ($n === 'findAll') return $this->rows;
return $this;
}
};
$statusStub = new class($statusRows) {
private array $rows;
public function __construct(array $rows) { $this->rows = $rows; }
public function __call(string $n, array $a): mixed
{
if ($n === 'findAll') return $this->rows;
return $this;
}
};
$this->inject($ctrl, 'ticketHistoryModel', $histStub);
$this->inject($ctrl, 'claimStatusModel', $statusStub);
$resp = $ctrl->claimHistory(10);
$body = $this->body($resp);
print_r($body);
$this->assertCount(2, $body['history']);
$this->assertSame('Claim Intimation', $body['history'][0]['status']);
$this->assertSame('Under Process', $body['history'][1]['status']);
}
public function testHistoryItemHasRequiredKeys(): void
{
$ctrl = $this->makeController(['id' => 1, 'name' => 'U', 'email' => 'u@t.com', 'mobile' => '9']);
$this->inject($ctrl, 'nonEbTicketModel', $this->makeFluentStub([
'id' => 10,
'client_id' => 5,
'policy_type_id' => 10,
]));
$historyRows = [
['new_value' => '1', 'created_at' => '2026-03-22 10:15:00'],
];
$statusRows = [
['id' => 1, 'claim_status' => 'A', 'display_name' => 'Claim Settled'],
];
$histStub = new class($historyRows) {
private array $rows;
public function __construct(array $rows) { $this->rows = $rows; }
public function __call(string $n, array $a): mixed { if ($n === 'findAll') return $this->rows; return $this; }
};
$statusStub = new class($statusRows) {
private array $rows;
public function __construct(array $rows) { $this->rows = $rows; }
public function __call(string $n, array $a): mixed { if ($n === 'findAll') return $this->rows; return $this; }
};
$this->inject($ctrl, 'ticketHistoryModel', $histStub);
$this->inject($ctrl, 'claimStatusModel', $statusStub);
$resp = $ctrl->claimHistory(10);
$body = $this->body($resp);
print_r($body);
$item = $body['history'][0];
$this->assertArrayHasKey('status', $item);
$this->assertArrayHasKey('changed_at', $item);
$this->assertArrayNotHasKey('modified_by', $item); // must not expose who changed it
}
}