Skip to content

Commit

Permalink
fix(WPTestCase) restore inheritance chain correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
lucatume committed Oct 7, 2023
1 parent aba8b1d commit fa05d63
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 17 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ package: update_core_phpunit_includes test

update_sqlite_plugin:
bin/update_sqlite_plugin
.PHONY: update_sqlite_plugin

docs_serve:
mkdocs serve -a 0.0.0.0:8000
Expand Down
130 changes: 130 additions & 0 deletions bin/namespace_global_class_names.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#! /usr/bin/env php

<?php

use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\NodeVisitorAbstract;
use PhpParser\ParserFactory;

require_once dirname(__DIR__) . '/vendor/autoload.php';

// Build a PHP parser using nikic/php-parser
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP5);

// Build an iterator over all the .php files in the includes directory
$files = new RegexIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
dirname(__DIR__) . '/includes/core-phpunit/includes',
RecursiveDirectoryIterator::SKIP_DOTS | RecursiveDirectoryIterator::CURRENT_AS_PATHNAME
)
),
'/\.php$/'
);

// Add a node visitor that will resolve to fully qualified namespaces.
$traverser = new NodeTraverser();
$traverser->addVisitor(new NameResolver());

// Add a visitor that will flag any use of a class name that does not exist.
$namespaceFlagVisitor = new class extends NodeVisitorAbstract {
private array $matchesByFile = [];
private string $file;

private function addMatch(string $file, int $line, string $match)
{
// Pick the fragment after the last \ in the match.
$class = substr($match, strrpos($match, '\\') + 1);
$this->matchesByFile[$file][] = [$line, $class];
}

public function getMatchesByFile(): array
{
return $this->matchesByFile;
}

public function setFile(string $file): void
{
$this->file = $file;
}

public function leaveNode(Node $node)
{
if ($node instanceof New_) {
$class = $node->class;
if ($class instanceof Name) {
$name = $class->toString();
if (!class_exists($name) && !interface_exists($name) && !trait_exists($name)) {
$file = $this->file;
$line = $node->getAttribute('startLine');
$match = $class->toString();
$this->addMatch($file, $line, $match);
}
}
} elseif ($node instanceof Function_ || $node instanceof ClassMethod) {
foreach ($node->getParams() as $param) {
$type = $param->type;
if ($type instanceof Name) {
$name = $type->toString();
if (!class_exists($name) && !interface_exists($name) && !trait_exists($name)) {
$file = $this->file;
$line = $node->getAttribute('startLine');
$match = $name;
$this->addMatch($file, $line, $match);
}
}
}
}
}

public function setPossibleNamespaces(array $possibleNamespaces): void
{
$this->possibleNamespaces = $possibleNamespaces;
}
};

$traverser->addVisitor($namespaceFlagVisitor);
// Scan all the files to build the parser information.
foreach ($files as $file) {
$stmts = $parser->parse(file_get_contents($file));
$namespaceFlagVisitor->setFile($file);
$stmts = $traverser->traverse($stmts);
}

$filesToCure = [
dirname(__DIR__) . "/includes/core-phpunit/includes/testcase-ajax.php",
dirname(__DIR__) . "/includes/core-phpunit/includes/testcase-canonical.php",
dirname(__DIR__) . "/includes/core-phpunit/includes/testcase-rest-api.php",
dirname(__DIR__) . "/includes/core-phpunit/includes/testcase-rest-controller.php",
dirname(__DIR__) . "/includes/core-phpunit/includes/testcase-rest-post-type-controller.php",
dirname(__DIR__) . "/includes/core-phpunit/includes/testcase-xml.php",
dirname(__DIR__) . '/includes/core-phpunit/includes/testcase-xmlrpc.php',
];
foreach ($namespaceFlagVisitor->getMatchesByFile() as $file => $matches) {
if (!in_array($file, $filesToCure, true)) {
// Target only the files to cure.
continue;
}

$updatedContents = file($file);

if ($updatedContents === false) {
throw new RuntimeException('Could not read file: ' . $file);
}

foreach ($matches as [$line, $match]) {
$updatedContents[$line - 1] = str_replace($match, '\\' . $match, $updatedContents[$line - 1]);
}

printf('Updating file: %s ... ', $file);
if (!file_put_contents($file, implode('', $updatedContents), LOCK_EX)) {
throw new RuntimeException('Could not update file: ' . $file);
}
echo "ok\n";
}
5 changes: 4 additions & 1 deletion bin/update_core_phpunit_includes
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#! /usr/bin/env sh

