clqms-be/tests/feature/OrderTest/OrderTestPatchTest.php
mahdahar 6b4ffe017c Support test lifecycle updates in order patch
- add Tests delta handling to order patch endpoint\n- create/edit/soft-delete patres rows in transaction\n- update OpenAPI request schema for Tests payload\n- add feature coverage for create/edit/delete lifecycle
2026-04-23 10:45:23 +07:00

223 lines
7.5 KiB
PHP
Executable File

<?php
declare(strict_types=1);
namespace Tests\Feature\OrderTest;
use App\Models\OrderTest\OrderTestModel;
use App\Models\PatResultModel;
use App\Models\Patient\PatientModel;
use App\Models\Test\TestDefSiteModel;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;
use Firebase\JWT\JWT;
class OrderTestPatchTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected string $token;
protected string $endpoint = 'api/ordertest';
protected function setUp(): void
{
parent::setUp();
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
$payload = [
'iss' => 'localhost',
'aud' => 'localhost',
'iat' => time(),
'nbf' => time(),
'exp' => time() + 3600,
'uid' => 1,
'email' => 'admin@admin.com',
];
$this->token = JWT::encode($payload, $key, 'HS256');
}
private function authHeaders(): array
{
return ['Cookie' => 'token=' . $this->token];
}
private function findResultByOrderAndSite(int $internalOID, int $testSiteID): ?array
{
$resultModel = new PatResultModel();
return $resultModel->where('OrderID', $internalOID)
->where('TestSiteID', $testSiteID)
->where('DelDate', null)
->orderBy('ResultID', 'DESC')
->first();
}
private function findRowBySite(array $rows, int $testSiteID): ?array
{
foreach ($rows as $row) {
if ((int) ($row['TestSiteID'] ?? 0) === $testSiteID) {
return $row;
}
}
return null;
}
private function createOrderWithTest(): array
{
$patientModel = new PatientModel();
$patient = $patientModel->where('DelDate', null)->first();
$this->assertNotEmpty($patient, 'No active patient found for order patch test.');
$testModel = new TestDefSiteModel();
$tests = $testModel->where('EndDate', null)
->where('TestType', 'TEST')
->findAll(2);
if (count($tests) < 2) {
$tests = $testModel->where('EndDate', null)->findAll(2);
}
$this->assertGreaterThanOrEqual(2, count($tests), 'Need at least 2 test definitions for lifecycle patch test.');
$response = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('post', $this->endpoint, [
'InternalPID' => (int) $patient['InternalPID'],
'SiteID' => (int) ($tests[0]['SiteID'] ?? 1),
'Tests' => [
[
'TestSiteID' => (int) $tests[0]['TestSiteID'],
],
],
]);
$response->assertStatus(201);
$decoded = json_decode($response->getJSON(), true);
$this->assertSame('success', $decoded['status'] ?? null);
return [
'order' => $decoded['data'],
'baseTest' => $tests[0],
'extraTest' => $tests[1],
];
}
public function testPatchTestsLifecycleCreatedEditedDeleted(): void
{
$fixture = $this->createOrderWithTest();
$order = $fixture['order'];
$baseTest = $fixture['baseTest'];
$extraTest = $fixture['extraTest'];
$orderID = $order['OrderID'];
$internalOID = (int) $order['InternalOID'];
$baseSiteID = (int) $baseTest['TestSiteID'];
$extraSiteID = (int) $extraTest['TestSiteID'];
$createResponse = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('patch', "{$this->endpoint}/{$orderID}", [
'Tests' => [
'created' => [
[
'TestSiteID' => $extraSiteID,
'Result' => 'CREATED',
],
],
],
]);
$createResponse->assertStatus(200);
$createJson = json_decode($createResponse->getJSON(), true);
$this->assertSame('success', $createJson['status'] ?? null);
$createdRow = $this->findRowBySite($createJson['data']['Tests'] ?? [], $extraSiteID);
$this->assertNotNull($createdRow, 'Created test not returned by patch response.');
$this->assertSame('CREATED', $createdRow['Result'] ?? null);
$createdResultID = (int) ($createdRow['ResultID'] ?? 0);
$this->assertGreaterThan(0, $createdResultID, 'Created test missing ResultID.');
$createdDbRow = $this->findResultByOrderAndSite($internalOID, $extraSiteID);
$this->assertNotNull($createdDbRow, 'Created test not found in DB.');
$this->assertSame('CREATED', $createdDbRow['Result'] ?? null);
$editResponse = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('patch', "{$this->endpoint}/{$orderID}", [
'Tests' => [
'edited' => [
[
'TestSiteID' => $baseSiteID,
'Result' => 'EDITED',
],
],
],
]);
$editResponse->assertStatus(200);
$editJson = json_decode($editResponse->getJSON(), true);
$this->assertSame('success', $editJson['status'] ?? null);
$editedRow = $this->findRowBySite($editJson['data']['Tests'] ?? [], $baseSiteID);
$this->assertNotNull($editedRow, 'Edited test not returned by patch response.');
$this->assertSame('EDITED', $editedRow['Result'] ?? null);
$deleteResponse = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('patch', "{$this->endpoint}/{$orderID}", [
'Tests' => [
'deleted' => [
$extraSiteID,
],
],
]);
$deleteResponse->assertStatus(200);
$deleteJson = json_decode($deleteResponse->getJSON(), true);
$this->assertSame('success', $deleteJson['status'] ?? null);
$this->assertNull($this->findRowBySite($deleteJson['data']['Tests'] ?? [], $extraSiteID), 'Deleted test still returned by patch response.');
$deletedDbRow = (new PatResultModel())->find($createdResultID);
$this->assertNotNull($deletedDbRow, 'Deleted test row missing from DB.');
$this->assertNotNull($deletedDbRow['DelDate'] ?? null, 'Deleted test row not soft deleted.');
}
public function testPatchTestsNotFound(): void
{
$response = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('patch', "{$this->endpoint}/999999999", [
'Tests' => [
'deleted' => [1],
],
]);
$response->assertStatus(404);
}
public function testPatchTestsInvalidId(): void
{
$response = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('patch', "{$this->endpoint}/invalid", [
'Tests' => [
'deleted' => [1],
],
]);
$response->assertStatus(404);
}
public function testPatchTestsEmptyPayload(): void
{
$fixture = $this->createOrderWithTest();
$orderID = $fixture['order']['OrderID'];
$response = $this->withHeaders($this->authHeaders())
->withBodyFormat('json')
->call('patch', "{$this->endpoint}/{$orderID}", []);
$response->assertStatus(400);
}
}