$default ) { $out[ $name ] = array_key_exists( $name, $atts ) ? $atts[ $name ] : $default; } return $out; } } if ( ! function_exists( 'register_rest_route' ) ) { function register_rest_route( $namespace, $route, $args = array(), $override = false ) { return true; } } if ( ! function_exists( 'rest_url' ) ) { function rest_url( $path = '' ) { return 'https://example.com/wp-json/' . ltrim( $path, '/' ); } } if ( ! function_exists( 'esc_url_raw' ) ) { function esc_url_raw( $url, $protocols = null ) { return filter_var( $url, FILTER_SANITIZE_URL ) ?: ''; } } if ( ! function_exists( 'esc_attr' ) ) { function esc_attr( $text ) { return htmlspecialchars( $text, ENT_QUOTES, 'UTF-8' ); } } if ( ! function_exists( 'esc_html' ) ) { function esc_html( $text ) { return htmlspecialchars( $text, ENT_QUOTES, 'UTF-8' ); } } if ( ! function_exists( 'esc_html__' ) ) { function esc_html__( $text, $domain = 'default' ) { return htmlspecialchars( $text, ENT_QUOTES, 'UTF-8' ); } } if ( ! function_exists( 'esc_html_e' ) ) { function esc_html_e( $text, $domain = 'default' ) { echo htmlspecialchars( $text, ENT_QUOTES, 'UTF-8' ); } } if ( ! function_exists( '__' ) ) { function __( $text, $domain = 'default' ) { return $text; } } if ( ! function_exists( 'is_admin' ) ) { function is_admin() { global $_test_is_admin; return ! empty( $_test_is_admin ); } } if ( ! function_exists( 'wp_enqueue_style' ) ) { function wp_enqueue_style( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' ) { return true; } } if ( ! function_exists( 'wp_enqueue_script' ) ) { function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) { return true; } } if ( ! function_exists( 'wp_localize_script' ) ) { function wp_localize_script( $handle, $object_name, $l10n ) { return true; } } if ( ! function_exists( 'get_transient' ) ) { function get_transient( $transient ) { global $_test_transients; return isset( $_test_transients[ $transient ] ) ? $_test_transients[ $transient ] : false; } } if ( ! function_exists( 'set_transient' ) ) { function set_transient( $transient, $value, $expiration = 0 ) { global $_test_transients; $_test_transients[ $transient ] = $value; return true; } } if ( ! function_exists( 'delete_transient' ) ) { function delete_transient( $transient ) { global $_test_transients; unset( $_test_transients[ $transient ] ); return true; } } if ( ! function_exists( 'register_activation_hook' ) ) { function register_activation_hook( $file, $callback ) { return true; } } if ( ! function_exists( 'register_deactivation_hook' ) ) { function register_deactivation_hook( $file, $callback ) { return true; } } if ( ! function_exists( 'delete_option' ) ) { function delete_option( $option ) { global $_test_options; unset( $_test_options[ $option ] ); return true; } } if ( ! function_exists( 'wp_cache_flush' ) ) { function wp_cache_flush() { return true; } } if ( ! function_exists( 'get_option' ) ) { function get_option( $option, $default = false ) { global $_test_options; return isset( $_test_options[ $option ] ) ? $_test_options[ $option ] : $default; } } if ( ! function_exists( 'do_action' ) ) { function do_action( $tag, ...$args ) { return null; } } // WP_REST_Request stub used by REST controller tests. if ( ! class_exists( 'WP_REST_Request' ) ) { class WP_REST_Request { /** @var array */ private array $params = array(); private string $method; public function __construct( string $method = 'GET', string $route = '' ) { $this->method = $method; } /** * @param string $key * @param mixed $value */ public function set_param( string $key, $value ): void { $this->params[ $key ] = $value; } /** * @param string $key * @return mixed */ public function get_param( string $key ) { return $this->params[ $key ] ?? null; } /** @return array */ public function get_params(): array { return $this->params; } } } // WP_REST_Response stub. if ( ! class_exists( 'WP_REST_Response' ) ) { class WP_REST_Response { /** @var mixed */ public $data; public int $status; /** * @param mixed $data */ public function __construct( $data = null, int $status = 200 ) { $this->data = $data; $this->status = $status; } /** @return mixed */ public function get_data() { return $this->data; } public function get_status(): int { return $this->status; } } } // WP_Error stub. if ( ! class_exists( 'WP_Error' ) ) { class WP_Error { /** @var array */ public array $errors = array(); /** @var array */ public array $error_data = array(); /** * @param mixed $data */ public function __construct( string $code = '', string $message = '', $data = '' ) { if ( $code ) { $this->errors[ $code ][] = $message; if ( $data ) { $this->error_data[ $code ] = $data; } } } public function get_error_code(): string { $codes = array_keys( $this->errors ); return $codes ? $codes[0] : ''; } public function get_error_message( string $code = '' ): string { if ( ! $code ) { $code = $this->get_error_code(); } return isset( $this->errors[ $code ] ) ? $this->errors[ $code ][0] : ''; } } } if ( ! function_exists( 'is_wp_error' ) ) { function is_wp_error( $thing ): bool { return ( $thing instanceof WP_Error ); } } // ── Load plugin classes for testing ────────────────────────────────── // The autoloader resolves PRC_ classes from includes/ — register it now. require_once PRC_PLUGIN_DIR . 'includes/class-prc-autoloader.php'; PRC_Autoloader::register(); // Load pure classes explicitly (no WP hooks fire at require time). require_once PRC_PLUGIN_DIR . 'includes/class-prc-math.php'; require_once PRC_PLUGIN_DIR . 'includes/class-prc-default-presets.php'; require_once PRC_PLUGIN_DIR . 'includes/class-prc-calculator.php'; require_once PRC_PLUGIN_DIR . 'includes/class-prc-preset-provider.php'; require_once PRC_PLUGIN_DIR . 'includes/api/class-prc-rest-controller.php'; require_once PRC_PLUGIN_DIR . 'includes/frontend/class-prc-shortcode.php';