clqms-be/tests/feature/v2/master/TestDef/TestDefCalcTest.php
mahdahar cd65e91db1 refactor: Rename controllers to follow CodeIgniter 4 naming convention
- Rename all controllers from X.php to XController.php format
- Add new RefTxtModel for text-based reference ranges
- Rename group_dialog.php to grp_dialog.php and remove title_dialog.php
- Add comprehensive test suite for v2/master/TestDef module
- Update Routes.php to reflect controller renames
- Remove obsolete data files (clqms_v2.sql, lab.dbml)
2026-01-05 16:55:34 +07:00

329 lines
9.7 KiB
PHP

<?php
namespace Tests\Feature\v2\master\TestDef;
use Tests\Support\v2\MasterTestCase;
/**
* Feature tests for CALC type test definitions
*
* Tests CALC-specific functionality including formula configuration
*/
class TestDefCalcTest extends MasterTestCase
{
protected string $endpoint = 'v2/master/tests';
/**
* Test create CALC with formula
*/
public function testCreateCalcWithFormula(): void
{
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'CALC' . substr(time(), -4),
'TestSiteName' => 'Calculated Test ' . time(),
'TestType' => $this::TEST_TYPE_CALC,
'Description' => 'Calculated test with formula',
'SeqScr' => 50,
'SeqRpt' => 50,
'VisibleScr' => 1,
'VisibleRpt' => 1,
'CountStat' => 1,
'details' => [
'DisciplineID' => 1,
'DepartmentID' => 1,
'FormulaInput' => '["CHOL", "HDL", "TG"]',
'FormulaCode' => 'CHOL - HDL - (TG / 5)',
'FormulaLang' => 'SQL',
'RefType' => 1, // NMRC
'Unit1' => 'mg/dL',
'Decimal' => 0,
'Method' => 'Friedewald Formula'
]
];
$result = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$status = $result->response()->getStatusCode();
$this->assertTrue(
in_array($status, [201, 400, 500]),
"Expected 201, 400, or 500, got $status"
);
if ($status === 201) {
$body = json_decode($result->response()->getBody(), true);
$this->assertEquals('created', $body['status']);
// Verify calc details were created
$calcId = $body['data']['TestSiteId'];
$showResult = $this->get($this->endpoint . '/' . $calcId);
$showBody = json_decode($showResult->response()->getBody(), true);
if ($showBody['data'] !== null) {
$this->assertArrayHasKey('testdefcal', $showBody['data']);
}
}
}
/**
* Test CALC with different formula languages
*/
public function testCalcWithDifferentFormulaLanguages(): void
{
$languages = ['Phyton', 'CQL', 'FHIRP', 'SQL'];
foreach ($languages as $lang) {
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'C' . substr(time(), -5) . strtoupper(substr($lang, 0, 1)),
'TestSiteName' => "Calc with $lang",
'TestType' => $this::TEST_TYPE_CALC,
'details' => [
'FormulaInput' => '["TEST1"]',
'FormulaCode' => 'TEST1 * 2',
'FormulaLang' => $lang
]
];
$result = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$status = $result->response()->getStatusCode();
$this->assertTrue(
in_array($status, [201, 400, 500]),
"CALC with $lang: Expected 201, 400, or 500, got $status"
);
}
}
/**
* Test CALC with JSON formula input
*/
public function testCalcWithJsonFormulaInput(): void
{
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'CJSN' . substr(time(), -3),
'TestSiteName' => 'Calc with JSON Input',
'TestType' => $this::TEST_TYPE_CALC,
'details' => [
'FormulaInput' => '["parameter1", "parameter2", "parameter3"]',
'FormulaCode' => '(param1 + param2) / param3',
'FormulaLang' => 'FHIRP'
]
];
$result = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$status = $result->response()->getStatusCode();
$this->assertTrue(
in_array($status, [201, 400, 500]),
"Expected 201, 400, or 500, got $status"
);
}
/**
* Test CALC with complex formula
*/
public function testCalcWithComplexFormula(): void
{
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'CCMP' . substr(time(), -3),
'TestSiteName' => 'Calc with Complex Formula',
'TestType' => $this::TEST_TYPE_CALC,
'details' => [
'FormulaInput' => '["WBC", "NEUT", "LYMPH", "MONO", "EOS", "BASO"]',
'FormulaCode' => 'if WBC > 0 then (NEUT + LYMPH + MONO + EOS + BASO) / WBC * 100 else 0',
'FormulaLang' => 'Phyton'
]
];
$result = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$status = $result->response()->getStatusCode();
$this->assertTrue(
in_array($status, [201, 400, 500]),
"Expected 201, 400, or 500, got $status"
);
}
/**
* Test update CALC formula
*/
public function testUpdateCalcFormula(): void
{
// Create a CALC first
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'UPCL' . substr(time(), -4),
'TestSiteName' => 'Update Calc Test',
'TestType' => $this::TEST_TYPE_CALC,
'details' => [
'FormulaInput' => '["A", "B"]',
'FormulaCode' => 'A + B',
'FormulaLang' => 'SQL'
]
];
$createResult = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$createStatus = $createResult->response()->getStatusCode();
if ($createStatus === 201) {
$createBody = json_decode($createResult->response()->getBody(), true);
$calcId = $createBody['data']['TestSiteId'] ?? null;
if ($calcId) {
// Update formula
$updateData = [
'TestSiteName' => 'Updated Calc Test Name',
'details' => [
'FormulaInput' => '["A", "B", "C"]',
'FormulaCode' => 'A + B + C'
]
];
$updateResult = $this->put($this->endpoint . '/' . $calcId, ['body' => json_encode($updateData)]);
$updateStatus = $updateResult->response()->getStatusCode();
$this->assertTrue(
in_array($updateStatus, [200, 400, 500]),
"Expected 200, 400, or 500, got $updateStatus"
);
}
}
}
/**
* Test CALC has correct TypeCode in response
*/
public function testCalcTypeCodeInResponse(): void
{
$indexResult = $this->get($this->endpoint . '?TestType=CALC');
$indexBody = json_decode($indexResult->response()->getBody(), true);
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
$calc = $indexBody['data'][0];
// Verify TypeCode is CALC
$this->assertEquals('CALC', $calc['TypeCode'] ?? '');
}
}
/**
* Test CALC details structure
*/
public function testCalcDetailsStructure(): void
{
$indexResult = $this->get($this->endpoint . '?TestType=CALC');
$indexBody = json_decode($indexResult->response()->getBody(), true);
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
$calc = $indexBody['data'][0];
$calcId = $calc['TestSiteID'] ?? null;
if ($calcId) {
$showResult = $this->get($this->endpoint . '/' . $calcId);
$showBody = json_decode($showResult->response()->getBody(), true);
if ($showBody['data'] !== null && isset($showBody['data']['testdefcal'])) {
$calcDetails = $showBody['data']['testdefcal'];
if (is_array($calcDetails) && !empty($calcDetails)) {
$firstDetail = $calcDetails[0];
// Check required fields in calc structure
$this->assertArrayHasKey('TestCalID', $firstDetail);
$this->assertArrayHasKey('TestSiteID', $firstDetail);
$this->assertArrayHasKey('FormulaInput', $firstDetail);
$this->assertArrayHasKey('FormulaCode', $firstDetail);
// Check for joined discipline/department
if (isset($firstDetail['DisciplineName'])) {
$this->assertArrayHasKey('DepartmentName', $firstDetail);
}
}
}
}
}
}
/**
* Test CALC delete cascades to details
*/
public function testCalcDeleteCascadesToDetails(): void
{
// Create a CALC
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'CDEL' . substr(time(), -4),
'TestSiteName' => 'Calc to Delete',
'TestType' => $this::TEST_TYPE_CALC,
'details' => [
'FormulaInput' => '["TEST1"]',
'FormulaCode' => 'TEST1 * 2'
]
];
$createResult = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$createStatus = $createResult->response()->getStatusCode();
if ($createStatus === 201) {
$createBody = json_decode($createResult->response()->getBody(), true);
$calcId = $createBody['data']['TestSiteId'] ?? null;
if ($calcId) {
// Delete the CALC
$deleteResult = $this->delete($this->endpoint . '/' . $calcId);
$deleteStatus = $deleteResult->response()->getStatusCode();
$this->assertTrue(
in_array($deleteStatus, [200, 404, 500]),
"Expected 200, 404, or 500, got $deleteStatus"
);
if ($deleteStatus === 200) {
// Verify CALC details are also soft deleted
$showResult = $this->get($this->endpoint . '/' . $calcId);
$showBody = json_decode($showResult->response()->getBody(), true);
// CALC should show EndDate set
if ($showBody['data'] !== null) {
$this->assertNotNull($showBody['data']['EndDate']);
}
}
}
}
}
/**
* Test CALC with result unit configuration
*/
public function testCalcWithResultUnit(): void
{
$units = ['mg/dL', 'g/L', 'mmol/L', '%', 'IU/L'];
foreach ($units as $unit) {
$calcData = [
'SiteID' => 1,
'TestSiteCode' => 'CUNT' . substr(time(), -3) . substr($unit, 0, 1),
'TestSiteName' => "Calc with $unit",
'TestType' => $this::TEST_TYPE_CALC,
'details' => [
'Unit1' => $unit,
'Decimal' => 2,
'FormulaInput' => '["TEST1"]',
'FormulaCode' => 'TEST1'
]
];
$result = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
$status = $result->response()->getStatusCode();
$this->assertTrue(
in_array($status, [201, 400, 500]),
"CALC with unit $unit: Expected 201, 400, or 500, got $status"
);
}
}
}