Update Patient Unit Testing

This commit is contained in:
mikael-zakaria 2025-10-14 15:50:22 +07:00
parent b5939e1cc9
commit f33cd6cc7b
8 changed files with 551 additions and 334 deletions

View File

@ -20,7 +20,9 @@ class Patient extends Controller {
'AlternatePID' => 'permit_empty|max_length[50]',
'NameFirst' => 'required|min_length[1]|max_length[255]',
'EmailAddress1' => 'required',
'Gender' => 'required'
'Gender' => 'required',
'Birthdate' => 'required',
"PatIdt.Identifier" => 'max_length[255]'
];
}
@ -80,7 +82,6 @@ class Patient extends Controller {
}
}
// Unit Testing Pass : \clqms-be\tests\feature\Patients\PatientDeleteTest.php
public function delete() {
try {
$input = $this->request->getJSON(true);

View File

@ -119,9 +119,9 @@ class PatientModel extends BaseUtcModel {
$input['LinkTo'] = empty($input['LinkTo']) ? null : $input['LinkTo'];
$input['Birthdate'] = $this->isValidDateTime($input['Birthdate']);
$input['DeathDateTime'] = $this->isValidDateTime($input['DeathDateTime']);
$db->transBegin();
try {
$db->transStart();
$this->insert($input);
$newInternalPID = $this->getInsertID();
@ -147,14 +147,15 @@ class PatientModel extends BaseUtcModel {
$this->checkDbError($db, 'Insert patatt');
}
$db->transComplete();
if ($db->transStatus() === false) {
throw new \Exception("Failed to sync patient relations");
}
$db->transCommit();
// $db->transComplete();
// if ($db->transStatus() === false) {
// throw new \Exception("Failed to sync patient relations");
// }
return $newInternalPID;
} catch (\Exception $e) {
// $db->transRollback();
$db->transRollback();
throw $e;
}
}
@ -168,8 +169,9 @@ class PatientModel extends BaseUtcModel {
$input['Birthdate'] = $this->isValidDateTime($input['Birthdate']);
$input['DeathDateTime'] = $this->isValidDateTime($input['DeathDateTime']);
$db->transBegin();
try {
$db->transStart();
$InternalPID = $input['InternalPID'];
$this->where('InternalPID',$InternalPID)->set($input)->update();
$this->checkDbError($db, 'Update patient');
@ -269,23 +271,20 @@ class PatientModel extends BaseUtcModel {
$this->checkDbError($db, 'Update/Delete patatt');
}
$db->transComplete();
if ($db->transStatus() === false) {
throw new \Exception('Failed to sync patient relations');
}
$db->transCommit();
// if ($db->transStatus() === false) {
// throw new \Exception('Failed to sync patient relations');
// }
return $InternalPID;
} catch (\Exception $e) {
// $db->transRollback();
$db->transRollback();
throw $e;
}
}
private function transformPatientData(array $patient): array {
$patient["Age"] = $this->calculateAgeFromBirthdate($patient["Birthdate"], $patient["DeathDateTime"]);
// $patient["Birthdate"] = $this->formatedDate($patient["Birthdate"]);
// $patient["CreateDate"] = $this->formatedDate($patient["CreateDate"]);
// $patient["DelDate"] = $this->formatedDate($patient["DelDate"]);
$patient["DeathDateTime"] = $this->formattedDate($patient["DeathDateTime"]);
$patient["CreateDate"] = $this->formattedDate($patient["CreateDate"]);
$patient["BirthdateConversion"] = $this->formatedDateForDisplay($patient["Birthdate"]);
@ -320,7 +319,7 @@ class PatientModel extends BaseUtcModel {
->getRowArray() ?: null;
}
// Conversion to (Years Months Days)
// Conversion to (Years Months Days) - For Age
private function calculateAgeFromBirthdate($birthdate, $deathdatetime) {
$dob = new \DateTime($birthdate);
@ -350,9 +349,7 @@ class PatientModel extends BaseUtcModel {
// Conversion Time to Format Y-m-d\TH:i:s\Z
private function formattedDate(?string $dateString): ?string {
try {
if (empty($dateString)) {
return null;
}
if (empty($dateString)) {return null;}
$dt = new \DateTime($dateString, new \DateTimeZone("UTC"));
return $dt->format('Y-m-d\TH:i:s\Z'); // ISO 8601 UTC
@ -361,7 +358,7 @@ class PatientModel extends BaseUtcModel {
}
}
// Conversion Time to Format j M Y
// Conversion Time to Format j M Y - For BirthdateConversion
private function formatedDateForDisplay($dateString) {
$date = \DateTime::createFromFormat('Y-m-d H:i', $dateString);

View File

@ -42,11 +42,11 @@
</exclude>
</source>
<php>
<!-- Enable / Disable -->
<!-- Enable / Disable --> <!-- WAJIB DISESUAIKAN -->
<!-- <env name="CI_ENVIRONMENT" value="testing"/> -->
<!-- <server name="app.baseURL" value="http://example.com/"/> -->
<server name="app.baseURL" value="http://localhost/clqms01/"/>
<server name="app.baseURL" value="http://localhost/clqms01/"/> <!-- WAJIB DISESUAIKAN -->
<server name="CODEIGNITER_SCREAM_DEPRECA TIONS" value="0"/>
<!-- Directory containing phpunit.xml -->
<const name="HOMEPATH" value="./"/>
@ -55,11 +55,11 @@
<!-- Directory containing the front controller (index.php) -->
<const name="PUBLICPATH" value="./public/"/>
<!-- Database configuration -->
<env name="database.tests.hostname" value="localhost"/>
<env name="database.tests.database" value="clqms01"/>
<env name="database.tests.username" value="root"/>
<env name="database.tests.password" value="adminsakti"/>
<env name="database.tests.DBDriver" value="MySQLi"/>
<env name="database.tests.hostname" value="localhost"/> <!-- WAJIB DISESUAIKAN -->
<env name="database.tests.database" value="clqm01"/> <!-- WAJIB DISESUAIKAN -->
<env name="database.tests.username" value="root"/> <!-- WAJIB DISESUAIKAN -->
<env name="database.tests.password" value=""/> <!-- WAJIB DISESUAIKAN -->
<env name="database.tests.DBDriver" value="MySQLi"/> <!-- WAJIB DISESUAIKAN -->
<!-- <env name="database.tests.DBPrefix" value="tests_"/> -->
</php>
</phpunit>

View File

@ -4,12 +4,14 @@ namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
use Faker\Factory;
class PatientCreateTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected $endpoint = 'api/patient';
// 400 - Passed
public function testCreatePatientValidationFail() {
// error 400 yg diharapkan
$payload = ['Name' => 'Ngawur'];
@ -43,117 +45,310 @@ class PatientCreateTest extends CIUnitTestCase
}
// Wajib Diganti ya payloadnya kalau mau dijalankan
// 201 - Passed
public function testCreatePatientSuccess() {
$faker = Factory::create('id_ID');
for ($i = 0; $i < 7; $i++) {
$payload = [
"PatientID"=> "SMAJ6", //Wajib Ganti
"AlternatePID"=> "P0234",
"Prefix"=> "Mr.",
"NameFirst"=> "Budi",
"NameMiddle"=> "Santoso",
"NameMaiden"=> "Kiki",
"NameLast"=> "Wijaya",
"Suffix"=> "S.kom",
"NameAlias"=> "Bud",
"Gender"=> "1",
'EmailAddress1' => 'kaka@gmail.a1com', //Wajib Ganti
'Identity' => [
"PatientID" => "DUM" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"AlternatePID" => "DMY" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"Prefix" => $faker->title,
"NameFirst" => $faker->firstName,
"NameMiddle" => $faker->firstName,
"NameMaiden" => $faker->firstName,
"NameLast" => $faker->lastName,
"Suffix" => "S.Kom",
"NameAlias" => $faker->userName,
"Gender" => $faker->numberBetween(5, 6),
"PlaceOfBirth" => $faker->city,
"Birthdate" => $faker->date('Y-m-d'),
"ZIP" => $faker->postcode,
"Street_1" => $faker->streetAddress,
"Street_2" => "RT " . $faker->numberBetween(1, 10) . " RW " . $faker->numberBetween(1, 10),
"Street_3" => "Blok " . $faker->numberBetween(1, 20),
"City" => $faker->city,
"Province" => $faker->state,
"EmailAddress1" => "A" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000).'@gmail.com',
"EmailAddress2" => "B" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000).'@gmail.com',
"Phone" => $faker->phoneNumber,
"MobilePhone" => $faker->phoneNumber,
"Race" => (string) $faker->numberBetween(175, 205),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Religion" => (string) $faker->numberBetween(206, 212),
"Ethnic" => (string) $faker->numberBetween(213, 220),
"Citizenship" => "WNI",
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
"LinkTo" => (string) $faker->numberBetween(2, 3),
"Custodian" => $i-1,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => "317409050590100" //Wajib Ganti
]
"Identifier" => $faker->nik() ?? $faker->numerify('################')
],
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
],
"PatCom" => $faker->sentence,
];
// $result = $this->call('post', 'api/patient', $payload);
$result = $this->withBodyFormat('json')
->call('post', 'api/patient', $payload);
$result->assertStatus(201);
$result->assertJSONFragment([
'status' => 'success',
]);
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
// public function testCreatePatientValidationError() {
// $payload = [
// "NameFirst" => "Jane" // PatientID kosong
// ];
$result = $this->withBodyFormat('json')->call('post', 'api/patient', $payload);
$result->assertStatus(201);
$result->assertJSONFragment(['status' => 'success']);
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
}
}
// $result->assertStatus(422);
// $result->assertJSONFragment(["field" => "patient"]);
// }
// Error - Passed
public function testCreatePatientValidationError() {
$payload = [
"NameFirst" => "Jane" // PatientID kosong
];
// public function testCreatePatidtValidationError() {
// $payload = [
// "PatientID" => "PX002",
// "NameFirst" => "Jane",
// "Identity" => [
// "IdentifierType" => null,
// "Identifier" => null
// ]
// ];
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// dd($result);
$result->assertArrayHasKey("errors", $result);
}
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// Error - Passed
public function testCreatePatidtValidationError() {
// $result->assertStatus(422);
// $result->assertJSONFragment(["field" => "patidt"]);
// }
$faker = Factory::create('id_ID');
// public function testCreateWithoutAttachments() {
// $payload = [
// "PatientID" => "PX003",
// "NameFirst" => "NoAttach",
// "Identity" => [
// "IdentifierType" => "KTP",
// "Identifier" => "99999"
// ]
// ];
$payload = [
"PatientID" => "DUMQ" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"AlternatePID" => "DMYQ" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"Prefix" => $faker->title,
"NameFirst" => $faker->firstName,
"NameMiddle" => $faker->firstName,
"NameMaiden" => $faker->firstName,
"NameLast" => $faker->lastName,
"Suffix" => "S.Kom",
"NameAlias" => $faker->userName,
"Gender" => $faker->numberBetween(5, 6),
"PlaceOfBirth" => $faker->city,
"Birthdate" => $faker->date('Y-m-d'),
"ZIP" => $faker->postcode,
"Street_1" => $faker->streetAddress,
"Street_2" => "RT " . $faker->numberBetween(1, 10) . " RW " . $faker->numberBetween(1, 10),
"Street_3" => "Blok " . $faker->numberBetween(1, 20),
"City" => $faker->city,
"Province" => $faker->state,
"EmailAddress1" => "AAQ" . (string)$faker->numberBetween(1, 1110).'@gmail.com',
"EmailAddress2" => "BAQ" . (string)$faker->numberBetween(1, 1110).'@gmail.com',
"Phone" => $faker->phoneNumber,
"MobilePhone" => $faker->phoneNumber,
"Race" => (string) $faker->numberBetween(175, 205),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Religion" => (string) $faker->numberBetween(206, 212),
"Ethnic" => (string) $faker->numberBetween(213, 220),
"Citizenship" => "WNI",
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
"LinkTo" => (string) $faker->numberBetween(2, 3),
"Custodian" => 1,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => "numberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetween"
// "Identifier" => $faker->nik() ?? $faker->numerify('################')
],
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
],
"PatCom" => $faker->sentence,
];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
// $result->assertStatus(201);
// }
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// public function testCreateWithoutComment() {
// $payload = [
// "PatientID" => "PX004",
// "NameFirst" => "NoComment",
// "Identity" => [
// "IdentifierType" => "SIM",
// "Identifier" => "A12345"
// ],
// "Attachments" => [
// ["Address" => "Jl. Melati No.2"]
// ]
// ];
$result->assertArrayHasKey("errors", $result);
}
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// 201 - Passed
public function testCreateWithoutAttachments() {
$faker = Factory::create('id_ID');
// $result->assertStatus(201);
// }
$payload = [
"PatientID" => "DUAU" . $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"AlternatePID" => "DMAU" . $faker->numberBetween(5, 1000).$faker->numberBetween(1, 1000),
"Prefix" => $faker->title,
"NameFirst" => $faker->firstName,
"NameMiddle" => $faker->firstName,
"NameMaiden" => $faker->firstName,
"NameLast" => $faker->lastName,
"Suffix" => "S.Kom",
"NameAlias" => $faker->userName,
"Gender" => $faker->numberBetween(5, 6),
"PlaceOfBirth" => $faker->city,
"Birthdate" => $faker->date('Y-m-d'),
"ZIP" => $faker->postcode,
"Street_1" => $faker->streetAddress,
"Street_2" => "RT " . $faker->numberBetween(1, 10) . " RW " . $faker->numberBetween(1, 10),
"Street_3" => "Blok " . $faker->numberBetween(1, 20),
"City" => $faker->city,
"Province" => $faker->state,
"EmailAddress1" => "AiA" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"EmailAddress2" => "BiA" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"Phone" => $faker->phoneNumber,
"MobilePhone" => $faker->phoneNumber,
"Race" => (string) $faker->numberBetween(175, 205),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Religion" => (string) $faker->numberBetween(206, 212),
"Ethnic" => (string) $faker->numberBetween(213, 220),
"Citizenship" => "WNI",
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
"LinkTo" => (string) $faker->numberBetween(2, 3),
"Custodian" => 1,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik() ?? $faker->numerify('################')
],
"PatAtt" => [],
"PatCom" => $faker->sentence,
];
// public function testCreateDatabaseError() {
// // Insert patient pertama
// $payload = [
// "InternalPID" => 999, // Force ID
// "PatientID" => "PX005",
// "NameFirst" => "First",
// "Identity" => [
// "IdentifierType" => "KTP",
// "Identifier" => "DBERR1"
// ]
// ];
// $this->withBodyFormat('json')->post($this->endpoint, $payload);
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
// // Insert kedua dengan InternalPID sama → trigger error
// $payload["NameFirst"] = "Second";
// $payload["Identity"]["Identifier"] = "DBERR2";
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
$result->assertStatus(201);
}
// $result->assertStatus(500);
// }
// 201 - Passed
public function testCreateWithoutPatComments() {
$faker = Factory::create('id_ID');
$payload = [
"PatientID" => "DUALU" . $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"AlternatePID" => "DMALU" . $faker->numberBetween(5, 1000).$faker->numberBetween(1, 1000),
"Prefix" => $faker->title,
"NameFirst" => $faker->firstName,
"NameMiddle" => $faker->firstName,
"NameMaiden" => $faker->firstName,
"NameLast" => $faker->lastName,
"Suffix" => "S.Kom",
"NameAlias" => $faker->userName,
"Gender" => $faker->numberBetween(5, 6),
"PlaceOfBirth" => $faker->city,
"Birthdate" => $faker->date('Y-m-d'),
"ZIP" => $faker->postcode,
"Street_1" => $faker->streetAddress,
"Street_2" => "RT " . $faker->numberBetween(1, 10) . " RW " . $faker->numberBetween(1, 10),
"Street_3" => "Blok " . $faker->numberBetween(1, 20),
"City" => $faker->city,
"Province" => $faker->state,
"EmailAddress1" => "AiAe" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"EmailAddress2" => "BiAe" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"Phone" => $faker->phoneNumber,
"MobilePhone" => $faker->phoneNumber,
"Race" => (string) $faker->numberBetween(175, 205),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Religion" => (string) $faker->numberBetween(206, 212),
"Ethnic" => (string) $faker->numberBetween(213, 220),
"Citizenship" => "WNI",
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
"LinkTo" => (string) $faker->numberBetween(2, 3),
"Custodian" => 1,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik() ?? $faker->numerify('################')
],
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
],
"PatCom" => null,
];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
$result->assertStatus(201);
}
// 500 - Passed
public function testCreateDatabaseError() {
$faker = Factory::create('id_ID');
// Insert patient pertama
$payload = [
"PatientID" => "DaUALU" . $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"AlternatePID" => "DaMALU" . $faker->numberBetween(5, 1000).$faker->numberBetween(1, 1000),
"Prefix" => $faker->title,
"NameFirst" => $faker->firstName,
"NameMiddle" => $faker->firstName,
"NameMaiden" => $faker->firstName,
"NameLast" => $faker->lastName,
"Suffix" => "S.Kom",
"NameAlias" => $faker->userName,
"Gender" => $faker->numberBetween(5, 6),
"PlaceOfBirth" => $faker->city,
"Birthdate" => $faker->date('Y-m-d'),
"ZIP" => $faker->postcode,
"Street_1" => $faker->streetAddress,
"Street_2" => "RT " . $faker->numberBetween(1, 10) . " RW " . $faker->numberBetween(1, 10),
"Street_3" => "Blok " . $faker->numberBetween(1, 20),
"City" => $faker->city,
"Province" => $faker->state,
"EmailAddress1" => "AiaAe" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"EmailAddress2" => "BiaAe" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"Phone" => $faker->phoneNumber,
"MobilePhone" => $faker->phoneNumber,
"Race" => (string) $faker->numberBetween(175, 205),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Religion" => (string) $faker->numberBetween(206, 212),
"Ethnic" => (string) $faker->numberBetween(213, 220),
"Citizenship" => "WNI",
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
"LinkTo" => (string) $faker->numberBetween(2, 3),
"Custodian" => 1,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik() ?? $faker->numerify('################')
],
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
],
"PatCom" => [], // Ini Salah
];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
$result->assertStatus(500);
}
// public function testCreateDuplicateIdentifier() {
// $payload = [
@ -178,44 +373,4 @@ class PatientCreateTest extends CIUnitTestCase
// $result->assertStatus(422);
// }
// public function testCreateWithLinkTo() {
// $payload = [
// "PatientID" => "PX008",
// "NameFirst" => "LinkTo",
// "Identity" => [
// "IdentifierType" => "KTP",
// "Identifier" => "LINK123"
// ],
// "LinkTo" => [
// ["InternalPID" => 1],
// ["InternalPID" => 2]
// ]
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(201);
// $data = json_decode($result->getBody(), true);
// $this->assertIsInt($data["data"]);
// }
// public function testCreateWithNumericAndNullFields() {
// $payload = [
// "PatientID" => "PX009",
// "NameFirst" => "Numeric",
// "Gender" => null,
// "RaceID" => "3",
// "DeathIndicator" => 0,
// "Identity" => [
// "IdentifierType" => "SIM",
// "Identifier" => "NUM123"
// ]
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(201);
// }
}

