/** * Descomplicar® Crescimento Digital * https://descomplicar.pt */ markTestIncomplete( 'Encounters GET endpoint not implemented yet - TDD RED phase' ); // ARRANGE: Authenticated doctor wp_set_current_user( $this->doctor_user ); // ACT: Make GET request to encounters endpoint $response = $this->make_request( '/wp-json/kivicare/v1/encounters' ); // ASSERT: Response contract $this->assertRestResponse( $response, 200 ); $data = $response->get_data(); $this->assertIsArray( $data ); // Validate pagination structure if ( ! empty( $data ) ) { $this->assertArrayHasKey( 'data', $data ); $this->assertArrayHasKey( 'total', $data ); $this->assertArrayHasKey( 'page', $data ); $this->assertArrayHasKey( 'per_page', $data ); // Validate encounter data structure $encounter = $data['data'][0]; $this->assertEncounterStructure( $encounter ); } } /** * Test POST /wp-json/kivicare/v1/encounters endpoint contract. * * @test */ public function test_create_encounter_endpoint_contract() { // This test will fail initially as the endpoint doesn't exist yet $this->markTestIncomplete( 'Encounters POST endpoint not implemented yet - TDD RED phase' ); // ARRANGE: Valid encounter data $clinic_id = $this->create_test_clinic(); $appointment_id = $this->create_test_appointment( $clinic_id, $this->doctor_user, $this->patient_user ); $encounter_data = array( 'encounter_date' => gmdate( 'Y-m-d' ), 'appointment_id' => $appointment_id, 'patient_id' => $this->patient_user, 'doctor_id' => $this->doctor_user, 'clinic_id' => $clinic_id, 'description' => 'Patient presents with mild fever and fatigue. Diagnosed with common cold.', 'status' => 1, 'chief_complaint' => 'Fever and fatigue', 'diagnosis' => 'Common cold (J00)', 'treatment_plan' => 'Rest, fluids, symptomatic treatment', ); // ACT: Make POST request as doctor $response = $this->make_request( '/wp-json/kivicare/v1/encounters', 'POST', $encounter_data, $this->doctor_user ); // ASSERT: Response contract $this->assertRestResponse( $response, 201 ); $data = $response->get_data(); $this->assertEncounterStructure( $data ); $this->assertEquals( $encounter_data['appointment_id'], $data['appointment_id'] ); $this->assertEquals( $encounter_data['patient_id'], $data['patient_id'] ); $this->assertIsInt( $data['id'] ); $this->assertGreaterThan( 0, $data['id'] ); } /** * Test POST /wp-json/kivicare/v1/encounters with invalid data. * * @test */ public function test_create_encounter_invalid_data() { // This test will fail initially as the endpoint doesn't exist yet $this->markTestIncomplete( 'Encounters POST validation not implemented yet - TDD RED phase' ); // ARRANGE: Invalid encounter data $invalid_data = array( 'encounter_date' => 'invalid-date', 'appointment_id' => 'not_a_number', 'description' => '', // Empty description should fail ); // ACT: Make POST request with invalid data $response = $this->make_request( '/wp-json/kivicare/v1/encounters', 'POST', $invalid_data, $this->doctor_user ); // ASSERT: Validation error contract $this->assertRestResponse( $response, 400 ); $data = $response->get_data(); $this->assertArrayHasKey( 'code', $data ); $this->assertEquals( 'rest_invalid_param', $data['code'] ); } /** * Test GET /wp-json/kivicare/v1/encounters/{id} endpoint contract. * * @test */ public function test_get_encounter_by_id_endpoint_contract() { // This test will fail initially as the endpoint doesn't exist yet $this->markTestIncomplete( 'Encounter by ID endpoint not implemented yet - TDD RED phase' ); // ARRANGE: Existing encounter $clinic_id = $this->create_test_clinic(); $appointment_id = $this->create_test_appointment( $clinic_id, $this->doctor_user, $this->patient_user ); $encounter_id = $this->create_test_encounter( $appointment_id ); // ACT: Make GET request for specific encounter $response = $this->make_request( "/wp-json/kivicare/v1/encounters/{$encounter_id}", 'GET', array(), $this->doctor_user ); // ASSERT: Response contract $this->assertRestResponse( $response, 200 ); $data = $response->get_data(); $this->assertEncounterStructure( $data ); $this->assertEquals( $encounter_id, $data['id'] ); } /** * Test PUT /wp-json/kivicare/v1/encounters/{id} endpoint contract. * * @test */ public function test_update_encounter_endpoint_contract() { // This test will fail initially as the endpoint doesn't exist yet $this->markTestIncomplete( 'Encounter PUT endpoint not implemented yet - TDD RED phase' ); // ARRANGE: Existing encounter and update data $clinic_id = $this->create_test_clinic(); $appointment_id = $this->create_test_appointment( $clinic_id, $this->doctor_user, $this->patient_user ); $encounter_id = $this->create_test_encounter( $appointment_id ); $update_data = array( 'description' => 'Updated encounter notes with additional observations.', 'diagnosis' => 'Viral upper respiratory infection (J06.9)', 'treatment_plan' => 'Updated treatment plan with additional recommendations.', 'status' => 1, ); // ACT: Make PUT request to update encounter $response = $this->make_request( "/wp-json/kivicare/v1/encounters/{$encounter_id}", 'PUT', $update_data, $this->doctor_user ); // ASSERT: Response contract $this->assertRestResponse( $response, 200 ); $data = $response->get_data(); $this->assertEncounterStructure( $data ); $this->assertEquals( $update_data['description'], $data['description'] ); $this->assertEquals( $update_data['diagnosis'], $data['diagnosis'] ); } /** * Test GET /wp-json/kivicare/v1/encounters/{id}/prescriptions endpoint contract. * * @test */ public function test_get_encounter_prescriptions_contract() { // This test will fail initially as the endpoint doesn't exist yet $this->markTestIncomplete( 'Encounter prescriptions endpoint not implemented yet - TDD RED phase' ); // ARRANGE: Encounter with prescriptions $clinic_id = $this->create_test_clinic(); $appointment_id = $this->create_test_appointment( $clinic_id, $this->doctor_user, $this->patient_user ); $encounter_id = $this->create_test_encounter( $appointment_id ); // ACT: Make GET request for encounter prescriptions $response = $this->make_request( "/wp-json/kivicare/v1/encounters/{$encounter_id}/prescriptions", 'GET', array(), $this->doctor_user ); // ASSERT: Response contract $this->assertRestResponse( $response, 200 ); $data = $response->get_data(); $this->assertIsArray( $data ); if ( ! empty( $data ) ) { $prescription = $data[0]; $this->assertPrescriptionStructure( $prescription ); $this->assertEquals( $encounter_id, $prescription['encounter_id'] ); } } /** * Test medical encounter workflow integration. * * @test */ public function test_encounter_workflow_contract() { // This test will fail initially as the workflow isn't implemented $this->markTestIncomplete( 'Encounter workflow not implemented yet - TDD RED phase' ); // ARRANGE: Complete appointment to encounter workflow $clinic_id = $this->create_test_clinic(); $appointment_id = $this->create_test_appointment( $clinic_id, $this->doctor_user, $this->patient_user ); // ACT: Create encounter from appointment $encounter_data = array( 'appointment_id' => $appointment_id, 'description' => 'Patient consultation completed successfully.', 'status' => 1, ); $response = $this->make_request( '/wp-json/kivicare/v1/encounters', 'POST', $encounter_data, $this->doctor_user ); // ASSERT: Encounter creation triggers appointment status update $this->assertRestResponse( $response, 201 ); $encounter = $response->get_data(); $this->assertEncounterStructure( $encounter ); // Verify appointment status was updated $appointment_response = $this->make_request( "/wp-json/kivicare/v1/appointments/{$appointment_id}", 'GET', array(), $this->doctor_user ); $appointment = $appointment_response->get_data(); $this->assertEquals( 'completed', $appointment['status'] ); } /** * Test encounter access permissions by role. * * @test */ public function test_encounter_permissions_contract() { // This test will fail initially as permissions aren't implemented $this->markTestIncomplete( 'Encounter permissions not implemented yet - TDD RED phase' ); // ARRANGE: Encounter created by doctor $clinic_id = $this->create_test_clinic(); $appointment_id = $this->create_test_appointment( $clinic_id, $this->doctor_user, $this->patient_user ); $encounter_id = $this->create_test_encounter( $appointment_id ); // ACT & ASSERT: Patient should be able to view their encounters (read-only) $response = $this->make_request( "/wp-json/kivicare/v1/encounters/{$encounter_id}", 'GET', array(), $this->patient_user ); $this->assertRestResponse( $response, 200 ); // ACT & ASSERT: Patient should not be able to modify encounters $response = $this->make_request( "/wp-json/kivicare/v1/encounters/{$encounter_id}", 'PUT', array( 'description' => 'Hacked' ), $this->patient_user ); $this->assertRestResponse( $response, 403 ); // ACT & ASSERT: Receptionist should not access medical encounters $response = $this->make_request( "/wp-json/kivicare/v1/encounters/{$encounter_id}", 'GET', array(), $this->receptionist_user ); $this->assertRestResponse( $response, 403 ); } /** * Helper method to create test encounter. * * @param int $appointment_id Appointment ID. * @return int Encounter ID. */ private function create_test_encounter( $appointment_id ) { global $wpdb; $encounter_data = array( 'encounter_date' => gmdate( 'Y-m-d' ), 'clinic_id' => get_option( 'kivicare_api_test_clinic_id', 1 ), 'doctor_id' => $this->doctor_user, 'patient_id' => $this->patient_user, 'appointment_id' => $appointment_id, 'description' => 'Test medical encounter', 'status' => 1, 'added_by' => $this->doctor_user, 'created_at' => current_time( 'mysql' ), ); $wpdb->insert( $wpdb->prefix . 'kc_patient_encounters', $encounter_data ); return $wpdb->insert_id; } /** * Helper method to assert encounter data structure. * * @param array $encounter Encounter data to validate. */ private function assertEncounterStructure( $encounter ) { $this->assertIsArray( $encounter ); // Required fields $expected_fields = array( 'id', 'encounter_date', 'patient_id', 'doctor_id', 'clinic_id', 'appointment_id', 'description', 'status', 'created_at' ); foreach ( $expected_fields as $field ) { $this->assertArrayHasKey( $field, $encounter ); } // Data type validations $this->assertIsInt( $encounter['id'] ); $this->assertIsInt( $encounter['patient_id'] ); $this->assertIsInt( $encounter['doctor_id'] ); $this->assertIsInt( $encounter['clinic_id'] ); $this->assertIsInt( $encounter['status'] ); // Date format validation $this->assertMatchesRegularExpression( '/^\d{4}-\d{2}-\d{2}$/', $encounter['encounter_date'] ); // Optional expanded data if ( isset( $encounter['patient'] ) ) { $this->assertIsArray( $encounter['patient'] ); $this->assertArrayHasKey( 'display_name', $encounter['patient'] ); } if ( isset( $encounter['doctor'] ) ) { $this->assertIsArray( $encounter['doctor'] ); $this->assertArrayHasKey( 'display_name', $encounter['doctor'] ); } if ( isset( $encounter['prescriptions'] ) ) { $this->assertIsArray( $encounter['prescriptions'] ); } } /** * Helper method to assert prescription data structure. * * @param array $prescription Prescription data to validate. */ private function assertPrescriptionStructure( $prescription ) { $this->assertIsArray( $prescription ); $expected_fields = array( 'id', 'encounter_id', 'patient_id', 'name', 'frequency', 'duration', 'instruction', 'created_at' ); foreach ( $expected_fields as $field ) { $this->assertArrayHasKey( $field, $prescription ); } $this->assertIsInt( $prescription['id'] ); $this->assertIsInt( $prescription['encounter_id'] ); $this->assertIsInt( $prescription['patient_id'] ); $this->assertIsString( $prescription['name'] ); } }