Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for rsync-ing a codebase from within the testing suite #332

Merged
merged 19 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"mockery/mockery": "^1.3",
"nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.3.3",
"nunomaduro/termwind": "^1.14",
"symplify/monorepo-builder": "^10.1"
},
"replace": {
Expand Down
10 changes: 8 additions & 2 deletions src/mantle/testing/class-installation-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* Installation Manager
*/
class Installation_Manager {
use Concerns\Rsync_Installation;
use Singleton;

/**
Expand Down Expand Up @@ -99,15 +100,20 @@ public function on( string $hook, ?callable $callback, int $priority = 10, int $
public function install() {
require_once __DIR__ . '/core-polyfill.php';

if ( $this->rsync_to ) {
$this->perform_rsync_testsuite();
return;
}

foreach ( $this->before_install_callbacks as $callback ) {
$callback();
}

try {
require_once __DIR__ . '/wordpress-bootstrap.php';
} catch ( \Throwable $throwable ) {
echo "ERROR: Failed to load WordPress!\n";
echo "{$throwable}\n"; // phpcs:ignore
Utils::error( '🚨 Failed to load the WordPress installation. Exception thrown:' );
Utils::code( $throwable->getMessage() );
exit( 1 );
}

Expand Down
120 changes: 119 additions & 1 deletion src/mantle/testing/class-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
namespace Mantle\Testing;

use Mantle\Testing\Doubles\Spy_REST_Server;
use function Termwind\render;

require_once __DIR__ . '/concerns/trait-output-messages.php';

/**
* Assorted testing utilities.
*
* A fork of https://github.com/WordPress/wordpress-develop/blob/master/tests/phpunit/includes/utils.php.
*/
class Utils {
use Concerns\Output_Messages;

/**
* Default database name.
*
Expand Down Expand Up @@ -62,6 +67,7 @@ public static function get_echo( $callable, $args = [] ) {
call_user_func_array( $callable, $args );
return ob_get_clean();
}

/**
* Unregister a post status.
*
Expand Down Expand Up @@ -197,7 +203,7 @@ public static function setup_configuration(): void {
global $table_prefix;

// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
defined( 'ABSPATH' ) || define( 'ABSPATH', preg_replace( '#/wp-content/.*$#', '/', __DIR__ ) );
defined( 'ABSPATH' ) || define( 'ABSPATH', ensure_trailingslash( preg_replace( '#/wp-content/.*$#', '/', __DIR__ ) ) );
defined( 'WP_DEBUG' ) || define( 'WP_DEBUG', true );

defined( 'DB_NAME' ) || define( 'DB_NAME', static::DEFAULT_DB_NAME );
Expand Down Expand Up @@ -254,4 +260,116 @@ public static function env( string $variable, $default ) {
public static function shell_safe( string $string ): string {
return empty( trim( $string ) ) ? "''" : $string;
}

/**
* Install a WordPress codebase through a shell script.
*
* This installs the WordPress codebase in the specified directory. It does
* not install the WordPress database.
*
* @param string $directory Directory to install WordPress in.
*/
public static function install_wordpress( string $directory ): void {
$command = sprintf(
'export WP_CORE_DIR=%s && curl -s %s | bash -s %s %s %s %s %s %s',
$directory,
'https://raw.githubusercontent.com/alleyinteractive/mantle-ci/HEAD/install-wp-tests.sh',
static::shell_safe( defined( 'DB_NAME' ) ? DB_NAME : static::env( 'WP_DB_NAME', 'wordpress_unit_tests' ) ),
static::shell_safe( defined( 'DB_USER' ) ? DB_USER : static::env( 'WP_DB_USER', 'root' ) ),
static::shell_safe( defined( 'DB_PASSWORD' ) ? DB_PASSWORD : static::env( 'WP_DB_PASSWORD', 'root' ) ),
static::shell_safe( defined( 'DB_HOST' ) ? DB_HOST : static::env( 'WP_DB_HOST', 'localhost' ) ),
static::shell_safe( static::env( 'WP_VERSION', 'latest' ) ),
static::shell_safe( static::env( 'WP_SKIP_DB_CREATE', 'false' ) ),
);

$output = static::command( $command, $retval );

if ( 0 !== $retval ) {
static::error( '🚨 Error installing WordPress! Output from installation:', 'Install Rsync' );
static::code( $output );
exit( 1 );
}
}

/**
* Check if the command is being run in debug mode.
*
* @return bool
*/
public static function is_debug_mode(): bool {
return ! empty(
array_intersect(
(array) $_SERVER['argv'] ?? [], // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
[
'--debug',
'--verbose',
'-v',
],
)
);
}

/**
* Run a system command and return the output.
*
* @param string|string[] $command Command to run.
* @param int $exit_code Exit code.
* @return string[]
*/
public static function command( $command, &$exit_code = null ) {
$is_debug_mode = static::is_debug_mode();

// Display the command if in debug mode.
if ( $is_debug_mode ) {
$time = microtime( true );

render(
'<div class="p-1">
Running:
<code>' . implode( ' ', (array) $command ) . '</code>
</div>'
);
}

if ( is_array( $command ) ) {
$command = implode( ' ', $command );
}

exec( $command, $output, $exit_code ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.system_calls_exec

// Display the command runtime if in debug mode.
if ( $is_debug_mode ) {
$time = microtime( true ) - $time;

render(
'<div class="p-1">
Finished in ' . number_format( $time, 2 ) . 's with exit code ' . $exit_code . '.
</div>'
);
}

return $output;
}

/**
* Ensure that Composer is loaded for the current environment.
*/
public static function ensure_composer_loaded() {
if ( class_exists( 'Composer\Autoload\ClassLoader' ) ) {
return;
}

$paths = [
preg_replace( '#/vendor/.*$#', '/vendor/autoload.php', __DIR__ ),
__DIR__ . '/../../../vendor/autoload.php',
__DIR__ . '/../../vendor/autoload.php',
];

foreach ( $paths as $path ) {
if ( ! is_dir( $path ) && file_exists( $path ) ) {
require_once $path;
return;
}
}
}
}
3 changes: 2 additions & 1 deletion src/mantle/testing/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"mantle-framework/database": "^0.7",
"mantle-framework/http-client": "^0.7",
"mantle-framework/http": "^0.7",
"mantle-framework/support": "^0.7"
"mantle-framework/support": "^0.7",
"nunomaduro/termwind": "^1.14"
},
"extra": {
"branch-alias": {
Expand Down
96 changes: 96 additions & 0 deletions src/mantle/testing/concerns/trait-output-messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* Output_Messages trait file
*
* @package Mantle
*/

namespace Mantle\Testing\Concerns;

use function Termwind\render;

/**
* Messages for testing managed with Termwind.
*/
trait Output_Messages {
/**
* Render a message to the console.
*
* @param string $prefix Prefix for the message.
* @param string $prefix_color Color for the prefix.
* @param string $message Message to render.
* @param string $message_color Color for the message.
* @param string $parent_classes Parent classes for the message.
* @return void
*/
protected static function message(
string $prefix,
string $prefix_color,
string $message,
string $message_color = 'white',
string $parent_classes = '',
Comment on lines +27 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need additional defaults?

) {
render(
sprintf(
'<div class="%s">
<div class="px-1 bg-%s text-%s">%s:</div>
<span class="ml-1">%s</span>
</div>',
$parent_classes,
$prefix_color,
$message_color,
$prefix,
$message,
)
);
}

/**
* Output a info message to the console.
*
* @param string $message Message to output.
* @param string $prefix Prefix to output.
* @return void
*/
public static function info( string $message, $prefix = 'Install' ): void {
static::message( $prefix, 'yellow-600', $message );
}

/**
* Output a success message to the console.
*
* @param string $message Message to output.
* @param string $prefix Prefix to output.
* @return void
*/
public static function success( string $message, $prefix = 'Install' ): void {
static::message( $prefix, 'lime-600', $message );
}

/**
* Output a error message to the console.
*
* @param string $message Message to output.
* @param string $prefix Prefix to output.
* @return void
*/
public static function error( string $message, $prefix = 'Install' ): void {
static::message( $prefix, 'red-800', $message, 'red-100', 'pt-1' );
}

/**
* Display a formatted code block.
*
* @link https://github.com/nunomaduro/termwind#code
*
* @param string|string[] $code Code to display.
* @return void
*/
public static function code( $code ): void {
if ( is_array( $code ) ) {
$code = implode( PHP_EOL, $code );
}

render( "<div class=\"my-1\"><code>{$code}</code></div>" );
}
}
Loading