View File

@ -10,87 +10,87 @@ class PatientDeleteTest extends CIUnitTestCase
use FeatureTestTrait;
protected $endpoint = 'api/patient';
// 500 error catch
public function testDeleteWithoutInternalPID() {
$result = $this->withBodyFormat('json')
->delete($this->endpoint, []);
// // 500 error catch
// public function testDeleteWithoutInternalPID() {
// $result = $this->withBodyFormat('json')
// ->delete($this->endpoint, []);
$result->assertStatus(500);
$result->assertJSONFragment([
'status' => 500,
'messages' => [
'error' => 'Internal server error: Undefined array key "InternalPID"'
]
]);
}
// $result->assertStatus(500);
// $result->assertJSONFragment([
// 'status' => 500,
// 'messages' => [
// 'error' => 'Internal server error: Undefined array key "InternalPID"'
// ]
// ]);
// }
// 400
public function testDeleteWitWrongInternalPID() {
$result = $this->withBodyFormat('json')
->delete($this->endpoint, [
// Pilih salah satu
// 'InternalPID' => [],
// 'InternalPID' => 0,
// 'InternalPID' => '0',
// 'InternalPID' => '',
'InternalPID' => null,
]);
// // 400
// public function testDeleteWitWrongInternalPID() {
// $result = $this->withBodyFormat('json')
// ->delete($this->endpoint, [
// // Pilih salah satu
// // 'InternalPID' => [],
// // 'InternalPID' => 0,
// // 'InternalPID' => '0',
// // 'InternalPID' => '',
// 'InternalPID' => null,
// ]);
$result->assertStatus(400);
$result->assertJSONFragment([
'status' => 'error',
'message' => 'Patient ID must be a valid integer.'
]);
}
// $result->assertStatus(400);
// $result->assertJSONFragment([
// 'status' => 'error',
// 'message' => 'Patient ID must be a valid integer.'
// ]);
// }
// 404 not found
public function testDeleteNotFound() {
$testId = 9999;
// // 404 not found
// public function testDeleteNotFound() {
// $testId = 9999;
$result = $this->withBodyFormat('json')
->delete($this->endpoint, [
'InternalPID' => $testId
]);
// $result = $this->withBodyFormat('json')
// ->delete($this->endpoint, [
// 'InternalPID' => $testId
// ]);
$result->assertStatus(404);
$result->assertJSONFragment([
'status' => 404,
'error' => 404,
'messages' => [
'error' => 'Patient ID with '.$testId.' not found.'
]
]);
}
// $result->assertStatus(404);
// $result->assertJSONFragment([
// 'status' => 404,
// 'error' => 404,
// 'messages' => [
// 'error' => 'Patient ID with '.$testId.' not found.'
// ]
// ]);
// }
// 200 ok
public function testDeleteSuccess() {
// // 200 ok
// public function testDeleteSuccess() {
$testId = 3;
// Anggap patient 1 2 3 ada di seed DB
$result = $this->withBodyFormat('json')
->delete($this->endpoint, [
'InternalPID' => $testId
]);
// $testId = 3;
// // Anggap patient 1 2 3 ada di seed DB
// $result = $this->withBodyFormat('json')
// ->delete($this->endpoint, [
// 'InternalPID' => $testId
// ]);
$result->assertStatus(200);
$result->assertJSONFragment([
'status' => 'success',
'message' => 'Patient ID with '.$testId.' deleted successfully.'
]);
}
// $result->assertStatus(200);
// $result->assertJSONFragment([
// 'status' => 'success',
// 'message' => 'Patient ID with '.$testId.' deleted successfully.'
// ]);
// }
// 400 - SQL Inject
public function testDeleteServerError() {
// Simulasi: kirim input aneh yang trigger exception
$result = $this->withBodyFormat('json')
->delete($this->endpoint, [
'InternalPID' => "' OR 1=1 --"
]);
$result->assertStatus(400);
$result->assertJSONFragment([
'status' => 'error',
'message' => 'Patient ID must be a valid integer.'
]);
}
// // 400 - SQL Inject
// public function testDeleteServerError() {
// // Simulasi: kirim input aneh yang trigger exception
// $result = $this->withBodyFormat('json')
// ->delete($this->endpoint, [
// 'InternalPID' => "' OR 1=1 --"
// ]);
// $result->assertStatus(400);
// $result->assertJSONFragment([
// 'status' => 'error',
// 'message' => 'Patient ID must be a valid integer.'
// ]);
// }
}

