"ORD" . $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" => "Order", "NameMiddle" => $faker->firstName, "NameMaiden" => $faker->firstName, "NameLast" => "Test", "Suffix" => "S.Kom", "NameAlias" => $faker->userName, "Sex" => $faker->numberBetween(5, 6), "PlaceOfBirth" => $faker->city, "Birthdate" => "1990-01-01", "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->numerify('08##########'), "MobilePhone" => $faker->numerify('08##########'), "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->uuid . ".jpg" ] ], "PatCom" => $faker->sentence, ]; if($patientPayload['DeathIndicator'] == '16') { $patientPayload['DeathDateTime'] = $faker->date('Y-m-d H:i:s'); } else { $patientPayload['DeathDateTime'] = null; } $patientResult = $this->withBodyFormat('json')->call('post', 'api/patient', $patientPayload); // Check patient creation succeeded $patientResult->assertStatus(201); $patientBody = json_decode($patientResult->getBody(), true); $internalPID = $patientBody['data']['InternalPID'] ?? null; $this->assertNotNull($internalPID, 'Failed to create test patient. Response: ' . print_r($patientBody, true)); // Get available tests from testdefsite $testsResult = $this->call('get', 'api/test'); $testsBody = json_decode($testsResult->getBody(), true); $availableTests = $testsBody['data'] ?? []; // Skip if no tests available if (empty($availableTests)) { $this->markTestSkipped('No tests available in testdefsite table'); } $testSiteID = $availableTests[0]['TestSiteID']; // Create order with tests $payload = [ 'InternalPID' => $internalPID, 'Priority' => 'R', 'Tests' => [ ['TestSiteID' => $testSiteID] ] ]; $result = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload); // Assertions $result->assertStatus(201); $body = json_decode($result->getBody(), true); $this->assertEquals('success', $body['status']); $this->assertArrayHasKey('data', $body); $this->assertArrayHasKey('OrderID', $body['data']); $this->assertArrayHasKey('Specimens', $body['data']); $this->assertArrayHasKey('Tests', $body['data']); $this->assertIsArray($body['data']['Specimens']); $this->assertIsArray($body['data']['Tests']); $this->assertNotEmpty($body['data']['Tests'], 'Tests array should not be empty'); return $body['data']['OrderID']; } public function testCreateOrderValidationFailsWithoutInternalPID() { $payload = [ 'Tests' => [ ['TestSiteID' => 1] ] ]; $result = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload); $result->assertStatus(400); $body = json_decode($result->getBody(), true); $this->assertIsArray($body); $this->assertArrayHasKey('errors', $body); } public function testCreateOrderFailsWithInvalidPatient() { $payload = [ 'InternalPID' => 999999, 'Tests' => [ ['TestSiteID' => 1] ] ]; $result = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload); $result->assertStatus(400); $body = json_decode($result->getBody(), true); $this->assertIsArray($body); $this->assertArrayHasKey('errors', $body); } public function testCreateOrderWithMultipleTests() { $faker = Factory::create('id_ID'); // First create a patient $patientPayload = [ "PatientID" => "ORDM" . $faker->numberBetween(1, 1000). $faker->numberBetween(1, 1000), "NameFirst" => "Multi", "NameLast" => "Test", "Sex" => "2", "Birthdate" => "1985-05-15", "PatIdt" => [ "IdentifierType" => "KTP", "Identifier" => $faker->numerify('################') ] ]; $patientResult = $this->withBodyFormat('json')->call('post', 'api/patient', $patientPayload); $patientBody = json_decode($patientResult->getBody(), true); $internalPID = $patientBody['data']['InternalPID'] ?? null; $this->assertNotNull($internalPID, 'Failed to create test patient'); // Get available tests $testsResult = $this->call('get', 'api/test'); $testsBody = json_decode($testsResult->getBody(), true); $availableTests = $testsBody['data'] ?? []; if (count($availableTests) < 2) { $this->markTestSkipped('Need at least 2 tests for this test'); } $testSiteID1 = $availableTests[0]['TestSiteID']; $testSiteID2 = $availableTests[1]['TestSiteID']; // Create order with multiple tests $payload = [ 'InternalPID' => $internalPID, 'Priority' => 'S', 'Comment' => 'Urgent order for multiple tests', 'Tests' => [ ['TestSiteID' => $testSiteID1], ['TestSiteID' => $testSiteID2] ] ]; $result = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload); $result->assertStatus(201); $body = json_decode($result->getBody(), true); $this->assertEquals('success', $body['status']); $this->assertGreaterThanOrEqual(1, count($body['data']['Specimens']), 'Should have at least one specimen'); $this->assertGreaterThanOrEqual(2, count($body['data']['Tests']), 'Should have at least two tests'); } }