Skip to content

Commit

Permalink
transpile #758
Browse files Browse the repository at this point in the history
  • Loading branch information
lucatume committed Oct 16, 2024
1 parent 9f78e69 commit 2fb3d1e
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [unreleased] Unreleased

### Changed

- Improve `LoadSandbox` error and messaging (used by the `WPLoader` module when `loadOnly: true`) around Codeception early exits. (thanks @andronocean)

## [3.7.5] 2024-09-13;

## Fixed
Expand Down
11 changes: 11 additions & 0 deletions src/WordPress/InstallationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class InstallationException extends Exception
public const SQLITE_PLUGIN_NOT_FOUND = 37;
public const DB_DROPIN_ALREADY_EXISTS = 38;
public const WORDPRESS_NOT_FOUND = 39;
public const COMMAND_DID_NOT_FINISH_PROPERLY = 40;

public static function becauseWordPressFailedToLoad(string $bodyContent): self
{
Expand Down Expand Up @@ -71,4 +72,14 @@ public static function becauseWordPressMultsiteIsNotInstalled(bool $isSubdomainI

return new self('WordPress multisite (sub-folder) is not installed.', self::MULTISITE_SUBFOLDER_NOT_INSTALLED);
}

public static function becauseCodeceptionCommandDidNotFinish(): self
{
return new self(
"The current Codeception command did not finish properly. WordPress exited early while loading. "
."A plugin, theme, or WP-CLI package may have exited before the wp_loaded action could be fired. " .
"If there is error output above, it may provide clues.",
self::COMMAND_DID_NOT_FINISH_PROPERLY
);
}
}
7 changes: 7 additions & 0 deletions src/WordPress/LoadSandbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ class_exists(InstallationException::class);
}
}

if ($bodyContent === 'COMMAND DID NOT FINISH PROPERLY.') {
// We got here from \Codeception\Subscriber\ErrorHandler::shutdownHandler().
// We'll try to provide some clues to the user in the exception message.
codecept_debug('Codeception error: ' . $bodyContent . ' Check logs for details.');
throw InstallationException::becauseCodeceptionCommandDidNotFinish();
}

// We do not know what happened, throw and try to be helpful.
throw InstallationException::becauseWordPressFailedToLoad($bodyContent ?: $reason);
}
Expand Down
67 changes: 67 additions & 0 deletions tests/unit/lucatume/WPBrowser/WordPress/LoadSandboxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

use Codeception\Test\Unit;
use Exception;
use lucatume\WPBrowser\Tests\Traits\Fork;
use lucatume\WPBrowser\Tests\Traits\LoopIsolation;
use lucatume\WPBrowser\Tests\Traits\TmpFilesCleanup;
use lucatume\WPBrowser\Traits\UopzFunctions;
use lucatume\WPBrowser\Utils\Env;
use lucatume\WPBrowser\Utils\Filesystem as FS;
use lucatume\WPBrowser\Utils\Random;
Expand All @@ -24,6 +26,7 @@ class LoadSandboxTest extends Unit
{
use LoopIsolation;
use TmpFilesCleanup;
use UopzFunctions;

/**
* It should correctly load installed WordPress
Expand Down Expand Up @@ -322,4 +325,68 @@ public function should_handle_wp_die_called_during_loading(): void
$loadSandbox->load();
});
}

/**
* It should handle an unexpected early exit if something interferes with Codeception
*
* @test
*/
public function should_handle_codeception_command_not_finished_error(): void {
$wpRootDir = FS::tmpDir('sandbox_');
$dbName = Random::dbName();
$dbHost = Env::get('WORDPRESS_DB_HOST');
$dbUser = Env::get('WORDPRESS_DB_USER');
$dbPassword = Env::get('WORDPRESS_DB_PASSWORD');
$db = new MysqlDatabase($dbName, $dbUser, $dbPassword, $dbHost, 'wp_');
$installation = Installation::scaffold($wpRootDir, '6.1.1')
->configure($db)
->install(
'http://wordpress.test',
'admin',
'admin',
'[email protected]',
'Sandbox'
);

$exitingPluginCode = <<<'PHP'
<?php
/**
* Plugin Name: Codeception Early Shutdown Mock
*
* Suppose a plugin or CLI package messes up and exits early, e.g. `exit(1)`, prior to `wp_loaded`.
* That will trigger Codeception's shutdown handler. If the suite is not finished running, and an error has not occurred,
* Codeception echoes a message and exits. LoadSandbox's output buffer will catch this.
* This plugin mocks the Codeception behavior.
*
* @see \Codeception\Subscriber\ErrorHandler::shutdownHandler()
*/
add_action('after_setup_theme', function () {
// Output and exit from \Codeception\Subscriber\ErrorHandler::shutdownHandler.
echo "\n\n\nCOMMAND DID NOT FINISH PROPERLY.\n";
exit(125);
});
PHP;

$muPluginsDir = $installation->getMuPluginsDir();
if (
!is_dir($muPluginsDir)
&& !(
mkdir($muPluginsDir, 0755, true)
&& is_dir($muPluginsDir)
)
) {
throw new \RuntimeException('Could not create mu-plugins directory.');
}
if(!file_put_contents($muPluginsDir . '/exiting-mu-plugin.php', $exitingPluginCode)){
throw new \RuntimeException('Could not write exiting-mu-plugin.php.');
}

$this->expectException(InstallationException::class);
$this->expectExceptionMessage(InstallationException::becauseCodeceptionCommandDidNotFinish()->getMessage());

$this->assertInIsolation(static function () use ($wpRootDir) {
$loadSandbox = new LoadSandbox($wpRootDir, 'wordpress.test');
$loadSandbox->load();
});
}
}

0 comments on commit 2fb3d1e

Please sign in to comment.