2014-09-01 06:04:02 +00:00
|
|
|
<?php
|
|
|
|
/**
|
2018-01-15 17:38:13 +00:00
|
|
|
* Base test case for all WooCommerce tests.
|
|
|
|
*
|
|
|
|
* @package WooCommerce\Tests
|
|
|
|
*/
|
|
|
|
|
2020-06-23 12:04:41 +00:00
|
|
|
use Automattic\WooCommerce\Proxies\LegacyProxy;
|
2020-05-18 09:31:59 +00:00
|
|
|
use Automattic\WooCommerce\Testing\Tools\CodeHacking\CodeHacker;
|
2020-04-13 07:32:19 +00:00
|
|
|
|
2018-01-15 17:38:13 +00:00
|
|
|
/**
|
|
|
|
* WC Unit Test Case.
|
2014-09-01 06:04:02 +00:00
|
|
|
*
|
|
|
|
* Provides WooCommerce-specific setup/tear down/assert methods, custom factories,
|
2015-11-03 13:31:20 +00:00
|
|
|
* and helper functions.
|
2014-09-01 06:04:02 +00:00
|
|
|
*
|
|
|
|
* @since 2.2
|
|
|
|
*/
|
2018-07-19 17:17:06 +00:00
|
|
|
class WC_Unit_Test_Case extends WP_HTTP_TestCase {
|
2014-09-01 06:04:02 +00:00
|
|
|
|
2018-01-15 17:38:13 +00:00
|
|
|
/**
|
|
|
|
* Holds the WC_Unit_Test_Factory instance.
|
|
|
|
*
|
|
|
|
* @var WC_Unit_Test_Factory
|
|
|
|
*/
|
2014-09-01 06:04:02 +00:00
|
|
|
protected $factory;
|
|
|
|
|
2020-05-06 12:40:17 +00:00
|
|
|
/**
|
|
|
|
* @var int Keeps the count of how many times disable_code_hacker has been invoked.
|
|
|
|
*/
|
|
|
|
private static $code_hacker_temporary_disables_requested = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Increase the count of Code Hacker disable requests, and effectively disable it if the count was zero.
|
|
|
|
* Does nothing if the code hacker wasn't enabled when the test suite started running.
|
|
|
|
*/
|
|
|
|
protected static function disable_code_hacker() {
|
|
|
|
if ( CodeHacker::is_enabled() ) {
|
|
|
|
CodeHacker::disable();
|
|
|
|
self::$code_hacker_temporary_disables_requested = 1;
|
|
|
|
} elseif ( self::$code_hacker_temporary_disables_requested > 0 ) {
|
|
|
|
self::$code_hacker_temporary_disables_requested++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decrease the count of Code Hacker disable requests, and effectively re-enable it if the count reaches zero.
|
|
|
|
* Does nothing if the count is already zero.
|
|
|
|
*/
|
|
|
|
protected static function reenable_code_hacker() {
|
|
|
|
if ( self::$code_hacker_temporary_disables_requested > 0 ) {
|
|
|
|
self::$code_hacker_temporary_disables_requested--;
|
|
|
|
if ( 0 === self::$code_hacker_temporary_disables_requested ) {
|
|
|
|
CodeHacker::enable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-01 06:04:02 +00:00
|
|
|
/**
|
2015-11-03 13:31:20 +00:00
|
|
|
* Setup test case.
|
2014-09-01 06:04:02 +00:00
|
|
|
*
|
|
|
|
* @since 2.2
|
|
|
|
*/
|
|
|
|
public function setUp() {
|
|
|
|
|
|
|
|
parent::setUp();
|
|
|
|
|
2018-01-15 17:38:13 +00:00
|
|
|
// Add custom factories.
|
2014-09-01 06:04:02 +00:00
|
|
|
$this->factory = new WC_Unit_Test_Factory();
|
2014-09-05 06:35:53 +00:00
|
|
|
|
2018-01-15 17:38:13 +00:00
|
|
|
// Setup mock WC session handler.
|
2014-09-05 06:35:53 +00:00
|
|
|
add_filter( 'woocommerce_session_handler', array( $this, 'set_mock_session_handler' ) );
|
|
|
|
|
|
|
|
$this->setOutputCallback( array( $this, 'filter_output' ) );
|
2014-10-09 19:24:37 +00:00
|
|
|
|
2018-01-15 17:38:13 +00:00
|
|
|
// Register post types before each test.
|
2014-10-09 19:24:37 +00:00
|
|
|
WC_Post_types::register_post_types();
|
|
|
|
WC_Post_types::register_taxonomies();
|
2014-09-05 06:35:53 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 11:50:31 +00:00
|
|
|
/**
|
|
|
|
* Set up class unit test.
|
|
|
|
*
|
|
|
|
* @since 3.5.0
|
|
|
|
*/
|
|
|
|
public static function setUpBeforeClass() {
|
2018-09-13 11:35:22 +00:00
|
|
|
parent::setUpBeforeClass();
|
|
|
|
|
2018-06-23 11:50:31 +00:00
|
|
|
// Terms are deleted in WP_UnitTestCase::tearDownAfterClass, then e.g. Uncategorized product_cat is missing.
|
|
|
|
WC_Install::create_terms();
|
|
|
|
}
|
|
|
|
|
2014-09-05 06:35:53 +00:00
|
|
|
/**
|
2015-11-03 13:31:20 +00:00
|
|
|
* Mock the WC session using the abstract class as cookies are not available.
|
|
|
|
* during tests.
|
2014-09-05 06:35:53 +00:00
|
|
|
*
|
2015-02-04 16:22:52 +00:00
|
|
|
* @since 2.2
|
2018-01-15 17:38:13 +00:00
|
|
|
* @return string The $output string, sans newlines and tabs.
|
2014-09-05 06:35:53 +00:00
|
|
|
*/
|
|
|
|
public function set_mock_session_handler() {
|
|
|
|
return 'WC_Mock_Session_Handler';
|
|
|
|
}
|
2014-09-05 06:36:46 +00:00
|
|
|
|
|
|
|
/**
|
2015-11-03 13:31:20 +00:00
|
|
|
* Strip newlines and tabs when using expectedOutputString() as otherwise.
|
|
|
|
* the most template-related tests will fail due to indentation/alignment in.
|
|
|
|
* the template not matching the sample strings set in the tests.
|
2014-09-05 06:36:46 +00:00
|
|
|
*
|
|
|
|
* @since 2.2
|
2018-01-15 17:38:13 +00:00
|
|
|
*
|
|
|
|
* @param string $output The captured output.
|
|
|
|
* @return string The $output string, sans newlines and tabs.
|
2014-09-05 06:36:46 +00:00
|
|
|
*/
|
|
|
|
public function filter_output( $output ) {
|
|
|
|
|
|
|
|
$output = preg_replace( '/[\n]+/S', '', $output );
|
|
|
|
$output = preg_replace( '/[\t]+/S', '', $output );
|
|
|
|
|
|
|
|
return $output;
|
2014-09-01 06:04:02 +00:00
|
|
|
}
|
|
|
|
|
2017-11-22 16:03:58 +00:00
|
|
|
/**
|
|
|
|
* Throws an exception with an optional message and code.
|
|
|
|
*
|
|
|
|
* Note: can't use `throwException` as that's reserved.
|
|
|
|
*
|
|
|
|
* @since 3.3-dev
|
2018-01-15 17:38:13 +00:00
|
|
|
* @param string $message Optional. The exception message. Default is empty.
|
|
|
|
* @param int $code Optional. The exception code. Default is empty.
|
|
|
|
* @throws Exception Containing the given message and code.
|
2017-11-22 16:03:58 +00:00
|
|
|
*/
|
|
|
|
public function throwAnException( $message = null, $code = null ) {
|
|
|
|
$message = $message ? $message : "We're all doomed!";
|
|
|
|
throw new Exception( $message, $code );
|
|
|
|
}
|
2020-04-12 11:09:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copies a file, temporarily disabling the code hacker.
|
|
|
|
* Use this instead of "copy" in tests for compatibility with the code hacker.
|
|
|
|
*
|
|
|
|
* TODO: Investigate why invoking "copy" within a test with the code hacker active causes the test to fail.
|
|
|
|
*
|
2020-04-13 07:32:19 +00:00
|
|
|
* @param string $source Path to the source file.
|
|
|
|
* @param string $dest The destination path.
|
2020-04-12 11:09:57 +00:00
|
|
|
* @return bool true on success or false on failure.
|
|
|
|
*/
|
2020-05-06 12:40:17 +00:00
|
|
|
public static function file_copy( $source, $dest ) {
|
|
|
|
self::disable_code_hacker();
|
|
|
|
$result = copy( $source, $dest );
|
|
|
|
self::reenable_code_hacker();
|
|
|
|
return $result;
|
2020-04-12 11:09:57 +00:00
|
|
|
}
|
2020-06-23 12:04:41 +00:00
|
|
|
|
2020-06-25 07:47:25 +00:00
|
|
|
/**
|
|
|
|
* Get an instance of a class that has been registered in the dependency injection container.
|
|
|
|
* To get an instance of a legacy class (such as the ones in the 'íncludes' directory) use
|
|
|
|
* 'get_legacy_instance_of' instead.
|
|
|
|
*
|
|
|
|
* @param string $class_name The class name to get an instance of.
|
|
|
|
*
|
|
|
|
* @return mixed The instance.
|
|
|
|
*/
|
|
|
|
public function get_instance_of( string $class_name ) {
|
|
|
|
return wc_get_container()->get( $class_name );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an instance of legacy class (such as the ones in the 'íncludes' directory).
|
|
|
|
* To get an instance of a class registered in the dependency injection container use 'get_instance_of' instead.
|
|
|
|
*
|
|
|
|
* @param string $class_name The class name to get an instance of.
|
|
|
|
*
|
|
|
|
* @return mixed The instance.
|
|
|
|
*/
|
|
|
|
public function get_legacy_instance_of( string $class_name ) {
|
|
|
|
return wc_get_container()->get( LegacyProxy::class )->get_instance_of( $class_name );
|
|
|
|
}
|
|
|
|
|
2020-06-23 12:04:41 +00:00
|
|
|
/**
|
|
|
|
* Reset all the cached resolutions in the dependency injection container, so any further "get"
|
|
|
|
* for shared definitions will generate the instance again.
|
|
|
|
* This may be needed when registering mocks for already resolved shared classes.
|
|
|
|
*/
|
|
|
|
public function reset_container_resolutions() {
|
2020-07-14 12:51:43 +00:00
|
|
|
wc_get_container()->reset_all_resolved();
|
2020-06-23 12:04:41 +00:00
|
|
|
}
|
|
|
|
|
2020-06-25 07:47:25 +00:00
|
|
|
/**
|
|
|
|
* Reset the mock legacy proxy class so that all the registered mocks are unregistered.
|
|
|
|
*/
|
|
|
|
public function reset_legacy_proxy_mocks() {
|
|
|
|
wc_get_container()->get( LegacyProxy::class )->reset();
|
|
|
|
}
|
|
|
|
|
2020-06-23 12:04:41 +00:00
|
|
|
/**
|
|
|
|
* Register the function mocks to use in the mockable LegacyProxy.
|
|
|
|
*
|
|
|
|
* @param array $mocks An associative array where keys are function names and values are function replacement callbacks.
|
|
|
|
*
|
|
|
|
* @throws \Exception Invalid parameter.
|
|
|
|
*/
|
|
|
|
public function register_legacy_proxy_function_mocks( array $mocks ) {
|
|
|
|
wc_get_container()->get( LegacyProxy::class )->register_function_mocks( $mocks );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register the static method mocks to use in the mockable LegacyProxy.
|
|
|
|
*
|
|
|
|
* @param array $mocks An associative array where keys are class names and values are associative arrays, in which keys are method names and values are method replacement callbacks.
|
|
|
|
*
|
|
|
|
* @throws \Exception Invalid parameter.
|
|
|
|
*/
|
|
|
|
public function register_legacy_proxy_static_mocks( array $mocks ) {
|
|
|
|
wc_get_container()->get( LegacyProxy::class )->register_static_mocks( $mocks );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register the class mocks to use in the mockable LegacyProxy.
|
|
|
|
*
|
|
|
|
* @param array $mocks An associative array where keys are class names and values are either factory callbacks (optionally with a $class_name argument) or objects.
|
|
|
|
*
|
|
|
|
* @throws \Exception Invalid parameter.
|
|
|
|
*/
|
|
|
|
public function register_legacy_proxy_class_mocks( array $mocks ) {
|
|
|
|
wc_get_container()->get( LegacyProxy::class )->register_class_mocks( $mocks );
|
|
|
|
}
|
2014-09-01 06:04:02 +00:00
|
|
|
}
|