- Added GitHub spec-kit for development workflow - Standardized file signatures to Descomplicar® format - Updated development configuration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
361 lines
12 KiB
PHP
361 lines
12 KiB
PHP
/**
|
|
* Descomplicar® Crescimento Digital
|
|
* https://descomplicar.pt
|
|
*/
|
|
|
|
<?php
|
|
/**
|
|
* Contract test for wp_ajax_care_booking_get_restrictions endpoint
|
|
*
|
|
* @package CareBookingBlock
|
|
*/
|
|
|
|
/**
|
|
* Test AJAX endpoint: wp_ajax_care_booking_get_restrictions
|
|
*/
|
|
class Test_Ajax_Get_Restrictions extends Care_Booking_Test_Case
|
|
{
|
|
|
|
/**
|
|
* Test AJAX handler is registered
|
|
*/
|
|
public function test_ajax_handler_registered()
|
|
{
|
|
$this->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']);
|
|
}
|
|
} |