Merge branch 'main' of https://github.com/mahdahar/clqms-be
This commit is contained in:
commit
c8e18ed283
@ -230,6 +230,13 @@ $routes->group('api', function ($routes) {
|
||||
|
||||
// Specimen
|
||||
$routes->group('specimen', function ($routes) {
|
||||
// Container aliases - 'container' and 'containerdef' both point to ContainerDefController
|
||||
$routes->group('container', function ($routes) {
|
||||
$routes->get('/', 'Specimen\ContainerDefController::index');
|
||||
$routes->get('(:num)', 'Specimen\ContainerDefController::show/$1');
|
||||
$routes->post('/', 'Specimen\ContainerDefController::create');
|
||||
$routes->patch('/', 'Specimen\ContainerDefController::update');
|
||||
});
|
||||
$routes->group('containerdef', function ($routes) {
|
||||
$routes->get('/', 'Specimen\ContainerDefController::index');
|
||||
$routes->get('(:num)', 'Specimen\ContainerDefController::show/$1');
|
||||
|
||||
55
app/Database/Seeds/AreaGeoSeeder.php
Normal file
55
app/Database/Seeds/AreaGeoSeeder.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Seeds;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
use CodeIgniter\HTTP\CURLRequest;
|
||||
|
||||
class AreaGeoSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* API configuration for fetching zones data
|
||||
*/
|
||||
protected string $apiUrl = 'https://your-api-domain.com/api/zones';
|
||||
|
||||
public function run()
|
||||
{
|
||||
// Fetch data from external API
|
||||
$options = [
|
||||
'baseURI' => $this->apiUrl,
|
||||
'timeout' => 30,
|
||||
];
|
||||
|
||||
$client = new CURLRequest($options);
|
||||
|
||||
$response = $client->get('');
|
||||
|
||||
if ($response->getStatusCode() !== 200) {
|
||||
echo "Failed to fetch data from API. Status: " . $response->getStatusCode() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$externalData = $response->getJSON(true);
|
||||
|
||||
if (empty($externalData)) {
|
||||
echo "No data found from API.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare data for insertion (exclude AreaGeoID to allow auto-increment)
|
||||
$data = [];
|
||||
foreach ($externalData as $row) {
|
||||
$data[] = [
|
||||
'AreaCode' => $row['zonecode'] ?? null,
|
||||
'Class' => $row['zoneclass'] ?? null,
|
||||
'AreaName' => str_replace('_', ' ', $row['zonename'] ?? ''),
|
||||
'Parent' => $row['parentzoneid'] ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
// Insert into local database
|
||||
$this->db->table('areageo')->insertBatch($data);
|
||||
|
||||
echo "Successfully seeded " . count($data) . " area geo records.\n";
|
||||
}
|
||||
}
|
||||
@ -4,14 +4,17 @@ namespace App\Database\Seeds;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
|
||||
class DBSeeder extends Seeder {
|
||||
public function run() {
|
||||
class DBSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$this->call('ValueSetSeeder');
|
||||
$this->call('ValueSetCountrySeeder');
|
||||
$this->call('OrganizationSeeder');
|
||||
$this->call('CounterSeeder');
|
||||
$this->call('ContactSeeder');
|
||||
$this->call('LocationSeeder');
|
||||
$this->call('AreaGeoSeeder');
|
||||
$this->call('SpecimenSeeder');
|
||||
$this->call('TestSeeder');
|
||||
$this->call('PatientSeeder');
|
||||
|
||||
@ -4,17 +4,18 @@ namespace App\Database\Seeds;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
|
||||
class DummySeeder extends Seeder {
|
||||
public function run() {
|
||||
class DummySeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
// users
|
||||
// Password: 'password' for all users (bcrypt hash)
|
||||
$passwordHash = password_hash('password', PASSWORD_BCRYPT);
|
||||
$passwordHash = password_hash('123', PASSWORD_BCRYPT);
|
||||
$data = [
|
||||
['id' => 1, 'role_id' => 1, 'username' => 'zaka', 'password' => $passwordHash],
|
||||
['id' => 2, 'role_id' => 1, 'username' => 'tes' , 'password' => $passwordHash],
|
||||
['id' => 3, 'role_id' => 1, 'username' => 'tes2', 'password' => $passwordHash],
|
||||
['id' => 1, 'role_id' => 1, 'username' => 'lisfse', 'password' => $passwordHash],
|
||||
['id' => 2, 'role_id' => 1, 'username' => 'tes', 'password' => $passwordHash]
|
||||
];
|
||||
$this->db->table('users')->insertBatch($data);
|
||||
|
||||
|
||||
@ -13,12 +13,12 @@ use CodeIgniter\Database\Seeder;
|
||||
* Run with: php spark db:seed PatientTestSeeder
|
||||
* Or for test DB: php spark db:seed PatientTestSeeder --all --n tests
|
||||
*/
|
||||
class PatientSeeder extends Seeder
|
||||
class PatientSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
public function run()
|
||||
{
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
|
||||
// ========================================
|
||||
// 1. VALUESET - Required for joins
|
||||
// ========================================
|
||||
@ -27,38 +27,38 @@ class PatientSeeder extends Seeder
|
||||
['VID' => 5, 'SiteID' => 1, 'VSetID' => 1, 'VOrder' => 1, 'VValue' => 'M', 'VDesc' => 'Male', 'CreateDate' => $now],
|
||||
['VID' => 6, 'SiteID' => 1, 'VSetID' => 1, 'VOrder' => 2, 'VValue' => 'F', 'VDesc' => 'Female', 'CreateDate' => $now],
|
||||
['VID' => 7, 'SiteID' => 1, 'VSetID' => 1, 'VOrder' => 3, 'VValue' => 'O', 'VDesc' => 'Other', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Marital Status (VSetID = 3)
|
||||
['VID' => 8, 'SiteID' => 1, 'VSetID' => 3, 'VOrder' => 1, 'VValue' => 'S', 'VDesc' => 'Single', 'CreateDate' => $now],
|
||||
['VID' => 9, 'SiteID' => 1, 'VSetID' => 3, 'VOrder' => 2, 'VValue' => 'M', 'VDesc' => 'Married', 'CreateDate' => $now],
|
||||
['VID' => 10, 'SiteID' => 1, 'VSetID' => 3, 'VOrder' => 3, 'VValue' => 'D', 'VDesc' => 'Divorced', 'CreateDate' => $now],
|
||||
['VID' => 11, 'SiteID' => 1, 'VSetID' => 3, 'VOrder' => 4, 'VValue' => 'W', 'VDesc' => 'Widowed', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Death Indicator (VSetID = 4)
|
||||
['VID' => 16, 'SiteID' => 1, 'VSetID' => 4, 'VOrder' => 1, 'VValue' => 'Y', 'VDesc' => 'Deceased', 'CreateDate' => $now],
|
||||
['VID' => 17, 'SiteID' => 1, 'VSetID' => 4, 'VOrder' => 2, 'VValue' => 'N', 'VDesc' => 'Alive', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Race (VSetID = 5)
|
||||
['VID' => 175, 'SiteID' => 1, 'VSetID' => 5, 'VOrder' => 1, 'VValue' => 'AS', 'VDesc' => 'Asian', 'CreateDate' => $now],
|
||||
['VID' => 176, 'SiteID' => 1, 'VSetID' => 5, 'VOrder' => 2, 'VValue' => 'WH', 'VDesc' => 'White', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Religion (VSetID = 6)
|
||||
['VID' => 206, 'SiteID' => 1, 'VSetID' => 6, 'VOrder' => 1, 'VValue' => 'IS', 'VDesc' => 'Islam', 'CreateDate' => $now],
|
||||
['VID' => 207, 'SiteID' => 1, 'VSetID' => 6, 'VOrder' => 2, 'VValue' => 'CH', 'VDesc' => 'Christian', 'CreateDate' => $now],
|
||||
['VID' => 208, 'SiteID' => 1, 'VSetID' => 6, 'VOrder' => 3, 'VValue' => 'CA', 'VDesc' => 'Catholic', 'CreateDate' => $now],
|
||||
['VID' => 209, 'SiteID' => 1, 'VSetID' => 6, 'VOrder' => 4, 'VValue' => 'HI', 'VDesc' => 'Hindu', 'CreateDate' => $now],
|
||||
['VID' => 210, 'SiteID' => 1, 'VSetID' => 6, 'VOrder' => 5, 'VValue' => 'BU', 'VDesc' => 'Buddha', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Ethnic (VSetID = 7)
|
||||
['VID' => 213, 'SiteID' => 1, 'VSetID' => 7, 'VOrder' => 1, 'VValue' => 'JV', 'VDesc' => 'Javanese', 'CreateDate' => $now],
|
||||
['VID' => 214, 'SiteID' => 1, 'VSetID' => 7, 'VOrder' => 2, 'VValue' => 'SD', 'VDesc' => 'Sundanese', 'CreateDate' => $now],
|
||||
['VID' => 215, 'SiteID' => 1, 'VSetID' => 7, 'VOrder' => 3, 'VValue' => 'BT', 'VDesc' => 'Batak', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Country (VSetID = 8)
|
||||
['VID' => 221, 'SiteID' => 1, 'VSetID' => 8, 'VOrder' => 1, 'VValue' => 'ID', 'VDesc' => 'Indonesia', 'CreateDate' => $now],
|
||||
['VID' => 222, 'SiteID' => 1, 'VSetID' => 8, 'VOrder' => 2, 'VValue' => 'MY', 'VDesc' => 'Malaysia', 'CreateDate' => $now],
|
||||
['VID' => 223, 'SiteID' => 1, 'VSetID' => 8, 'VOrder' => 3, 'VValue' => 'SG', 'VDesc' => 'Singapore', 'CreateDate' => $now],
|
||||
|
||||
|
||||
// Link Type (VSetID = 9)
|
||||
['VID' => 2, 'SiteID' => 1, 'VSetID' => 9, 'VOrder' => 1, 'VValue' => 'F', 'VDesc' => 'Family', 'CreateDate' => $now],
|
||||
['VID' => 3, 'SiteID' => 1, 'VSetID' => 9, 'VOrder' => 2, 'VValue' => 'S', 'VDesc' => 'Spouse', 'CreateDate' => $now],
|
||||
@ -74,30 +74,7 @@ class PatientSeeder extends Seeder
|
||||
echo "Valueset data seeded.\n";
|
||||
|
||||
// ========================================
|
||||
// 2. AREAGEO - Province & City
|
||||
// ========================================
|
||||
$areageos = [
|
||||
['AreaGeoID' => 1, 'AreaCode' => '31', 'Class' => 1, 'AreaName' => 'DKI Jakarta', 'Parent' => null],
|
||||
['AreaGeoID' => 2, 'AreaCode' => '3101', 'Class' => 2, 'AreaName' => 'Jakarta Pusat', 'Parent' => 1],
|
||||
['AreaGeoID' => 3, 'AreaCode' => '3102', 'Class' => 2, 'AreaName' => 'Jakarta Utara', 'Parent' => 1],
|
||||
['AreaGeoID' => 4, 'AreaCode' => '3103', 'Class' => 2, 'AreaName' => 'Jakarta Barat', 'Parent' => 1],
|
||||
['AreaGeoID' => 5, 'AreaCode' => '3104', 'Class' => 2, 'AreaName' => 'Jakarta Selatan', 'Parent' => 1],
|
||||
['AreaGeoID' => 6, 'AreaCode' => '3105', 'Class' => 2, 'AreaName' => 'Jakarta Timur', 'Parent' => 1],
|
||||
['AreaGeoID' => 7, 'AreaCode' => '32', 'Class' => 1, 'AreaName' => 'Jawa Barat', 'Parent' => null],
|
||||
['AreaGeoID' => 8, 'AreaCode' => '3201', 'Class' => 2, 'AreaName' => 'Bandung', 'Parent' => 7],
|
||||
['AreaGeoID' => 9, 'AreaCode' => '3202', 'Class' => 2, 'AreaName' => 'Bogor', 'Parent' => 7],
|
||||
];
|
||||
|
||||
foreach ($areageos as $area) {
|
||||
$exists = $this->db->table('areageo')->where('AreaGeoID', $area['AreaGeoID'])->get()->getRow();
|
||||
if (!$exists) {
|
||||
$this->db->table('areageo')->insert($area);
|
||||
}
|
||||
}
|
||||
echo "AreaGeo data seeded.\n";
|
||||
|
||||
// ========================================
|
||||
// 3. PATIENT - Main patient data
|
||||
// 2. PATIENT - Main patient data
|
||||
// ========================================
|
||||
$patients = [
|
||||
[
|
||||
@ -111,14 +88,14 @@ class PatientSeeder extends Seeder
|
||||
'NameLast' => 'Patient',
|
||||
'Suffix' => 'S.Kom',
|
||||
'NameAlias' => 'DummyTest',
|
||||
'Gender' => 5, // Male
|
||||
'Gender' => 5,
|
||||
'PlaceOfBirth' => 'Jakarta',
|
||||
'Birthdate' => '1990-05-15',
|
||||
'Street_1' => 'Jl. Sudirman No. 123',
|
||||
'Street_2' => 'RT 01 RW 02',
|
||||
'Street_3' => 'Kelurahan Menteng',
|
||||
'City' => '2', // Jakarta Pusat
|
||||
'Province' => '1', // DKI Jakarta
|
||||
'City' => '2',
|
||||
'Province' => '1',
|
||||
'ZIP' => '10110',
|
||||
'EmailAddress1' => 'dummy1@test.com',
|
||||
'EmailAddress2' => 'dummy1alt@test.com',
|
||||
@ -126,13 +103,13 @@ class PatientSeeder extends Seeder
|
||||
'MobilePhone' => '081234567890',
|
||||
'Custodian' => null,
|
||||
'AccountNumber' => null,
|
||||
'Country' => 221, // Indonesia
|
||||
'Race' => 175, // Asian
|
||||
'MaritalStatus' => 9, // Married
|
||||
'Religion' => 206, // Islam
|
||||
'Ethnic' => 213, // Javanese
|
||||
'Country' => 221,
|
||||
'Race' => 175,
|
||||
'MaritalStatus' => 9,
|
||||
'Religion' => 206,
|
||||
'Ethnic' => 213,
|
||||
'Citizenship' => 'WNI',
|
||||
'DeathIndicator' => 17, // Alive
|
||||
'DeathIndicator' => 17,
|
||||
'TimeOfDeath' => null,
|
||||
'LinkTo' => null,
|
||||
'CreateDate' => $now,
|
||||
|
||||
BIN
docs/prj_clinical laboratory quality management system_3a.docx
Normal file
BIN
docs/prj_clinical laboratory quality management system_3a.docx
Normal file
Binary file not shown.
@ -1,374 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\TestDef;
|
||||
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use App\Models\Test\TestDefSiteModel;
|
||||
use App\Models\Test\TestDefTechModel;
|
||||
use App\Models\Test\TestDefCalModel;
|
||||
use App\Models\Test\TestDefGrpModel;
|
||||
|
||||
/**
|
||||
* Integration tests for Test Definitions API
|
||||
*
|
||||
* Tests the CRUD operations for test definitions through the API
|
||||
*/
|
||||
class TestDefSiteTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
|
||||
protected $seed = 'App\Database\Seeds\TestSeeder';
|
||||
protected $refresh = true;
|
||||
|
||||
/**
|
||||
* Test listing all tests returns success response
|
||||
*/
|
||||
public function testIndexReturnsSuccessResponse(): void
|
||||
{
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$result->assertJSONExact([
|
||||
'status' => 'success',
|
||||
'message' => 'Data fetched successfully',
|
||||
'data' => $result->getJSON(true)['data']
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test listing all tests returns array
|
||||
*/
|
||||
public function testIndexReturnsArray(): void
|
||||
{
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertIsArray($response['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test index contains test type information
|
||||
*/
|
||||
public function testIndexContainsTypeInformation(): void
|
||||
{
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
|
||||
if (!empty($response['data'])) {
|
||||
$test = $response['data'][0];
|
||||
$this->assertArrayHasKey('TypeCode', $test);
|
||||
$this->assertArrayHasKey('TypeName', $test);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering by test type
|
||||
*/
|
||||
public function testIndexFiltersByTestType(): void
|
||||
{
|
||||
// Test filtering by TEST type (VID = 1)
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests?TestType=1');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
|
||||
foreach ($response['data'] as $test) {
|
||||
$this->assertEquals('TEST', $test['TypeCode']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering by keyword
|
||||
*/
|
||||
public function testIndexFiltersByKeyword(): void
|
||||
{
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests?TestSiteName=HB');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
|
||||
if (!empty($response['data'])) {
|
||||
foreach ($response['data'] as $test) {
|
||||
$this->assertStringContainsString('HB', $test['TestSiteName']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test showing single test returns success
|
||||
*/
|
||||
public function testShowReturnsSuccess(): void
|
||||
{
|
||||
// Get a test ID from the seeder data
|
||||
$model = new TestDefSiteModel();
|
||||
$test = $model->first();
|
||||
|
||||
if ($test) {
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get("api/tests/{$test['TestSiteID']}");
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
} else {
|
||||
$this->markTestSkipped('No test data available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test showing single test includes type-specific details for TEST type
|
||||
*/
|
||||
public function testShowIncludesTechDetailsForTestType(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$test = $model->first();
|
||||
|
||||
if ($test && $test['TypeCode'] === 'TEST') {
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get("api/tests/{$test['TestSiteID']}");
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertArrayHasKey('testdeftech', $response['data']);
|
||||
} else {
|
||||
$this->markTestSkipped('No TEST type data available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test showing single test includes type-specific details for CALC type
|
||||
*/
|
||||
public function testShowIncludesCalcDetailsForCalcType(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$test = $model->first();
|
||||
|
||||
if ($test && $test['TypeCode'] === 'CALC') {
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get("api/tests/{$test['TestSiteID']}");
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertArrayHasKey('testdefcal', $response['data']);
|
||||
} else {
|
||||
$this->markTestSkipped('No CALC type data available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test showing single test includes type-specific details for GROUP type
|
||||
*/
|
||||
public function testShowIncludesGrpDetailsForGroupType(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$test = $model->first();
|
||||
|
||||
if ($test && $test['TypeCode'] === 'GROUP') {
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get("api/tests/{$test['TestSiteID']}");
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertArrayHasKey('testdefgrp', $response['data']);
|
||||
} else {
|
||||
$this->markTestSkipped('No GROUP type data available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a new test
|
||||
*/
|
||||
public function testCreateTest(): void
|
||||
{
|
||||
$testData = [
|
||||
'SiteID' => 1,
|
||||
'TestSiteCode' => 'NEWTEST',
|
||||
'TestSiteName' => 'New Test',
|
||||
'TestType' => 1, // TEST type
|
||||
'Description' => 'Test description',
|
||||
'SeqScr' => 100,
|
||||
'SeqRpt' => 100,
|
||||
'VisibleScr' => 1,
|
||||
'VisibleRpt' => 1,
|
||||
'CountStat' => 1
|
||||
];
|
||||
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->post('api/tests', $testData);
|
||||
|
||||
$result->assertStatus(201);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertArrayHasKey('TestSiteId', $response['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating test with validation error (missing required fields)
|
||||
*/
|
||||
public function testCreateTestValidationError(): void
|
||||
{
|
||||
$testData = [
|
||||
'SiteID' => 1
|
||||
// Missing required fields
|
||||
];
|
||||
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->post('api/tests', $testData);
|
||||
|
||||
$result->assertStatus(400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updating a test
|
||||
*/
|
||||
public function testUpdateTest(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$test = $model->first();
|
||||
|
||||
if ($test) {
|
||||
$updateData = [
|
||||
'TestSiteID' => $test['TestSiteID'],
|
||||
'TestSiteName' => 'Updated Test Name',
|
||||
'Description' => 'Updated description'
|
||||
];
|
||||
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->patch('api/tests', $updateData);
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertEquals('success', $response['status']);
|
||||
} else {
|
||||
$this->markTestSkipped('No test data available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deleting a test (soft delete)
|
||||
*/
|
||||
public function testDeleteTest(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$test = $model->first();
|
||||
|
||||
if ($test) {
|
||||
$deleteData = [
|
||||
'TestSiteID' => $test['TestSiteID']
|
||||
];
|
||||
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->delete('api/tests', $deleteData);
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertEquals('success', $response['status']);
|
||||
$this->assertArrayHasKey('EndDate', $response['data']);
|
||||
} else {
|
||||
$this->markTestSkipped('No test data available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting non-existent test returns empty data
|
||||
*/
|
||||
public function testShowNonExistentTest(): void
|
||||
{
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests/999999');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
$this->assertNull($response['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test test types are correctly mapped from valueset
|
||||
*/
|
||||
public function testTestTypesAreMapped(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$tests = $model->findAll();
|
||||
|
||||
$validTypes = ['TEST', 'PARAM', 'CALC', 'GROUP', 'TITLE'];
|
||||
|
||||
foreach ($tests as $test) {
|
||||
if (isset($test['TypeCode'])) {
|
||||
$this->assertContains($test['TypeCode'], $validTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering by visible on screen
|
||||
*/
|
||||
public function testIndexFiltersByVisibleScr(): void
|
||||
{
|
||||
$result = $this->withHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
])->get('api/tests?VisibleScr=1');
|
||||
|
||||
$result->assertStatus(200);
|
||||
$response = $result->getJSON(true);
|
||||
|
||||
foreach ($response['data'] as $test) {
|
||||
$this->assertEquals(1, $test['VisibleScr']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all test types from seeder are present
|
||||
*/
|
||||
public function testAllTestTypesArePresent(): void
|
||||
{
|
||||
$model = new TestDefSiteModel();
|
||||
$tests = $model->findAll();
|
||||
|
||||
$typeCodes = array_column($tests, 'TypeCode');
|
||||
$uniqueTypes = array_unique($typeCodes);
|
||||
|
||||
// Check that we have at least TEST and PARAM types from seeder
|
||||
$this->assertContains('TEST', $uniqueTypes);
|
||||
$this->assertContains('PARAM', $uniqueTypes);
|
||||
$this->assertContains('CALC', $uniqueTypes);
|
||||
$this->assertContains('GROUP', $uniqueTypes);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user