diff --git a/.travis.yml b/.travis.yml index 14f3a5f6a8b..3bac1469de0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ php: - "7.2" - "7.3" - "7.4" + - "8.0" env: - WP_VERSION=latest WP_MULTISITE=0 @@ -87,6 +88,14 @@ install: echo "xdebug.ini does not exist" fi - composer install + - | + if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then + curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip + unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip + composer bin phpunit config --unset platform + composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}' + composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs + fi - | # Install WP Test suite: if [[ ! -z "$WP_VERSION" ]]; then diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index ff76250170c..47d0167b703 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -1771,6 +1771,11 @@ function wc_uasort_comparison( $a, $b ) { * @return int */ function wc_ascii_uasort_comparison( $a, $b ) { + // 'setlocale' is required for compatibility with PHP 8. + // Without it, 'iconv' will return '?'s instead of transliterated characters. + $prev_locale = setlocale( LC_CTYPE, 0 ); + setlocale( LC_ALL, 'C.UTF-8' ); + // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged if ( function_exists( 'iconv' ) && defined( 'ICONV_IMPL' ) && @strcasecmp( ICONV_IMPL, 'unknown' ) !== 0 ) { $a = @iconv( 'UTF-8', 'ASCII//TRANSLIT//IGNORE', $a ); @@ -1778,6 +1783,7 @@ function wc_ascii_uasort_comparison( $a, $b ) { } // phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged + setlocale( LC_ALL, $prev_locale ); return strcmp( $a, $b ); } diff --git a/tests/README.md b/tests/README.md index 5bf19e7ddf5..37a149f0af4 100644 --- a/tests/README.md +++ b/tests/README.md @@ -55,6 +55,30 @@ A text code coverage summary can be displayed using the `--coverage-text` option $ vendor/bin/phpunit --coverage-text +### Running tests in PHP 8 + +WooCommerce currently supports PHP versions from 7.0 up to 8.0, and this poses an issue with PHPUnit: + +* The latest PHPUnit version that supports PHP 7.0 is 6.5.14 +* The latest PHPUnit version that WordPress (and thus WooCommerce) supports is 7.5.20, but that version doesn't work on PHP 8 + +To workaround this, the testing strategy used by WooCommerce is as follows: + +* We normally use PHPUnit 6.5.14 +* For PHP 8 we use [a custom fork of PHPUnit 7.5.20 with support for PHP 8](https://github.com/woocommerce/phpunit/pull/1). The Travis build is configured to use this fork instead of the old version 6 when running in PHP 8. + +If you want to run the tests locally under PHP 8 you'll need to temporarily modify `composer.json` to use the custom PHPUnit fork in the same way that the Travis setup script does. These are the commands that you'll need (run them after a regular `composer install`): + +```shell +curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip +unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip +composer bin phpunit config --unset platform +composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}' +composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs +``` + +Just remember that you can't include the modified `composer.json` in any commit! + ## Writing Tests diff --git a/tests/legacy/unit-tests/log/log-handler-email.php b/tests/legacy/unit-tests/log/log-handler-email.php index d89da86bc88..aef0bbec8c7 100644 --- a/tests/legacy/unit-tests/log/log-handler-email.php +++ b/tests/legacy/unit-tests/log/log-handler-email.php @@ -1,4 +1,9 @@ get_sent( 0 )->body + $this->normalize_eol( $mailer->get_sent( 0 )->body ) ); $this->assertEquals( "[{$site_name}] EMERGENCY: 2 WooCommerce log messages", @@ -62,7 +73,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { 'You have received the following WooCommerce log message:' . PHP_EOL . PHP_EOL - . date( 'c', $time ) . ' EMERGENCY msg_emergency' + . gmdate( 'c', $time ) . ' EMERGENCY msg_emergency' . PHP_EOL . PHP_EOL . "Visit {$site_name} admin area:" @@ -70,11 +81,19 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { . admin_url() . PHP_EOL ), - $mailer->get_sent( 1 )->body + $this->normalize_eol( $mailer->get_sent( 1 )->body ) ); - } + /** + * Replace network-style end of lines with PHP-style end of lines in a string. + * + * @param string $string The string to do the replacements in. + * @return string The string once the replacement has been done. + */ + private function normalize_eol( $string ) { + return str_replace( "\r\n", PHP_EOL, $string ); + } /** * Test email subject @@ -160,7 +179,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { $handler->handle( time(), 'info', '', array() ); $handler->send_log_email(); - // Info should not be handled, get_sent is false + // Info should not be handled, get_sent is false. $this->assertFalse( $mailer->get_sent( 0 ) ); $handler->handle( time(), 'notice', '', array() ); @@ -180,7 +199,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { $handler->handle( time(), 'info', '', array() ); $handler->send_log_email(); - // Info should not be handled, get_sent is false + // Info should not be handled, get_sent is false. $this->assertFalse( $mailer->get_sent( 0 ) ); $handler->set_threshold( 'info' ); @@ -215,7 +234,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { 'You have received the following WooCommerce log message:' . PHP_EOL . PHP_EOL - . date( 'c', $time ) . ' EMERGENCY message 1' + . gmdate( 'c', $time ) . ' EMERGENCY message 1' . PHP_EOL . PHP_EOL . "Visit {$site_name} admin area:" @@ -223,7 +242,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { . admin_url() . PHP_EOL ), - $mailer->get_sent( 0 )->body + $this->normalize_eol( $mailer->get_sent( 0 )->body ) ); $this->assertEquals( @@ -231,7 +250,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { 'You have received the following WooCommerce log message:' . PHP_EOL . PHP_EOL - . date( 'c', $time ) . ' EMERGENCY message 2' + . gmdate( 'c', $time ) . ' EMERGENCY message 2' . PHP_EOL . PHP_EOL . "Visit {$site_name} admin area:" @@ -239,9 +258,7 @@ class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case { . admin_url() . PHP_EOL ), - $mailer->get_sent( 1 )->body + $this->normalize_eol( $mailer->get_sent( 1 )->body ) ); } - - }