Update order test patch flow to use Tests.added instead of Tests.created across controller, model, bundled OpenAPI, and feature test coverage. Reject legacy created payloads, align validation/error text, and adjust test payloads and assertions for new added lifecycle.
225 lines
7.6 KiB
PHP
Executable File
225 lines
7.6 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 testPatchTestsLifecycleAddedEditedDeleted(): 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'];
|
|
|
|
$addResponse = $this->withHeaders($this->authHeaders())
|
|
->withBodyFormat('json')
|
|
->call('patch', "{$this->endpoint}/{$orderID}", [
|
|
'Tests' => [
|
|
'added' => [
|
|
[
|
|
'TestSiteID' => (string) $extraSiteID,
|
|
'Result' => 'ADDED',
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$addResponse->assertStatus(200);
|
|
$addJson = json_decode($addResponse->getJSON(), true);
|
|
$this->assertSame('success', $addJson['status'] ?? null);
|
|
|
|
$addedRow = $this->findRowBySite($addJson['data']['Tests'] ?? [], $extraSiteID);
|
|
$this->assertNotNull($addedRow, 'Added test not returned by patch response.');
|
|
$this->assertSame('ADDED', $addedRow['Result'] ?? null);
|
|
$addedResultID = (int) ($addedRow['ResultID'] ?? 0);
|
|
$this->assertGreaterThan(0, $addedResultID, 'Added test missing ResultID.');
|
|
|
|
$addedDbRow = $this->findResultByOrderAndSite($internalOID, $extraSiteID);
|
|
$this->assertNotNull($addedDbRow, 'Added test not found in DB.');
|
|
$this->assertSame('ADDED', $addedDbRow['Result'] ?? null);
|
|
|
|
$editResponse = $this->withHeaders($this->authHeaders())
|
|
->withBodyFormat('json')
|
|
->call('patch', "{$this->endpoint}/{$orderID}", [
|
|
'Tests' => [
|
|
'edited' => [
|
|
[
|
|
'TestSiteID' => (string) $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' => [
|
|
[
|
|
'TestSiteID' => (string) $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($addedResultID);
|
|
$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);
|
|
}
|
|
}
|