/** * Descomplicar® Crescimento Digital * https://descomplicar.pt */ assertTrue(has_action('wp_ajax_care_booking_get_restrictions'), 'AJAX handler should be registered'); $this->assertFalse(has_action('wp_ajax_nopriv_care_booking_get_restrictions'), 'Non-privileged AJAX should not be registered'); } /** * Test successful request returns correct structure */ public function test_successful_request_structure() { // Set up admin user $this->set_current_user($this->admin_user_id); // Create test restrictions $this->create_test_doctor_restriction(999, true); $this->create_test_service_restriction(888, 999, false); // Mock AJAX request $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'all' ]; // Capture AJAX response ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) { // Expected for wp_die() in AJAX handlers } $response = ob_get_clean(); $data = json_decode($response, true); // Test response structure according to contract $this->assert_ajax_response($data, true); $this->assertArrayHasKey('restrictions', $data['data']); $this->assertArrayHasKey('total', $data['data']); $this->assertIsArray($data['data']['restrictions']); $this->assertIsInt($data['data']['total']); // Test restriction object structure $this->assertGreaterThan(0, count($data['data']['restrictions'])); $restriction = $data['data']['restrictions'][0]; $this->assertArrayHasKey('id', $restriction); $this->assertArrayHasKey('restriction_type', $restriction); $this->assertArrayHasKey('target_id', $restriction); $this->assertArrayHasKey('doctor_id', $restriction); $this->assertArrayHasKey('is_blocked', $restriction); $this->assertArrayHasKey('created_at', $restriction); $this->assertArrayHasKey('updated_at', $restriction); } /** * Test filter by restriction type */ public function test_filter_by_restriction_type() { $this->set_current_user($this->admin_user_id); // Create different types $this->create_test_doctor_restriction(999, true); $this->create_test_service_restriction(888, 999, true); // Test filter by doctor $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'doctor' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Should only return doctor restrictions foreach ($data['data']['restrictions'] as $restriction) { $this->assertEquals('doctor', $restriction['restriction_type']); } // Test filter by service $_POST['restriction_type'] = 'service'; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); // Should only return service restrictions foreach ($data['data']['restrictions'] as $restriction) { $this->assertEquals('service', $restriction['restriction_type']); } } /** * Test filter by doctor for service restrictions */ public function test_filter_services_by_doctor() { $this->set_current_user($this->admin_user_id); // Create service restrictions for different doctors $this->create_test_service_restriction(888, 999, true); $this->create_test_service_restriction(887, 998, true); $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'service', 'doctor_id' => 999 ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } 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 foreach ($data['data']['restrictions'] as $restriction) { $this->assertEquals('service', $restriction['restriction_type']); $this->assertEquals(999, $restriction['doctor_id']); } } /** * Test invalid nonce returns error */ public function test_invalid_nonce_error() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => 'invalid_nonce', 'restriction_type' => 'all' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } 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() { // Create subscriber user (no manage_options capability) $subscriber_id = $this->factory->user->create(['role' => 'subscriber']); $this->set_current_user($subscriber_id); $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'all' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } 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 parameters return error */ public function test_invalid_parameters_error() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'invalid_type' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertEquals('Invalid parameters', $data['data']['message']); } /** * Test empty results return correct structure */ public function test_empty_results() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'all' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $data = json_decode($response, true); $this->assert_ajax_response($data, true); $this->assertIsArray($data['data']['restrictions']); $this->assertEmpty($data['data']['restrictions']); $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); // Create test data for ($i = 1; $i <= 50; $i++) { $this->create_test_doctor_restriction(900 + $i, $i % 2 === 0); } $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'all' ]; $start_time = microtime(true); ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); $end_time = microtime(true); $response_time = ($end_time - $start_time) * 1000; // Convert to milliseconds $this->assertLessThan(200, $response_time, 'Response time should be under 200ms according to contract'); $data = json_decode($response, true); $this->assert_ajax_response($data, true); $this->assertEquals(50, $data['data']['total']); } /** * Test JSON response format compliance */ public function test_json_response_format() { $this->set_current_user($this->admin_user_id); $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'all' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); // Test valid JSON $data = json_decode($response, true); $this->assertNotNull($data, 'Response should be valid JSON'); $this->assertEquals(JSON_ERROR_NONE, json_last_error(), 'JSON should be valid'); // Test WordPress AJAX standard format $this->assertArrayHasKey('success', $data); $this->assertArrayHasKey('data', $data); $this->assertIsBool($data['success']); } /** * Test database error handling */ public function test_database_error_handling() { $this->set_current_user($this->admin_user_id); // Mock database error by temporarily corrupting table name global $wpdb; $original_prefix = $wpdb->prefix; $wpdb->prefix = 'invalid_prefix_'; $_POST = [ 'action' => 'care_booking_get_restrictions', 'nonce' => $this->mock_wp_nonce('care_booking_get_restrictions'), 'restriction_type' => 'all' ]; ob_start(); try { do_action('wp_ajax_care_booking_get_restrictions'); } catch (WPAjaxDieStopException $e) {} $response = ob_get_clean(); // Restore database prefix $wpdb->prefix = $original_prefix; $data = json_decode($response, true); $this->assert_ajax_response($data, false); $this->assertContains('Database error', $data['data']['message']); } }