Update Unit Testing Create

This commit is contained in:
mikael-zakaria 2025-09-25 14:01:33 +07:00
parent 88e0de78ba
commit e186c6f3de
6 changed files with 368 additions and 145 deletions

View File

@ -20,7 +20,7 @@ class Patient extends Controller {
$this->rulesPatIdt = ['Identifier' => 'required|is_unique[patidt.Identifier]'];
}
// OK - Done
// Unit Testing Pass : \clqms-be\tests\feature\Patients\PatientIndexTest.php
public function index() {
try {
$InternalPID = $this->request->getVar('InternalPID');
@ -64,6 +64,7 @@ class Patient extends Controller {
}
}
// Unit Testing Pass : \clqms-be\tests\feature\Patients\PatientShowTest.php
public function show($InternalPID = null) {
try {
$rows = $this->db->table('patient')
@ -131,7 +132,7 @@ class Patient extends Controller {
}
}
// Transform Data Conversion
private function transformPatientData(array $patient): array {
$patient["Age"] = $this->calculateAgeFromBirthdate($patient["Birthdate"]);
$patient["Birthdate"] = $this->formatedDate($patient["Birthdate"]);
@ -146,6 +147,7 @@ class Patient extends Controller {
return $patient;
}
// Linkto is not empty? then Query and return array data (InternalPID, PatientID)
private function getLinkedPatients(?string $linkTo): ?array {
if (empty($linkTo)) {
return null;
@ -160,6 +162,7 @@ class Patient extends Controller {
->getResultArray() ?: null;
}
// Custodian is not empty? then Query and return array data (InternalPID, PatientID)
private function getCustodian($custodianId): ?array {
if (empty($custodianId)) {
return null;
@ -169,10 +172,10 @@ class Patient extends Controller {
->select('InternalPID, PatientID')
->where('InternalPID', (int) $custodianId)
->get()
->getResultArray() ?: null;
->getRowArray() ?: null;
}
// Unit Testing Pass : On Progress
public function create() {
try {
$input = $this->request->getJSON(true);
@ -201,7 +204,6 @@ class Patient extends Controller {
}
*/
$this->db->transStart();
$this->db->table('patient')->insert($dataPatient);
@ -251,6 +253,7 @@ class Patient extends Controller {
}
}
// Setting up data
private function preparePatientData(array $input, string $mode = 'create'): array {
$LinkTo = null;
if (!empty($input['LinkTo'])) {
@ -298,7 +301,6 @@ class Patient extends Controller {
return $data;
}
private function preparePatidtData(array $input ): array {
$data = [
"IdentifierType" => $input['Identity']['IdentifierType'] ?? null,
@ -307,7 +309,6 @@ class Patient extends Controller {
return $data;
}
private function preparePatattData(array $input): array {
if (empty($input['Attachments'])) {
return [];
@ -320,7 +321,6 @@ class Patient extends Controller {
return $row;
}, $input['Attachments']);
}
private function preparePatcomData(array $input): array {
$data = [
"Comment" => $input['Comment'] ?? null,
@ -328,7 +328,6 @@ class Patient extends Controller {
return $data;
}
private function validationError(string $context, array $errors) {
return $this->respond([
'status' => 'error',
@ -337,6 +336,7 @@ class Patient extends Controller {
], 400);
}
// Unit Testing Pass : On Progress
public function update() {
try {
$input = $this->request->getJSON(true);
@ -344,7 +344,7 @@ class Patient extends Controller {
if (!$input["InternalPID"] || !is_numeric($input["InternalPID"])) { return $this->respond(['status' => 'error', 'message' => 'Invalid or missing InternalPID'], 400); }
$InternalPID = $input["InternalPID"];
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getResultArray();
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRowArray();
if (!$patient) { return $this->respond(['status' => 'error', 'message' => 'Patient not found'], 404); }
$dataPatient = $this->preparePatientData($input);
@ -420,13 +420,18 @@ class Patient extends Controller {
}
}
// Unit Testing Pass : \clqms-be\tests\feature\Patients\PatientDeleteTest.php
public function delete() {
try {
$input = $this->request->getJSON(true);
$InternalPID = $input["InternalPID"];
if (!$InternalPID) {
return $this->failValidationError('Patient ID is required.');
// Mencegah Inputan 0, [], null, sql injection
if (empty($InternalPID) || !ctype_digit((string) $InternalPID)) {
return $this->respond([
'status' => 'error',
'message' => "Patient ID must be a valid integer."
], 400);
}
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRow();
@ -447,7 +452,6 @@ class Patient extends Controller {
}
}
// OK - Done
public function patientCheck() {
try {
$PatientID = $this->request->getVar('PatientID');
@ -466,7 +470,7 @@ class Patient extends Controller {
$patient = $this->db->table('patient')
->where($tableName, $searchName)
->get()
->getResultArray();
->getRowArray();
if (!$patient) {
return $this->respond([
@ -489,8 +493,7 @@ class Patient extends Controller {
}
}
// Ubah ke format Years Months Days
// Conversion to (Years Months Days)
private function calculateAgeFromBirthdate($birthdate) {
$dob = new \DateTime($birthdate);
$today = new \DateTime();
@ -510,7 +513,7 @@ class Patient extends Controller {
return $formattedAge;
}
// Ubah ke format Y-m-d H:i
// Conversion Time to Format Y-m-d H:i
private function formatedDate($dateString) {
$date = \DateTime::createFromFormat('Y-m-d H:i', $dateString);
@ -525,7 +528,7 @@ class Patient extends Controller {
return $date->format('Y-m-d H:i');
}
// Ubah ke format j M Y
// Conversion Time to Format j M Y
private function formatedDateForDisplay($dateString) {
$date = \DateTime::createFromFormat('Y-m-d H:i', $dateString);

View File

@ -1,6 +1,6 @@
<?php
namespace Tests\Feature\Patient;
namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
@ -8,71 +8,251 @@ use CodeIgniter\Test\CIUnitTestCase;
class PatientCreateTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected $endpoint = 'api/patient';
// public function testCreatePatientValidationFail()
// {
// // error 400 yg diharapkan
// $payload = ['Name' => 'Ngawur'];
// $result = $this->withBodyFormat('json')
// ->call('post', 'api/patient', $payload);
// $result->assertStatus(400);
// $result->assertJSONFragment([
// 'status' => 'error'
// ]);
// public function testCreatePatientValidationFail()
// {
// // error 400 yg diharapkan
// $payload = ['Name' => 'Ngawur'];
// $result = $this->withBodyFormat('json')
// ->call('post', 'api/patient', $payload);
// $result->assertStatus(400);
// $result->assertJSONFragment([
// 'status' => 'error'
// ]);
// // Kondisi Jika PatiD Sama
// $payload = [
// "PatientID"=> "SMAJ1",
// "AlternatePID"=> "ALT001234",
// "Prefix"=> "Mr.",
// "NameFirst"=> "Budi",
// "NameMiddle"=> "Santoso",
// "NameMaiden"=> "Kiki",
// "NameLast"=> "Wijaya",
// "Suffix"=> "S.kom",
// "NameAlias"=> "Bud",
// "Gender"=> "1",
// ];
// $result = $this->withBodyFormat('json')
// ->call('post', 'api/patient', $payload);
// $result->assertStatus(400);
// $result->assertJSONFragment([
// 'status' => 'error',
// "message" => "Validation failed (patient)",
// ]);
// // Kondisi Jika PatiD Sama
// $payload = [
// "PatientID"=> "SMAJ1",
// "AlternatePID"=> "ALT001234",
// "Prefix"=> "Mr.",
// "NameFirst"=> "Budi",
// "NameMiddle"=> "Santoso",
// "NameMaiden"=> "Kiki",
// "NameLast"=> "Wijaya",
// "Suffix"=> "S.kom",
// "NameAlias"=> "Bud",
// "Gender"=> "1",
// ];
// $result = $this->withBodyFormat('json')
// ->call('post', 'api/patient', $payload);
// $result->assertStatus(400);
// $result->assertJSONFragment([
// 'status' => 'error',
// "message" => "Validation failed (patient)",
// ]);
// }
// }
// // Wajib Diganti ya payloadnya kalau mau dijalankan
// public function testCreateSuccess()
// {
// $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' => [
// "IdentifierType" => "KTP",
// "Identifier" => "317409050590100" //Wajib Ganti
// ]
// ];
// // Wajib Diganti ya payloadnya kalau mau dijalankan
// public function testCreateSuccess()
// {
// $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' => [
// "IdentifierType" => "KTP",
// "Identifier" => "317409050590100" //Wajib Ganti
// ]
// ];
// // $result = $this->call('post', 'api/patient', $payload);
// $result = $this->withBodyFormat('json')
// ->call('post', 'api/patient', $payload);
// // $result = $this->call('post', 'api/patient', $payload);
// $result = $this->withBodyFormat('json')
// ->call('post', 'api/patient', $payload);
// $result->assertStatus(201);
// $result->assertJSONFragment([
// 'status' => 'success',
// ]);
// }
// $result->assertStatus(201);
// $result->assertJSONFragment([
// 'status' => 'success',
// ]);
// }
// dd($result);
public function testCreatePatientSuccess() {
$payload = [
"PatientID" => "PX004",
"NameFirst" => "Johan",
"NameLast" => "Doe",
"Gender" => 1,
"Birthdate" => "1990-01-01",
"EmailAddress1" => "johnaa@examaple.com",
"Identity" => [
"IdentifierType" => "KTP",
"Identifier" => "1232457893",
],
"Attachments" => [
["Address" => "Jl. Mawar No.1"]
],
"Comment" => "Pasien test"
];
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
$result->assertStatus(201);
$result->assertJSONFragment([
"status" => "success",
"message" => "Patient created successfully"
]);
// $data = json_decode($result->getBody(), true);
// $this->assertArrayHasKey("data", $data);
// $this->assertIsInt($data["data"]); // InternalPID
}
// public function testCreatePatientValidationError() {
// $payload = [
// "NameFirst" => "Jane" // PatientID kosong
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(422);
// $result->assertJSONFragment(["field" => "patient"]);
// }
// public function testCreatePatidtValidationError() {
// $payload = [
// "PatientID" => "PX002",
// "NameFirst" => "Jane",
// "Identity" => [
// "IdentifierType" => null,
// "Identifier" => null
// ]
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(422);
// $result->assertJSONFragment(["field" => "patidt"]);
// }
// public function testCreateWithoutAttachments() {
// $payload = [
// "PatientID" => "PX003",
// "NameFirst" => "NoAttach",
// "Identity" => [
// "IdentifierType" => "KTP",
// "Identifier" => "99999"
// ]
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(201);
// }
// public function testCreateWithoutComment() {
// $payload = [
// "PatientID" => "PX004",
// "NameFirst" => "NoComment",
// "Identity" => [
// "IdentifierType" => "SIM",
// "Identifier" => "A12345"
// ],
// "Attachments" => [
// ["Address" => "Jl. Melati No.2"]
// ]
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(201);
// }
// 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);
// // Insert kedua dengan InternalPID sama → trigger error
// $payload["NameFirst"] = "Second";
// $payload["Identity"]["Identifier"] = "DBERR2";
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $result->assertStatus(500);
// }
// public function testCreateDuplicateIdentifier() {
// $payload = [
// "PatientID" => "PX006",
// "NameFirst" => "Alpha",
// "Identity" => [
// "IdentifierType" => "KTP",
// "Identifier" => "DUP123"
// ]
// ];
// $this->withBodyFormat('json')->post($this->endpoint, $payload);
// $payload2 = [
// "PatientID" => "PX007",
// "NameFirst" => "Beta",
// "Identity" => [
// "IdentifierType" => "KTP",
// "Identifier" => "DUP123" // Sama
// ]
// ];
// $result = $this->withBodyFormat('json')->post($this->endpoint, $payload2);
// $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

@ -1,6 +1,6 @@
<?php
namespace Tests\Feature\Patient;
namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
@ -8,41 +8,89 @@ use CodeIgniter\Test\CIUnitTestCase;
class PatientDeleteTest extends CIUnitTestCase
{
use FeatureTestTrait;
protected $endpoint = 'api/patient';
// public function testDeleteFail() {
// $payload = [
// 'InternalPID' => 9999999
// ];
// $result = $this->withBodyFormat('json')
// ->withBody(json_encode($payload))
// ->delete('api/patient');
// 500 error catch
public function testDeleteWithoutInternalPID() {
$result = $this->withBodyFormat('json')
->delete($this->endpoint, []);
// $result->assertStatus(404);
// $json = $result->getJSON(); // bentuk string JSON
// $json = json_decode($json, true);
$result->assertStatus(500);
$result->assertJSONFragment([
'status' => 500,
'messages' => [
'error' => 'Internal server error: Undefined array key "InternalPID"'
]
]);
}
// $result->assertJSONFragment([
// 'status' => 404,
// 'error' => 404
// ]);
// }
// 400
public function testDeleteWitWrongInternalPID() {
$result = $this->withBodyFormat('json')
->delete($this->endpoint, [
// Pilih salah satu
// 'InternalPID' => [],
// 'InternalPID' => 0,
// 'InternalPID' => '0',
// 'InternalPID' => '',
'InternalPID' => null,
]);
// public function testDeleteSuccess() {
// $payload = [
// 'InternalPID' => 2
// ];
// $result = $this->withBodyFormat('json')
// ->withBody(json_encode($payload))
// ->delete('api/patient');
// $result->assertStatus(200);
// $json = $result->getJSON(); // bentuk string JSON
// $json = json_decode($json, true);
$result->assertStatus(400);
$result->assertJSONFragment([
'status' => 'error',
'message' => 'Patient ID must be a valid integer.'
]);
}
// // $this->assertSame('Patient with ID 999999 not found.', $json['message']);
// $result->assertJSONFragment([
// 'status' => 'success'
// ]);
// }
// 404 not found
public function testDeleteNotFound() {
$testId = 9999;
$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.'
]
]);
}
// 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
]);
$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.'
]);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Tests\Feature\Patient;
namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
@ -14,8 +14,7 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 1: tanpa parameter, harus 200 dan status success
*/
public function testIndexWithoutParams()
{
public function testIndexWithoutParams() {
$result = $this->call('get', $this->endpoint);
$result->assertStatus(200);
@ -27,8 +26,7 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 2: parameter Name yang tidak ada return kosong []
*/
public function testIndexWithWrongNameParam()
{
public function testIndexWithWrongNameParam() {
$result = $this->call('get', $this->endpoint, [
'Name' => 'TidakAdaNama'
]);
@ -43,8 +41,7 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 3: parameter Name benar return array tidak kosong
*/
public function testIndexWithCorrectNameParam()
{
public function testIndexWithCorrectNameParam() {
// Sesuaikan dengan data di database test Anda
$result = $this->call('get', $this->endpoint, [
'Name' => 'Dummy'
@ -63,8 +60,7 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 4: parameter InternalPID return data sesuai ID
*/
public function testIndexWithInternalPID()
{
public function testIndexWithInternalPID() {
$result = $this->call('get', $this->endpoint, [
'InternalPID' => 1
]);
@ -83,8 +79,7 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 5: parameter PatientID return data sesuai PatientID
*/
public function testIndexWithPatientID()
{
public function testIndexWithPatientID() {
$result = $this->call('get', $this->endpoint, [
'PatientID' => '123'
]);
@ -103,8 +98,7 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 6: parameter Birthdate return data sesuai tanggal
*/
public function testIndexWithBirthdate()
{
public function testIndexWithBirthdate() {
$result = $this->call('get', $this->endpoint, [
'Birthdate' => '2000-01-01'
]);
@ -123,11 +117,10 @@ class PatientIndexTest extends CIUnitTestCase
/**
* Case 7: Simulasi server error (optional, jika bisa trigger)
*/
public function testIndexServerErrorSimulation()
{
public function testIndexServerErrorSimulation() {
// Misalnya panggil dengan param aneh untuk trigger exception
$result = $this->call('get', $this->endpoint, [
'InternalPID' => "'asasa-"
'InternalPID' => "' OR 1=2 --"
]);
// dd([

View File

@ -1,6 +1,6 @@
<?php
namespace Tests\Feature\Patient;
namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
@ -9,31 +9,30 @@ class PatientShowTest extends CIUnitTestCase
{
use FeatureTestTrait;
public function testShowNotFound()
{
$result = $this->call('get', 'api/patient/999999'); // ID yang tidak ada
$result->assertStatus(200);
$json = $result->getJSON(); // bentuk string JSON
$json = json_decode($json, true);
protected $endpoint = 'api/patient';
// $this->assertSame('Patient with ID 999999 not found.', $json['message']);
// 200 ok not found
public function testShowNotFound() {
$result = $this->get($this->endpoint . '/90909090');
$result->assertStatus(200);
$result->assertJSONFragment([
'status' => 'success',
"message" => "Patient with ID 90909090 not found.",
'data' => []
]);
}
public function testShowFound() {
$result = $this->call('get', 'api/patient/1'); // ID yang tidak ada
// 200 ok
public function testShowSingleRow() {
// Pastikan DB test punya seed patient InternalPID=10 tanpa id/addr
$result = $this->get($this->endpoint . '/1');
$result->assertStatus(200);
$json = $result->getJSON();
$data = json_decode($json, true);
$data = $result->getJSON(true);
$data = json_decode($data, true);
$this->assertEquals('success', $data['status']);
$this->assertNotNull($data['data']); // data tidak null
$this->assertIsArray($data['data']); // data berupa array
// $this->assertNull($data['data']['Attachments']);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Tests\Feature\Patient;
namespace Tests\Feature\Patients;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;