/** * Descomplicar® Crescimento Digital * https://descomplicar.pt */ assertTrue(has_action('wp_ajax_care_booking_get_entities'), 'AJAX handler should be registered'); $this->assertFalse(has_action('wp_ajax_nopriv_care_booking_get_entities'), 'Non-privileged AJAX should not be registered'); } /** * Test successful doctors retrieval */ public function test_successful_doctors_retrieval() { $this->set_current_user($this->admin_user_id); // Create some test restrictions to show restriction status $this->create_test_doctor_restriction(999, true); $this->create_test_doctor_restriction(998, false); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Test response structure according to contract $this->assertArrayHasKey('entities', $data['data']); $this->assertArrayHasKey('total', $data['data']); $this->assertIsArray($data['data']['entities']); $this->assertIsInt($data['data']['total']); // Test entity structure if entities exist if (!empty($data['data']['entities'])) { $entity = $data['data']['entities'][0]; $this->assertArrayHasKey('id', $entity); $this->assertArrayHasKey('name', $entity); $this->assertArrayHasKey('email', $entity); $this->assertArrayHasKey('is_blocked', $entity); $this->assertIsBool($entity['is_blocked']); } } /** * Test successful services retrieval */ public function test_successful_services_retrieval() { $this->set_current_user($this->admin_user_id); // Create service restriction for testing status $this->create_test_service_restriction(888, 999, true); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'services' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); $this->assertArrayHasKey('entities', $data['data']); $this->assertArrayHasKey('total', $data['data']); // Test service entity structure if services exist if (!empty($data['data']['entities'])) { $service = $data['data']['entities'][0]; $this->assertArrayHasKey('id', $service); $this->assertArrayHasKey('name', $service); $this->assertArrayHasKey('doctor_id', $service); $this->assertArrayHasKey('is_blocked', $service); } } /** * Test services retrieval filtered by doctor */ public function test_services_filtered_by_doctor() { $this->set_current_user($this->admin_user_id); // Create services for different doctors $this->create_test_service_restriction(888, 999, true); $this->create_test_service_restriction(887, 998, false); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'services', 'doctor_id' => 999 ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Should only return services for doctor 999 if (!empty($data['data']['entities'])) { foreach ($data['data']['entities'] as $service) { $this->assertEquals(999, $service['doctor_id'], 'All services should belong to doctor 999'); } } } /** * Test invalid nonce returns error */ public function test_invalid_nonce_error() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => 'invalid_nonce', 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertEquals('Invalid nonce', $data['data']['message']); } /** * Test insufficient permissions returns error */ public function test_insufficient_permissions_error() { $subscriber_id = $this->factory->user->create(['role' => 'subscriber']); $this->set_current_user($subscriber_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertEquals('Insufficient permissions', $data['data']['message']); } /** * Test invalid entity type returns error */ public function test_invalid_entity_type_error() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'invalid_type' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertEquals('Invalid entity type', $data['data']['message']); } /** * Test missing entity_type parameter */ public function test_missing_entity_type_parameter() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities') // Missing entity_type parameter ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertEquals('Missing entity_type parameter', $data['data']['message']); } /** * Test KiviCare plugin not available */ public function test_kivicare_not_available() { $this->set_current_user($this->admin_user_id); // Mock KiviCare as not available add_filter('pre_option_active_plugins', function($plugins) { return []; // No active plugins }); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); remove_all_filters('pre_option_active_plugins'); $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertEquals('KiviCare plugin not available', $data['data']['message']); } /** * Test empty results return correct structure */ public function test_empty_results() { $this->set_current_user($this->admin_user_id); // Mock empty KiviCare tables global $wpdb; $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); $this->assertIsArray($data['data']['entities']); $this->assertEquals(0, $data['data']['total']); } /** * Test response time performance requirement */ public function test_response_time_performance() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; $start_time = microtime(true); ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $end_time = microtime(true); $response_time = ($end_time - $start_time) * 1000; $this->assertLessThan(400, $response_time, 'Response time should be under 400ms according to contract'); $data = json_decode($response, true); $this->assert_ajax_response($data, true); } /** * Test restriction status accuracy */ public function test_restriction_status_accuracy() { $this->set_current_user($this->admin_user_id); // Create known restrictions $this->create_test_doctor_restriction(999, true); // Blocked $this->create_test_doctor_restriction(998, false); // Not blocked $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Find our test doctors and verify restriction status foreach ($data['data']['entities'] as $doctor) { if ($doctor['id'] == 999) { $this->assertTrue($doctor['is_blocked'], 'Doctor 999 should be marked as blocked'); } elseif ($doctor['id'] == 998) { $this->assertFalse($doctor['is_blocked'], 'Doctor 998 should not be marked as blocked'); } } } /** * Test service restriction status with doctor context */ public function test_service_restriction_status_with_doctor() { $this->set_current_user($this->admin_user_id); // Create service restrictions for specific doctors $this->create_test_service_restriction(888, 999, true); // Service 888 blocked for doctor 999 $this->create_test_service_restriction(888, 998, false); // Service 888 not blocked for doctor 998 // Get services for doctor 999 $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'services', 'doctor_id' => 999 ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Check service 888 status for doctor 999 foreach ($data['data']['entities'] as $service) { if ($service['id'] == 888) { $this->assertTrue($service['is_blocked'], 'Service 888 should be blocked for doctor 999'); } } // Get services for doctor 998 $_POST['doctor_id'] = 998; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Check service 888 status for doctor 998 foreach ($data['data']['entities'] as $service) { if ($service['id'] == 888) { $this->assertFalse($service['is_blocked'], 'Service 888 should not be blocked for doctor 998'); } } } /** * Test database error handling */ public function test_database_error_handling() { $this->set_current_user($this->admin_user_id); // Mock database error global $wpdb; $original_prefix = $wpdb->prefix; $wpdb->prefix = 'invalid_prefix_'; $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); // Restore prefix $wpdb->prefix = $original_prefix; $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertContains('Database error', $data['data']['message']); } /** * Test large dataset handling */ public function test_large_dataset_handling() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; // This test verifies the system can handle large result sets // without timing out or running into memory issues $start_memory = memory_get_usage(); ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $end_memory = memory_get_usage(); $memory_used = $end_memory - $start_memory; // Memory usage should be reasonable (less than 10MB for the operation) $this->assertLessThan(10 * 1024 * 1024, $memory_used, 'Memory usage should be reasonable'); $data = json_decode($response, true); $this->assert_ajax_response($data, true); } /** * Test concurrent request handling */ public function test_concurrent_request_handling() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_entities', 'nonce' => $this->mock_wp_nonce('care_booking_get_entities'), 'entity_type' => 'doctors' ]; // Simulate multiple concurrent requests $responses = []; for ($i = 0; $i < 3; $i++) { ob_start(); try { do_action('wp_ajax_care_booking_get_entities'); } catch (WPAjaxDieStopException $e) {} $responses[] = ob_get_clean(); } // All responses should be valid and consistent foreach ($responses as $response) { $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Structure should be consistent across all responses $this->assertArrayHasKey('entities', $data['data']); $this->assertArrayHasKey('total', $data['data']); } } }