id = 'method_with_no_settings'; } }, new class() { public $id; public $method_title; public function has_settings() { return true; } public function __construct() { $this->id = 'method_1_id'; $this->method_title = null; } }, new class() { public $id; public $method_title; public function has_settings() { return true; } public function __construct() { $this->id = 'method_2_id'; $this->method_title = 'method_2_title'; } }, //phpcs:enable ); $sut = $this->getMockBuilder( WC_Settings_Shipping::class ) ->setMethods( array( 'get_shipping_methods', 'wc_is_installing' ) ) ->getMock(); $sut->method( 'get_shipping_methods' )->willReturn( $methods ); $sut->method( 'wc_is_installing' )->willReturn( false ); $sections = $sut->get_sections(); $expected = array( '' => 'Shipping zones', 'options' => 'Shipping options', 'classes' => 'Shipping classes', 'method_1_id' => 'Method_1_id', 'method_2_id' => 'method_2_title', ); $this->assertEquals( $expected, $sections ); } /** * @testDox 'get_settings' returns proper default settings, also 'options' is an alias for the default section. * * @testWith [""] * ["options"] * * @param string $section_name The name of the section to get the settings for. */ public function test_get_default_and_options_settings_returns_all_settings( $section_name ) { $sut = new WC_Settings_Shipping(); $settings = $sut->get_settings( $section_name ); $settings_ids_and_types = $this->get_ids_and_types( $settings ); $expected = array( 'shipping_options' => array( 'title', 'sectionend' ), 'woocommerce_enable_shipping_calc' => 'checkbox', 'woocommerce_shipping_cost_requires_address' => 'checkbox', 'woocommerce_ship_to_destination' => 'radio', 'woocommerce_shipping_debug_mode' => 'checkbox', ); $this->assertEquals( $expected, $settings_ids_and_types ); } /** * @testDox 'output' for a predefined section invokes the appropriate internal method. * * @testWith ["", "output_zones_screen"] * ["classes", "output_shipping_class_screen"] * * @param string $section_name Current section name. * @param string $expected_method_invoked Name of the internal method expected to be invoked. */ public function test_output_for_predefined_section( $section_name, $expected_method_invoked ) { global $current_section; $current_section = $section_name; $method_invoked = null; $sut = $this->getMockBuilder( WC_Settings_Shipping::class ) ->setMethods( array( 'get_shipping_methods', 'output_zones_screen', 'output_fields', 'output_shipping_class_screen' ) ) ->getMock(); $sut->method( 'get_shipping_methods' )->willReturn( array() ); $sut->method( 'output_zones_screen' )->will( $this->returnCallback( function() use ( &$method_invoked ) { $method_invoked = 'output_zones_screen'; } ) ); $sut->method( 'output_shipping_class_screen' )->will( $this->returnCallback( function() use ( &$method_invoked ) { $method_invoked = 'output_shipping_class_screen'; } ) ); $sut->output(); $this->assertEquals( $expected_method_invoked, $method_invoked ); } /** * @testDox 'output' invokes 'admin_options' of the method if section is the id of a shipping method with settings. */ public function test_output_for_shipping_method_id_with_settings() { global $current_section; $current_section = 'method_id'; //phpcs:disable Squiz.Commenting $method = new class() { public $id; public $method_title; public $admin_options_invoked; public function has_settings() { return true; } public function admin_options() { $this->admin_options_invoked = true; } public function __construct() { $this->id = 'method_id'; $this->admin_options_invoked = false; } }; //phpcs:enable $sut = $this->getMockBuilder( WC_Settings_Shipping::class ) ->setMethods( array( 'get_shipping_methods' ) ) ->getMock(); $sut->method( 'get_shipping_methods' )->willReturn( array( $method ) ); $sut->output(); $this->assertTrue( $method->admin_options_invoked ); } /** * @testDox 'output' fallbacks to default behavior when section is for a shipping method without settings, or not a known shipping method. * * @testWith ["method_name"] * ["foobar"] * * @param string $section_name Current section name. */ public function test_output_for_shipping_method_without_settings_or_unknown_section( $section_name ) { global $current_section; $current_section = $section_name; $output_fields_in_admin_settings_invoked = false; StaticMockerHack::add_method_mocks( array( 'WC_Admin_Settings' => array( 'output_fields' => function( $settings ) use ( &$output_fields_in_admin_settings_invoked ) { $output_fields_in_admin_settings_invoked = true; }, ), ) ); //phpcs:disable Squiz.Commenting $method = new class() { public $id; public $method_title; public $admin_options_invoked; public function has_settings() { return false; } public function admin_options() { $this->admin_options_invoked = true; } public function __construct() { $this->id = 'method_id'; $this->admin_options_invoked = false; } }; //phpcs:enable $sut = $this->getMockBuilder( WC_Settings_Shipping::class ) ->setMethods( array( 'get_shipping_methods' ) ) ->getMock(); $sut->method( 'get_shipping_methods' )->willReturn( array( $method ) ); $sut->output(); $this->assertFalse( $method->admin_options_invoked ); $this->assertTrue( $output_fields_in_admin_settings_invoked ); } /** * @testDox 'save' triggers the appropriate action, and also 'save_settings_for_current_section' if needed, when the current section is a predefined one. * * @testWith ["", false, false] * ["options", true, true] * ["classes", false, true] * * @param string $section_name Current section name. * @param bool $expect_save_settings_for_current_section_invoked Is 'save_settings_for_current_section' expected to be invoked?. * @param bool $expect_update_options_action_invoked Is the 'woocommerce_update_options_' action expected to be triggered?. */ public function test_save_predefined_section( $section_name, $expect_save_settings_for_current_section_invoked, $expect_update_options_action_invoked ) { global $current_section; $current_section = $section_name; $save_settings_for_current_section_invoked = false; $sut = $this->getMockBuilder( WC_Settings_Shipping::class ) ->setMethods( array( 'get_shipping_methods', 'save_settings_for_current_section' ) ) ->getMock(); $sut->method( 'get_shipping_methods' )->willReturn( array() ); $sut->method( 'save_settings_for_current_section' )->will( $this->returnCallback( function() use ( &$save_settings_for_current_section_invoked ) { $save_settings_for_current_section_invoked = true; } ) ); $sut->save(); $this->assertEquals( $expect_save_settings_for_current_section_invoked, $save_settings_for_current_section_invoked ); $this->assertEquals( $expect_update_options_action_invoked ? 1 : 0, did_action( 'woocommerce_update_options_shipping_' . $section_name ) ); } /** * @testDox 'save' triggers 'woocommerce_update_options_shipping_{method_id}' when the current section is the id of a shipping method with settings. */ public function test_save_for_shipping_method_triggers_appropriate_action() { global $current_section; $current_section = 'method_id'; //phpcs:disable Squiz.Commenting $method = new class() { public $id; public $method_title; public $admin_options_invoked; public function has_settings() { return true; } public function __construct() { $this->id = 'method_id'; } }; //phpcs:enable $sut = $this->getMockBuilder( WC_Settings_Shipping::class ) ->setMethods( array( 'get_shipping_methods' ) ) ->getMock(); $sut->method( 'get_shipping_methods' )->willReturn( array( $method ) ); $sut->save(); $this->assertEquals( 1, did_action( 'woocommerce_update_options_shipping_method_id' ) ); } }