From fc0c687d3d983224f00afee44e8961aee81d1b22 Mon Sep 17 00:00:00 2001 From: Jean-Michel Batty Date: Thu, 2 Oct 2025 14:21:55 -0500 Subject: [PATCH 1/6] bug fix and feature update for logs added a toggle for logging. this way we don't saturate the logs and we have fine control on the process. changed the logic around checking for store ID and isolate the check for storeID instead of having 2 checks. Also fixed a decimal rounding issue. --- .../class-helloextend-protection-admin.php | 28 +++++++++++- .../includes/class-helloextend-global.php | 44 +++++++++---------- .../class-helloextend-protection-logger.php | 27 +++++++++++- .../class-helloextend-protection-orders.php | 2 +- .../js/helloextend-global.js | 5 ++- 5 files changed, 77 insertions(+), 29 deletions(-) diff --git a/helloextend-protection/admin/class-helloextend-protection-admin.php b/helloextend-protection/admin/class-helloextend-protection-admin.php index 6248ce7..f2347ee 100644 --- a/helloextend-protection/admin/class-helloextend-protection-admin.php +++ b/helloextend-protection/admin/class-helloextend-protection-admin.php @@ -161,10 +161,12 @@ public function enqueue_scripts() $nonce = wp_create_nonce('helloextend_sync_nonce'); $helloextend_sync_batch = $this->helloextend_protection_for_woocommerce_settings_catalog_sync_options['helloextend_sync_batch']; $debug_log_enabled = $this->helloextend_protection_for_woocommerce_settings_general_options['enable_helloextend_debug']; + $log_enabled = $this->helloextend_protection_for_woocommerce_settings_general_options['enable_helloextend_log']; - wp_enqueue_script('helloextend_script'); + + wp_enqueue_script('helloextend_script'); wp_enqueue_script('helloextend_sync_script'); - wp_localize_script('helloextend_sync_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment', 'nonce', 'helloextend_sync_batch', 'debug_log_enabled')); + wp_localize_script('helloextend_sync_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment', 'nonce', 'helloextend_sync_batch', 'debug_log_enabled', 'log_enabled')); /* end for sync */ global $current_screen; @@ -480,6 +482,14 @@ public function helloextend_protection_for_woocommerce_settings_page_init() 'helloextend_setting_environment_section' // section ); + add_settings_field( + 'enable_helloextend_log', // id + 'Enable General Log', // title + array($this, 'enable_helloextend_log_callback'), // callback + 'helloextend-protection-for-woocommerce-settings-admin-general', // page + 'helloextend_setting_environment_section' // section + ); + add_settings_field( 'enable_helloextend_debug', // id 'Enable Debugging Log', // title @@ -568,6 +578,7 @@ public function helloextend_protection_for_woocommerce_settings_page_init() if (get_option('helloextend_protection_for_woocommerce_general_settings') == null) { $settings = [ 'enable_helloextend_debug' => '0', + 'enable_helloextend_log' => '0', 'helloextend_environment' => 'sandbox', 'helloextend_sandbox_store_id' => '', 'helloextend_live_store_id' => '', @@ -682,6 +693,10 @@ public function helloextend_protection_for_woocommerce_settings_sanitize($input) $sanitary_values['enable_helloextend_debug'] = $input['enable_helloextend_debug']; } + if (isset($input['enable_helloextend_log'])) { + $sanitary_values['enable_helloextend_log'] = $input['enable_helloextend_log']; + } + if (isset($input['helloextend_enable_cart_offers'])) { $sanitary_values['helloextend_enable_cart_offers'] = $input['helloextend_enable_cart_offers']; } @@ -1225,6 +1240,15 @@ public function enable_helloextend_debug_callback() ); } + public function enable_helloextend_log_callback() + { + printf( + '', + (isset($this->helloextend_protection_for_woocommerce_settings_general_options['enable_helloextend_log']) + && $this->helloextend_protection_for_woocommerce_settings_general_options['enable_helloextend_log'] === '1') ? 'checked' : '' + ); + } + public function helloextend_use_special_price_callback() { printf( diff --git a/helloextend-protection/includes/class-helloextend-global.php b/helloextend-protection/includes/class-helloextend-global.php index e67cc48..a41fb00 100644 --- a/helloextend-protection/includes/class-helloextend-global.php +++ b/helloextend-protection/includes/class-helloextend-global.php @@ -186,6 +186,9 @@ public static function helloextend_get_settings() $settings['enable_helloextend_debug'] = array_key_exists('enable_helloextend_debug', $helloextend_protection_general_settings) ? $helloextend_protection_general_settings['enable_helloextend_debug'] : 0; + $settings['enable_helloextend_log'] = array_key_exists('enable_helloextend_log', $helloextend_protection_general_settings) + ? $helloextend_protection_general_settings['enable_helloextend_log'] : 0; + /* shipping protection */ if ($helloextend_protection_shipping_protection_settings) { $settings['enable_helloextend_sp'] = array_key_exists('enable_helloextend_sp', $helloextend_protection_shipping_protection_settings) @@ -405,28 +408,25 @@ public function helloextend_init_global() $helloextend_enabled = array_key_exists('enable_helloextend', $settings) ? $settings['enable_helloextend'] : 0; $ajaxurl = admin_url('admin-ajax.php'); - if ($store_id && ($helloextend_enabled === '1')) { - wp_enqueue_script('helloextend_script'); - wp_enqueue_script('helloextend_global_script'); - wp_localize_script('helloextend_global_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment')); - - // Get the leadToken from URL parameters - $lead_token = $this->get_lead_token_from_url(); - if ($lead_token) { - // Sanitize the token for safe JavaScript output - $safe_lead_token = esc_js($lead_token); - - // Output JavaScript to console - echo "\n"; - - // next step: Run Post Purchase logic to handle lead Token - $this->helloextend_post_purchase($lead_token, $store_id, $environment, $ajaxurl); - } - } else { - HelloExtend_Protection_Logger::helloextend_log_error('Store Id missing or Extend Product Protection is disabled'); - } + if ($store_id){ + if ($helloextend_enabled === '1') { + wp_enqueue_script('helloextend_script'); + wp_enqueue_script('helloextend_global_script'); + wp_localize_script('helloextend_global_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment')); + + // Get the leadToken from URL parameters + $lead_token = $this->get_lead_token_from_url(); + if ($lead_token) { + // Sanitize the token for safe JavaScript output + $safe_lead_token = esc_js($lead_token); + + // next step: Run Post Purchase logic to handle lead Token + $this->helloextend_post_purchase($lead_token, $store_id, $environment, $ajaxurl); + } + } + } else { + HelloExtend_Protection_Logger::helloextend_log_error('Store Id is missing'); + } } /* diff --git a/helloextend-protection/includes/class-helloextend-protection-logger.php b/helloextend-protection/includes/class-helloextend-protection-logger.php index 162b17f..d41913c 100644 --- a/helloextend-protection/includes/class-helloextend-protection-logger.php +++ b/helloextend-protection/includes/class-helloextend-protection-logger.php @@ -13,12 +13,23 @@ exit; } + class HelloExtend_Protection_Logger { + public static array $settings; + + + public function __construct() + { + /* retrieve environment variables */ + self::$settings = HelloExtend_Protection_Global::helloextend_get_settings(); + } public static function helloextend_log_error( $message ) { - + if (self::$settings['enable_helloextend_log'] == 0) { + return; + } /* Get error logs from the wp_options table... */ $error_log = get_option('helloextend_error_log'); @@ -63,7 +74,9 @@ public static function helloextend_log_error( $message ) public static function helloextend_log_notice( $message ) { - + if (self::$settings['enable_helloextend_log'] == 0) { + return; + } /* Get notice logs from the wp_options table... */ $notice_log = get_option('helloextend_notice_log', true); if (! $notice_log ) { @@ -110,6 +123,12 @@ public static function helloextend_log_notice( $message ) public static function helloextend_log_debug( $message ) { + if (self::$settings['enable_helloextend_log'] == 0) { + return; + } + if (self::$settings['enable_helloextend_debug'] == 0) { + return; + } /* Get debug logs from the wp_options table... */ $debug_log = get_option('helloextend_debug_log', true); @@ -563,6 +582,10 @@ public static function helloextend_logger_add_to_new_logs( $id, $type ) public static function helloextend_logger_ajax_call() { + if (self::$settings['enable_helloextend_log'] == 0) { + return; + } + $method = isset($_POST['method']) ? sanitize_text_field(wp_unslash($_POST['method'])) : null; $message = isset($_POST['message']) ? sanitize_text_field(wp_unslash($_POST['message'])) : null; diff --git a/helloextend-protection/includes/class-helloextend-protection-orders.php b/helloextend-protection/includes/class-helloextend-protection-orders.php index 55d800a..4f742fb 100644 --- a/helloextend-protection/includes/class-helloextend-protection-orders.php +++ b/helloextend-protection/includes/class-helloextend-protection-orders.php @@ -156,7 +156,7 @@ private function is_item_helloextend_lead($item) private function get_price_in_cents($item_price) { - return (int) floatval($item_price * 100); + return (int) round((float) $item_price * 100); } private function get_purchased_leads($order) diff --git a/helloextend-protection/js/helloextend-global.js b/helloextend-protection/js/helloextend-global.js index 4406ef5..b43f774 100644 --- a/helloextend-protection/js/helloextend-global.js +++ b/helloextend-protection/js/helloextend-global.js @@ -4,7 +4,7 @@ if(!ExtendWooCommerce) { return; } - const { store_id: storeId, ajaxurl, environment, debug_log_enabled: debugLogEnabled } = ExtendWooCommerce; + const { store_id: storeId, ajaxurl, environment, debug_log_enabled: debugLogEnabled, log_enabled: logEnabled } = ExtendWooCommerce; Extend.config({ storeId, @@ -91,7 +91,8 @@ getCart, warrantyAlreadyInCart, extendAjaxLog, - debugLogEnabled + debugLogEnabled, + logEnabled } $(document).trigger('integration.extend'); From 2d0e72c50deeefd2dfc83a6d35ccbe13fa05f359 Mon Sep 17 00:00:00 2001 From: JM <100705862+jm-extend@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:49:15 -0500 Subject: [PATCH 2/6] Update class-helloextend-protection-logger.php added an initialize function to make sure the settings is never undefined. --- .../class-helloextend-protection-logger.php | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/helloextend-protection/includes/class-helloextend-protection-logger.php b/helloextend-protection/includes/class-helloextend-protection-logger.php index d41913c..6997ac9 100644 --- a/helloextend-protection/includes/class-helloextend-protection-logger.php +++ b/helloextend-protection/includes/class-helloextend-protection-logger.php @@ -16,17 +16,18 @@ class HelloExtend_Protection_Logger { - public static array $settings; - - - public function __construct() - { - /* retrieve environment variables */ - self::$settings = HelloExtend_Protection_Global::helloextend_get_settings(); - } + private static ?array $settings = null; + private static function helloextend_log_initialize(): void { + if (self::$settings === null) { + /* retrieve environment variables */ + self::$settings = HelloExtend_Protection_Global::helloextend_get_settings(); + } + } + public static function helloextend_log_error( $message ) { + self::helloextend_log_initialize(); if (self::$settings['enable_helloextend_log'] == 0) { return; } @@ -74,6 +75,7 @@ public static function helloextend_log_error( $message ) public static function helloextend_log_notice( $message ) { + self::helloextend_log_initialize(); if (self::$settings['enable_helloextend_log'] == 0) { return; } @@ -123,6 +125,7 @@ public static function helloextend_log_notice( $message ) public static function helloextend_log_debug( $message ) { + self::helloextend_log_initialize(); if (self::$settings['enable_helloextend_log'] == 0) { return; } @@ -582,6 +585,7 @@ public static function helloextend_logger_add_to_new_logs( $id, $type ) public static function helloextend_logger_ajax_call() { + self::helloextend_log_initialize(); if (self::$settings['enable_helloextend_log'] == 0) { return; } @@ -614,4 +618,4 @@ public static function helloextend_logger_ajax_call() add_action('wp_ajax_helloextend_logger_delete_single', array( $helloextendProtectionLogger, 'helloextend_logger_delete_single' )); add_action('wp_ajax_nopriv_helloextend_logger_ajax_call', array( $helloextendProtectionLogger, 'helloextend_logger_ajax_call' ), 10); -add_action('wp_ajax_helloextend_logger_ajax_call', array( $helloextendProtectionLogger, 'helloextend_logger_ajax_call' ), 10); \ No newline at end of file +add_action('wp_ajax_helloextend_logger_ajax_call', array( $helloextendProtectionLogger, 'helloextend_logger_ajax_call' ), 10); From 45c8c23084a0ef6bf58c6e095c2e08f57a9fc5c8 Mon Sep 17 00:00:00 2001 From: JM <100705862+jm-extend@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:55:29 -0500 Subject: [PATCH 3/6] Update class-helloextend-global.php added log_enabled and debug_log_enabled to the compact function --- helloextend-protection/includes/class-helloextend-global.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/helloextend-protection/includes/class-helloextend-global.php b/helloextend-protection/includes/class-helloextend-global.php index a41fb00..0220646 100644 --- a/helloextend-protection/includes/class-helloextend-global.php +++ b/helloextend-protection/includes/class-helloextend-global.php @@ -407,12 +407,14 @@ public function helloextend_init_global() $environment = ($environment == 'live') ? $environment : 'demo'; $helloextend_enabled = array_key_exists('enable_helloextend', $settings) ? $settings['enable_helloextend'] : 0; $ajaxurl = admin_url('admin-ajax.php'); + $debug_log_enabled = array_key_exists('enable_helloextend_debug', $settings) ? $settings['enable_helloextend_debug'] : 0; + $log_enabled = array_key_exists('enable_helloextend_log', $settings) ? $settings['enable_helloextend_log'] : 0; if ($store_id){ if ($helloextend_enabled === '1') { wp_enqueue_script('helloextend_script'); wp_enqueue_script('helloextend_global_script'); - wp_localize_script('helloextend_global_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment')); + wp_localize_script('helloextend_global_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment', 'debug_log_enabled', 'log_enabled')); // Get the leadToken from URL parameters $lead_token = $this->get_lead_token_from_url(); From 89547d0d316f0a53faae0dab67d83341c4232f82 Mon Sep 17 00:00:00 2001 From: JM <100705862+jm-extend@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:57:37 -0500 Subject: [PATCH 4/6] Update class-helloextend-global.php removed unused variable --- helloextend-protection/includes/class-helloextend-global.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/helloextend-protection/includes/class-helloextend-global.php b/helloextend-protection/includes/class-helloextend-global.php index 0220646..bc5e18e 100644 --- a/helloextend-protection/includes/class-helloextend-global.php +++ b/helloextend-protection/includes/class-helloextend-global.php @@ -419,9 +419,6 @@ public function helloextend_init_global() // Get the leadToken from URL parameters $lead_token = $this->get_lead_token_from_url(); if ($lead_token) { - // Sanitize the token for safe JavaScript output - $safe_lead_token = esc_js($lead_token); - // next step: Run Post Purchase logic to handle lead Token $this->helloextend_post_purchase($lead_token, $store_id, $environment, $ajaxurl); } From aa810ece9740d91fb93fd6199b8edbda9f91a166 Mon Sep 17 00:00:00 2001 From: JM <100705862+jm-extend@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:02:04 -0500 Subject: [PATCH 5/6] Update class-helloextend-global.php removed a circular reference --- helloextend-protection/includes/class-helloextend-global.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/helloextend-protection/includes/class-helloextend-global.php b/helloextend-protection/includes/class-helloextend-global.php index bc5e18e..ab82646 100644 --- a/helloextend-protection/includes/class-helloextend-global.php +++ b/helloextend-protection/includes/class-helloextend-global.php @@ -255,9 +255,11 @@ public static function helloextend_get_settings() $settings['warranty_product_id'] = array_key_exists('warranty_product_id', $settings) ? $settings['warranty_product_id'] : helloextend_product_protection_id(); - if (empty($settings['warranty_product_id'])) { + /* circular reference removed. + if (empty($settings['warranty_product_id'])) { HelloExtend_Protection_Logger::helloextend_log_error('Error: Warranty product is not created.'); } + */ return $settings; } From 665a5ad8ac899e3b9476b72112e90d0875c94411 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 9 Oct 2025 16:10:01 -0400 Subject: [PATCH 6/6] Refactored frontend test to use in-stock product --- cypress/integration/02_frontend_checks.cy.js | 41 ++++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/cypress/integration/02_frontend_checks.cy.js b/cypress/integration/02_frontend_checks.cy.js index 5a52c15..2cf80b8 100644 --- a/cypress/integration/02_frontend_checks.cy.js +++ b/cypress/integration/02_frontend_checks.cy.js @@ -1,6 +1,13 @@ +const URLS = { + EXTEND_API_OFFER: 'https://api.helloextend.com/offers*', + WOO_ADD_TO_CART: 'https://woocommerce.woodys.extend.com/?wc-ajax=add_to_cart', + WOODYS: 'https://woocommerce.woodys.extend.com/', + WOODYS_PRODUCT: 'https://woocommerce.woodys.extend.com/product/air-purifier/', +} + describe('Frontend Page and API Validation', () => { it('Checks Homepage for 500 Errors', () => { - cy.visit('https://woocommerce.woodys.extend.com/', { failOnStatusCode: false }); + cy.visit(URLS.WOODYS, { failOnStatusCode: false }); // Ensure the page loaded without 500 errors cy.document().then((doc) => { @@ -9,7 +16,7 @@ describe('Frontend Page and API Validation', () => { }); it('Checks Product Page for 500 Errors', () => { - cy.visit('https://woocommerce.woodys.extend.com/product/15in-dell-laptop/', { failOnStatusCode: false }); + cy.visit(URLS.WOODYS_PRODUCT, { failOnStatusCode: false }); // Ensure the page loaded without 500 errors cy.document().then((doc) => { @@ -18,10 +25,10 @@ describe('Frontend Page and API Validation', () => { }); it('Intercepts Offers API Request and Validates Query Parameters', () => { - cy.intercept('GET', 'https://api.helloextend.com/offers*').as('offersRequest'); + cy.intercept('GET', URLS.EXTEND_API_OFFER).as('offersRequest'); // Visit the product page - cy.visit('https://woocommerce.woodys.extend.com/product/15in-dell-laptop/'); + cy.visit(URLS.WOODYS_PRODUCT); // Wait for the intercepted API request cy.wait('@offersRequest').then((interception) => { @@ -34,9 +41,9 @@ describe('Frontend Page and API Validation', () => { // Validate expected query parameters expect(queryParams.storeId).to.equal('0e03bcd1-8a00-4a2a-bf2d-7c4d336c07e9'); - expect(queryParams.productId).to.equal('104'); + expect(queryParams.productId).to.equal('15'); expect(queryParams.category).to.equal('Electronics'); - expect(queryParams.price).to.equal('69900'); + expect(queryParams.price).to.equal('22900'); } else { throw new Error('API request was not intercepted.'); } @@ -44,10 +51,10 @@ describe('Frontend Page and API Validation', () => { }); it('Intercepts Offers API Response Checks for Plans In ADH or Base', () => { - cy.intercept('GET', 'https://api.helloextend.com/offers*').as('offersResponse'); + cy.intercept('GET', URLS.EXTEND_API_OFFER).as('offersResponse'); // Visit the product page - cy.visit('https://woocommerce.woodys.extend.com/product/15in-dell-laptop/'); + cy.visit(URLS.WOODYS_PRODUCT); // Wait for the API response cy.wait('@offersResponse').then((interception) => { @@ -76,7 +83,7 @@ describe('Frontend Page and API Validation', () => { it('Validates Extend PDP Offers & Modal Are Working', () => { // Visit product page - cy.visit('https://woocommerce.woodys.extend.com/product/15in-dell-laptop/'); + cy.visit(URLS.WOODYS_PRODUCT); // Check if the Extend Offer iFrame exists cy.get('div.helloextend-offer > div.extend-product-offer > iframe') @@ -135,11 +142,11 @@ describe('Frontend Page and API Validation', () => { }); it('Ensures Cart Normalization and Simple Offers Are working', () => { - cy.visit('https://woocommerce.woodys.extend.com/product/15in-dell-laptop/'); + cy.visit(URLS.WOODYS_PRODUCT); cy.get('[name="add-to-cart"]').then(($button) => { let productDetails = { - productId: '104'// Check for different attributes + productId: '15'// Check for different attributes // ... other product details you need ... }; @@ -151,9 +158,9 @@ describe('Frontend Page and API Validation', () => { // the UI and directly interacts with WooCommerce's backend. cy.request({ method: 'POST', - url: 'https://woocommerce.woodys.extend.com/?wc-ajax=add_to_cart', // Adjust if needed + url: URLS.WOO_ADD_TO_CART, // Adjust if needed body: { - product_id: '104', // Use the extracted product ID + product_id: '15', // Use the extracted product ID quantity: 1, // Or whatever quantity you want // ... any other required parameters (variation IDs, etc.) ... }, @@ -222,7 +229,7 @@ describe('Frontend Page and API Validation', () => { }); it('Validates Checkout Flow and Shipping Protection', () => { - cy.visit('https://woocommerce.woodys.extend.com/product/15in-dell-laptop/'); + cy.visit(URLS.WOODYS_PRODUCT); // 1. Get Product Details (Important!) // You'll need to extract the product ID and any other relevant info @@ -230,7 +237,7 @@ describe('Frontend Page and API Validation', () => { // to see how WooCommerce structures its product data. Here's an example: cy.get('[name="add-to-cart"]').then(($button) => { let productDetails = { - productId: '104'// Check for different attributes + productId: '15'// Check for different attributes // ... other product details you need ... }; @@ -242,9 +249,9 @@ describe('Frontend Page and API Validation', () => { // the UI and directly interacts with WooCommerce's backend. cy.request({ method: 'POST', - url: 'https://woocommerce.woodys.extend.com/?wc-ajax=add_to_cart', // Adjust if needed + url: URLS.WOO_ADD_TO_CART, // Adjust if needed body: { - product_id: '104', // Use the extracted product ID + product_id: '15', // Use the extracted product ID quantity: 1, // Or whatever quantity you want // ... any other required parameters (variation IDs, etc.) ... },