- 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
260 lines
8.7 KiB
PHP
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);
|
|
}
|
|
}
|