_mockUser = $mockUser; } 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 minimal fluent stub model that returns $returnValue on ->first(). * Unknown chained method calls return $this (fluent builder pattern). */ protected function makeFluentStub(mixed $returnValue): object { return new class($returnValue) { private mixed $rv; private array $inserts = []; public function __construct(mixed $rv) { $this->rv = $rv; } public function __call(string $name, array $args): mixed { if ($name === 'first') return $this->rv; if ($name === 'findAll') return is_array($this->rv) ? $this->rv : [$this->rv]; if ($name === 'insert') { $this->inserts[] = $args[0] ?? []; return 99; } if ($name === 'insertID') return 99; return $this; // fluent chain } public function getInserts(): array { return $this->inserts; } }; } /** * Inject a stub into a named property of the controller. */ 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); } /** Decode response body to array. */ 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->createClaim(); $this->assertSame(401, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertFalse($body['status']); $this->assertSame(401, $body['code']); } public function testReturns400WhenRequiredFieldsMissing(): void { $_POST = []; // empty body — all required fields missing $ctrl = $this->makeController(['id' => 1, 'name' => 'Test', 'email' => 't@t.com', 'mobile' => '9999']); $resp = $ctrl->createClaim(); $this->assertSame(400, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertFalse($body['status']); $this->assertSame(400, $body['code']); $this->assertArrayHasKey('errors', $body); $this->assertArrayHasKey('nature_of_loss', $body['errors']); } public function testReturns404WhenClientPolicyNotFound(): void { $_POST = [ 'client_policy_id' => 8101, 'nature_of_loss' => 'Fire damage', 'loss_location' => 'Chennai', 'loss_date' => '22-03-2026', ]; $ctrl = $this->makeController(['id' => 1, 'name' => 'User', 'email' => 'u@t.com', 'mobile' => '999']); // clientPolicyModel returns null — policy not found $this->inject($ctrl, 'clientPolicyModel', $this->makeFluentStub(null)); $resp = $ctrl->createClaim(); $this->assertSame(404, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertFalse($body['status']); $this->assertSame(404, $body['code']); $this->assertStringContainsString('policy', strtolower($body['message'])); } public function testReturns422WhenPolicyTypeIsEB(): void { $_POST = [ 'client_policy_id' => 10, 'nature_of_loss' => 'Theft', 'loss_location' => 'Mumbai', 'loss_date' => '01-03-2026', ]; $ctrl = $this->makeController(['id' => 1, 'name' => 'User', 'email' => 'u@t.com', 'mobile' => '999']); $this->inject($ctrl, 'clientPolicyModel', $this->makeFluentStub([ 'id' => 10, 'client_id' => 5, 'client_branch_id' => 2, 'policy_type_id' => 3, 'insurer_id' => 7, 'policy_no' => 'POL/2026/001', ])); // policyTypeModel returns EB — should be rejected $this->inject($ctrl, 'policyTypeModel', $this->makeFluentStub(['allocg' => 'EB'])); $resp = $ctrl->createClaim(); $this->assertSame(422, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertFalse($body['status']); $this->assertSame(422, $body['code']); } public function testReturns422WhenNoClaimStatusConfigured(): void { $_POST = [ 'client_policy_id' => 10, 'nature_of_loss' => 'Flood', 'loss_location' => 'Kochi', 'loss_date' => '05-03-2026', ]; $ctrl = $this->makeController(['id' => 1, 'name' => 'User', 'email' => 'u@t.com', 'mobile' => '999']); $this->inject($ctrl, 'clientPolicyModel', $this->makeFluentStub([ 'id' => 10, 'client_id' => 5, 'client_branch_id' => 2, 'policy_type_id' => 10, 'insurer_id' => 7, 'policy_no' => 'POL/2026/002', ])); $this->inject($ctrl, 'policyTypeModel', $this->makeFluentStub(['allocg' => 'Non-EB'])); $this->inject($ctrl, 'clientRMModel', $this->makeFluentStub(['user_id' => 4])); // claimStatusModel returns null — no status configured $this->inject($ctrl, 'claimStatusModel', $this->makeFluentStub(null)); $resp = $ctrl->createClaim(); $this->assertSame(422, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertFalse($body['status']); $this->assertStringContainsString('status', strtolower($body['message'])); } public function testReturns409OnDuplicateClaim(): void { $_POST = [ 'client_policy_id' => 8101, 'nature_of_loss' => 'Fire accident one edited two', 'loss_location' => 'bjdbkkjb', 'loss_date' => '01-03-2026', ]; $ctrl = $this->makeController(['id' => 1, 'name' => 'User', 'email' => 'u@t.com', 'mobile' => '999']); $this->inject($ctrl, 'clientPolicyModel', $this->makeFluentStub([ 'id' => 10, 'client_id' => 12, 'client_branch_id' => 2, 'policy_type_id' => 10, 'insurer_id' => 7, 'policy_no' => 'POL/2026/DUPJHBVJH', ])); $this->inject($ctrl, 'policyTypeModel', $this->makeFluentStub(['allocg' => 'Non-EB'])); $this->inject($ctrl, 'clientRMModel', $this->makeFluentStub(['user_id' => 4])); $this->inject($ctrl, 'claimStatusModel', $this->makeFluentStub(['id' => 1])); // nonEbTicketModel->first() returns existing row => duplicate detected $this->inject($ctrl, 'nonEbTicketModel', $this->makeFluentStub(['id' => 550])); $resp = $ctrl->createClaim(); $this->assertSame(409, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertFalse($body['status']); $this->assertSame(409, $body['code']); $this->assertStringContainsString('Duplicate', $body['message']); } public function testReturns200AndClaimIdOnSuccess(): void { $_POST = [ 'client_policy_id' => 10, 'nature_of_loss' => 'Storm damage', 'loss_location' => 'Hyderabad', 'loss_date' => '15-03-2026', ]; $ctrl = $this->makeController(['id' => 1, 'name' => 'Test User', 'email' => 'u@t.com', 'mobile' => '9876543210']); $this->inject($ctrl, 'clientPolicyModel', $this->makeFluentStub([ 'id' => 10, 'client_id' => 5, 'client_branch_id' => 2, 'policy_type_id' => 10, 'insurer_id' => 7, 'policy_no' => 'POL/2026/STR', ])); $this->inject($ctrl, 'policyTypeModel', $this->makeFluentStub(['allocg' => 'Marine'])); $this->inject($ctrl, 'clientRMModel', $this->makeFluentStub(['user_id' => 4])); $this->inject($ctrl, 'claimStatusModel', $this->makeFluentStub(['id' => 1])); // nonEbTicketModel: first() returns null (no duplicate), insert() returns 99 $ticketStub = new class { private int $callCount = 0; public function __call(string $name, array $args): mixed { if ($name === 'first') return null; // no duplicate if ($name === 'insert') return 99; if ($name === 'insertID') return 99; return $this; } }; $this->inject($ctrl, 'nonEbTicketModel', $ticketStub); // Provide pass-through stubs for asset and history models $noopStub = new class { public function __call(string $n, array $a): mixed { return $this; } }; $this->inject($ctrl, 'assetModel', $noopStub); $this->inject($ctrl, 'ticketHistoryModel', $noopStub); $resp = $ctrl->createClaim(); $this->assertSame(200, $resp->getStatusCode()); $body = $this->body($resp); print_r($body); $this->assertTrue($body['status']); $this->assertSame(200, $body['code']); $this->assertSame(99, $body['claim_id']); $this->assertStringContainsString('created', strtolower($body['message'])); } }