set -eux

script_dir=$(dirname "$0")
root_dir=$(cd "$script_dir/.." && pwd)
includes_src="https://github.com/WordPress/wordpress-develop/branches/trunk/tests/phpunit/includes"
Expand All @@ -15,5 +17,6 @@ rm -rf "${root_dir}"/includes/core-phpunit/includes &&
git apply "${root_dir}"/config/patches/core-phpunit/includes/testcase-rest-controller.php.patch &&
git apply "${root_dir}"/config/patches/core-phpunit/includes/testcase-rest-post-type-controller.php.patch &&
git apply "${root_dir}"/config/patches/core-phpunit/includes/testcase-xml.php.patch &&
git apply "${root_dir}"/config/patches/core-phpunit/includes/testcase-xmlrpc.php.patch
git apply "${root_dir}"/config/patches/core-phpunit/includes/testcase-xmlrpc.php.patch &&
php "${root_dir}/bin/namespace_global_class_names.php"

4 changes: 2 additions & 2 deletions includes/core-phpunit/includes/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
if ( ! file_exists( $config_file_path . '/wp-tests-config.php' ) ) {
// Support the config file from the root of the develop repository.
if ( basename( $config_file_path ) === 'phpunit' && basename( dirname( $config_file_path ) ) === 'tests' ) {
$config_file_path = dirname( dirname( $config_file_path ) );
$config_file_path = dirname( $config_file_path, 2 );
}
}
$config_file_path .= '/wp-tests-config.php';
Expand Down Expand Up @@ -79,7 +79,7 @@
*/
if ( ! class_exists( 'Yoast\PHPUnitPolyfills\Autoload' ) ) {
// Default location of the autoloader for WP core test runs.
$phpunit_polyfills_autoloader = dirname( dirname( dirname( __DIR__ ) ) ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php';
$phpunit_polyfills_autoloader = dirname( __DIR__, 3 ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php';
$phpunit_polyfills_error = false;

// Allow for a custom installation location to be provided for plugin/theme integration tests.
Expand Down
6 changes: 3 additions & 3 deletions includes/core-phpunit/includes/testcase-ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,12 @@ public function dieHandler( $message ) {

if ( '' === $this->_last_response ) {
if ( is_scalar( $message ) ) {
throw new WPAjaxDieStopException( (string) $message );
throw new \WPAjaxDieStopException( (string) $message );
} else {
throw new WPAjaxDieStopException( '0' );
throw new \WPAjaxDieStopException( '0' );
}
} else {
throw new WPAjaxDieContinueException( $message );
throw new \WPAjaxDieContinueException( $message );
}
}

Expand Down
4 changes: 2 additions & 2 deletions includes/core-phpunit/includes/testcase-canonical.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstract class WPCanonicalTestCase extends WPTestCase {
*/
public $structure = '/%year%/%monthnum%/%day%/%postname%/';

public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
public static function wpSetUpBeforeClass( \WP_UnitTest_Factory $factory ) {
self::generate_shared_fixtures( $factory );
}

Expand All @@ -43,7 +43,7 @@ public function set_up() {
*
* @since 4.1.0
*/
public static function generate_shared_fixtures( WP_UnitTest_Factory $factory ) {
public static function generate_shared_fixtures( \WP_UnitTest_Factory $factory ) {
self::$old_current_user = get_current_user_id();
self::$author_id = $factory->user->create( array( 'user_login' => 'canonical-author' ) );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public function set_up() {
add_filter( 'rest_url', array( $this, 'filter_rest_url_for_leading_slash' ), 10, 2 );
/** @var WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$wp_rest_server = new Spy_REST_Server();
$wp_rest_server = new \Spy_REST_Server();
do_action( 'rest_api_init', $wp_rest_server );
}

Expand Down
4 changes: 2 additions & 2 deletions includes/core-phpunit/includes/testcase-xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function loadXML( $xml, $options = 0 ) {
$internal = libxml_use_internal_errors( true );
libxml_clear_errors();

$xml_dom = new DOMDocument();
$xml_dom = new \DOMDocument();
$xml_dom->loadXML( $xml, $options );
$libxml_last_error = libxml_get_last_error();

Expand Down Expand Up @@ -49,7 +49,7 @@ public function normalizeXML( $xml, $options = 0 ) {
static $xslt_proc;

if ( ! $xslt_proc ) {
$xslt_proc = new XSLTProcessor();
$xslt_proc = new \XSLTProcessor();
$xslt_proc->importStyleSheet( simplexml_load_file( __DIR__ . '/normalize-xml.xsl' ) );
}

Expand Down
2 changes: 1 addition & 1 deletion includes/core-phpunit/includes/testcase-xmlrpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function set_up() {

add_filter( 'pre_option_enable_xmlrpc', '__return_true' );

$this->myxmlrpcserver = new wp_xmlrpc_server();
$this->myxmlrpcserver = new \wp_xmlrpc_server();
}

public function tear_down() {
Expand Down
1 change: 0 additions & 1 deletion includes/core-phpunit/includes/unregister-blocks-hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,3 @@
remove_action( 'init', 'register_block_core_social_link' );
remove_action( 'init', 'register_block_core_tag_cloud' );
remove_action( 'init', 'register_block_core_template_part' );
remove_action( 'init', 'register_block_core_term_description' );
8 changes: 4 additions & 4 deletions src/TestCase/WPTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,26 @@ public static function setUpBeforeClass(): void
protected function setUp(): void
{
parent::setUp();
self::getCoreTestCase()->set_up();
$this->set_up(); //@phpstan-ignore-line magic __call
}

protected function tearDown(): void
{
self::getCoreTestCase()->tear_down();
$this->tear_down(); //@phpstan-ignore-line magic __call
parent::tearDown();
}


public static function tearDownAfterClass(): void
{
self::getCoreTestCase()->tear_down_after_class();
static::tear_down_after_class(); //@phpstan-ignore-line magic __callStatic
parent::tearDownAfterClass();
}

protected function assertPostConditions(): void
{
parent::assertPostConditions();
self::getCoreTestCase()->assert_post_conditions();
static::assert_post_conditions(); //@phpstan-ignore-line magic __callStatic
}

public function __destruct()
Expand Down
38 changes: 38 additions & 0 deletions tests/wploadersuite/AjaxTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

use lucatume\WPBrowser\TestCase\WPAjaxTestCase;

class AjaxTest extends WPAjaxTestCase
{
public function ajaxCallback(): void
{
if (
!isset($_POST['test_nonce']) ||
!wp_verify_nonce(sanitize_key($_POST['test_nonce']), 'test_ajax_action')
) {
wp_send_json_error('Number not only once is invalid', 404);
}
// The rest of the code...
}

public function setUp(): void
{
parent::setUp();
add_action('wp_ajax_test_ajax_action', [$this, 'ajaxCallback']);
add_action('wp_ajax_nopriv_test_ajax_action', [$this, 'ajaxCallback']);
}

public function testAjaxCallbackWillFailIfNumberNotOnlyOnceIsInvalid(): void
{
$response = null;
try {
$this->_handleAjax('test_ajax_action');
} catch (\WPAjaxDieContinueException) {
$response = json_decode($this->_last_response);
}

$this->assertNotNull($response);
$this->assertFalse($response->success);
$this->assertEquals('Number not only once is invalid', $response->data);
}
}

0 comments on commit fa05d63

Please sign in to comment.