View File

@ -12,7 +12,7 @@ class PatientIndexTest extends CIUnitTestCase
protected $endpoint = 'api/patient';
/**
* Case 1: tanpa parameter, harus 200 dan status success
* Case 1: tanpa parameter, harus 200 dan status success - Passed
*/
public function testIndexWithoutParams() {
$result = $this->call('get', $this->endpoint);
@ -24,7 +24,7 @@ class PatientIndexTest extends CIUnitTestCase
}
/**
* Case 2: parameter Name yang tidak ada return kosong []
* Case 2: parameter Name yang tidak ada return kosong [] - Passed
*/
public function testIndexWithWrongNameParam() {
$result = $this->call('get', $this->endpoint, [
@ -39,7 +39,7 @@ class PatientIndexTest extends CIUnitTestCase
}
/**
* Case 3: parameter Name benar return array tidak kosong
* Case 3: parameter Name benar return array tidak kosong - Passed
*/
public function testIndexWithCorrectNameParam() {
// Sesuaikan dengan data di database test Anda
@ -58,7 +58,7 @@ class PatientIndexTest extends CIUnitTestCase
}
/**
* Case 4: parameter InternalPID return data sesuai ID
* Case 4: parameter InternalPID return data sesuai ID - Passed
*/
public function testIndexWithInternalPID() {
$result = $this->call('get', $this->endpoint, [
@ -77,7 +77,7 @@ class PatientIndexTest extends CIUnitTestCase
}
/**
* Case 5: parameter PatientID return data sesuai PatientID
* Case 5: parameter PatientID return data sesuai PatientID - Passed
*/
public function testIndexWithPatientID() {
$result = $this->call('get', $this->endpoint, [
@ -96,7 +96,7 @@ class PatientIndexTest extends CIUnitTestCase
}
/**
* Case 6: parameter Birthdate return data sesuai tanggal
* Case 6: parameter Birthdate return data sesuai tanggal - Passed
*/
public function testIndexWithBirthdate() {
$result = $this->call('get', $this->endpoint, [
@ -115,7 +115,7 @@ class PatientIndexTest extends CIUnitTestCase
}
/**
* Case 7: Simulasi server error (optional, jika bisa trigger)
* Case 7: Simulasi server error (optional, jika bisa trigger) - Passed
*/
public function testIndexServerErrorSimulation() {
// Misalnya panggil dengan param aneh untuk trigger exception
@ -123,12 +123,6 @@ class PatientIndexTest extends CIUnitTestCase
'InternalPID' => "' OR 1=2 --"
]);
// dd([
// 'status' => $result->getStatusCode(),
// 'body' => $result->getBody(),
// 'json' => $result->getJSON(),
// ]);
// Boleh assert 200 (jika sanitasi bagus) atau 500 (kalau exception)
$this->assertContains($result->getStatusCode(), [200, 500, null]);
}

View File

@ -11,28 +11,29 @@ class PatientShowTest extends CIUnitTestCase
protected $endpoint = 'api/patient';
// 200 ok not found
// 200 ok not found - Passed
public function testShowNotFound() {
$result = $this->get($this->endpoint . '/90909090');
$result->assertStatus(200);
$result->assertJSONFragment([
'status' => 'success',
"message" => "Patient with ID 90909090 not found.",
'data' => []
"message" => "data not found."
]);
}
// 200 ok
// 200 ok found - Passed
public function testShowSingleRow() {
// Pastikan DB test punya seed patient InternalPID=10 tanpa id/addr
$result = $this->get($this->endpoint . '/1');
$result->assertStatus(200);
$data = $result->getJSON(true);
$data = json_decode($data, true);
$this->assertEquals('success', $data['status']);
// $this->assertNull($data['data']['Attachments']);
$result->assertStatus(200);
$result->assertArrayHasKey('data', $data);
$result->assertIsArray($data['data']);
// $this->assertEquals('success', $data['status']);
}
}

View File

@ -4,86 +4,155 @@ namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
use Faker\Factory;
class PatientUpdateTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected $endpoint = 'api/patient';
// Belon
public function testUpdatePatientSuccess()
{
$faker = Factory::create('id_ID');
// public function testUpdateFail()
// {
// $payload = [];
// $result = $this->withBodyFormat('json')
// ->call('patch', 'api/patient', $payload);
// $result->assertStatus(400);
$payload = [
"InternalPID" => 1,
"PatientID" => "UPDT" . $faker->numberBetween(100, 999),
"NameFirst" => $faker->firstName,
"NameLast" => $faker->lastName,
"Gender" => (string) $faker->numberBetween(5, 6),
"Birthdate" => $faker->date('Y-m-d'),
"DeathDateTime" => null,
"EmailAddress1" => "asasa@gmail.com",
"PlaceOfBirth" => $faker->city,
"Race" => (string) $faker->numberBetween(175, 205),
"Religion" => (string) $faker->numberBetween(206, 212),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Citizenship" => "WNI",
"LinkTo" => null,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik(),
],
"PatCom" => $faker->sentence(5),
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
]
];
// $payload = [
// "InternalPID"=> 100,
// "PatientID"=> "SMAJ50", //Wajib Ganti
// "AlternatePID"=> "P0234",
// "Prefix"=> "Mr.",
// "NameFirst"=> "Budi",
// "NameMiddle"=> "Santoso",
// "NameMaiden"=> "Kiki",
// "NameLast"=> "Wijaya",
// "Suffix"=> "S.kom",
// "NameAlias"=> "Bud",
// "Gender"=> "1",
// 'EmailAddress1' => 'kaka@gmail.a1com', //Wajib Ganti
// 'Identity' => [
// "IdentifierType" => "KTP",
// "Identifier" => "317409050590100" //Wajib Ganti
// ]
// ];
// $result = $this->withBodyFormat('json')
// ->call('patch', 'api/patient', $payload);
// $result->assertStatus(404);
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload);
$result->assertStatus(201);
}
// /**
// * ❌ Test gagal karena InternalPID kosong (validasi)
// */
public function testUpdatePatientValidationError()
{
$faker = Factory::create('id_ID');
$payload = [
"NameFirst" => $faker->firstName,
"Gender" => (string) $faker->numberBetween(5, 6),
"Birthdate" => $faker->date('Y-m-d'),
// Tidak kirim InternalPID
];
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload);
$json = $result->getJSON();
$data = json_decode($json, true);
$result->assertStatus(400);
$this->assertArrayHasKey('errors', $data);
}
// /**
// * ✅ Test update dengan address baru & hapus address lama
// */
public function testUpdatePatientWithAddressChange()
{
$faker = Factory::create('id_ID');
$payload = [
"InternalPID" => 1,
"PatientID" => "UPDT" . $faker->numberBetween(100, 999),
"NameFirst" => $faker->firstName,
"NameLast" => $faker->lastName,
"Gender" => (string) $faker->numberBetween(5, 6),
"Birthdate" => $faker->date('Y-m-d'),
"DeathDateTime" => null,
"EmailAddress1" => "asasa@gmail.com",
"PlaceOfBirth" => $faker->city,
"Race" => (string) $faker->numberBetween(175, 205),
"Religion" => (string) $faker->numberBetween(206, 212),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Citizenship" => "WNI",
"LinkTo" => null,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik(),
],
"PatCom" => $faker->sentence(5),
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
]
];
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload);
$result->assertStatus(201);
$json = $result->getJSON();
$data = json_decode($json, true);
$this->assertEquals('success', $data['status']);
}
// /**
// * ⚠️ Test update kosong → semua pattat address dihapus (soft delete)
// */
public function testUpdatePatientEmptyAddress()
{
$faker = Factory::create('id_ID');
$payload = [
"InternalPID" => 1,
"PatientID" => "UPDT" . $faker->numberBetween(100, 999),
"NameFirst" => $faker->firstName,
"NameLast" => $faker->lastName,
"Gender" => (string) $faker->numberBetween(5, 6),
"Birthdate" => $faker->date('Y-m-d'),
"DeathDateTime" => null,
"EmailAddress1" => "asasa@gmail.com",
"PlaceOfBirth" => $faker->city,
"Race" => (string) $faker->numberBetween(175, 205),
"Religion" => (string) $faker->numberBetween(206, 212),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Citizenship" => "WNI",
"LinkTo" => null,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik(),
],
"PatCom" => $faker->sentence(5),
"PatAtt" => []
];
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload);
$json = $result->getJSON();
$data = json_decode($json, true);
$result->assertStatus(201);
$this->assertEquals('success', $data['status']);
}
// $payload = [
// "PatientID"=> "SMAJ50", //Wajib Ganti
// "AlternatePID"=> "P0234",
// "Prefix"=> "Mr.",
// "NameFirst"=> "Budi",
// "NameMiddle"=> "Santoso",
// "NameMaiden"=> "Kiki",
// "NameLast"=> "Wijaya",
// "Suffix"=> "S.kom",
// "NameAlias"=> "Bud",
// "Gender"=> "1",
// 'EmailAddress1' => 'kaka@gmail.a1com', //Wajib Ganti
// 'Identity' => [
// "IdentifierType" => "KTP",
// "Identifier" => "317409050590100" //Wajib Ganti
// ]
// ];
// $result = $this->withBodyFormat('json')
// ->call('patch', 'api/patient', $payload);
// $result->assertStatus(500);
// }
// public function testUpdateSuccess()
// {
// $payload = [
// "InternalPID"=> 1, //Wajib Ganti
// "PatientID"=> "SMAJ50",
// "AlternatePID"=> "asasasa",
// "Prefix"=> "Mr.",
// "NameFirst"=> "Budi",
// "NameMiddle"=> "Santoso",
// "NameMaiden"=> "Kiki",
// "NameLast"=> "Wijaya",
// "Suffix"=> "S.kom",
// "NameAlias"=> "Bud",
// "Gender"=> "1",
// 'EmailAddress1' => 'kaka@gmail.a1com',
// 'Identity' => [
// "IdentifierType" => "KTP",
// "Identifier" => "317409050590100"
// ]
// ];
// $result = $this->withBodyFormat('json')
// ->call('patch', 'api/patient', $payload);
// $result->assertStatus(200);
// }
}