clqms-be/tests/feature/TestDef/TestDefSiteTest.php
mahdahar 97edfe50a8 feat: enhance Test Management module with improved UI and tests
- Refactor Tests.php controller with updated logic and error handling
- Update Test migration with schema improvements
- Enhance TestDefCalModel, TestDefGrpModel, TestDefTechModel with CRUD operations
- Improve TestMapModel with better test mapping relationships
- Redesign test dialog views (calc, group, param) with improved UX
- Update tests_index view with better data presentation
- Add CSS styles for test management UI components
- Add TestDefSiteTest feature test for site-based test definitions
- Add TestDefModelsTest unit test for model validation
- Remove obsolete Test Management.docx documentation
2026-01-02 08:33:22 +07:00

260 lines
8.7 KiB
PHP

<?php
namespace Tests\Feature\TestDef;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
class TestDefSiteTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected $endpoint = 'api/tests';
protected $token;
protected function setUp(): void
{
parent::setUp();
// Generate Token
$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 = \Firebase\JWT\JWT::encode($payload, $key, 'HS256');
}
public function get(string $path, array $options = []) {
$this->withHeaders(['Cookie' => 'token=' . $this->token]);
return $this->call('get', $path, $options);
}
public function post(string $path, array $options = []) {
$this->withHeaders(['Cookie' => 'token=' . $this->token]);
return $this->call('post', $path, $options);
}
public function put(string $path, array $options = []) {
$this->withHeaders(['Cookie' => 'token=' . $this->token]);
return $this->call('put', $path, $options);
}
public function delete(string $path, array $options = []) {
$this->withHeaders(['Cookie' => 'token=' . $this->token]);
return $this->call('delete', $path, $options);
}
/**
* Test index endpoint returns list of tests
*/
public function testIndexReturnsTestList()
{
$result = $this->get($this->endpoint);
$result->assertStatus(200);
$body = json_decode($result->response()->getBody(), true);
$this->assertArrayHasKey('status', $body);
$this->assertArrayHasKey('data', $body);
$this->assertArrayHasKey('message', $body);
}
/**
* Test index with SiteID filter
*/
public function testIndexWithSiteFilter()
{
$result = $this->get($this->endpoint . '?SiteID=1');
$result->assertStatus(200);
$body = json_decode($result->response()->getBody(), true);
$this->assertEquals('success', $body['status']);
}
/**
* Test index with TestType filter
*/
public function testIndexWithTypeFilter()
{
$result = $this->get($this->endpoint . '?TestType=TEST');
$result->assertStatus(200);
$body = json_decode($result->response()->getBody(), true);
$this->assertEquals('success', $body['status']);
}
/**
* Test show endpoint returns single test
*/
public function testShowReturnsSingleTest()
{
// First get the list to find a valid ID
$indexResult = $this->get($this->endpoint);
$indexBody = json_decode($indexResult->response()->getBody(), true);
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
$firstItem = $indexBody['data'][0];
$testSiteID = $firstItem['TestSiteID'] ?? 1;
$showResult = $this->get($this->endpoint . '/' . $testSiteID);
$showResult->assertStatus(200);
$body = json_decode($showResult->response()->getBody(), true);
$this->assertArrayHasKey('data', $body);
$this->assertEquals('success', $body['status']);
// Check that related details are loaded based on TestType
if ($body['data'] !== null) {
$typeCode = $body['data']['TypeCode'] ?? '';
if ($typeCode === 'CALC') {
$this->assertArrayHasKey('testdefcal', $body['data']);
} elseif ($typeCode === 'GROUP') {
$this->assertArrayHasKey('testdefgrp', $body['data']);
} elseif (in_array($typeCode, ['TEST', 'PARAM'])) {
$this->assertArrayHasKey('testdeftech', $body['data']);
}
// All types should have testmap
$this->assertArrayHasKey('testmap', $body['data']);
}
}
}
/**
* Test show with non-existent ID returns null data
*/
public function testShowWithInvalidIDReturnsNull()
{
$result = $this->get($this->endpoint . '/9999999');
$result->assertStatus(200);
$body = json_decode($result->response()->getBody(), true);
$this->assertArrayHasKey('data', $body);
$this->assertNull($body['data']);
}
/**
* Test create new test definition
*/
public function testCreateTest()
{
$testData = [
'SiteID' => 1,
'TestSiteCode' => 'HB',
'TestSiteName' => 'Hemoglobin',
'TestType' => 'TEST',
'Description' => 'Hemoglobin concentration test',
'SeqScr' => 3,
'SeqRpt' => 3,
'IndentLeft' => 0,
'FontStyle' => 'Bold',
'VisibleScr' => 1,
'VisibleRpt' => 1,
'CountStat' => 1,
'StartDate' => date('Y-m-d H:i:s')
];
$result = $this->post($this->endpoint, ['body' => json_encode($testData)]);
// If validation fails due to duplicate code, that's expected
$status = $result->response()->getStatusCode();
$this->assertTrue(in_array($status, [201, 400]), "Expected 201 or 400, got $status");
if ($status === 201) {
$body = json_decode($result->response()->getBody(), true);
$this->assertEquals('created', $body['status']);
$this->assertArrayHasKey('TestSiteId', $body['data']);
}
}
/**
* Test update existing test
*/
public function testUpdateTest()
{
// Get a valid test ID first
$indexResult = $this->get($this->endpoint);
$indexBody = json_decode($indexResult->response()->getBody(), true);
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
$firstItem = $indexBody['data'][0];
$testSiteID = $firstItem['TestSiteID'] ?? null;
if ($testSiteID) {
$updateData = [
'TestSiteName' => 'Updated Test Name',
'Description' => 'Updated description'
];
$result = $this->put($this->endpoint . '/' . $testSiteID, ['body' => json_encode($updateData)]);
$status = $result->response()->getStatusCode();
$this->assertTrue(in_array($status, [200, 404]), "Expected 200 or 404, got $status");
if ($status === 200) {
$body = json_decode($result->response()->getBody(), true);
$this->assertEquals('success', $body['status']);
}
}
}
}
/**
* Test soft delete (disable) test
*/
public function testDeleteTest()
{
// Get a valid test ID first
$indexResult = $this->get($this->endpoint);
$indexBody = json_decode($indexResult->response()->getBody(), true);
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
$firstItem = $indexBody['data'][0];
$testSiteID = $firstItem['TestSiteID'] ?? null;
if ($testSiteID) {
$result = $this->delete($this->endpoint . '/' . $testSiteID);
$status = $result->response()->getStatusCode();
$this->assertTrue(in_array($status, [200, 404]), "Expected 200 or 404, got $status");
if ($status === 200) {
$body = json_decode($result->response()->getBody(), true);
$this->assertEquals('success', $body['status']);
$this->assertArrayHasKey('EndDate', $body['data']);
}
}
}
}
/**
* Test validation - missing required fields
*/
public function testCreateValidation()
{
$invalidData = [
'TestSiteName' => 'Test without code'
];
$result = $this->post($this->endpoint, ['body' => json_encode($invalidData)]);
$result->assertStatus(400);
}
/**
* Test that TestSiteCode is max 6 characters
*/
public function testTestSiteCodeLength()
{
$invalidData = [
'SiteID' => 1,
'TestSiteCode' => 'HB123456', // 8 characters - invalid
'TestSiteName' => 'Test with too long code',
'TestType' => 'TEST'
];
$result = $this->post($this->endpoint, ['body' => json_encode($invalidData)]);
$result->assertStatus(400);
}
}