From 2176d63f1329cd058a49dd8c63315f617b386547 Mon Sep 17 00:00:00 2001 From: Timur Karimov Date: Thu, 19 Dec 2024 17:46:54 +0100 Subject: [PATCH] Show ECE buttons on products w/o shipping tax included in price, and improve tests (#9954) Co-authored-by: Timur Karimov Co-authored-by: Mike Moore --- .../fix-ece-button-for-price-including-tax | 4 + ...ayments-express-checkout-button-helper.php | 8 +- ...yments-express-checkout-button-handler.php | 136 ++++++++++++++++++ ...ayments-express-checkout-button-helper.php | 112 ++++++--------- 4 files changed, 185 insertions(+), 75 deletions(-) create mode 100644 changelog/fix-ece-button-for-price-including-tax create mode 100644 tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-handler.php diff --git a/changelog/fix-ece-button-for-price-including-tax b/changelog/fix-ece-button-for-price-including-tax new file mode 100644 index 00000000000..521ceb2af68 --- /dev/null +++ b/changelog/fix-ece-button-for-price-including-tax @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Show express checkout for products w/o shipping but where tax is included into price. diff --git a/includes/express-checkout/class-wc-payments-express-checkout-button-helper.php b/includes/express-checkout/class-wc-payments-express-checkout-button-helper.php index 672f2584c67..86d1a82c54d 100644 --- a/includes/express-checkout/class-wc-payments-express-checkout-button-helper.php +++ b/includes/express-checkout/class-wc-payments-express-checkout-button-helper.php @@ -415,7 +415,7 @@ public function should_show_express_checkout_button() { return true; } - // Non-shipping product and billing is calculated based on shopper billing addres. Excludes Pay for Order page. + // Non-shipping product and tax is calculated based on shopper billing address. Excludes Pay for Order page. if ( // If the product doesn't needs shipping. ( @@ -426,8 +426,10 @@ public function should_show_express_checkout_button() { ( ( $this->is_cart() || $this->is_checkout() ) && ! WC()->cart->needs_shipping() ) ) - // ...and billing is calculated based on billing address. - && wc_tax_enabled() && 'billing' === get_option( 'woocommerce_tax_based_on' ) + // ...and tax is calculated based on billing address. + && wc_tax_enabled() + && 'billing' === get_option( 'woocommerce_tax_based_on' ) + && 'yes' !== get_option( 'woocommerce_prices_include_tax' ) ) { return false; } diff --git a/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-handler.php b/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-handler.php new file mode 100644 index 00000000000..0b10752c0f5 --- /dev/null +++ b/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-handler.php @@ -0,0 +1,136 @@ +shipping()->unregister_shipping_methods(); + + $this->mock_wcpay_account = $this->createMock( WC_Payments_Account::class ); + $this->mock_wcpay_gateway = $this->createMock( WC_Payment_Gateway_WCPay::class ); + $this->mock_ece_button_helper = $this->createMock( WC_Payments_Express_Checkout_Button_Helper::class ); + $this->mock_express_checkout_ajax_handler = $this->createMock( WC_Payments_Express_Checkout_Ajax_Handler::class ); + + $this->system_under_test = new WC_Payments_Express_Checkout_Button_Handler( + $this->mock_wcpay_account, + $this->mock_wcpay_gateway, + $this->mock_ece_button_helper, + $this->mock_express_checkout_ajax_handler + ); + + // Set up shipping zones and methods. + $this->zone = new WC_Shipping_Zone(); + $this->zone->set_zone_name( 'Worldwide' ); + $this->zone->set_zone_order( 1 ); + $this->zone->save(); + + $flat_rate = $this->zone->add_shipping_method( 'flat_rate' ); + $this->flat_rate_id = $flat_rate; + + $local_pickup = $this->zone->add_shipping_method( 'local_pickup' ); + $this->local_pickup_id = $local_pickup; + } + + public function tear_down() { + parent::tear_down(); + + // Clean up shipping zones and methods. + $this->zone->delete(); + } + + public function test_filter_cart_needs_shipping_address_regular_products() { + $this->assertEquals( + true, + $this->system_under_test->filter_cart_needs_shipping_address( true ), + 'Should not modify shipping address requirement for regular products' + ); + } + + + public function test_filter_cart_needs_shipping_address_subscription_products() { + WC_Subscriptions_Cart::set_cart_contains_subscription( true ); + $this->mock_ece_button_helper->method( 'is_checkout' )->willReturn( true ); + + $this->zone->delete_shipping_method( $this->flat_rate_id ); + $this->zone->delete_shipping_method( $this->local_pickup_id ); + + $this->assertFalse( + $this->system_under_test->filter_cart_needs_shipping_address( true ), + 'Should not require shipping address for subscription without shipping methods' + ); + + remove_filter( 'woocommerce_shipping_method_count', '__return_zero' ); + WC_Subscriptions_Cart::set_cart_contains_subscription( false ); + } +} diff --git a/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-helper.php b/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-helper.php index 2432c61172c..8006faac78f 100644 --- a/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-helper.php +++ b/tests/unit/express-checkout/test-class-wc-payments-express-checkout-button-helper.php @@ -28,13 +28,6 @@ class WC_Payments_Express_Checkout_Button_Helper_Test extends WCPAY_UnitTestCase */ private $mock_wcpay_account; - /** - * Express Checkout Helper instance. - * - * @var WC_Payments_Express_Checkout_Button_Helper - */ - private $express_checkout_helper; - /** * Test shipping zone. * @@ -61,21 +54,7 @@ class WC_Payments_Express_Checkout_Button_Helper_Test extends WCPAY_UnitTestCase * * @var WC_Payments_Express_Checkout_Button_Helper */ - private $mock_express_checkout_helper; - - /** - * Express Checkout Ajax Handler instance. - * - * @var WC_Payments_Express_Checkout_Ajax_Handler - */ - private $mock_express_checkout_ajax_handler; - - /** - * Express Checkout ECE Button Handler instance. - * - * @var WC_Payments_Express_Checkout_Button_Handler - */ - private $mock_express_checkout_ece_button_handler; + private $system_under_test; /** * Test product to add to the cart @@ -92,23 +71,7 @@ public function set_up() { $this->mock_wcpay_account = $this->createMock( WC_Payments_Account::class ); $this->mock_wcpay_gateway = $this->make_wcpay_gateway(); - $this->mock_express_checkout_helper = new WC_Payments_Express_Checkout_Button_Helper( $this->mock_wcpay_gateway, $this->mock_wcpay_account ); - $this->mock_express_checkout_ajax_handler = $this->getMockBuilder( WC_Payments_Express_Checkout_Ajax_Handler::class ) - ->setConstructorArgs( - [ - $this->mock_express_checkout_helper, - ] - ) - ->getMock(); - - $this->mock_ece_button_helper = $this->getMockBuilder( WC_Payments_Express_Checkout_Button_Helper::class ) - ->setConstructorArgs( - [ - $this->mock_wcpay_gateway, - $this->mock_wcpay_account, - ] - ) - ->getMock(); + $this->system_under_test = new WC_Payments_Express_Checkout_Button_Helper( $this->mock_wcpay_gateway, $this->mock_wcpay_account ); WC_Helper_Shipping::delete_simple_flat_rate(); $zone = new WC_Shipping_Zone(); @@ -128,7 +91,7 @@ public function set_up() { WC()->session->init(); WC()->cart->add_to_cart( $this->simple_product->get_id(), 1 ); - $this->mock_express_checkout_helper->update_shipping_method( [ self::get_shipping_option_rate_id( $this->flat_rate_id ) ] ); + $this->system_under_test->update_shipping_method( [ self::get_shipping_option_rate_id( $this->flat_rate_id ) ] ); WC()->cart->calculate_totals(); } @@ -195,34 +158,34 @@ public function test_common_get_button_settings() { 'height' => '48', 'radius' => '', ], - $this->mock_express_checkout_helper->get_common_button_settings() + $this->system_under_test->get_common_button_settings() ); } public function test_cart_prices_include_tax_with_tax_disabled() { add_filter( 'wc_tax_enabled', '__return_false' ); - $this->assertTrue( $this->mock_express_checkout_helper->cart_prices_include_tax() ); + $this->assertTrue( $this->system_under_test->cart_prices_include_tax() ); } public function test_cart_prices_include_tax_with_tax_enabled_and_display_incl() { add_filter( 'wc_tax_enabled', '__return_true' ); // reset in tear_down. add_filter( 'pre_option_woocommerce_tax_display_cart', [ $this, '__return_incl' ] ); // reset in tear_down. - $this->assertTrue( $this->mock_express_checkout_helper->cart_prices_include_tax() ); + $this->assertTrue( $this->system_under_test->cart_prices_include_tax() ); } public function test_cart_prices_include_tax_with_tax_enabled_and_display_excl() { add_filter( 'wc_tax_enabled', '__return_true' ); // reset in tear_down. add_filter( 'pre_option_woocommerce_tax_display_cart', [ $this, '__return_excl' ] ); // reset in tear_down. - $this->assertFalse( $this->mock_express_checkout_helper->cart_prices_include_tax() ); + $this->assertFalse( $this->system_under_test->cart_prices_include_tax() ); } public function test_get_total_label() { $this->mock_wcpay_account->method( 'get_statement_descriptor' ) ->willReturn( 'Google Pay' ); - $result = $this->mock_express_checkout_helper->get_total_label(); + $result = $this->system_under_test->get_total_label(); $this->assertEquals( 'Google Pay (via WooCommerce)', $result ); } @@ -238,49 +201,54 @@ function () { } ); - $result = $this->mock_express_checkout_helper->get_total_label(); + $result = $this->system_under_test->get_total_label(); $this->assertEquals( 'Google Pay (via WooPayments)', $result ); remove_all_filters( 'wcpay_payment_request_total_label_suffix' ); } - public function test_filter_cart_needs_shipping_address_returns_false() { - sleep( 1 ); - $this->zone->delete_shipping_method( $this->flat_rate_id ); - $this->zone->delete_shipping_method( $this->local_pickup_id ); + public function test_should_show_express_checkout_button_for_non_shipping_but_price_includes_tax() { + $this->mock_wcpay_account + ->method( 'is_stripe_connected' ) + ->willReturn( true ); - WC_Subscriptions_Cart::set_cart_contains_subscription( true ); + WC_Payments::mode()->dev(); - $this->mock_ece_button_helper - ->method( 'is_product' ) - ->willReturn( true ); + add_filter( 'woocommerce_is_checkout', '__return_true' ); + add_filter( 'wc_shipping_enabled', '__return_false' ); + add_filter( 'wc_tax_enabled', '__return_true' ); - $this->mock_express_checkout_ece_button_handler = new WC_Payments_Express_Checkout_Button_Handler( - $this->mock_wcpay_account, - $this->mock_wcpay_gateway, - $this->mock_ece_button_helper, - $this->mock_express_checkout_ajax_handler - ); + update_option( 'woocommerce_tax_based_on', 'billing' ); + update_option( 'woocommerce_prices_include_tax', 'yes' ); - $this->assertFalse( $this->mock_express_checkout_ece_button_handler->filter_cart_needs_shipping_address( true ) ); + $this->assertTrue( $this->system_under_test->should_show_express_checkout_button() ); + + remove_filter( 'woocommerce_is_checkout', '__return_true' ); + remove_filter( 'wc_tax_enabled', '__return_true' ); + remove_filter( 'pre_option_woocommerce_tax_display_cart', [ $this, '__return_incl' ] ); } - public function test_filter_cart_needs_shipping_address_returns_true() { - WC_Subscriptions_Cart::set_cart_contains_subscription( true ); - $this->mock_ece_button_helper - ->method( 'is_product' ) + public function test_should_not_show_express_checkout_button_for_non_shipping_but_price_does_not_include_tax() { + $this->mock_wcpay_account + ->method( 'is_stripe_connected' ) ->willReturn( true ); - $this->mock_express_checkout_ece_button_handler = new WC_Payments_Express_Checkout_Button_Handler( - $this->mock_wcpay_account, - $this->mock_wcpay_gateway, - $this->mock_ece_button_helper, - $this->mock_express_checkout_ajax_handler - ); + WC_Payments::mode()->dev(); + + add_filter( 'woocommerce_is_checkout', '__return_true' ); + add_filter( 'wc_shipping_enabled', '__return_false' ); + add_filter( 'wc_tax_enabled', '__return_true' ); + + update_option( 'woocommerce_tax_based_on', 'billing' ); + update_option( 'woocommerce_prices_include_tax', 'no' ); - $this->assertTrue( $this->mock_express_checkout_ece_button_handler->filter_cart_needs_shipping_address( true ) ); + $this->assertFalse( $this->system_under_test->should_show_express_checkout_button() ); + + remove_filter( 'woocommerce_is_checkout', '__return_true' ); + remove_filter( 'wc_tax_enabled', '__return_true' ); + remove_filter( 'pre_option_woocommerce_tax_display_cart', [ $this, '__return_incl' ] ); } /**