Files
care-book-block-ultimate/BACKUP-ESSENTIALS/PRODUCTION-READY/care-booking-block-ultimate/tests/integration/test-frontend-javascript.php
Emanuel Almeida 38bb926742 chore: add spec-kit and standardize signatures
- 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>
2025-09-12 01:27:34 +01:00

374 lines
14 KiB
PHP

/**
* Descomplicar® Crescimento Digital
* https://descomplicar.pt
*/
<?php
/**
* Integration test for frontend JavaScript graceful degradation (T032)
*
* @package CareBookingBlock
*/
/**
* Test frontend JavaScript enqueuing and configuration
*/
class Test_Frontend_JavaScript extends Care_Booking_Test_Case
{
/**
* Test frontend scripts are enqueued on appropriate pages
*/
public function test_frontend_scripts_enqueued()
{
// Mock KiviCare as active
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare_booking]'
];
$integration = $this->plugin->kivicare_integration;
// Trigger script enqueuing
do_action('wp_enqueue_scripts');
// Check if script is registered
$this->assertTrue(wp_script_is('care-booking-frontend', 'registered'),
'Frontend script should be registered');
// Note: wp_script_is('enqueued') might not work in test environment
// as it depends on KiviCare being active and page content detection
}
/**
* Test script localization with correct configuration
*/
public function test_script_localization()
{
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare]'
];
$integration = $this->plugin->kivicare_integration;
// Mock wp_localize_script to capture data
$localized_data = null;
add_filter('wp_localize_script_care-booking-frontend_careBookingConfig', function($data) use (&$localized_data) {
$localized_data = $data;
return $data;
});
// Trigger script enqueuing
do_action('wp_enqueue_scripts');
// If script was enqueued and localized, check the data
if ($localized_data) {
$this->assertArrayHasKey('ajaxurl', $localized_data, 'Should include AJAX URL');
$this->assertArrayHasKey('nonce', $localized_data, 'Should include nonce');
$this->assertArrayHasKey('debug', $localized_data, 'Should include debug flag');
$this->assertArrayHasKey('fallbackEnabled', $localized_data, 'Should include fallback flag');
$this->assertArrayHasKey('retryAttempts', $localized_data, 'Should include retry attempts');
$this->assertArrayHasKey('selectors', $localized_data, 'Should include selectors');
// Check selectors structure
$this->assertArrayHasKey('doctors', $localized_data['selectors'], 'Should include doctor selectors');
$this->assertArrayHasKey('services', $localized_data['selectors'], 'Should include service selectors');
$this->assertArrayHasKey('forms', $localized_data['selectors'], 'Should include form selectors');
}
}
/**
* Test should_load_frontend_scripts logic
*/
public function test_should_load_frontend_scripts_logic()
{
$integration = $this->plugin->kivicare_integration;
// Use reflection to access private method
$reflection = new ReflectionClass($integration);
$method = $reflection->getMethod('should_load_frontend_scripts');
$method->setAccessible(true);
global $post;
// Test with KiviCare shortcode
$post = (object) [
'ID' => 123,
'post_content' => 'Some content [kivicare] more content'
];
$should_load = $method->invoke($integration);
$this->assertTrue($should_load, 'Should load scripts on pages with kivicare shortcode');
// Test with KiviCare block
$post = (object) [
'ID' => 124,
'post_content' => '<!-- wp:kivicare/booking --><div>Booking form</div><!-- /wp:kivicare/booking -->'
];
$should_load = $method->invoke($integration);
$this->assertTrue($should_load, 'Should load scripts on pages with kivicare block');
// Test with regular content
$post = (object) [
'ID' => 125,
'post_content' => 'Regular page content without KiviCare'
];
$should_load = $method->invoke($integration);
$this->assertFalse($should_load, 'Should not load scripts on regular pages');
// Test with URL parameters
$_GET['kivicare'] = '1';
$should_load = $method->invoke($integration);
$this->assertTrue($should_load, 'Should load scripts when URL contains kivicare parameter');
unset($_GET['kivicare']);
$_GET['booking'] = '1';
$should_load = $method->invoke($integration);
$this->assertTrue($should_load, 'Should load scripts when URL contains booking parameter');
unset($_GET['booking']);
}
/**
* Test frontend script file exists and has correct content structure
*/
public function test_frontend_script_file_structure()
{
$script_path = CARE_BOOKING_BLOCK_PLUGIN_DIR . 'public/js/frontend.js';
$this->assertFileExists($script_path, 'Frontend JavaScript file should exist');
$script_content = file_get_contents($script_path);
// Check for main structure
$this->assertStringContainsString('CareBooking', $script_content,
'Should contain CareBooking object');
$this->assertStringContainsString('init:', $script_content,
'Should contain init method');
$this->assertStringContainsString('setupObservers:', $script_content,
'Should contain setupObservers method');
$this->assertStringContainsString('enhanceExistingElements:', $script_content,
'Should contain enhanceExistingElements method');
// Check for graceful degradation features
$this->assertStringContainsString('setupFallbacks:', $script_content,
'Should contain setupFallbacks method');
$this->assertStringContainsString('MutationObserver', $script_content,
'Should use MutationObserver for dynamic content');
$this->assertStringContainsString('ajaxError', $script_content,
'Should handle AJAX errors');
// Check for validation features
$this->assertStringContainsString('validateBookingForm:', $script_content,
'Should contain form validation');
$this->assertStringContainsString('showLoadingState:', $script_content,
'Should contain loading state management');
// Check for offline detection
$this->assertStringContainsString('online offline', $script_content,
'Should handle online/offline events');
}
/**
* Test script dependencies are correct
*/
public function test_script_dependencies()
{
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare]'
];
// Trigger script enqueuing
do_action('wp_enqueue_scripts');
// Check if jQuery is a dependency
global $wp_scripts;
if (isset($wp_scripts->registered['care-booking-frontend'])) {
$script = $wp_scripts->registered['care-booking-frontend'];
$this->assertContains('jquery', $script->deps, 'Should depend on jQuery');
$this->assertEquals(CARE_BOOKING_BLOCK_VERSION, $script->ver, 'Should use plugin version');
$this->assertTrue($script->extra['in_footer'], 'Should load in footer');
}
}
/**
* Test script configuration values
*/
public function test_script_configuration_values()
{
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare]'
];
$integration = $this->plugin->kivicare_integration;
// Capture localized data
$captured_data = null;
// Mock wp_localize_script
add_filter('wp_scripts_print_extra_script', function($output, $handle) use (&$captured_data) {
if ($handle === 'care-booking-frontend') {
// Extract config from JavaScript
if (preg_match('/careBookingConfig\s*=\s*({.+?});/', $output, $matches)) {
$captured_data = json_decode($matches[1], true);
}
}
return $output;
}, 10, 2);
// Trigger script enqueuing
do_action('wp_enqueue_scripts');
// If we captured data, validate it
if ($captured_data) {
// Check AJAX URL
$this->assertStringContainsString('admin-ajax.php', $captured_data['ajaxurl'],
'AJAX URL should point to admin-ajax.php');
// Check nonce is valid
$this->assertTrue(wp_verify_nonce($captured_data['nonce'], 'care_booking_frontend'),
'Nonce should be valid');
// Check boolean values
$this->assertIsBool($captured_data['debug'], 'Debug should be boolean');
$this->assertIsBool($captured_data['fallbackEnabled'], 'Fallback should be boolean');
// Check numeric values
$this->assertIsNumeric($captured_data['retryAttempts'], 'Retry attempts should be numeric');
$this->assertIsNumeric($captured_data['retryDelay'], 'Retry delay should be numeric');
$this->assertGreaterThan(0, $captured_data['retryAttempts'], 'Should have positive retry attempts');
$this->assertGreaterThan(0, $captured_data['retryDelay'], 'Should have positive retry delay');
// Check selectors
$this->assertIsArray($captured_data['selectors'], 'Selectors should be array');
$this->assertArrayHasKey('doctors', $captured_data['selectors']);
$this->assertArrayHasKey('services', $captured_data['selectors']);
$this->assertArrayHasKey('forms', $captured_data['selectors']);
// Check selector format
$this->assertStringContainsString('.kivicare-doctor', $captured_data['selectors']['doctors'],
'Doctor selectors should include .kivicare-doctor');
$this->assertStringContainsString('.kivicare-service', $captured_data['selectors']['services'],
'Service selectors should include .kivicare-service');
}
}
/**
* Test script only loads when KiviCare is active
*/
public function test_script_kivicare_dependency()
{
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare]'
];
$integration = $this->plugin->kivicare_integration;
// Mock KiviCare as inactive
$reflection = new ReflectionClass($integration);
$method = $reflection->getMethod('is_kivicare_active');
$method->setAccessible(true);
// The method checks for actual plugin files, so in test environment
// it will likely return false, which is correct behavior
// Trigger script enqueuing
do_action('wp_enqueue_scripts');
// Script should not be enqueued if KiviCare is not active
// This is mainly to test the logic path doesn't cause errors
$this->assertTrue(true, 'Script enqueuing should handle inactive KiviCare gracefully');
}
/**
* Test admin area script exclusion
*/
public function test_admin_area_script_exclusion()
{
// Mock admin area
set_current_screen('edit-post');
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare]'
];
// Trigger script enqueuing
do_action('wp_enqueue_scripts');
// Script should not be enqueued in admin area
$this->assertFalse(wp_script_is('care-booking-frontend', 'enqueued'),
'Frontend script should not be enqueued in admin area');
}
/**
* Test script file is minified in production
*/
public function test_script_optimization()
{
$script_path = CARE_BOOKING_BLOCK_PLUGIN_DIR . 'public/js/frontend.js';
$script_content = file_get_contents($script_path);
// In development, script should be readable
if (defined('WP_DEBUG') && WP_DEBUG) {
$this->assertGreaterThan(100, substr_count($script_content, "\n"),
'Development script should have line breaks');
$this->assertStringContainsString(' ', $script_content,
'Development script should have indentation');
}
// Script should have proper structure regardless of minification
$this->assertStringContainsString('CareBooking', $script_content,
'Script should contain CareBooking object');
$this->assertStringContainsString('jQuery', $script_content,
'Script should reference jQuery');
}
/**
* Test error handling in script enqueuing
*/
public function test_script_enqueuing_error_handling()
{
global $post;
$post = (object) [
'ID' => 123,
'post_content' => '[kivicare]'
];
// Mock file not found scenario by temporarily renaming the file
$script_path = CARE_BOOKING_BLOCK_PLUGIN_DIR . 'public/js/frontend.js';
$temp_path = CARE_BOOKING_BLOCK_PLUGIN_DIR . 'public/js/frontend.js.temp';
if (file_exists($script_path)) {
rename($script_path, $temp_path);
}
// Trigger script enqueuing - should not cause fatal errors
ob_start();
do_action('wp_enqueue_scripts');
$output = ob_get_clean();
// Restore file
if (file_exists($temp_path)) {
rename($temp_path, $script_path);
}
// Should not produce PHP errors
$this->assertStringNotContainsString('Fatal error', $output,
'Should handle missing script file gracefully');
$this->assertStringNotContainsString('Warning:', $output,
'Should handle missing script file without warnings');
}
}