diff --git a/includes/Hautelook/Phpass/PasswordHash.php b/includes/Hautelook/Phpass/PasswordHash.php index a39f0d38d..06a3a6f39 100644 --- a/includes/Hautelook/Phpass/PasswordHash.php +++ b/includes/Hautelook/Phpass/PasswordHash.php @@ -36,22 +36,10 @@ */ class PasswordHash { - /** - * @var string - */ - private $itoa64; - /** - * @var int - */ - private $iteration_count_log2; - /** - * @var bool - */ - private $portable_hashes; - /** - * @var string - */ - private $random_state; + private string $itoa64; + private int $iteration_count_log2; + private bool $portable_hashes; + private string $random_state; /** * Constructor diff --git a/includes/cli-server/router.php b/includes/cli-server/router.php index d7e85a3fe..9a8648a5b 100644 --- a/includes/cli-server/router.php +++ b/includes/cli-server/router.php @@ -4,40 +4,29 @@ * Extracted from the `wp-cli` project: https://wp-cli.org/ */ -if (function_exists('uopz_allow_exit')) { - uopz_allow_exit(true); -} - $root = $_SERVER['DOCUMENT_ROOT']; -$path = '/' . ltrim(parse_url(urldecode($_SERVER['REQUEST_URI']), PHP_URL_PATH), '/'); +$path = '/'. ltrim( parse_url( urldecode( $_SERVER['REQUEST_URI'] ),PHP_URL_PATH ), '/' ); define('DB_ENGINE', getenv('DB_ENGINE') ?: 'mysql'); -// The self-call will slow down the response handling and will not benefit the test environment. -global $wp_filter; -$wp_filter['do_mu_upgrade'][10][] = [ - 'accepted_args' => 0, - 'function' => static function () { - return false; - } -]; +if ( file_exists( $root.$path ) ) { -if (file_exists($root . $path)) { - // Enforces trailing slash, keeping links tidy in the admin - if (is_dir($root . $path) && substr_compare($path, '/', -strlen('/')) !== 0) { - header("Location: $path/"); - exit; - } + // Enforces trailing slash, keeping links tidy in the admin + if ( is_dir( $root.$path ) && ! str_ends_with( $path, '/' ) ) { + header( "Location: $path/" ); + exit; + } - // Runs PHP file if it exists - if (strpos($path, '.php') !== false) { - chdir(dirname($root . $path)); - require_once $root . $path; - } else { - return false; - } + // Runs PHP file if it exists + if ( str_contains( $path, '.php' ) ) { + chdir( dirname( $root.$path ) ); + require_once $root.$path; + } else { + return false; + } } else { - // Otherwise, run `index.php` - chdir($root); - require_once 'index.php'; + + // Otherwise, run `index.php` + chdir( $root ); + require_once 'index.php'; } diff --git a/includes/core-phpunit/includes/abstract-testcase.php b/includes/core-phpunit/includes/abstract-testcase.php index 4a195960a..67c4d71ce 100644 --- a/includes/core-phpunit/includes/abstract-testcase.php +++ b/includes/core-phpunit/includes/abstract-testcase.php @@ -20,10 +20,7 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase { protected $expected_doing_it_wrong = array(); protected $caught_doing_it_wrong = array(); - /** - * @var string|null - */ - private static $calledClass; + private static ?string $calledClass = null; protected static $hooks_saved = array(); protected static $ignore_files; diff --git a/includes/core-phpunit/includes/functions.php b/includes/core-phpunit/includes/functions.php index 81d4339db..c2976dba9 100644 --- a/includes/core-phpunit/includes/functions.php +++ b/includes/core-phpunit/includes/functions.php @@ -339,10 +339,26 @@ function _wp_rest_server_class_filter() { * @since 5.0.0 */ function _unhook_block_registration() { + // Block types. require __DIR__ . '/unregister-blocks-hooks.php'; remove_action( 'init', 'register_core_block_types_from_metadata' ); remove_action( 'init', 'register_block_core_legacy_widget' ); remove_action( 'init', 'register_block_core_widget_group' ); remove_action( 'init', 'register_core_block_types_from_metadata' ); + + // Block binding sources. + remove_action( 'init', '_register_block_bindings_pattern_overrides_source' ); + remove_action( 'init', '_register_block_bindings_post_meta_source' ); } tests_add_filter( 'init', '_unhook_block_registration', 1000 ); + +/** + * After the init action has been run once, trying to re-register font collections can cause + * errors. To avoid this, unhook the font registration functions. + * + * @since 6.5.0 + */ +function _unhook_font_registration() { + remove_action( 'init', '_wp_register_default_font_collections' ); +} +tests_add_filter( 'init', '_unhook_font_registration', 1000 ); diff --git a/includes/core-phpunit/includes/testcase-rest-api.php b/includes/core-phpunit/includes/testcase-rest-api.php index 670a2cd1f..144bcc93c 100644 --- a/includes/core-phpunit/includes/testcase-rest-api.php +++ b/includes/core-phpunit/includes/testcase-rest-api.php @@ -5,7 +5,7 @@ abstract class WPRestApiTestCase extends WPTestCase { protected function assertErrorResponse( $code, $response, $status = null ) { - if ( $response instanceof WP_REST_Response ) { + if ( $response instanceof \WP_REST_Response ) { $response = $response->as_error(); } diff --git a/includes/core-phpunit/includes/unregister-blocks-hooks.php b/includes/core-phpunit/includes/unregister-blocks-hooks.php index 164c9c98d..65f2db4e2 100644 --- a/includes/core-phpunit/includes/unregister-blocks-hooks.php +++ b/includes/core-phpunit/includes/unregister-blocks-hooks.php @@ -64,3 +64,9 @@ remove_action( 'init', 'register_block_core_tag_cloud' ); remove_action( 'init', 'register_block_core_template_part' ); remove_action( 'init', 'register_block_core_term_description' ); + +// Temporary hook removals to prevent impacting the phpunit tests timing. +remove_action( 'registered_post_type', 'block_core_navigation_link_register_post_type_variation' ); +remove_action( 'registered_taxonomy', 'block_core_navigation_link_register_taxonomy_variation' ); +remove_action( 'unregistered_post_type', 'block_core_navigation_link_unregister_post_type_variation' ); +remove_action( 'unregistered_taxonomy', 'block_core_navigation_link_unregister_taxonomy_variation' ); diff --git a/includes/sqlite-database-integration/activate.php b/includes/sqlite-database-integration/activate.php index 6af9ba198..e91e18194 100644 --- a/includes/sqlite-database-integration/activate.php +++ b/includes/sqlite-database-integration/activate.php @@ -15,8 +15,9 @@ */ function sqlite_plugin_activation_redirect( $plugin ) { if ( plugin_basename( SQLITE_MAIN_FILE ) === $plugin ) { - wp_redirect( admin_url( 'options-general.php?page=sqlite-integration' ) ); - exit; + if ( wp_safe_redirect( admin_url( 'options-general.php?page=sqlite-integration' ) ) ) { + exit; + } } } add_action( 'activated_plugin', 'sqlite_plugin_activation_redirect' ); diff --git a/includes/sqlite-database-integration/admin-page.php b/includes/sqlite-database-integration/admin-page.php index 99b513980..f0528e886 100644 --- a/includes/sqlite-database-integration/admin-page.php +++ b/includes/sqlite-database-integration/admin-page.php @@ -12,7 +12,13 @@ * @since 1.0.0 */ function sqlite_add_admin_menu() { - add_options_page(__( 'SQLite integration', 'sqlite-database-integration' ), __( 'SQLite integration', 'sqlite-database-integration' ), 'manage_options', 'sqlite-integration', 'sqlite_integration_admin_screen'); + add_options_page( + __( 'SQLite integration', 'sqlite-database-integration' ), + __( 'SQLite integration', 'sqlite-database-integration' ), + 'manage_options', + 'sqlite-integration', + 'sqlite_integration_admin_screen' + ); } add_action( 'admin_menu', 'sqlite_add_admin_menu' ); diff --git a/includes/sqlite-database-integration/deactivate.php b/includes/sqlite-database-integration/deactivate.php index b64fbcfe0..2b79d9a33 100644 --- a/includes/sqlite-database-integration/deactivate.php +++ b/includes/sqlite-database-integration/deactivate.php @@ -33,7 +33,7 @@ function sqlite_plugin_remove_db_file() { // Run an action on `shutdown`, to deactivate the option in the MySQL database. add_action( 'shutdown', - function() { + function () { global $table_prefix; // Get credentials for the MySQL database. diff --git a/includes/sqlite-database-integration/load.php b/includes/sqlite-database-integration/load.php index c082c78f9..5dc7acad2 100644 --- a/includes/sqlite-database-integration/load.php +++ b/includes/sqlite-database-integration/load.php @@ -2,9 +2,9 @@ /** * Plugin Name: SQLite Database Integration * Description: SQLite database driver drop-in. - * Author: WordPress Performance Team - * Version: 2.1.2 - * Requires PHP: 5.6 + * Author: The WordPress Team + * Version: 2.1.6 + * Requires PHP: 7.0 * Textdomain: sqlite-database-integration * * This feature plugin allows WordPress to use SQLite instead of MySQL as its database. diff --git a/includes/sqlite-database-integration/readme.txt b/includes/sqlite-database-integration/readme.txt index 83f67a866..e2e3c18ae 100644 --- a/includes/sqlite-database-integration/readme.txt +++ b/includes/sqlite-database-integration/readme.txt @@ -4,12 +4,12 @@ Contributors: wordpressdotorg, aristath Requires at least: 6.0 Tested up to: 6.4 Requires PHP: 5.6 -Stable tag: 2.1.2 +Stable tag: 2.1.6 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: performance, database -SQLite-integration plugin from the WordPress Performance Team. +SQLite integration plugin by the WordPress Team. == Description == diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php index b3db03574..ed80e19b5 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php @@ -103,7 +103,7 @@ public function select( $db, $dbh = null ) { * * @return string escaped */ - function _real_escape( $str ) { + public function _real_escape( $str ) { return addslashes( $str ); } @@ -278,7 +278,7 @@ public function query( $query ) { } $this->result = $this->dbh->query( $query ); - $this->num_queries++; + ++$this->num_queries; if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); @@ -349,7 +349,7 @@ public function has_cap( $db_cap ) { * @see wpdb::db_version() */ public function db_version() { - return '5.5'; + return '8.0'; } /** diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php index f61e59e37..5e7cc6584 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php @@ -1,6 +1,6 @@ $method(); if ( $token ) { @@ -1668,10 +1668,10 @@ private function solve_ambiguity_on_function_keywords() { $next = $this->tokens_get_next(); if ( ( WP_SQLite_Token::TYPE_KEYWORD !== $next->type - || ! in_array( $next->value, $this->keyword_name_indicators, true ) + || ! in_array( $next->value, self::KEYWORD_NAME_INDICATORS, true ) ) && ( WP_SQLite_Token::TYPE_OPERATOR !== $next->type - || ! in_array( $next->value, $this->operator_name_indicators, true ) + || ! in_array( $next->value, self::OPERATOR_NAME_INDICATORS, true ) ) && ( null !== $next->value ) ) { @@ -2068,7 +2068,7 @@ public function parse_number() { } elseif ( $this->last + 1 < $this->string_length && '0' === $this->str[ $this->last ] - && ( 'x' === $this->str[ $this->last + 1 ] || 'X' === $this->str[ $this->last + 1 ] ) + && 'x' === $this->str[ $this->last + 1 ] ) { $token .= $this->str[ $this->last++ ]; $state = 2; @@ -2260,7 +2260,7 @@ public function parse_symbol() { if ( null === $str ) { $str = $this->parse_unknown(); - if ( null === $str ) { + if ( null === $str && ! ( $flags & WP_SQLite_Token::FLAG_SYMBOL_PARAMETER ) ) { $this->error( 'Variable name was expected.', $this->str[ $this->last ], $this->last ); } } @@ -2288,7 +2288,7 @@ public function parse_unknown() { $token .= $this->str[ $this->last ]; // Test if end of token equals the current delimiter. If so, remove it from the token. - if ( substr_compare($token, $this->delimiter, -strlen($this->delimiter)) === 0 ) { + if ( str_ends_with( $token, $this->delimiter ) ) { $token = substr( $token, 0, -$this->delimiter_length ); $this->last -= $this->delimiter_length - 1; break; @@ -2514,15 +2514,10 @@ public static function is_separator( $str ) { * Constructor. * * @param stdClass[] $tokens The initial array of tokens. - * @param int $count The count of tokens in the initial array. */ - public function tokens( array $tokens = array(), $count = -1 ) { - if ( empty( $tokens ) ) { - return; - } - + public function tokens( array $tokens = array() ) { $this->tokens = $tokens; - $this->tokens_count = -1 === $count ? count( $tokens ) : $count; + $this->tokens_count = count( $tokens ); } /** diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php index 59c6ae607..7d4ac5ee7 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php @@ -221,7 +221,7 @@ public function month( $field ) { * From https://www.php.net/manual/en/datetime.format.php: * * n - Numeric representation of a month, without leading zeros. - * 1 through 12 + * 1 through 12 */ return intval( gmdate( 'n', strtotime( $field ) ) ); } @@ -446,14 +446,14 @@ public function isnull( $field ) { * * As 'IF' is a reserved word for PHP, function name must be changed. * - * @param mixed $expression the statement to be evaluated as true or false. - * @param mixed $true statement or value returned if $expression is true. - * @param mixed $false statement or value returned if $expression is false. + * @param mixed $expression The statement to be evaluated as true or false. + * @param mixed $truthy Statement or value returned if $expression is true. + * @param mixed $falsy Statement or value returned if $expression is false. * * @return mixed */ - public function _if( $expression, $true, $false ) { - return ( true === $expression ) ? $true : $false; + public function _if( $expression, $truthy, $falsy ) { + return ( true === $expression ) ? $truthy : $falsy; } /** diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php index 5d1a6c47a..9976cf341 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php @@ -161,7 +161,7 @@ class WP_SQLite_Token { * * @var mixed|string|null */ - public $keyword; + public $keyword = null; /** * The type of this token. @@ -195,11 +195,10 @@ class WP_SQLite_Token { * @param int $flags The flags of the token. */ public function __construct( $token, $type = 0, $flags = 0 ) { - $this->token = $token; - $this->type = $type; - $this->flags = $flags; - $this->keyword = null; - $this->value = $this->extract(); + $this->token = $token; + $this->type = $type; + $this->flags = $flags; + $this->value = $this->extract(); } /** @@ -262,8 +261,8 @@ private function extract() { case self::TYPE_NUMBER: $ret = str_replace( '--', '', $this->token ); // e.g. ---42 === -42. if ( $this->flags & self::FLAG_NUMBER_HEX ) { + $ret = str_replace( array( '-', '+' ), '', $this->token ); if ( $this->flags & self::FLAG_NUMBER_NEGATIVE ) { - $ret = str_replace( '-', '', $this->token ); $ret = -hexdec( $ret ); } else { $ret = hexdec( $ret ); diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php index 0f1d4a302..9c784244b 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -31,6 +31,8 @@ class WP_SQLite_Translator { /** * Class variable to reference to the PDO instance. * + * @access private + * * @var PDO object */ private $pdo; @@ -168,6 +170,20 @@ class WP_SQLite_Translator { */ public $executed_sqlite_queries = array(); + /** + * The affected table name. + * + * @var array + */ + private $table_name = array(); + + /** + * The type of the executed query (SELECT, INSERT, etc). + * + * @var array + */ + private $query_type = array(); + /** * The columns to insert. * @@ -178,6 +194,8 @@ class WP_SQLite_Translator { /** * Class variable to store the result of the query. * + * @access private + * * @var array reference to the PHP object */ private $results = null; @@ -192,6 +210,8 @@ class WP_SQLite_Translator { /** * Class variable to store the file name and function to cause error. * + * @access private + * * @var array */ private $errors; @@ -199,6 +219,8 @@ class WP_SQLite_Translator { /** * Class variable to store the error messages. * + * @access private + * * @var array */ private $error_messages = array(); @@ -207,6 +229,7 @@ class WP_SQLite_Translator { * Class variable to store the affected row id. * * @var int integer + * @access private */ private $last_insert_id; @@ -243,7 +266,7 @@ class WP_SQLite_Translator { /** * Variable to keep track of nested transactions level. * - * @var number + * @var int */ private $transaction_level = 0; @@ -312,6 +335,13 @@ class WP_SQLite_Translator { */ private $sqlite_system_tables = array(); + /** + * The last error message from SQLite. + * + * @var string + */ + private $last_sqlite_error; + /** * Constructor. * @@ -385,7 +415,8 @@ public function __construct( $pdo = null ) { // WordPress happens to use no foreign keys. $statement = $this->pdo->query( 'PRAGMA foreign_keys' ); - if ( $statement->fetchColumn( 0 ) == '0' ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual + if ( $statement->fetchColumn( 0 ) == '0' ) { $this->pdo->query( 'PRAGMA foreign_keys = ON' ); } $this->pdo->query( 'PRAGMA encoding="UTF-8";' ); @@ -399,7 +430,7 @@ public function __construct( $pdo = null ) { * * This definition is changed since version 1.7. */ - function __destruct() { + public function __destruct() { if ( defined( 'SQLITE_MEM_DEBUG' ) && SQLITE_MEM_DEBUG ) { $max = ini_get( 'memory_limit' ); if ( is_null( $max ) ) { @@ -591,8 +622,31 @@ public function query( $statement, $mode = PDO::FETCH_OBJ, ...$fetch_mode_args ) } } while ( $error ); + /** + * Notifies that a query has been translated and executed. + * + * @param string $query The executed SQL query. + * @param string $query_type The type of the SQL query (e.g. SELECT, INSERT, UPDATE, DELETE). + * @param string $table_name The name of the table affected by the SQL query. + * @param array $insert_columns The columns affected by the INSERT query (if applicable). + * @param int $last_insert_id The ID of the last inserted row (if applicable). + * @param int $affected_rows The number of affected rows (if applicable). + * + * @since 0.1.0 + */ + do_action( + 'sqlite_translated_query_executed', + $this->mysql_query, + $this->query_type, + $this->table_name, + $this->insert_columns, + $this->last_insert_id, + $this->affected_rows + ); + // Commit the nested transaction. $this->commit(); + return $this->return_value; } catch ( Exception $err ) { // Rollback the nested transaction. @@ -710,11 +764,11 @@ public function get_return_value() { * @throws Exception If the query is not supported. */ private function execute_mysql_query( $query ) { - $tokens = ( new WP_SQLite_Lexer( $query ) )->tokens; - $this->rewriter = new WP_SQLite_Query_Rewriter( $tokens ); - $query_type = $this->rewriter->peek()->value; + $tokens = ( new WP_SQLite_Lexer( $query ) )->tokens; + $this->rewriter = new WP_SQLite_Query_Rewriter( $tokens ); + $this->query_type = $this->rewriter->peek()->value; - switch ( $query_type ) { + switch ( $this->query_type ) { case 'ALTER': $this->execute_alter(); break; @@ -785,11 +839,11 @@ private function execute_mysql_query( $query ) { case 'OPTIMIZE': case 'REPAIR': case 'ANALYZE': - $this->execute_optimize( $query_type ); + $this->execute_optimize( $this->query_type ); break; default: - throw new Exception( 'Unknown query type: ' . $query_type ); + throw new Exception( 'Unknown query type: ' . $this->query_type ); } } @@ -1204,7 +1258,7 @@ private function execute_delete() { // Naive rewriting of DELETE JOIN query. // @TODO: Actually rewrite the query instead of using a hardcoded workaround. - if ( strpos($updated_query, ' JOIN ') !== false ) { + if ( str_contains( $updated_query, ' JOIN ' ) ) { $table_prefix = isset( $GLOBALS['table_prefix'] ) ? $GLOBALS['table_prefix'] : 'wp_'; $this->execute_sqlite_query( "DELETE FROM {$table_prefix}options WHERE option_id IN (SELECT MIN(option_id) FROM {$table_prefix}options GROUP BY option_name HAVING COUNT(*) > 1)" @@ -1241,7 +1295,7 @@ private function execute_delete() { // SELECT to fetch the IDs of the rows to delete, then delete them // using a separate DELETE query. - $table_name = $rewriter->skip()->value; + $this->table_name = $rewriter->skip()->value; $rewriter->add( new WP_SQLite_Token( 'SELECT', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) ); /* @@ -1257,11 +1311,11 @@ private function execute_delete() { for ( $i = $index + 1; $i < $rewriter->max; $i++ ) { // Assume the table name is the first token after FROM. if ( ! $rewriter->input_tokens[ $i ]->is_semantically_void() ) { - $table_name = $rewriter->input_tokens[ $i ]->value; + $this->table_name = $rewriter->input_tokens[ $i ]->value; break; } } - if ( ! $table_name ) { + if ( ! $this->table_name ) { throw new Exception( 'Could not find table name for dual delete query.' ); } @@ -1269,7 +1323,7 @@ private function execute_delete() { * Now, let's figure out the primary key name. * This assumes that all listed table names are the same. */ - $q = $this->execute_sqlite_query( 'SELECT l.name FROM pragma_table_info("' . $table_name . '") as l WHERE l.pk = 1;' ); + $q = $this->execute_sqlite_query( 'SELECT l.name FROM pragma_table_info("' . $this->table_name . '") as l WHERE l.pk = 1;' ); $pk_name = $q->fetch()['name']; /* @@ -1317,8 +1371,8 @@ private function execute_delete() { $query = ( count( $ids_to_delete ) - ? "DELETE FROM {$table_name} WHERE {$pk_name} IN (" . implode( ',', $ids_to_delete ) . ')' - : "DELETE FROM {$table_name} WHERE 0=1" + ? "DELETE FROM {$this->table_name} WHERE {$pk_name} IN (" . implode( ',', $ids_to_delete ) . ')' + : "DELETE FROM {$this->table_name} WHERE 0=1" ); $this->execute_sqlite_query( $query ); $this->set_result_from_affected_rows( @@ -1346,7 +1400,8 @@ private function execute_select() { $this->remember_last_reserved_keyword( $token ); if ( ! $table_name ) { - $table_name = $this->peek_table_name( $token ); + $this->table_name = $this->peek_table_name( $token ); + $table_name = $this->peek_table_name( $token ); } if ( $this->skip_sql_calc_found_rows( $token ) ) { @@ -1367,7 +1422,7 @@ private function execute_select() { $updated_query = $this->rewriter->get_updated_query(); - if ( $table_name && strncmp(strtolower( $table_name ), 'information_schema', strlen('information_schema')) === 0 ) { + if ( $table_name && str_starts_with( strtolower( $table_name ), 'information_schema' ) ) { $this->is_information_schema_query = true; $updated_query = $this->get_information_schema_query( $updated_query ); $params = array(); @@ -1418,7 +1473,9 @@ private function execute_select() { */ private function execute_truncate() { $this->rewriter->skip(); // TRUNCATE. - $this->rewriter->skip(); // TABLE. + if ( 'TABLE' === strtoupper( $this->rewriter->peek()->value ) ) { + $this->rewriter->skip(); // TABLE. + } $this->rewriter->add( new WP_SQLite_Token( 'DELETE', WP_SQLite_Token::TYPE_KEYWORD ) ); $this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) ); $this->rewriter->add( new WP_SQLite_Token( 'FROM', WP_SQLite_Token::TYPE_KEYWORD ) ); @@ -1435,8 +1492,8 @@ private function execute_truncate() { */ private function execute_describe() { $this->rewriter->skip(); - $table_name = $this->rewriter->consume()->value; - $stmt = $this->execute_sqlite_query( + $this->table_name = $this->rewriter->consume()->value; + $stmt = $this->execute_sqlite_query( "SELECT `name` as `Field`, ( @@ -1465,9 +1522,9 @@ private function execute_describe() { ELSE 'PRI' END ) as `Key` - FROM pragma_table_info(\"$table_name\") p + FROM pragma_table_info(\"$this->table_name\") p LEFT JOIN " . self::DATA_TYPES_CACHE_TABLE . " d - ON d.`table` = \"$table_name\" + ON d.`table` = \"$this->table_name\" AND d.`column_or_index` = p.`name` ; " @@ -1493,6 +1550,17 @@ private function execute_update() { break; } + // Record the table name. + if ( + ! $this->table_name && + ! $token->matches( + WP_SQLite_Token::TYPE_KEYWORD, + WP_SQLite_Token::FLAG_KEYWORD_RESERVED + ) + ) { + $this->table_name = $token->value; + } + $this->remember_last_reserved_keyword( $token ); if ( @@ -1517,7 +1585,6 @@ private function execute_update() { private function execute_insert_or_replace() { $params = array(); $is_in_duplicate_section = false; - $table_name = null; $this->rewriter->consume(); // INSERT or REPLACE. @@ -1531,7 +1598,7 @@ private function execute_insert_or_replace() { // Consume and record the table name. $this->insert_columns = array(); $this->rewriter->consume(); // INTO. - $table_name = $this->rewriter->consume()->value; // Table name. + $this->table_name = $this->rewriter->consume()->value; // Table name. /* * A list of columns is given if the opening parenthesis @@ -1590,7 +1657,7 @@ private function execute_insert_or_replace() { ) ) { $is_in_duplicate_section = true; - $this->translate_on_duplicate_key( $table_name ); + $this->translate_on_duplicate_key( $this->table_name ); continue; } @@ -1606,6 +1673,7 @@ private function execute_insert_or_replace() { if ( is_numeric( $this->last_insert_id ) ) { $this->last_insert_id = (int) $this->last_insert_id; } + $this->last_insert_id = apply_filters( 'sqlite_last_insert_id', $this->last_insert_id, $this->table_name ); } /** @@ -1683,9 +1751,9 @@ private function preprocess_string_literal( $value ) { private function preprocess_like_expr( &$token ) { /* * This code handles escaped wildcards in LIKE clauses. - * If we are within a LIKE expression, we look for \_ and \%, the + * If we are within a LIKE experession, we look for \_ and \%, the * escaped LIKE wildcards, the ones where we want a literal, not a - * wildcard match. We change the \ escape for an ASCII \x1A (SUB) character, + * wildcard match. We change the \ escape for an ASCII \x1a (SUB) character, * so the \ characters won't get munged. * These \_ and \% escape sequences are in the token name, because * the lexer has already done stripcslashes on the value. @@ -1693,8 +1761,8 @@ private function preprocess_like_expr( &$token ) { if ( $this->like_expression_nesting > 0 ) { /* Remove the quotes around the name. */ $unescaped_value = mb_substr( $token->token, 1, -1, 'UTF-8' ); - if ( strpos($unescaped_value, '\_') !== false || strpos($unescaped_value, '\%') !== false ) { - $this->like_escape_count ++; + if ( str_contains( $unescaped_value, '\_' ) || str_contains( $unescaped_value, '\%' ) ) { + ++$this->like_escape_count; return str_replace( array( '\_', '\%' ), array( self::LIKE_ESCAPE_CHAR . '_', self::LIKE_ESCAPE_CHAR . '%' ), @@ -2320,14 +2388,14 @@ private function translate_like_escape( $token ) { } else { /* open parenthesis during LIKE parameter, count it. */ if ( $token->matches( WP_SQLite_Token::TYPE_OPERATOR, null, array( '(' ) ) ) { - $this->like_expression_nesting ++; + ++$this->like_expression_nesting; return false; } /* close parenthesis matching open parenthesis during LIKE parameter, count it. */ if ( $this->like_expression_nesting > 1 && $token->matches( WP_SQLite_Token::TYPE_OPERATOR, null, array( ')' ) ) ) { - $this->like_expression_nesting --; + --$this->like_expression_nesting; return false; } @@ -2368,7 +2436,7 @@ private function translate_like_escape( $token ) { private function get_information_schema_query( $updated_query ) { // @TODO: Actually rewrite the columns. $normalized_query = preg_replace( '/\s+/', ' ', strtolower( $updated_query ) ); - if ( strpos($normalized_query, 'bytes') !== false ) { + if ( str_contains( $normalized_query, 'bytes' ) ) { // Count rows per table. $tables = $this->execute_sqlite_query( "SELECT name as `table_name` FROM sqlite_master WHERE type='table' ORDER BY name" )->fetchAll(); @@ -2383,7 +2451,7 @@ private function get_information_schema_query( $updated_query ) { $rows .= 'ELSE 0 END) '; $updated_query = "SELECT name as `table_name`, $rows as `rows`, 0 as `bytes` FROM sqlite_master WHERE type='table' ORDER BY name"; - } elseif ( strpos($normalized_query, 'count(*)') !== false && strpos($normalized_query, 'table_name =') === false ) { + } elseif ( str_contains( $normalized_query, 'count(*)' ) && ! str_contains( $normalized_query, 'table_name =' ) ) { // @TODO This is a guess that the caller wants a count of tables. $list = array(); foreach ( $this->sqlite_system_tables as $system_table => $name ) { @@ -2415,12 +2483,20 @@ private function strip_sqlite_system_tables( $tables ) { array_filter( $tables, function ( $table ) { - // Bail early if $table is not an object. - if ( ! is_object( $table ) ) { - return true; + $table_name = false; + if ( is_array( $table ) ) { + if ( isset( $table['Name'] ) ) { + $table_name = $table['Name']; + } elseif ( isset( $table['table_name'] ) ) { + $table_name = $table['table_name']; + } + } elseif ( is_object( $table ) ) { + $table_name = property_exists( $table, 'Name' ) + ? $table->Name // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase + : $table->table_name; } - $table_name = property_exists( $table, 'Name' ) ? $table->Name : $table->table_name; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - return ! array_key_exists( $table_name, $this->sqlite_system_tables ); + + return $table_name && ! array_key_exists( $table_name, $this->sqlite_system_tables ); }, ARRAY_FILTER_USE_BOTH ) @@ -2591,7 +2667,7 @@ private function execute_alter() { throw new Exception( 'Unknown subject: ' . $subject ); } - $table_name = $this->normalize_column_name( $this->rewriter->consume()->token ); + $this->table_name = $this->normalize_column_name( $this->rewriter->consume()->token ); do { /* * This loop may be executed multiple times if there are multiple operations in the ALTER query. @@ -2603,13 +2679,13 @@ private function execute_alter() { new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( 'TABLE', WP_SQLite_Token::TYPE_KEYWORD ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), - new WP_SQLite_Token( $table_name, WP_SQLite_Token::TYPE_KEYWORD ), + new WP_SQLite_Token( $this->table_name, WP_SQLite_Token::TYPE_KEYWORD ), ) ); $op_type = strtoupper( $this->rewriter->consume()->token ); $op_subject = strtoupper( $this->rewriter->consume()->token ); $mysql_index_type = $this->normalize_mysql_index_type( $op_subject ); - $is_index_op = ! ! $mysql_index_type; + $is_index_op = (bool) $mysql_index_type; if ( 'ADD' === $op_type && 'COLUMN' === $op_subject ) { $column_name = $this->rewriter->consume()->value; @@ -2626,7 +2702,7 @@ private function execute_alter() { ) ); $this->update_data_type_cache( - $table_name, + $this->table_name, $column_name, $mysql_data_type ); @@ -2638,7 +2714,7 @@ private function execute_alter() { $new_field = $this->parse_mysql_create_table_field(); $alter_terminator = end( $this->rewriter->output_tokens ); $this->update_data_type_cache( - $table_name, + $this->table_name, $new_field->name, $new_field->mysql_data_type ); @@ -2659,8 +2735,8 @@ private function execute_alter() { */ // 1. Get the existing table schema. - $old_schema = $this->get_sqlite_create_table( $table_name ); - $old_indexes = $this->get_keys( $table_name, false ); + $old_schema = $this->get_sqlite_create_table( $this->table_name ); + $old_indexes = $this->get_keys( $this->table_name, false ); // 2. Adjust the column definition. @@ -2718,19 +2794,19 @@ private function execute_alter() { } // 3. Copy the data out of the old table - $cache_table_name = "_tmp__{$table_name}_" . rand( 10000000, 99999999 ); + $cache_table_name = "_tmp__{$this->table_name}_" . rand( 10000000, 99999999 ); $this->execute_sqlite_query( - "CREATE TABLE `$cache_table_name` as SELECT * FROM `$table_name`" + "CREATE TABLE `$cache_table_name` as SELECT * FROM `$this->table_name`" ); // 4. Drop the old table to free up the indexes names - $this->execute_sqlite_query( "DROP TABLE `$table_name`" ); + $this->execute_sqlite_query( "DROP TABLE `$this->table_name`" ); // 5. Create a new table from the updated schema $this->execute_sqlite_query( $create_table->get_updated_query() ); // 6. Copy the data from step 3 to the new table - $this->execute_sqlite_query( "INSERT INTO {$table_name} SELECT * FROM $cache_table_name" ); + $this->execute_sqlite_query( "INSERT INTO {$this->table_name} SELECT * FROM $cache_table_name" ); // 7. Drop the old table copy $this->execute_sqlite_query( "DROP TABLE `$cache_table_name`" ); @@ -2741,7 +2817,7 @@ private function execute_alter() { * Skip indexes prefixed with sqlite_autoindex_ * (these are automatically created by SQLite). */ - if ( strncmp($row['index']['name'], 'sqlite_autoindex_', strlen('sqlite_autoindex_')) === 0 ) { + if ( str_starts_with( $row['index']['name'], 'sqlite_autoindex_' ) ) { continue; } @@ -2759,7 +2835,7 @@ private function execute_alter() { * a part of the CREATE TABLE statement */ $this->execute_sqlite_query( - "CREATE $unique INDEX IF NOT EXISTS `{$row['index']['name']}` ON $table_name (" . implode( ', ', $columns ) . ')' + "CREATE $unique INDEX IF NOT EXISTS `{$row['index']['name']}` ON $this->table_name (" . implode( ', ', $columns ) . ')' ); } @@ -2776,7 +2852,7 @@ private function execute_alter() { } elseif ( 'ADD' === $op_type && $is_index_op ) { $key_name = $this->rewriter->consume()->value; $sqlite_index_type = $this->mysql_index_type_to_sqlite_type( $mysql_index_type ); - $sqlite_index_name = "{$table_name}__$key_name"; + $sqlite_index_name = "{$this->table_name}__$key_name"; $this->rewriter->replace_all( array( new WP_SQLite_Token( 'CREATE', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ), @@ -2787,13 +2863,13 @@ private function execute_alter() { new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( 'ON', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), - new WP_SQLite_Token( '"' . $table_name . '"', WP_SQLite_Token::TYPE_STRING, WP_SQLite_Token::FLAG_STRING_DOUBLE_QUOTES ), + new WP_SQLite_Token( '"' . $this->table_name . '"', WP_SQLite_Token::TYPE_STRING, WP_SQLite_Token::FLAG_STRING_DOUBLE_QUOTES ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( '(', WP_SQLite_Token::TYPE_OPERATOR ), ) ); $this->update_data_type_cache( - $table_name, + $this->table_name, $sqlite_index_name, $mysql_index_type ); @@ -2841,7 +2917,7 @@ private function execute_alter() { new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( 'INDEX', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), - new WP_SQLite_Token( "\"{$table_name}__$key_name\"", WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_KEY ), + new WP_SQLite_Token( "\"{$this->table_name}__$key_name\"", WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_KEY ), ) ); } else { @@ -3024,11 +3100,11 @@ function ( $row ) use ( $name_map ) { * the same as in the original CREATE TABLE. Let's * translate the name back. */ - if ( strncmp($mysql_key_name, 'sqlite_autoindex_', strlen('sqlite_autoindex_')) === 0 ) { + if ( str_starts_with( $mysql_key_name, 'sqlite_autoindex_' ) ) { $mysql_key_name = substr( $mysql_key_name, strlen( 'sqlite_autoindex_' ) ); $mysql_key_name = preg_replace( '/_[0-9]+$/', '', $mysql_key_name ); } - if ( strncmp($mysql_key_name, "{$table_name}__", strlen("{$table_name}__")) === 0 ) { + if ( str_starts_with( $mysql_key_name, "{$table_name}__" ) ) { $mysql_key_name = substr( $mysql_key_name, strlen( "{$table_name}__" ) ); } @@ -3209,7 +3285,7 @@ private function get_cached_mysql_data_type( $table, $column_or_index ) { ) ); $mysql_type = $stmt->fetchColumn( 0 ); - if ( substr_compare($mysql_type, ' KEY', -strlen(' KEY')) === 0 ) { + if ( str_ends_with( $mysql_type, ' KEY' ) ) { $mysql_type = substr( $mysql_type, 0, strlen( $mysql_type ) - strlen( ' KEY' ) ); } return $mysql_type; @@ -3381,16 +3457,16 @@ private function handle_error( Exception $err ) { * When $wpdb::suppress_errors is set to true or $wpdb::show_errors is set to false, * the error messages are ignored. * - * @param string $line Where the error occurred. - * @param string $function Indicate the function name where the error occurred. - * @param string $message The message. + * @param string $line Where the error occurred. + * @param string $function_name Indicate the function name where the error occurred. + * @param string $message The message. * * @return boolean|void */ - private function set_error( $line, $function, $message ) { + private function set_error( $line, $function_name, $message ) { $this->errors[] = array( 'line' => $line, - 'function' => $function, + 'function' => $function_name, ); $this->error_messages[] = $message; $this->is_error = true; @@ -3543,8 +3619,10 @@ private function flush() { $this->mysql_query = ''; $this->results = null; $this->last_exec_returned = null; + $this->table_name = null; $this->last_insert_id = null; $this->affected_rows = null; + $this->insert_columns = array(); $this->column_data = array(); $this->num_rows = null; $this->return_value = null; @@ -3574,6 +3652,16 @@ public function begin_transaction() { } finally { if ( $success ) { ++$this->transaction_level; + /** + * Notifies that a transaction-related query has been translated and executed. + * + * @param string $command The SQL statement (one of "START TRANSACTION", "COMMIT", "ROLLBACK"). + * @param bool $success Whether the SQL statement was successful or not. + * @param int $nesting_level The nesting level of the transaction. + * + * @since 0.1.0 + */ + do_action( 'sqlite_transaction_query_executed', 'START TRANSACTION', (bool) $this->last_exec_returned, $this->transaction_level - 1 ); } } return $success; @@ -3595,6 +3683,8 @@ public function commit() { } else { $this->execute_sqlite_query( 'RELEASE SAVEPOINT LEVEL' . $this->transaction_level ); } + + do_action( 'sqlite_transaction_query_executed', 'COMMIT', (bool) $this->last_exec_returned, $this->transaction_level ); return $this->last_exec_returned; } @@ -3614,6 +3704,7 @@ public function rollback() { } else { $this->execute_sqlite_query( 'ROLLBACK TO SAVEPOINT LEVEL' . $this->transaction_level ); } + do_action( 'sqlite_transaction_query_executed', 'ROLLBACK', (bool) $this->last_exec_returned, $this->transaction_level ); return $this->last_exec_returned; } } diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/db.php b/includes/sqlite-database-integration/wp-includes/sqlite/db.php index 2053736a4..13c2111dc 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/db.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/db.php @@ -7,7 +7,7 @@ */ // Require the constants file. -require_once dirname( dirname( __DIR__ ) ) . '/constants.php'; +require_once dirname( __DIR__, 2 ) . '/constants.php'; // Bail early if DB_ENGINE is not defined as sqlite. if ( ! defined( 'DB_ENGINE' ) || 'sqlite' !== DB_ENGINE ) { @@ -56,7 +56,7 @@ * that are present in the GitHub repository * but not the plugin published on WordPress.org. */ -$crosscheck_tests_file_path = dirname( dirname( __DIR__ ) ) . '/tests/class-wp-sqlite-crosscheck-db.php'; +$crosscheck_tests_file_path = dirname( __DIR__, 2 ) . '/tests/class-wp-sqlite-crosscheck-db.php'; if ( defined( 'SQLITE_DEBUG_CROSSCHECK' ) && SQLITE_DEBUG_CROSSCHECK && file_exists( $crosscheck_tests_file_path ) ) { require_once $crosscheck_tests_file_path; $GLOBALS['wpdb'] = new WP_SQLite_Crosscheck_DB(); diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php b/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php index 87ace27b0..514516425 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php @@ -69,7 +69,7 @@ function sqlite_make_db_sqlite() { if ( defined( 'SQLITE_DEBUG_CROSSCHECK' ) && SQLITE_DEBUG_CROSSCHECK ) { $host = DB_HOST; $port = 3306; - if ( strpos($host, ':') !== false ) { + if ( str_contains( $host, ':' ) ) { $host_parts = explode( ':', $host ); $host = $host_parts[0]; $port = $host_parts[1]; @@ -89,7 +89,8 @@ function sqlite_make_db_sqlite() { } catch ( PDOException $err ) { $err_data = $err->errorInfo; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $err_code = $err_data[1]; - if ( 5 == $err_code || 6 == $err_code ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual + if ( 5 == $err_code || 6 == $err_code ) { // If the database is locked, commit again. $pdo_mysql->commit(); } else { diff --git a/src/Adapters/Symfony/Component/Process/Process.php b/src/Adapters/Symfony/Component/Process/Process.php index c9bc6e399..5ec966a1d 100644 --- a/src/Adapters/Symfony/Component/Process/Process.php +++ b/src/Adapters/Symfony/Component/Process/Process.php @@ -2,12 +2,18 @@ namespace lucatume\WPBrowser\Adapters\Symfony\Component\Process; +use ReflectionMethod; +use ReflectionProperty; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Pipes\PipesInterface; use Symfony\Component\Process\Process as SymfonyProcess; class Process extends SymfonyProcess { + /** + * @var bool|null + */ + private static $inheritEnvironmentVariables; /** * @var bool */ @@ -27,8 +33,15 @@ public function __construct( ?float $timeout = 60, array $options = null ) { - if (method_exists($this, 'inheritEnvironmentVariables')) { - parent::__construct($command, $cwd, $env, $input, $timeout, $options); //@phpstan-ignore-line + parent::__construct($command, $cwd, $env, $input, $timeout, $options); //@phpstan-ignore-line + + if (self::$inheritEnvironmentVariables === null) { + self::$inheritEnvironmentVariables = method_exists($this, 'inheritEnvironmentVariables') + && strpos((string)(new ReflectionMethod($this, 'inheritEnvironmentVariables'))->getDocComment(), '@deprecated') === false; + } + + if (self::$inheritEnvironmentVariables) { + // @phpstan-ignore-next-line $this->inheritEnvironmentVariables(true); } @@ -45,7 +58,7 @@ public function getStartTime(): float throw new LogicException('Start time is only available after process start.'); } - $startTimeReflectionProperty = new \ReflectionProperty(SymfonyProcess::class, 'starttime'); + $startTimeReflectionProperty = new ReflectionProperty(SymfonyProcess::class, 'starttime'); $startTimeReflectionProperty->setAccessible(true); /** @var float $startTime */ $startTime = $startTimeReflectionProperty->getValue($this); @@ -56,7 +69,7 @@ public function getStartTime(): float public function __destruct() { if ($this->createNewConsole) { - $processPipesProperty = new \ReflectionProperty(SymfonyProcess::class, 'processPipes'); + $processPipesProperty = new ReflectionProperty(SymfonyProcess::class, 'processPipes'); $processPipesProperty->setAccessible(true); /** @var PipesInterface $processPipes */ $processPipes = $processPipesProperty->getValue($this); @@ -72,7 +85,7 @@ public function createNewConsole(): void { $this->createNewConsole = true; - $optionsReflectionProperty = new \ReflectionProperty(SymfonyProcess::class, 'options'); + $optionsReflectionProperty = new ReflectionProperty(SymfonyProcess::class, 'options'); $optionsReflectionProperty->setAccessible(true); $options = $optionsReflectionProperty->getValue($this); $options = is_array($options) ? $options : []; @@ -90,7 +103,7 @@ public static function __callStatic(string $name, array $arguments) if ($name === 'fromShellCommandline') { $command = array_shift($arguments); $process = new self([], ...$arguments); // @phpstan-ignore-line - $processCommandLineProperty = new \ReflectionProperty(SymfonyProcess::class, 'commandline'); + $processCommandLineProperty = new ReflectionProperty(SymfonyProcess::class, 'commandline'); $processCommandLineProperty->setAccessible(true); $processCommandLineProperty->setValue($process, $command); diff --git a/src/Command/GenerateWPAjax.php b/src/Command/GenerateWPAjax.php new file mode 100644 index 000000000..7a29bd212 --- /dev/null +++ b/src/Command/GenerateWPAjax.php @@ -0,0 +1,27 @@ +getSuiteConfig($suite); $wpLoaderConfigs = $this->getConfigsForModules($suiteConfig, $modules); - if (count($wpLoaderConfigs) === 0) { - $wpLoaderConfigs = $this->getConfigsForModules($globalConfig, $modules); - } $wploaderCorrectLoad = count($wpLoaderConfigs) && array_reduce($wpLoaderConfigs, function ($carry, $config) { @@ -90,12 +86,9 @@ public function execute(InputInterface $input, OutputInterface $output): int /** @var string $class */ $class = $input->getArgument('class'); - /** @var array{namespace: string, actor: string, path: string} $config */ - $config = $this->getSuiteConfig($suite); - - $filename = $this->buildPath($config['path'], $class); + $filename = $this->buildPath($suiteConfig['path'], $class); - $gen = $this->getGenerator($config, $class); + $gen = $this->getGenerator($suiteConfig, $class); if (!$this->createFile($filename, $gen->produce())) { $output->writeln("Test $filename already exists"); @@ -131,11 +124,11 @@ protected function buildPath(string $path, string $class): string * @param array{namespace: string, actor: string} $config The generator configuration. * @param string $class The class to generate the test case for. * - * @return WPUnitGenerator An instance of the test case code generator. + * @return AbstractGenerator An instance of the test case code generator. */ - protected function getGenerator(array $config, string $class): WPUnitGenerator + protected function getGenerator(array $config, string $class): AbstractGenerator { - return new WPUnitGenerator($config, $class, WPTestCase::class); + return new WPUnitGenerator($config, $class); } /** diff --git a/src/Command/GenerateWPXML.php b/src/Command/GenerateWPXML.php new file mode 100644 index 000000000..74a02c101 --- /dev/null +++ b/src/Command/GenerateWPXML.php @@ -0,0 +1,28 @@ +addOption( + 'porcelain', + 'p', + InputOption::VALUE_NONE, + 'Suppress output.' + ); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $cacheDir = dirname(MonkeyPatch::getReplacementFileName(__FILE__, 'default')); + + if (!is_dir($cacheDir)) { + return 0; + } + + try { + FS::rrmdir($cacheDir) && FS::mkdirp($cacheDir); + } catch (\Throwable $t) { + $output->writeln("{$t->getMessage()}"); + return 1; + } + + if (!$input->hasOption('porcelain')) { + $output->writeln("Monkey patch cache cleared."); + } + + return 0; + } +} diff --git a/src/Command/MonkeyCachePath.php b/src/Command/MonkeyCachePath.php new file mode 100644 index 000000000..c3db8f1d4 --- /dev/null +++ b/src/Command/MonkeyCachePath.php @@ -0,0 +1,47 @@ +addOption( + 'porcelain', + 'p', + InputOption::VALUE_NONE, + 'Output only the path to the monkey patch directory.' + ); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $path = MonkeyPatch::getCachePath(); + + if ($input->hasOption('porcelain')) { + $output->writeln($path); + } else { + $output->writeln("Monkey patch cache path: {$path}"); + } + + return 0; + } +} diff --git a/src/Events/Dispatcher.php b/src/Events/Dispatcher.php index 69bf902a6..360189f25 100644 --- a/src/Events/Dispatcher.php +++ b/src/Events/Dispatcher.php @@ -103,7 +103,7 @@ public static function dispatch(string $name, $origin = null, array $context = [ $firstParameterReflection = $dispatchMethodReflection->getParameters()[0] ?? null; $firstParameterType = $firstParameterReflection ? $firstParameterReflection->getType() : null; if ($firstParameterType instanceof \ReflectionNamedType && $firstParameterType->getName() === 'object') { - return $eventDispatcher->dispatch($name, $event); + return $eventDispatcher->dispatch($event, $name); } return $eventDispatcher->dispatch($name, $event); //@phpstan-ignore-line diff --git a/src/Extension/EventDispatcherBridge.php b/src/Extension/EventDispatcherBridge.php index 8cffb03f2..2c2ec6e4b 100644 --- a/src/Extension/EventDispatcherBridge.php +++ b/src/Extension/EventDispatcherBridge.php @@ -7,7 +7,6 @@ use Codeception\Exception\ExtensionException; use Codeception\Extension; use lucatume\WPBrowser\Events\Dispatcher; -use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface as SymfonyEventDispatcher; class EventDispatcherBridge extends Extension diff --git a/src/Extension/IsolationSupport.php b/src/Extension/IsolationSupport.php new file mode 100644 index 000000000..dab9bb41e --- /dev/null +++ b/src/Extension/IsolationSupport.php @@ -0,0 +1,414 @@ + + */ + public static $events = [ + Events::SUITE_INIT => 'onSuiteInit', + Events::TEST_START => 'onTestStart', + Events::TEST_FAIL => 'onTestFail', + ]; + + /** + * @var string + */ + private $processCode = <<< PHP +\$dataName = \$this->getName(); +\$args = func_get_args(); +foreach(\$args as &\$arg){ + if(\$arg instanceof \Closure){ + \$arg = new \lucatume\WPBrowser\Opis\Closure\SerializableClosure(\$arg); + } +} +\$encodedDataSet = base64_encode(serialize(\$args)); +\$modules = \$this->getMetadata()->getCurrent('modules'); +\$wploderModuleNameInSuite = isset(\$modules['WPLoader']) ? 'WPLoader' : \lucatume\WPBrowser\Module\WPLoader::class; +\$command = [ + \lucatume\WPBrowser\Utils\Composer::binDir('codecept'), + \lucatume\WPBrowser\Command\RunOriginal::getCommandName(), + sprintf('%s:%s', codecept_relative_path('{{file}}'), '{{name}}'), + '--override', + "modules: config: {\$wploderModuleNameInSuite}: skipInstall: true", + '--ext', + 'IsolationSupport' +]; +\$process = new \lucatume\WPBrowser\Adapters\Symfony\Component\Process\Process( + \$command, + null, + [ + 'WPBROWSER_ISOLATED_RUN' => '1', + 'WPBROWSER_DATA_NAME' => \$dataName, + 'WPBROWSER_DATA_SET' => \$encodedDataSet, + 'WPBROWSER_TEST_FILE' => '{{file}}' + ], +); +\$exitCode = \$process->run(); + +if (\$exitCode !== 0) { + \$output = \$process->getOutput(); + preg_match( + '/WPBROWSER_ISOLATION_RESULT_START(.*)WPBROWSER_ISOLATION_RESULT_END/us', + \$output, + \$matches + ); + \$failure = \$matches[1] ?? null; + + if (\$failure === null) { + \$this->fail("Test failed: {\$process->getErrorOutput()}"); + } + \$serializableThrowable = unserialize(base64_decode(\$failure), ['allowed_classes' => true]); + throw(\$serializableThrowable->getThrowable()); +} +return; +PHP; + + /** + * @throws ExtensionException + */ + public function onSuiteInit(SuiteEvent $event): void + { + if ($this->isMainProcess()) { + $this->monkeyPatchTestCasesToRunInSeparateProcess($event); + return; + } + + $this->monkeyPatchTestMethodsToReplaceAnnotations(); + } + + private function isMainProcess(): bool + { + return empty($_SERVER['WPBROWSER_ISOLATED_RUN']); + } + + /** + * @throws ExtensionException + */ + protected function monkeyPatchTestCasesToRunInSeparateProcess(SuiteEvent $event): void + { + /** @var array{path: string} $settings */ + $settings = $event->getSettings(); + + /** @var Iterator $testFiles */ + $testFiles = new RegexIterator( + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($settings['path'], FilesystemIterator::CURRENT_AS_PATHNAME) + ), + '/Test\.php$/' + ); + + foreach ($testFiles as $testFile) { + $patchedFile = $this->getPatchedFile($testFile); + + if ($patchedFile === false) { + continue; + } + + MonkeyPatch::redirectFileToFile( + $testFile, + $patchedFile, + false, + self::MAIN_PROCESS_PATCH_CONTEXT + ); + } + } + + /** + * @throws ExtensionException + * @return string|false + */ + private function getPatchedFile(string $testFile) + { + $patchedFile = MonkeyPatch::getReplacementFileName( + $testFile, + self::MAIN_PROCESS_PATCH_CONTEXT + ); + + if (is_file($patchedFile)) { + return $patchedFile; + } + + $fileContents = file_get_contents($testFile); + + if ($fileContents === false) { + throw new ExtensionException($this, "Failed to to open {$testFile} for reading."); + } + + if (strpos($fileContents, '@runTestsInSeparateProcesses') !== false + || strpos($fileContents, '#[RunTestsInSeparateProcesses') !== false + ) { + return $this->patchFileContentsToRunTestsInSeparateProcesses($testFile, $fileContents); + } + + if (strpos($fileContents, '@runInSeparateProcess') !== false + || strpos($fileContents, '#[RunInSeparateProcess') !== false + ) { + return $this->patchFileContentsToRunTestInSeparateProcess($testFile, $fileContents); + } + + return false; + } + + /** + * @throws ExtensionException + * @return string|false + */ + public function patchFileContentsToRunTestsInSeparateProcesses( + string $testFile, + string $fileContents + ) { + return $this->patchFileContentsToInjectSeparateProcessExecution( + '/\\s*?public\\s+function\\s+(?[^(]+)[^{]*?{/um', + $testFile, + $fileContents + ); + } + + /** + * @throws ExtensionException + * @return string|false + */ + private function patchFileContentsToInjectSeparateProcessExecution( + string $pattern, + string $testFile, + string $fileContents + ) { + // Starts with `test` OR contains the `@test` annotation OR contains the `#[Test]` attribute. + $patchedFileContents = preg_replace_callback( + $pattern, + function ($matches) use ($testFile, $fileContents) { + return $this->injectProcessCode($matches, $testFile, $fileContents); + }, + $fileContents + ); + + if ($patchedFileContents === $fileContents) { + return false; + } + + if ($patchedFileContents === null) { + throw new ExtensionException($this, "File contents patching failed for file {$testFile}."); + } + + $patchedFileContents = preg_replace( + [ + '/(^\\s*\\*\\s*)@runInSeparateProcess/um', + '/(^\\s+#\\[)RunInSeparateProcess([^]]*?])/um', + '/(^\\s*\\*\\s*)@runTestsInSeparateProcesses/um', + '/(^\\s+#\\[)RunTestsInSeparateProcesses([^]]*?])/um' + ], + [ + '$1@willRunInSeparateProcess', + '$1WillRunInSeparateProcess$2', + '$1@willRunTestsInSeparateProcesses', + '$1willRunTestsInSeparateProcesses$2' + ], + $patchedFileContents + ); + + $patchedFile = MonkeyPatch::getReplacementFileName( + $testFile, + self::MAIN_PROCESS_PATCH_CONTEXT + ); + + if (!file_put_contents($patchedFile, $patchedFileContents, LOCK_EX)) { + throw new ExtensionException($this, "Failed writing patch file {$patchedFile} for {$testFile}."); + } + + return $patchedFile; + } + + /** + * @param array $matches + */ + private function injectProcessCode(array $matches, string $testFile, string $fileContents): string + { + if (!$this->isTestMethod($matches['fname'], $fileContents)) { + return $matches[0]; + } + $compiledProcessCode = str_replace( + ['{{file}}', '{{name}}'], + [$testFile, $matches['fname']], + $this->processCode + ); + $processCode = preg_replace(["/[\r\n]*/", '~\\s{2,}~'], '', $compiledProcessCode); + return sprintf("%s %s", $matches[0], $processCode); + } + + private function isTestMethod(string $name, string $fileContents): bool + { + if (strncmp($name, 'test', strlen('test')) === 0) { + return true; + } + + $methodDocBlockLines = []; + $methodPos = strpos($fileContents, $name); + + if ($methodPos === false) { + return false; + } + + $input = substr($fileContents, 0, $methodPos); + // Drop the first line as it will be the `public function ...` one. + $lines = explode("\n", $input, -1); + $pattern = '/^(\\s*$|\\s*\\/\\*\\*|\\s*\\*|\\s*\\*\\s*\\/|\\s*#\\[[^]]+])/um'; + for ($i = count($lines) - 1; $i !== 0; $i--) { + $line = $lines [$i]; + if (!preg_match($pattern, $line)) { + break; + } + array_unshift($methodDocBlockLines, $line); + } + $methodDocBlock = implode("\n", $methodDocBlockLines); + return strpos($methodDocBlock, '#[Test]') !== false + || strpos($methodDocBlock, '@test') !== false; + } + + /** + * @throws ExtensionException + * @return string|false + */ + protected function patchFileContentsToRunTestInSeparateProcess( + string $testFile, + string $fileContents + ) { + $pattern = '/' + . '^\\s*' # Start of line and arbitrary number of spaces. + . '(' # Start OR group. + . '\\*\\s*@runInSeparateProcess' # @runInSeparateProcess annotation. + . '|' # OR ... + . '#\\[RunInSeparateProcess]' # [RunInSeparateProcess] attribute. + . ')' # Close OR group. + . '.*?public\\s+function\\s+(?[^(\\s]*?)\\([^{]*?{' # The function declaration until the `{`. + . '/usm'; # Multi-line pattern. + return $this->patchFileContentsToInjectSeparateProcessExecution( + $pattern, + $testFile, + $fileContents + ); + } + + /** + * @throws ExtensionException + */ + protected function monkeyPatchTestMethodsToReplaceAnnotations(): void + { + $testFile = $_SERVER['WPBROWSER_TEST_FILE']; + $fileContents = file_get_contents($testFile); + + if ($fileContents === false) { + throw new ExtensionException($this, "Failed to to open {$testFile} for reading."); + } + + $patchedTestFile = preg_replace( + [ + '/(^\\s*\\*\\s*)@dataProvider/um', + '/(^\\s+#\\[)DataProvider([^]]*?])/um', + '/(^\\s*\\*\\s*)@runInSeparateProcess/um', + '/(^\\s+#\\[)RunInSeparateProcess([^]]*?])/um', + '/(^\\s*\\*\\s*)@runTestsInSeparateProcesses/um', + '/(^\\s+#\\[)RunTestsInSeparateProcesses([^]]*?])/um' + ], + [ + '$1@dataProvidedBy', + '$1DataProvidedBy$2', + '$1@runningInSeparateProcess', + '$1RunningInSeparateProcess$2', + '$1@runningTestsInSeparateProcesses', + '$1RunningTestsInSeparateProcesses$2' + ], + $fileContents + ); + + if ($patchedTestFile === null) { + throw new ExtensionException($this, "File contents patching failed for file {$testFile}."); + } + + MonkeyPatch::redirectFileContents($testFile, $patchedTestFile, false, self::ISOLATED_PROCESS_PATCH_CONTEXT); + } + + public function onTestFail(FailEvent $failEvent): void + { + if ($this->isMainProcess()) { + return; + } + + $this->printSerializedFailure($failEvent); + } + + private function printSerializedFailure(FailEvent $failEvent): void + { + printf("\r\nWPBROWSER_ISOLATION_RESULT_START\n"); + $fail = $failEvent->getFail(); + $serializableThrowable = new SerializableThrowable($fail); + printf(base64_encode(serialize($serializableThrowable))); + printf("WPBROWSER_ISOLATION_RESULT_END\r\n"); + } + + /** + * @throws ReflectionException + */ + public function onTestStart(TestEvent $e): void + { + if ($this->isMainProcess()) { + return; + } + + $this->injectProvidedDataSet($e); + } + + /** + * @throws ReflectionException + */ + private function injectProvidedDataSet(TestEvent $e): void + { + $data = unserialize(base64_decode($_SERVER['WPBROWSER_DATA_SET']), ['allowed_classes' => true]); + + if (!is_array($data)) { + throw new \RuntimeException('Test method data must be an array, but it is ' . gettype($data)); + } + + foreach ($data as &$dataElement) { + if ($dataElement instanceof SerializableClosure) { + $dataElement = $dataElement->getClosure(); + } + } + unset($dataElement); + + $dataName = $_SERVER['WPBROWSER_DATA_NAME']; + + /** @var TestCaseWrapper|TestCase $testCaseWrapper */ + $testCaseWrapper = $e->getTest(); + $testCase = $testCaseWrapper instanceof TestCase ? $testCaseWrapper : $testCaseWrapper->getTestCase(); + Property::setPrivateProperties($testCase, [ + 'data' => $data, + 'dataName' => $dataName + ]); + } +} diff --git a/src/Lib/Generator/AbstractGenerator.php b/src/Lib/Generator/AbstractGenerator.php new file mode 100644 index 000000000..45c758d8a --- /dev/null +++ b/src/Lib/Generator/AbstractGenerator.php @@ -0,0 +1,78 @@ +settings = $settings; + $this->name = $this->removeSuffix($name, 'Test'); + } + + public function produce(): string + { + $ns = $this->getNamespaceHeader($this->settings['namespace'] . '\\' . $this->name); + + return (new Template($this->template))->place('namespace', $ns) + ->place('name', $this->getShortClassName($this->name)) + ->place('tester', $this->getTester()) + ->produce(); + } + + protected function getTester(): string + { + if (isset($this->settings['actor'])) { + $actor = $this->settings['actor']; + } + + try { + /** @var array{actor_suffix: string} $config */ + $config = Configuration::config(); + $propertyName = isset($config['actor_suffix']) ? + lcfirst($config['actor_suffix']) + : ''; + } catch (Exception $exception) { + $propertyName = ''; + } + + if (!isset($actor)) { + return ''; + } + + $testerFrag = <<post->create(); + + add_post_meta( \$post, 'testkey', 'initial_value' ); + + // Become an administrator. + \$this->_setRole( 'administrator' ); + + \$_POST = [ + '_ajax_nonce-add-meta' => wp_create_nonce('add-meta'), + 'post_id' => \$post, + 'key' => 'testkey', + 'value' => 'updated_value', + ]; + + // Make the request. + try { + \$this->_handleAjax( 'add-meta' ); + } catch ( WPAjaxDieContinueException \$e ) { + unset( \$e ); + } + + \$this->assertSame( 'updated_value', get_post_meta( \$post, 'testkey', true ) ); + } +} + +EOF; +} diff --git a/src/Lib/Generator/WPCanonical.php b/src/Lib/Generator/WPCanonical.php new file mode 100644 index 000000000..22f29ed14 --- /dev/null +++ b/src/Lib/Generator/WPCanonical.php @@ -0,0 +1,57 @@ +add_rule( + 'ccr/(.+?)/sort/(asc|desc)', + 'index.php?category_name=\$matches[1]&order=\$matches[2]', + 'top' + ); + \$wp_rewrite->flush_rules(); + + \$this->assertCanonical( + '/ccr/test-category/sort/asc/', + [ + 'url' => '/ccr/test-category/sort/asc/', + 'qv' => [ + 'category_name' => 'test-category', + 'order' => 'asc', + ], + ] + ); + } +} + +EOF; +} diff --git a/src/Lib/Generator/WPRestApi.php b/src/Lib/Generator/WPRestApi.php new file mode 100644 index 000000000..d829ef4ce --- /dev/null +++ b/src/Lib/Generator/WPRestApi.php @@ -0,0 +1,80 @@ +user->create( [ 'role' => 'author' ] ); + + // Create and become editor. + \$editor_id = static::factory()->user->create( [ 'role' => 'editor' ] ); + wp_set_current_user( \$editor_id ); + + // Create 2 posts, one from the editor and one from the author. + \$post_1_id = static::factory()->post->create( [ 'post_author' => \$editor_id ] ); + \$post_2_id = static::factory()->post->create( [ 'post_author' => \$author_id ] ); + + // Get all posts in the database. + \$request = new \WP_REST_Request( 'GET', '/wp/v2/posts' ); + \$request->set_param( 'per_page', 10 ); + \$response = rest_get_server()->dispatch( \$request ); + \$this->assertSame( 200, \$response->get_status() ); + \$this->assertCount( 2, \$response->get_data() ); + + // Exclude editor and author. + \$request = new \WP_REST_Request( 'GET', '/wp/v2/posts' ); + \$request->set_param( 'per_page', 10 ); + \$request->set_param( 'author_exclude', [ \$editor_id, \$author_id ] ); + \$response = rest_get_server()->dispatch( \$request ); + \$this->assertSame( 200, \$response->get_status() ); + \$data = \$response->get_data(); + \$this->assertCount( 0, \$data ); + + // Exclude editor. + \$request = new \WP_REST_Request( 'GET', '/wp/v2/posts' ); + \$request->set_param( 'per_page', 10 ); + \$request->set_param( 'author_exclude', \$editor_id ); + \$response = rest_get_server()->dispatch( \$request ); + \$this->assertSame( 200, \$response->get_status() ); + \$data = \$response->get_data(); + \$this->assertCount( 1, \$data ); + \$this->assertNotEquals( \$editor_id, \$data[0]['author'] ); + + // Invalid 'author_exclude' should error. + \$request = new \WP_REST_Request( 'GET', '/wp/v2/posts' ); + \$request->set_param( 'author_exclude', 'invalid' ); + \$response = rest_get_server()->dispatch( \$request ); + \$this->assertErrorResponse( 'rest_invalid_param', \$response, 400 ); + } +} + +EOF; +} diff --git a/src/Lib/Generator/WPRestController.php b/src/Lib/Generator/WPRestController.php new file mode 100644 index 000000000..012ce9e6d --- /dev/null +++ b/src/Lib/Generator/WPRestController.php @@ -0,0 +1,464 @@ +controller !== null) { + // Do not register the controller more than once. + return; + } + + \$controller = new class extends \WP_REST_Controller { + private array \$data = [ + 'minion' => [ + 'label' => 'Minion', + 'count' => 89, + ], + 'villain' => [ + 'label' => 'Villain', + 'count' => 23, + ], + 'bbeg' => [ + 'label' => 'Big Bad Evil Guy', + 'count' => 1, + ], + ]; + + public function anyone(): bool + { + return true; + } + + public function adminsOnly(): bool + { + return current_user_can('manage_options'); + } + + public function greet(\WP_REST_Request \$request): \WP_REST_Response + { + \$response = new \WP_REST_Response(); + \$name = \$request->get_param('name'); + \$greet = sprintf('Hello %s!', \$name); + \$response->set_data(\$greet); + + return \$response; + } + + public function get_item_schema(): array + { + return [ + '\$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'adversary', + 'type' => 'object', + 'properties' => [ + 'label' => [ + 'description' => 'The adversary display name', + 'type' => 'string', + 'context' => ['view', 'edit'], + ], + 'count' => [ + 'description' => 'The adversary current count', + 'type' => 'integer', + 'context' => ['edit'], + ] + ] + ]; + } + + public function prepare_item_for_response(\$item, \$request): array + { + \$context = \$request->get_param('context'); + \$item['count'] = (int)\$item['count']; + + if (\$context === 'edit') { + return \$item; + } + + return array_diff_key(\$item, ['count' => true]); + } + + public function getAdversary(\WP_REST_Request \$request): \WP_REST_Response + { + \$name = \$request->get_param('name'); + \$item = \$this->data[\$name] ?? null; + + if (\$item === null) { + return new \WP_REST_Response([], 404); + } + + \$item = \$this->prepare_item_for_response(\$item, \$request); + + return new \WP_REST_Response(\$item); + } + + public function getAdversaries(\WP_REST_Request \$request): \WP_REST_Response + { + \$data = \$this->data; + + foreach (\$data as &\$item) { + \$item = \$this->prepare_item_for_response(\$item, \$request); + } + + return new \WP_REST_Response(\$data); + } + + public function upsertAdversary(\WP_REST_Request \$request): \WP_REST_Response + { + \$name = (string)\$request->get_param('name'); + \$update = isset(\$this->data[\$name]); + \$label = (string)\$request->get_param('label') ?: \$this->data[\$name]['label']; + \$count = (string)\$request->get_param('count') ?: \$this->data[\$name]['count']; + + \$item = compact('label', 'count'); + \$this->data[\$name] = \$item; + + return new \WP_REST_Response(\$item, \$update ? 200 : 201); + } + + public function deleteAdversary(\WP_REST_Request \$request): \WP_REST_Response + { + \$name = \$request->get_param('name'); + + \$item = \$this->data[\$name] ?? null; + + if (\$item === null) { + return new \WP_REST_Response('NOT FOUND', 404); + } + + \$this->data = array_diff_key(\$this->data, [\$name => true]); + + return new \WP_REST_Response(\$item, 200); + } + }; + + \$this->controller = \$controller; + + register_rest_route( + 'example', + 'greet/(?P[\w-]+)', + [ + 'methods' => 'GET', + 'callback' => [\$controller, 'greet'], + 'permission_callback' => [\$controller, 'anyone'], + ] + ); + + register_rest_route( + 'example', + 'adversaries', + [ + 'methods' => 'GET', + 'callback' => [\$controller, 'getAdversaries'], + 'permission_callback' => [\$controller, 'anyone'], + 'schema' => [\$controller, 'get_item_schema'], + ], + ); + + register_rest_route( + 'example', + 'adversaries/(?[\w-]*)', + [ + 'methods' => 'GET', + 'callback' => [\$controller, 'getAdversary'], + 'permission_callback' => [\$controller, 'anyone'], + 'schema' => [\$controller, 'get_item_schema'], + ], + ); + + register_rest_route( + 'example', + 'adversary', + [ + 'methods' => ['POST', 'PUT'], + 'callback' => [\$controller, 'upsertAdversary'], + 'permission_callback' => [\$controller, 'adminsOnly'], + 'schema' => [\$controller, 'get_item_schema'], + ], + ); + + register_rest_route( + 'example', + 'adversary', + [ + 'methods' => 'DELETE', + 'callback' => [\$controller, 'deleteAdversary'], + 'permission_callback' => [\$controller, 'adminsOnly'], + 'schema' => [\$controller, 'get_item_schema'], + ], + ); + } + + public function tearDown(): void + { + // Your tear down methods here. + + // Then... + parent::tearDown(); + } + + public function test_register_routes() + { + \$routes = rest_get_server()->get_routes(); + \$this->assertArrayHasKey('/example', \$routes); + \$this->assertCount(1, \$routes['/example']); + \$this->assertArrayHasKey('/example/greet/(?P[\w-]+)', \$routes); + \$this->assertCount(1, \$routes['/example/greet/(?P[\w-]+)']); + \$this->assertArrayHasKey('/example/adversaries', \$routes); + \$this->assertCount(1, \$routes['/example/adversaries']); + } + + public function test_context_param() + { + \$request = new \WP_REST_Request('GET', '/example/adversaries'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals( + [ + 'minion' => ['label' => 'Minion'], + 'villain' => ['label' => 'Villain'], + 'bbeg' => ['label' => 'Big Bad Evil Guy'], + ], + \$response->data + ); + + \$request = new \WP_REST_Request('GET', '/example/adversaries'); + \$request->set_param('context', 'view'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals( + [ + 'minion' => ['label' => 'Minion'], + 'villain' => ['label' => 'Villain'], + 'bbeg' => ['label' => 'Big Bad Evil Guy'], + ], + \$response->data + ); + + \$request = new \WP_REST_Request('GET', '/example/adversaries'); + \$request->set_param('context', 'edit'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals( + [ + 'minion' => [ + 'label' => 'Minion', + 'count' => 89, + ], + 'villain' => [ + 'label' => 'Villain', + 'count' => 23, + ], + 'bbeg' => [ + 'label' => 'Big Bad Evil Guy', + 'count' => 1, + ], + ], + \$response->data + ); + } + + public function test_get_items() + { + \$request = new \WP_REST_Request('GET', '/example/adversaries'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals( + [ + 'minion' => ['label' => 'Minion'], + 'villain' => ['label' => 'Villain'], + 'bbeg' => ['label' => 'Big Bad Evil Guy'], + ], + \$response->data + ); + } + + public function test_get_item() + { + \$request = new \WP_REST_Request('GET', '/example/adversaries/bbeg'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(['label' => 'Big Bad Evil Guy'], \$response->data); + + \$request = new \WP_REST_Request('GET', '/example/adversaries/bbeg'); + \$request->set_param('context', 'edit'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(['label' => 'Big Bad Evil Guy', 'count' => 1], \$response->data); + + \$request = new \WP_REST_Request('GET', '/example/adversaries/troll'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals([], \$response->data); + \$this->assertEquals(404, \$response->status); + } + + public function test_create_item() + { + \$request = new \WP_REST_Request('POST', '/example/adversary'); + \$request->set_param('name', 'goblin'); + \$request->set_param('label', 'Goblin'); + \$request->set_param('count', 1000); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(401, \$response->status); + + // Become admin. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(201, \$response->status); + \$this->assertEquals([ + 'label' => 'Goblin', + 'count' => 1000, + ], \$response->data); + } + + public function test_update_item() + { + // Become admin. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + // Create a new item to operate on. + \$request = new \WP_REST_Request('POST', '/example/adversary'); + \$request->set_param('name', 'troll'); + \$request->set_param('label', 'Troll'); + \$request->set_param('count', 3); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(201, \$response->status); + \$this->assertEquals([ + 'label' => 'Troll', + 'count' => 3, + ], \$response->data); + + // Update the item. + \$request = new \WP_REST_Request('PUT', '/example/adversary'); + \$request->set_param('name', 'troll'); + \$request->set_param('count', 2); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'label' => 'Troll', + 'count' => 2, + ], \$response->data); + } + + public function test_delete_item() + { + // Become admin. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + // Create a new item to operate on. + \$request = new \WP_REST_Request('POST', '/example/adversary'); + \$request->set_param('name', 'ghast'); + \$request->set_param('label', 'Ghast'); + \$request->set_param('count', 5); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(201, \$response->status); + + // Delete a non-existing adversary. + \$request = new \WP_REST_Request('DELETE', '/example/adversary'); + \$request->set_param('name', 'beholder'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(404, \$response->status); + + // Delete the item. + \$request = new \WP_REST_Request('DELETE', '/example/adversary'); + \$request->set_param('name', 'ghast'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'label' => 'Ghast', + 'count' => 5, + ], \$response->data); + } + + public function test_prepare_item() + { + \$item = [ + 'label' => 'Ghoul', + 'count' => '123', + ]; + + \$request = new \WP_REST_Request('GET', '/example/adversaries/ghoul'); + + \$this->assertEquals( + [ + 'label' => 'Ghoul', + ], + \$this->controller->prepare_item_for_response(\$item, \$request) + ); + + \$request->set_param('context', 'edit'); + + \$this->assertEquals( + [ + 'label' => 'Ghoul', + 'count' => 123 + ], + \$this->controller->prepare_item_for_response(\$item, \$request) + ); + } + + public function test_get_item_schema() + { + \$controller = \$this->controller; + + \$this->assertEquals([ + '\$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'adversary', + 'type' => 'object', + 'properties' => [ + 'label' => [ + 'description' => 'The adversary display name', + 'type' => 'string', + 'context' => ['view', 'edit'], + ], + 'count' => [ + 'description' => 'The adversary current count', + 'type' => 'integer', + 'context' => ['edit'], + ] + ] + ], \$controller->get_item_schema()); + } +} + +EOF; +} diff --git a/src/Lib/Generator/WPRestPostTypeController.php b/src/Lib/Generator/WPRestPostTypeController.php new file mode 100644 index 000000000..7fe0dd977 --- /dev/null +++ b/src/Lib/Generator/WPRestPostTypeController.php @@ -0,0 +1,490 @@ +controller !== null) { + // Do not register the controller more than once. + return; + } + + register_post_type('book'); + + \$controller = new class('book') extends WP_REST_Posts_Controller { + public function anyone(): bool + { + return true; + } + + public function adminsOnly(): bool + { + return current_user_can('manage_options'); + } + + public function get_item_schema() + { + return [ + '\$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'book', + 'type' => 'object', + 'properties' => [ + 'title' => [ + 'description' => 'The book title', + 'type' => 'string', + 'context' => ['view', 'edit'], + ], + 'year' => [ + 'description' => 'The year the book was published', + 'type' => 'string', + 'context' => ['view', 'edit'], + ], + 'copies' => [ + 'description' => 'The number of book copies available', + 'type' => 'integer', + 'context' => ['edit'], + ] + ] + ]; + } + + public function prepare_item_for_response(\$item, \$request) + { + \$post = get_post(\$item); + \$data = [ + 'title' => \$post->post_title, + 'year' => (int)get_post_meta(\$post->ID, 'year', true), + ]; + + if (\$request->get_param('context') === 'edit') { + \$data['copies'] = get_post_meta(\$post->ID, 'copies', true); + } + + return \$data; + } + + + public function getBook(\WP_REST_Request \$request): \WP_REST_Response + { + \$book = get_post(\$request->get_param('id')); + + if (!\$book instanceof \WP_Post || get_post_type(\$book->ID) !== 'book') { + return new \WP_REST_Response(null, 404); + } + + return new \WP_REST_Response(\$this->prepare_item_for_response(\$book, \$request), 200); + } + + public function createBook(\WP_REST_Request \$request): \WP_REST_Response + { + \$prepareRequest = clone \$request; + \$prepareRequest->set_param('context', 'edit'); + \$postarr = [ + 'post_type' => 'book', + 'post_title' => \$request->get_param('title'), + 'meta_input' => [ + 'year' => \$request->get_param('year'), + 'copies' => \$request->get_param('copies') + ] + ]; + + \$inserted = wp_insert_post(\$postarr); + + if (\$inserted instanceof \WP_Error) { + return new \WP_REST_Response(\$inserted->get_error_message(), 500); + } + + return new \WP_REST_Response(\$this->prepare_item_for_response(\$inserted, \$prepareRequest), 201); + } + + public function updateBook(\WP_REST_Request \$request): \WP_REST_Response + { + \$book = get_post(\$request->get_param('id')); + \$prepareRequest = clone \$request; + \$prepareRequest->set_param('context', 'edit'); + + if (!\$book instanceof \WP_Post || get_post_type(\$book->ID) !== 'book') { + return new \WP_REST_Response(null, 404); + } + + \$postarr = [ + 'ID' => \$book->ID, + 'post_title' => \$request->get_param('title') ?: \$book->post_title, + 'meta_input' => [ + 'year' => \$request->get_param('year') ?: get_post_meta(\$book->ID, 'year', true), + 'copies' => \$request->get_param('copies') ?: get_post_meta(\$book->ID, 'copies', true) + ] + ]; + + if ((\$update = wp_update_post(\$postarr)) instanceof \WP_Error) { + return new \WP_REST_Response(\$update->get_error_message(), 500); + } + + return new \WP_REST_Response(\$this->prepare_item_for_response(\$book, \$prepareRequest), 200); + } + + public function deleteBook(\WP_REST_Request \$request): \WP_REST_Response + { + \$book = get_post(\$request->get_param('id')); + \$prepareRequest = clone \$request; + \$prepareRequest->set_param('context', 'edit'); + + if (!\$book instanceof \WP_Post || get_post_type(\$book->ID) !== 'book') { + return new \WP_REST_Response(null, 404); + } + + \$prepared = \$this->prepare_item_for_response(\$book, \$prepareRequest); + + if (!wp_delete_post(\$book->ID)) { + return new \WP_REST_Response(null, 500); + } + + return new \WP_REST_Response(\$prepared, 200); + } + + public function getBooks(\WP_REST_Request \$request): \WP_REST_Response + { + \$posts = get_posts(['post_type' => 'book']); + + \$books = array_map( + fn(\$post) => \$this->prepare_item_for_response(\$post, \$request), + \$posts + ); + + return new \WP_REST_Response(\$books, 200); + } + }; + + register_rest_route('example', '/books', [ + 'methods' => 'GET', + 'callback' => [\$controller, 'getBooks'], + 'permission_callback' => [\$controller, 'anyone'], + 'schema' => \$controller->get_item_schema() + ]); + + register_rest_route('example', '/book/(?P\d+)', [ + 'methods' => 'GET', + 'callback' => [\$controller, 'getBook'], + 'permission_callback' => [\$controller, 'anyone'], + 'schema' => \$controller->get_item_schema() + ]); + + register_rest_route('example', '/book', [ + 'methods' => 'POST', + 'callback' => [\$controller, 'createBook'], + 'permission_callback' => [\$controller, 'adminsOnly'], + 'schema' => \$controller->get_item_schema() + ]); + + register_rest_route('example', '/book/(?P\d+)', [ + 'methods' => 'PUT', + 'callback' => [\$controller, 'updateBook'], + 'permission_callback' => [\$controller, 'adminsOnly'], + 'schema' => \$controller->get_item_schema() + ]); + + register_rest_route('example', '/book/(?P\d+)', [ + 'methods' => 'DELETE', + 'callback' => [\$controller, 'deleteBook'], + 'permission_callback' => [\$controller, 'adminsOnly'], + 'schema' => \$controller->get_item_schema() + ]); + + \$this->controller = \$controller; + } + + public function tearDown(): void + { + // Your tear down methods here. + + // Then... + parent::tearDown(); + } + + public function test_register_routes() + { + \$routes = rest_get_server()->get_routes(); + \$this->assertArrayHasKey('/example', \$routes); + \$this->assertCount(1, \$routes['/example']); + \$this->assertArrayHasKey('/example/books', \$routes); + \$this->assertCount(1, \$routes['/example/books']); + \$this->assertArrayHasKey('/example/book', \$routes); + \$this->assertCount(1, \$routes['/example/book']); + \$this->assertArrayHasKey('/example/book/(?P\d+)', \$routes); + \$this->assertCount(3, \$routes['/example/book/(?P\d+)']); + } + + public function test_context_param() + { + \$book = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Alice in Wonderland', + 'meta_input' => [ + 'year' => 1865, + 'copies' => 13 + ] + ]); + + \$request = new \WP_REST_Request('GET', "/example/book/{\$book->ID}"); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865 + ], \$response->data); + + \$request->set_param('context', 'edit'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865, + 'copies' => 13 + ], \$response->data); + } + + public function test_get_items() + { + \$request = new \WP_REST_Request('GET', '/example/books'); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([], \$response->data); + + \$book1 = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Alice in Wonderland', + 'meta_input' => [ + 'year' => 1865, + 'copies' => 13 + ] + ]); + \$book2 = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Through the Looking-Glass', + 'meta_input' => [ + 'year' => 1871, + 'copies' => 10 + ] + ]); + + \$request = new \WP_REST_Request('GET', "/example/books"); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEqualSets([ + [ + 'title' => 'Alice in Wonderland', + 'year' => 1865 + ], + [ + 'title' => 'Through the Looking-Glass', + 'year' => 1871 + ] + ], \$response->data); + } + + public function test_get_item() + { + \$book = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Alice in Wonderland', + 'meta_input' => [ + 'year' => 1865, + 'copies' => 13 + ] + ]); + + \$request = new \WP_REST_Request('GET', "/example/book/2389"); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(404, \$response->status); + + \$request = new \WP_REST_Request('GET', "/example/book/{\$book->ID}"); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865 + ], \$response->data); + } + + public function test_create_item() + { + \$request = new \WP_REST_Request('POST', "/example/book"); + \$request->set_body_params([ + 'title' => 'Alice in Wonderland', + 'year' => 1865, + 'copies' => 13 + ]); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(401, \$response->status); + + // Become administrator. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(201, \$response->status); + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865, + 'copies' => 13 + ], \$response->data); + } + + public function test_update_item() + { + \$book = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Alice in Wonderland', + 'meta_input' => [ + 'year' => 1865, + 'copies' => 13 + ] + ]); + + \$request = new \WP_REST_Request('PUT', "/example/book/{\$book->ID}"); + \$request->set_param('copies', 10); + \$request->set_param('year', 1867); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(401, \$response->status); + + // Become administrator. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1867, + 'copies' => 10 + ], \$response->data); + } + + public function test_delete_item() + { + \$book = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Alice in Wonderland', + 'meta_input' => [ + 'year' => 1865, + 'copies' => 13 + ] + ]); + + \$request = new \WP_REST_Request('DELETE', "/example/book/{\$book->ID}"); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(401, \$response->status); + + // Become administrator. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + \$response = rest_get_server()->dispatch(\$request); + + \$this->assertEquals(200, \$response->status); + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865, + 'copies' => 13 + ], \$response->data); + } + + public function test_prepare_item() + { + \$book = static::factory()->post->create_and_get([ + 'post_type' => 'book', + 'post_title' => 'Alice in Wonderland', + 'meta_input' => [ + 'year' => 1865, + 'copies' => 13 + ] + ]); + + \$request = new \WP_REST_Request('GET', "/example/book/{\$book->ID}"); + + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865 + ], \$this->controller->prepare_item_for_response(\$book, \$request)); + + \$request->set_param('context', 'edit'); + + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865, + 'copies' => 13 + ], \$this->controller->prepare_item_for_response(\$book, \$request)); + + // Become administrator. + wp_set_current_user(static::factory()->user->create(['role' => 'administrator'])); + + \$this->assertEquals([ + 'title' => 'Alice in Wonderland', + 'year' => 1865, + 'copies' => 13 + ], \$this->controller->prepare_item_for_response(\$book, \$request)); + } + + public function test_get_item_schema() + { + \$this->assertEquals([ + '\$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'book', + 'type' => 'object', + 'properties' => [ + 'title' => [ + 'description' => 'The book title', + 'type' => 'string', + 'context' => ['view', 'edit'], + ], + 'year' => [ + 'description' => 'The year the book was published', + 'type' => 'string', + 'context' => ['view', 'edit'], + ], + 'copies' => [ + 'description' => 'The number of book copies available', + 'type' => 'integer', + 'context' => ['edit'], + ] + ] + ], \$this->controller->get_item_schema()); + } +} + +EOF; +} diff --git a/src/Lib/Generator/WPUnit.php b/src/Lib/Generator/WPUnit.php index d1a930212..d2388addd 100644 --- a/src/Lib/Generator/WPUnit.php +++ b/src/Lib/Generator/WPUnit.php @@ -19,31 +19,15 @@ * * @package Codeception\Lib\Generator */ -class WPUnit +class WPUnit extends AbstractGenerator { - /** - * @var string - */ - protected $baseClass; - use Classname; - use Namespaces; - - /** - * @var array{namespace: string, actor: string} - */ - private $settings; - /** - * @var string - */ - private $name; - /** * @var string */ protected $template = <<assertInstanceOf(\\WP_Post::class, \$post); } } - -EOF; - - /** - * WPUnit constructor. - * - * @param array{namespace: string, actor: string} $settings The template settings. - * @param string $name The template name. - * @param string $baseClass The base class. - */ - public function __construct(array $settings, string $name, string $baseClass) - { - $this->baseClass = $baseClass; - $this->settings = $settings; - $this->name = $this->removeSuffix($name, 'Test'); - } - - /** - * Produces and return the rendered template. - * - * @return string The rendered template. - */ - public function produce(): string - { - $ns = $this->getNamespaceHeader($this->settings['namespace'] . '\\' . $this->name); - - return (new Template($this->template))->place('namespace', $ns) - ->place('baseClass', '\\' . ltrim($this->baseClass, '\\')) - ->place('name', $this->getShortClassName($this->name)) - ->place('tester', $this->getTester()) - ->produce(); - } - - /** - * Returns the current tester name. - * - * @return string The current tester name. - */ - protected function getTester(): string - { - if (isset($this->settings['actor'])) { - $actor = $this->settings['actor']; - } - - try { - /** @var array{actor_suffix: string} $config */ - $config = Configuration::config(); - $propertyName = isset($config['actor_suffix']) ? - lcfirst($config['actor_suffix']) - : ''; - } catch (Exception $exception) { - $propertyName = ''; - } - - if (!isset($actor)) { - return ''; - } - - $testerFrag = << 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-posts-post-1.xml', + ], + [ + 'loc' => 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-posts-page-1.xml', + ], + [ + 'loc' => 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-taxonomies-category-1.xml', + ], + [ + 'loc' => 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-taxonomies-post_tag-1.xml', + ], + [ + 'loc' => 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-users-1.xml', + ], + ]; + + \$renderer = new \WP_Sitemaps_Renderer(); + + \$actual = \$renderer->get_sitemap_index_xml( \$entries ); + \$expected = '' . + '' . + '' . + 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-posts-post-1.xml' . + 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-posts-page-1.xml' . + 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-taxonomies-category-1.xml' . + 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-taxonomies-post_tag-1.xml' . + 'http://' . \WP_TESTS_DOMAIN . '/wp-sitemap-users-1.xml' . + ''; + + \$this->assertXMLEquals( \$expected, \$actual, 'Sitemap index markup incorrect.' ); + } +} + +EOF; +} diff --git a/src/Lib/Generator/WPXMLRPC.php b/src/Lib/Generator/WPXMLRPC.php new file mode 100644 index 000000000..b6cb9a592 --- /dev/null +++ b/src/Lib/Generator/WPXMLRPC.php @@ -0,0 +1,78 @@ +modify( '-1 hour' ); + \$datetimeutc = \$datetime->setTimezone( new DateTimeZone( 'UTC' ) ); + + \$this->make_user_by_role( 'administrator' ); + \$post_id = static::factory()->post->create(); + + \$comment_data = [ + 'comment_post_ID' => \$post_id, + 'comment_author' => 'Test commenter', + 'comment_author_url' => 'http://example.com/', + 'comment_author_email' => 'example@example.com', + 'comment_content' => 'Hello, world!', + 'comment_approved' => '1', + ]; + \$comment_id = wp_insert_comment( \$comment_data ); + + \$result = \$this->myxmlrpcserver->wp_editComment( + [ + 1, + 'administrator', + 'administrator', + \$comment_id, + [ + 'date_created_gmt' => new IXR_Date( \$datetimeutc->format( 'Ymd\TH:i:s' ) ), + ], + ] + ); + + \$fetched_comment = get_comment( \$comment_id ); + + \$this->assertTrue( \$result ); + \$this->assertSame( + \$datetime->format( 'Y-m-d H:i:s' ), + \$fetched_comment->comment_date, + 'UTC time into wp_editComment' + ); + } +} + +EOF; +} diff --git a/src/Module/WPBrowser.php b/src/Module/WPBrowser.php index b89d8ed79..68527981b 100644 --- a/src/Module/WPBrowser.php +++ b/src/Module/WPBrowser.php @@ -51,8 +51,8 @@ public function grabCookiesWithPattern(string $cookiePattern): ?array if (!$cookies) { return null; } - $matchingCookies = array_filter($cookies, static function ($cookie) use ($cookiePattern) { - return preg_match($cookiePattern, $cookie->getName()); + $matchingCookies = array_filter($cookies, static function (Cookie $cookie) use ($cookiePattern): bool { + return (bool)preg_match($cookiePattern, $cookie->getName()); }); $cookieList = array_map(static function ($cookie): string { return sprintf('{"%s": "%s"}', $cookie->getName(), $cookie->getValue()); diff --git a/src/Module/WPLoader.php b/src/Module/WPLoader.php index d54a9bc26..cddee6989 100644 --- a/src/Module/WPLoader.php +++ b/src/Module/WPLoader.php @@ -159,9 +159,9 @@ class WPLoader extends Module 'WP_PLUGIN_DIR' => null, 'WPMU_PLUGIN_DIR' => null, 'dump' => '', - 'backupGlobals' => true, + 'backupGlobals' => false, 'backupGlobalsExcludeList' => [], - 'backupStaticAttributes' => true, + 'backupStaticAttributes' => false, 'backupStaticAttributesExcludeList' => [], 'skipInstall' => false ]; @@ -500,9 +500,9 @@ public function _initialize(): void $this->checkInstallationToLoadOnly(); $this->debug('The WordPress installation will be loaded after all other modules have been initialized.'); - Dispatcher::addListener(Events::SUITE_BEFORE, function (): void { + Dispatcher::addListener(Events::SUITE_INIT, function (): void { $this->loadWordPress(true); - }, -100); + }); return; } diff --git a/src/Module/WPLoader/Filters.php b/src/Module/WPLoader/Filters.php new file mode 100644 index 000000000..336bd88a2 --- /dev/null +++ b/src/Module/WPLoader/Filters.php @@ -0,0 +1,205 @@ +> + */ + protected $toRemove = []; + + /** + * The list of filters to add. + * + * @var array> + */ + protected $toAdd = []; + + /** + * Filters constructor. + * + * @param array> $filters The filters to manage. + */ + public function __construct(array $filters = []) + { + $this->toRemove = !empty($filters['remove']) + ? array_map([$this, 'normalizeFilter'], $filters['remove']) + : []; + $this->toAdd = !empty($filters['add']) + ? array_map([$this, 'normalizeFilter'], $filters['add']) + : []; + } + + /** + * Formats and normalizes a list of filters. + * + * @param array> $filters The list of filters to format. + * + * @return array{remove: mixed[][], add: mixed[][]} The formatted list of filters. + */ + public static function format(array $filters): array + { + $instance = new self($filters); + + return $instance->toArray(); + } + + /** + * Returns the current state in array format. + * + * @return array{remove: mixed[][], add: mixed[][]} A map of the filters to remove and to add.j:w + */ + public function toArray(): array + { + return [ + 'remove' => $this->toRemove, + 'add' => $this->toAdd, + ]; + } + + /** + * Returns the list of filters to remove. + * + * @return FiltersGroup The group of filters to remove. + */ + public function toRemove(): FiltersGroup + { + return new FiltersGroup($this->toRemove, $this->removeWith, $this->addWith); + } + + /** + * Sets the callable that should be used to remove the filters. + * + * @param callable $removeWith The callable that should be used to remove the filters. + */ + public function removeWith(callable $removeWith): void + { + $this->removeWith = $removeWith; + } + + /** + * Sets the callable that should be used to remove the filters. + * + * @param callable $addWith The callable that should be used to add the filters. + */ + public function addWith(callable $addWith): void + { + $this->addWith = $addWith; + } + + /** + * Returns the list of filters to add. + * + * @return FiltersGroup The group of filters to add. + */ + public function toAdd(): FiltersGroup + { + return new FiltersGroup($this->toAdd, $this->removeWith, $this->addWith); + } + + /** + * Normalizes a filter contents. + * + * @param array $filter The current filter state. + * + * @return array The normalized filter. + * + * @throws ModuleException If the filters information is not complete or not coherent. + */ + protected function normalizeFilter(array $filter): array + { + if (count($filter) < 2) { + throw new ModuleException( + __CLASS__, + 'Callback ' . json_encode($filter) . ' does not specify enough data for a filter: ' + . 'required at least tag and callback.' + ); + } + + if (empty($filter[0]) || !is_string($filter[0])) { + throw new ModuleException(__CLASS__, 'Callback ' . json_encode($filter) . ' does not specify a valid tag.'); + } + + if (count($filter) === 2) { + $filter[] = $this->defaultPriority; + } + + if (count($filter) === 3) { + $filter[] = $this->defaultAcceptedArguments; + } + + if (count($filter) > 4) { + throw new ModuleException( + __CLASS__, + 'Callback ' . json_encode($filter) . ' contains too many arguments; ' + .'only tag, callback, priority and accepted arguments are supported' + ); + } + + + $callbackFunc = $filter[1]; + + if (empty($callbackFunc) || !(is_string($callbackFunc) || is_array($callbackFunc))) { + throw new ModuleException( + __CLASS__, + 'Callback for ' . json_encode($filter) . ' is empty or the wrong type: ' + .'it should be a string (a function name) or an array of two strings (class name and a static method).' + ); + } + + if (is_array($callbackFunc)) { + if (count($callbackFunc) !== 2 + || count(array_filter($callbackFunc, 'is_string')) !== 2 + ) { + throw new ModuleException( + __CLASS__, + 'Callback for ' . json_encode($filter) . ' is weird: ' + .'it should be a string (function name) or an array of two strings (class name and static method).' + ); + } + } + + return $filter; + } +} diff --git a/src/Module/WPLoader/FiltersGroup.php b/src/Module/WPLoader/FiltersGroup.php new file mode 100644 index 000000000..3e7628a5f --- /dev/null +++ b/src/Module/WPLoader/FiltersGroup.php @@ -0,0 +1,76 @@ +> + */ + protected $filters = []; + /** + * The callback that will be used to remove filters. + * + * @var callable + */ + protected $removeCallback; + + /** + * The callback that will be used to add filters. + * + * @var callable + */ + protected $addCallback; + + /** + * FiltersGroup constructor. + * + * @param array> $filters The list of filters to manage. + * @param callable|null $removeWith The callable that should be used to remove the filters or `null` to use + * the default one. + * @param callable|null $addWith The callable that should be used to add the filters, or `null` to use the + */ + public function __construct( + array $filters = [], + callable $removeWith = null, + callable $addWith = null + ) { + /** + * An array detailing each filter callback, priority and arguments. + */ + $this->filters = $filters; + $this->removeCallback = $removeWith ?? 'remove_filter'; + $this->addCallback = $addWith ?? 'add_filter'; + } + + /** + * Removes the filters of the group. + */ + public function remove(): void + { + foreach ($this->filters as $filter) { + $filterWithoutAcceptedArguments = array_slice($filter, 0, 3); + call_user_func_array($this->removeCallback, $filterWithoutAcceptedArguments); + } + } + + /** + * Adds the filters of the group. + */ + public function add(): void + { + foreach ($this->filters as $filter) { + call_user_func_array($this->addCallback, $filter); + } + } +} diff --git a/src/Module/WPQueries.php b/src/Module/WPQueries.php index 76f6a4cb2..814363099 100644 --- a/src/Module/WPQueries.php +++ b/src/Module/WPQueries.php @@ -70,7 +70,10 @@ public function __construct( */ public function _initialize(): void { - if (!$this->moduleContainer->hasModule(WPLoader::class)) { + if (!( + $this->moduleContainer->hasModule(WPLoader::class) + || $this->moduleContainer->hasModule('WPLoader') + )) { throw new ModuleException( __CLASS__, 'The WPLoader module is required for WPQueries to work.' diff --git a/src/Module/WPWebDriver.php b/src/Module/WPWebDriver.php index 7e214bc0d..5fc50418f 100644 --- a/src/Module/WPWebDriver.php +++ b/src/Module/WPWebDriver.php @@ -136,14 +136,14 @@ public function grabCookiesWithPattern(string $cookiePattern): ?array return null; } - /** @var array $cookies */ + /** @var Cookie[] $cookies */ $cookies = $this->webDriver->manage()->getCookies(); if (!$cookies) { return null; } - $matchingCookies = array_filter($cookies, static function ($cookie) use ($cookiePattern) { - return preg_match($cookiePattern, $cookie->getName()); + $matchingCookies = array_filter($cookies, static function ($cookie) use ($cookiePattern): bool { + return (bool)preg_match($cookiePattern, $cookie->getName()); }); $cookieList = array_map(static function ($cookie): string { return sprintf('{"%s": "%s"}', $cookie->getName(), $cookie->getValue()); diff --git a/src/MonkeyPatch/FileStreamWrapper.php b/src/MonkeyPatch/FileStreamWrapper.php index 681086e2b..b1ab1fced 100644 --- a/src/MonkeyPatch/FileStreamWrapper.php +++ b/src/MonkeyPatch/FileStreamWrapper.php @@ -15,7 +15,7 @@ class FileStreamWrapper protected static $isRegistered = false; /** - * @var array + * @var array */ private static $fileToPatcherMap = []; @@ -25,14 +25,18 @@ class FileStreamWrapper public $context; /** - * @var resource + * @var resource|null */ - private $fileResource; - - public static function setPatcherForFile(string $file, PatcherInterface $patcher): void - { + private $fileResource = null; + + public static function setPatcherForFile( + string $file, + PatcherInterface $patcher, + bool $redirectOpenedPath = true, + string $context = null + ): void { $fromFilePath = FS::realpath($file) ?: $file; - self::$fileToPatcherMap[$fromFilePath] = $patcher; + self::$fileToPatcherMap[$fromFilePath] = [$patcher, $redirectOpenedPath, $context ?? '']; self::register(); } @@ -120,6 +124,10 @@ public function stream_read(int $count) */ public function stream_cast() { + if (!is_resource($this->fileResource)) { + throw new MonkeyPatchingException('Cannot cast a non-resource to a resource.'); + } + return $this->fileResource; } @@ -132,6 +140,10 @@ public function stream_lock(int $operation): bool public function stream_set_option(int $option, int $arg1, int $arg2): bool { + if (!is_resource($this->fileResource)) { + return false; + } + switch ($option) { case STREAM_OPTION_BLOCKING: return stream_set_blocking($this->fileResource, (bool)$arg1); @@ -150,6 +162,10 @@ public function stream_set_option(int $option, int $arg1, int $arg2): bool */ public function stream_write(string $data): int { + if (!is_resource($this->fileResource)) { + throw new MonkeyPatchingException('Cannot write to a non-resource.'); + } + $written = fwrite($this->fileResource, $data); if ($written === false) { @@ -164,7 +180,7 @@ public function stream_write(string $data): int */ public function stream_tell(): int { - $pos = ftell($this->fileResource); + $pos = is_resource($this->fileResource) ? ftell($this->fileResource) : false; if ($pos === false) { throw new MonkeyPatchingException('Could not get the position of the file pointer.'); @@ -175,16 +191,28 @@ public function stream_tell(): int public function stream_close(): bool { + if (!is_resource($this->fileResource)) { + return false; + } + return fclose($this->fileResource); } public function stream_eof(): bool { + if (!is_resource($this->fileResource)) { + return true; + } + return feof($this->fileResource); } public function stream_seek(int $offset, int $whence = SEEK_SET): bool { + if (!is_resource($this->fileResource)) { + return false; + } + return fseek($this->fileResource, $offset, $whence) === 0; } @@ -236,6 +264,10 @@ public function rmdir(string $path, int $options = null): bool */ public function stream_stat() { + if (!is_resource($this->fileResource)) { + return false; + } + $stat = fstat($this->fileResource); if ($stat === false) { @@ -308,6 +340,10 @@ public function unlink(string $path): bool public function stream_truncate(int $newSize): bool { + if (!is_resource($this->fileResource)) { + return false; + } + return ftruncate($this->fileResource, max(0, $newSize)); } @@ -367,7 +403,7 @@ public function url_stat(string $path, int $flags) if (!(file_exists($path))) { if (isset(self::$fileToPatcherMap[$path])) { // Ask the patcher to provide stats. - $stat = self::$fileToPatcherMap[$path]->stat($path); + $stat = self::$fileToPatcherMap[$path][0]->stat($path); } else { $stat = false; } @@ -439,7 +475,7 @@ public function dir_opendir(string $path, int $options): bool static::register(); - return $this->fileResource !== null; + return true; } /** @@ -447,7 +483,7 @@ public function dir_opendir(string $path, int $options): bool */ private function patchFile(string $absPath): string { - $patcher = self::$fileToPatcherMap[$absPath]; + [$patcher, $redirectOpenedPath, $context] = self::$fileToPatcherMap[$absPath]; self::unregister(); // Do not use `is_file` here as it will use the cached stats: this check should be real. $fileContents = file_exists($absPath) ? file_get_contents($absPath) : ''; @@ -457,7 +493,7 @@ private function patchFile(string $absPath): string throw new MonkeyPatchingException("Could not read file $absPath contents."); } - [$fileContents, $openedPath] = $patcher->patch($fileContents, $absPath); + [$fileContents, $openedPath] = $patcher->patch($fileContents, $absPath, $context); if ($this->context !== null) { $fileResource = fopen('php://temp', 'rb+', false, $this->context); @@ -477,7 +513,7 @@ private function patchFile(string $absPath): string rewind($this->fileResource); - return $openedPath; + return $redirectOpenedPath ? $openedPath : $absPath; } /** diff --git a/src/MonkeyPatch/Patchers/FileContentsReplacementPatcher.php b/src/MonkeyPatch/Patchers/FileContentsReplacementPatcher.php index 14cbd49dc..194b72b17 100644 --- a/src/MonkeyPatch/Patchers/FileContentsReplacementPatcher.php +++ b/src/MonkeyPatch/Patchers/FileContentsReplacementPatcher.php @@ -4,6 +4,7 @@ use lucatume\WPBrowser\MonkeyPatch\MonkeyPatchingException; use lucatume\WPBrowser\Utils\Filesystem as FS; +use lucatume\WPBrowser\Utils\MonkeyPatch; class FileContentsReplacementPatcher implements PatcherInterface { @@ -19,10 +20,9 @@ public function __construct(string $fileContents) /** * @throws MonkeyPatchingException */ - public function patch(string $fileContents, string $pathname): array + public function patch(string $fileContents, string $pathname, string $context = null): array { - $hash = md5($pathname . $fileContents) . '_' . md5($this->fileContents); - $replacementFile = FS::getTmpSubDir('_monkeypatch') . '/' . $hash . '.php'; + $replacementFile = MonkeyPatch::getReplacementFileName($pathname, $context ?? $this->fileContents); $isFile = is_file($replacementFile); if (!$isFile && !file_put_contents($replacementFile, $this->fileContents, LOCK_EX)) { diff --git a/src/MonkeyPatch/Patchers/FileReplacementPatcher.php b/src/MonkeyPatch/Patchers/FileReplacementPatcher.php index 70ecc3c91..1eb2d55a1 100644 --- a/src/MonkeyPatch/Patchers/FileReplacementPatcher.php +++ b/src/MonkeyPatch/Patchers/FileReplacementPatcher.php @@ -18,7 +18,7 @@ public function __construct(string $replacementFile) /** * @throws MonkeyPatchingException */ - public function patch(string $fileContents, string $pathname): array + public function patch(string $fileContents, string $pathname, string $context = null): array { $replacementFileContents = file_get_contents($this->replacementFile); diff --git a/src/MonkeyPatch/Patchers/PatcherInterface.php b/src/MonkeyPatch/Patchers/PatcherInterface.php index 2b3ec579a..c33608e8a 100644 --- a/src/MonkeyPatch/Patchers/PatcherInterface.php +++ b/src/MonkeyPatch/Patchers/PatcherInterface.php @@ -7,7 +7,7 @@ interface PatcherInterface /** * @return array{string, string} */ - public function patch(string $fileContents, string $pathname): array; + public function patch(string $fileContents, string $pathname, string $context = null): array; /** * @return array{ diff --git a/src/Project/ContentProject.php b/src/Project/ContentProject.php index 7fcc2875e..2b093cb4d 100644 --- a/src/Project/ContentProject.php +++ b/src/Project/ContentProject.php @@ -36,7 +36,7 @@ abstract public function getActivationString(): string; abstract protected function symlinkProjectInContentDir(string $wpRootDir): void; - abstract protected function activate(string $wpRootDir, int $serverLocalhostPort): bool; + abstract public function activate(string $wpRootDir, int $serverLocalhostPort): bool; /** * @return array|false diff --git a/src/Project/PluginProject.php b/src/Project/PluginProject.php index 0fa33cca4..d2fcf388b 100644 --- a/src/Project/PluginProject.php +++ b/src/Project/PluginProject.php @@ -118,7 +118,7 @@ public function getPluginFilePathName(): string * @throws Throwable * @throws ProcessException */ - protected function activate(string $wpRootDir, int $serverLocalhostPort): bool + public function activate(string $wpRootDir, int $serverLocalhostPort): bool { $codeExec = new CodeExecutionFactory($wpRootDir, 'localhost:' . $serverLocalhostPort); $pluginString = basename(dirname($this->pluginFile)) . '/' . basename($this->pluginFile); @@ -127,6 +127,7 @@ protected function activate(string $wpRootDir, int $serverLocalhostPort): bool if ($activationResult instanceof Throwable) { $message = $activationResult->getMessage(); $this->sayWarning('Could not activate plugin: ' . $message); + $this->say($activationResult->getFile() . ":" . $activationResult->getLine()); $this->say('This might happen because the plugin has unmet dependencies; wp-browser configuration ' . 'will continue, but you will need to manually activate the plugin and update the dump in ' . 'tests/Support/Data/dump.sql.'); diff --git a/src/Project/SiteProject.php b/src/Project/SiteProject.php index 3d1b06682..bf2d39a4b 100644 --- a/src/Project/SiteProject.php +++ b/src/Project/SiteProject.php @@ -49,20 +49,6 @@ public function __construct(InputInterface $input, OutputInterface $output, stri try { $this->installation = Installation::findInDir($this->workDir, false); $installationState = $this->installation->getState(); - - if ($installationState instanceof EmptyDir) { - throw new RuntimeException( - 'The WordPress installation directory is empty' - ); - } - - if ($installationState instanceof Scaffolded) { - throw new RuntimeException( - 'The WordPress installation directory is scaffolded, but not configured.' - ); - } - - $this->testEnvironment = new TestEnvironment(); } catch (Throwable $t) { throw new RuntimeException( 'Failed to initialize the WordPress installation: ' . lcfirst($t->getMessage()), @@ -70,6 +56,23 @@ public function __construct(InputInterface $input, OutputInterface $output, stri $t ); } + + $suggest = "Make sure you're initializing wp-browser at the root of your site project,". + " and that the directory contains the WordPress files and a wp-config.php file."; + + if ($installationState instanceof EmptyDir) { + throw new RuntimeException( + "The WordPress installation directory is empty.\n{$suggest}" + ); + } + + if ($installationState instanceof Scaffolded) { + throw new RuntimeException( + "The WordPress installation directory is scaffolded, but not configured.\n{$suggest}" + ); + } + + $this->testEnvironment = new TestEnvironment(); } public function getType(): string diff --git a/src/Project/ThemeProject.php b/src/Project/ThemeProject.php index 589324530..fa3fd7819 100644 --- a/src/Project/ThemeProject.php +++ b/src/Project/ThemeProject.php @@ -108,14 +108,14 @@ protected function symlinkProjectInContentDir(string $wpRootDir): void * @throws Throwable * @throws ProcessException */ - protected function activate(string $wpRootDir, int $serverLocalhostPort): bool + public function activate(string $wpRootDir, int $serverLocalhostPort): bool { $codeExec = new CodeExecutionFactory($wpRootDir, 'localhost:' . $serverLocalhostPort); $switchTheme = $codeExec->toSwitchTheme($this->basename, false); $activationResult = Loop::executeClosure($switchTheme)->getReturnValue(); if ($activationResult instanceof Throwable) { $message = $activationResult->getMessage(); - $this->sayWarning('Could not activate plugin: ' . $message); + $this->sayWarning('Could not activate theme: ' . $message); $this->say('This might happen because the theme has unmet dependencies; wp-browser configuration ' . 'will continue, but you will need to manually activate the theme and update the dump in ' . 'tests/Support/Data/dump.sql.'); diff --git a/src/RemovedInPHPUnitVersion10.php b/src/RemovedInPHPUnitVersion10.php new file mode 100644 index 000000000..fa9dd469c --- /dev/null +++ b/src/RemovedInPHPUnitVersion10.php @@ -0,0 +1,7 @@ + [ 'enabled' => array_merge([RunFailed::class], array_keys($testEnv->extensionsEnabled)), 'config' => $testEnv->extensionsEnabled, - 'commands' => array_merge([RunOriginal::class, RunAll::class, GenerateWPUnit::class, DbExport::class, DbImport::class], $testEnv->customCommands) + 'commands' => array_merge([RunOriginal::class, RunAll::class, GenerateWPUnit::class, DbExport::class, DbImport::class, MonkeyCachePath::class, MonkeyCacheClear::class], $testEnv->customCommands) ] ]; diff --git a/src/TestCase/WPTestCase.php b/src/TestCase/WPTestCase.php index fa4240831..af2dde5a0 100644 --- a/src/TestCase/WPTestCase.php +++ b/src/TestCase/WPTestCase.php @@ -2,18 +2,92 @@ namespace lucatume\WPBrowser\TestCase; +use AllowDynamicProperties; +use Codeception\Actor; +use Codeception\Exception\ModuleException; +use Codeception\Module; use Codeception\Test\Unit; -use lucatume\WPBrowser\Module\WPLoader; use lucatume\WPBrowser\Module\WPQueries; use ReflectionException; use ReflectionMethod; +use ReflectionProperty; use WP_UnitTestCase; +/** + * @method static commit_transaction() + * @method static delete_user($user_id) + * @method static factory() + * @method static flush_cache() + * @method static forceTicket($ticket) + * @method static get_called_class() + * @method static set_up_before_class() + * @method static tear_down_after_class() + * @method static text_array_to_dataprovider($input) + * @method static touch($file) + * @method _create_temporary_tables($query) + * @method _drop_temporary_tables($query) + * @method _make_attachment($upload, $parent_post_id = 0) + * @method assertDiscardWhitespace($expected, $actual, $message = '') + * @method assertEqualFields($actual, $fields, $message = '') + * @method assertEqualSets($expected, $actual, $message = '') + * @method assertEqualSetsWithIndex($expected, $actual, $message = '') + * @method assertEqualsIgnoreEOL($expected, $actual, $message = '') + * @method assertIXRError($actual, $message = '') + * @method assertNonEmptyMultidimensionalArray($actual, $message = '') + * @method assertNotIXRError($actual, $message = '') + * @method assertNotWPError($actual, $message = '') + * @method assertQueryTrue($prop) + * @method assertSameIgnoreEOL($expected, $actual, $message = '') + * @method assertSameSets($expected, $actual, $message = '') + * @method assertSameSetsWithIndex($expected, $actual, $message = '') + * @method assertWPError($actual, $message = '') + * @method assert_post_conditions() + * @method clean_up_global_scope() + * @method delete_folders($path) + * @method deprecated_function_run($function_name, $replacement, $version, $message = '') + * @method doing_it_wrong_run($function_name, $message, $version) + * @method expectDeprecated() + * @method expectedDeprecated() + * @method files_in_dir($dir) + * @method get_wp_die_handler($handler) + * @method go_to($url) + * @method knownPluginBug($ticket_id) + * @method knownUTBug($ticket_id) + * @method knownWPBug($ticket_id) + * @method remove_added_uploads() + * @method rmdir($path) + * @method scan_user_uploads() + * @method scandir($dir) + * @method setExpectedDeprecated($deprecated) + * @method setExpectedException($exception, $message = '', $code = NULL) + * @method setExpectedIncorrectUsage($doing_it_wrong) + * @method set_permalink_structure($structure = '') + * @method set_up() + * @method skipOnAutomatedBranches() + * @method skipTestOnTimeout($response) + * @method skipWithMultisite() + * @method skipWithoutMultisite() + * @method start_transaction() + * @method tear_down() + * @method temp_filename() + * @method unlink($file) + * @method unregister_all_meta_keys() + * @method void setCalledClass(string $class) + * @method wp_die_handler($message, $title, $args) + */ class WPTestCase extends Unit { + use WPTestCasePHPUnitMethodsTrait; + /** + * @var string[]|null + */ + private $coreTestCaseProperties = null; + /** + * @var Actor + */ + protected $tester; // Backup, and reset, globals between tests. - protected $backupGlobals = true; - + protected $backupGlobals = false; // A list of globals that should not be backed up: they are handled by the Core test case. protected $backupGlobalsBlacklist = [ 'wpdb', @@ -48,10 +122,8 @@ class WPTestCase extends Unit '_wpTestsBackupStaticAttributes', '_wpTestsBackupStaticAttributesExcludeList' ]; - // Backup, and reset, static class attributes between tests. - protected $backupStaticAttributes = true; - + protected $backupStaticAttributes = false; // A list of static attributes that should not be backed up as they are wired to explode when doing so. protected $backupStaticAttributesBlacklist = [ // WordPress @@ -64,9 +136,9 @@ class WPTestCase extends Unit // WooCommerce. 'WooCommerce' => ['_instance'], 'Automattic\WooCommerce\Internal\Admin\FeaturePlugin' => ['instance'], - 'Automattic\WooCommerce\RestApi\Server' => ['instance'] + 'Automattic\WooCommerce\RestApi\Server' => ['instance'], + 'WC_Payment_Gateways' => ['_instance'], ]; - /** * @param array $data */ @@ -77,7 +149,7 @@ public function __construct(?string $name = null, array $data = [], $dataName = $_wpTestsBackupStaticAttributes, $_wpTestsBackupStaticAttributesExcludeList; - $backupGlobalsReflectionProperty = new \ReflectionProperty($this, 'backupGlobals'); + $backupGlobalsReflectionProperty = new ReflectionProperty($this, 'backupGlobals'); $backupGlobalsReflectionProperty->setAccessible(true); $isDefinedInThis = $backupGlobalsReflectionProperty->getDeclaringClass()->getName() !== WPTestCase::class; if (!$isDefinedInThis && isset($_wpTestsBackupGlobals) && is_bool($_wpTestsBackupGlobals)) { @@ -85,11 +157,11 @@ public function __construct(?string $name = null, array $data = [], $dataName = } if (property_exists($this, 'backupGlobalsExcludeList')) { - $backupGlobalsExcludeListReflectionProperty = new \ReflectionProperty($this, 'backupGlobalsExcludeList'); + $backupGlobalsExcludeListReflectionProperty = new ReflectionProperty($this, 'backupGlobalsExcludeList'); $backupGlobalsExcludeListReflectionProperty->setAccessible(true); } else { // Older versions of PHPUnit. - $backupGlobalsExcludeListReflectionProperty = new \ReflectionProperty($this, 'backupGlobalsBlacklist'); + $backupGlobalsExcludeListReflectionProperty = new ReflectionProperty($this, 'backupGlobalsBlacklist'); $backupGlobalsExcludeListReflectionProperty->setAccessible(true); } $backupGlobalsExcludeListReflectionProperty->setAccessible(true); @@ -105,7 +177,7 @@ public function __construct(?string $name = null, array $data = [], $dataName = ); } - $backupStaticAttributesReflectionProperty = new \ReflectionProperty($this, 'backupStaticAttributes'); + $backupStaticAttributesReflectionProperty = new ReflectionProperty($this, 'backupStaticAttributes'); $backupStaticAttributesReflectionProperty->setAccessible(true); $isDefinedInThis = $backupStaticAttributesReflectionProperty->getDeclaringClass() ->getName() !== WPTestCase::class; @@ -114,14 +186,14 @@ public function __construct(?string $name = null, array $data = [], $dataName = } if (property_exists($this, 'backupStaticAttributesExcludeList')) { - $backupStaticAttributesExcludeListReflectionProperty = new \ReflectionProperty( + $backupStaticAttributesExcludeListReflectionProperty = new ReflectionProperty( $this, 'backupStaticAttributesExcludeList' ); $backupStaticAttributesExcludeListReflectionProperty->setAccessible(true); } else { // Older versions of PHPUnit. - $backupStaticAttributesExcludeListReflectionProperty = new \ReflectionProperty( + $backupStaticAttributesExcludeListReflectionProperty = new ReflectionProperty( $this, 'backupStaticAttributesBlacklist' ); @@ -142,55 +214,33 @@ public function __construct(?string $name = null, array $data = [], $dataName = parent::__construct($name, $data, $dataName); } - /** * @var array */ protected $additionalGlobalsBackup = []; - /** * @var array */ private static $coreTestCaseMap = []; - private static function getCoreTestCase(): WP_UnitTestCase { if (isset(self::$coreTestCaseMap[static::class])) { return self::$coreTestCaseMap[static::class]; } $coreTestCase = new class extends WP_UnitTestCase { + use WPUnitTestCasePolyfillsTrait; }; $coreTestCase->setCalledClass(static::class); self::$coreTestCaseMap[static::class] = $coreTestCase; return $coreTestCase; } - - public static function setUpBeforeClass(): void - { - parent::setUpBeforeClass(); - self::getCoreTestCase()->set_up_before_class(); - } - protected function backupAdditionalGlobals(): void { - foreach ([ - '_wp_registered_theme_features' - ] as $key - ) { - if (isset($GLOBALS[$key])) { - $this->additionalGlobalsBackup = $GLOBALS[$key]; - } + if (isset($GLOBALS['_wp_registered_theme_features'])) { + $this->additionalGlobalsBackup = $GLOBALS['_wp_registered_theme_features']; } } - - protected function setUp(): void - { - parent::setUp(); - $this->set_up(); //@phpstan-ignore-line magic __call - $this->backupAdditionalGlobals(); - } - protected function restoreAdditionalGlobals(): void { foreach ($this->additionalGlobalsBackup as $key => $value) { @@ -198,33 +248,16 @@ protected function restoreAdditionalGlobals(): void unset($this->additionalGlobalsBackup[$key]); } } - - protected function tearDown(): void - { - $this->restoreAdditionalGlobals(); - $this->tear_down(); //@phpstan-ignore-line magic __call - parent::tearDown(); - } - - - public static function tearDownAfterClass(): void - { - static::tear_down_after_class(); //@phpstan-ignore-line magic __callStatic - parent::tearDownAfterClass(); - } - protected function assertPostConditions(): void { parent::assertPostConditions(); - static::assert_post_conditions(); //@phpstan-ignore-line magic __callStatic + static::assert_post_conditions(); } - public function __destruct() { // Allow garbage collection of the core test case instance. unset(self::$coreTestCaseMap[static::class]); } - /** * @param array $arguments * @throws ReflectionException @@ -232,12 +265,22 @@ public function __destruct() */ public static function __callStatic(string $name, array $arguments) { + switch ($name) { + case '_setUpBeforeClass': + $name = 'setUpBeforeClass'; + break; + case '_tearDownAfterClass': + $name = 'tearDownAfterClass'; + break; + default: + $name = $name; + break; + } $coreTestCase = self::getCoreTestCase(); $reflectionMethod = new ReflectionMethod($coreTestCase, $name); $reflectionMethod->setAccessible(true); return $reflectionMethod->invokeArgs(null, $arguments); } - /** * @param array $arguments * @throws ReflectionException @@ -250,11 +293,82 @@ public function __call(string $name, array $arguments) $reflectionMethod->setAccessible(true); return $reflectionMethod->invokeArgs($coreTestCase, $arguments); } - + /** + * @throws ModuleException If the WPQueries module is not available under any name. + */ protected function queries(): WPQueries { + /** @var array $modules */ + $modules = $this->getMetadata()->getCurrent('modules'); + $module = isset($modules['WPQueries']) ? 'WPQueries' : WPQueries::class; /** @var WPQueries $wpQueries */ - $wpQueries = $this->getModule(WPQueries::class); + $wpQueries = $this->getModule($module); + return $wpQueries; } + private function isCoreTestCaseProperty(string $name): bool + { + if ($this->coreTestCaseProperties === null) { + $this->coreTestCaseProperties = array_map( + static function (ReflectionProperty $p) { + return $p->getName(); + }, + (new \ReflectionClass(self::getCoreTestCase()))->getProperties() + ); + } + + return in_array($name, $this->coreTestCaseProperties, true); + } + /** + * @throws ReflectionException + * @return mixed + */ + public function __get(string $name) + { + if (!$this->isCoreTestCaseProperty($name)) { + return $this->{$name} ?? null; + } + + $coreTestCase = self::getCoreTestCase(); + $reflectionProperty = new ReflectionProperty($coreTestCase, $name); + $reflectionProperty->setAccessible(true); + $value = $reflectionProperty->getValue($coreTestCase); + +// if (is_array($value)) { +// return new ArrayReflectionPropertyAccessor($reflectionProperty, $coreTestCase); +// } + + return $value; + } + /** + * @throws ReflectionException + * @param mixed $value + */ + public function __set(string $name, $value): void + { + if (!$this->isCoreTestCaseProperty($name)) { + // Just set a dynamic property on the test case. + $this->{$name} = $value; + return; + } + + $coreTestCase = self::getCoreTestCase(); + $reflectionProperty = new ReflectionProperty($coreTestCase, $name); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($coreTestCase, $value); + } + /** + * @throws ReflectionException + */ + public function __isset(string $name): bool + { + if (!$this->isCoreTestCaseProperty($name)) { + return isset($this->{$name}); + } + + $coreTestCase = self::getCoreTestCase(); + $reflectionProperty = new ReflectionProperty($coreTestCase, $name); + $reflectionProperty->setAccessible(true); + return $reflectionProperty->isInitialized($coreTestCase); + } } diff --git a/src/TestCase/WPTestCasePHPUnitMethodsTrait.php b/src/TestCase/WPTestCasePHPUnitMethodsTrait.php new file mode 100644 index 000000000..19aad0651 --- /dev/null +++ b/src/TestCase/WPTestCasePHPUnitMethodsTrait.php @@ -0,0 +1,83 @@ +set_up_before_class(); + } + + public static function tearDownAfterClass() //@phpstan-ignore-line + { + static::tear_down_after_class(); //@phpstan-ignore-line magic __callStatic + parent::tearDownAfterClass(); + } + + protected function setUp() //@phpstan-ignore-line + { + parent::setUp(); + + // Restores the uploads directory if removed during tests. + $uploads = wp_upload_dir(); + if (!is_dir($uploads['basedir']) + && !mkdir($uploads['basedir'], 0755, true) + && !is_dir($uploads['basedir'])) { + throw new \RuntimeException('Failed to create uploads base directory.'); + } + + $this->set_up(); //@phpstan-ignore-line magic __call + $this->backupAdditionalGlobals(); + } + + protected function tearDown() //@phpstan-ignore-line + { + $this->restoreAdditionalGlobals(); + $this->tear_down(); //@phpstan-ignore-line magic __call + parent::tearDown(); + } + } +} else { + trait WPTestCasePHPUnitMethodsTrait + { + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + self::getCoreTestCase()->set_up_before_class(); + } + + public static function tearDownAfterClass(): void + { + static::tear_down_after_class(); //@phpstan-ignore-line magic __callStatic + parent::tearDownAfterClass(); + } + + protected function setUp(): void + { + parent::setUp(); + + // Restores the uploads directory if removed during tests. + $uploads = wp_upload_dir(); + if (!is_dir($uploads['basedir']) + && !mkdir($uploads['basedir'], 0755, true) + && !is_dir($uploads['basedir'])) { + throw new \RuntimeException('Failed to create uploads base directory.'); + } + + $this->set_up(); //@phpstan-ignore-line magic __call + $this->backupAdditionalGlobals(); + } + + protected function tearDown(): void + { + $this->restoreAdditionalGlobals(); + $this->tear_down(); //@phpstan-ignore-line magic __call + parent::tearDown(); + } + } +} diff --git a/src/TestCase/WPUnitTestCasePolyfillsTrait.php b/src/TestCase/WPUnitTestCasePolyfillsTrait.php new file mode 100644 index 000000000..795149d49 --- /dev/null +++ b/src/TestCase/WPUnitTestCasePolyfillsTrait.php @@ -0,0 +1,24 @@ + $arguments + */ + public function __call(string $name, array $arguments) //@phpstan-ignore-line cannot be type-hinted + { + return TestCase::$name(...$arguments); + } + + /** + * @param array $arguments + */ + public static function __callStatic(string $name, array $arguments) //@phpstan-ignore-line cannot be type-hinted + { + return TestCase::$name(...$arguments); + } +} diff --git a/src/Utils/ChromedriverInstaller.php b/src/Utils/ChromedriverInstaller.php index 70f9f8822..bcf3b583b 100644 --- a/src/Utils/ChromedriverInstaller.php +++ b/src/Utils/ChromedriverInstaller.php @@ -7,29 +7,28 @@ use lucatume\WPBrowser\Adapters\Symfony\Component\Process\Process; use lucatume\WPBrowser\Exceptions\InvalidArgumentException; use lucatume\WPBrowser\Exceptions\RuntimeException; +use lucatume\WPBrowser\Utils\Filesystem as FS; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; -use lucatume\WPBrowser\Utils\Filesystem as FS; use function lucatume\WPBrowser\useMemoString; class ChromedriverInstaller { - public const ERR_INVALID_VERSION = 1; - public const ERR_INVALID_BINARY = 2; - public const ERR_UNSUPPORTED_PLATFORM = 3; - public const ERR_REMOVE_EXISTING_ZIP_FILE = 4; - public const ERR_VERSION_NOT_STRING = 5; - public const ERR_INVALID_VERSION_FORMAT = 6; - public const ERR_DESTINATION_NOT_DIR = 7; - public const ERR_FETCH_MILESTONE_DOWNLOADS = 11; - public const ERR_DECODE_MILESTONE_DOWNLOADS = 12; - public const ERR_DOWNLOAD_URL_NOT_FOUND = 13; - public const ERR_REMOVE_EXISTING_BINARY = 14; - public const ERR_MOVE_BINARY = 15; - public const ERR_DETECT_PLATFORM = 16; - public const ERR_BINARY_CHMOD = 17; + public const ERR_INVALID_BINARY = 1; + public const ERR_UNSUPPORTED_PLATFORM = 2; + public const ERR_REMOVE_EXISTING_ZIP_FILE = 3; + public const ERR_VERSION_NOT_STRING = 4; + public const ERR_INVALID_VERSION_FORMAT = 5; + public const ERR_DESTINATION_NOT_DIR = 6; + public const ERR_FETCH_MILESTONE_DOWNLOADS = 7; + public const ERR_DECODE_MILESTONE_DOWNLOADS = 8; + public const ERR_DOWNLOAD_URL_NOT_FOUND = 9; + public const ERR_REMOVE_EXISTING_BINARY = 10; + public const ERR_DETECT_PLATFORM = 11; + public const ERR_BINARY_CHMOD = 12; + /** * @var \Symfony\Component\Console\Output\OutputInterface */ @@ -63,6 +62,7 @@ public function __construct( $this->output->writeln("Platform: $platform"); $binary = $binary ?? $this->detectBinary(); + $this->binary = $this->checkBinary($binary); $this->output->writeln("Binary: $binary"); @@ -73,116 +73,6 @@ public function __construct( $this->output->writeln("Version: $version"); } - /** - * @throws JsonException - */ - public function install(string $dir = null): string - { - if ($dir === null) { - global $_composer_bin_dir; - $dir = $_composer_bin_dir; - $composerEnvBinDir = getenv('COMPOSER_BIN_DIR'); - if ($composerEnvBinDir && is_string($composerEnvBinDir) && is_dir($composerEnvBinDir)) { - $dir = $composerEnvBinDir; - } - } - - if (!is_dir($dir)) { - throw new InvalidArgumentException( - "The directory $dir does not exist.", - self::ERR_DESTINATION_NOT_DIR - ); - } - - $this->output->writeln("Fetching Chromedriver version URL ..."); - - $zipFilePathname = $this->useEnvZipFile ? - Env::get('WPBROWSER_CHROMEDRIVER_ZIP_FILE', null) - : null; - $cacheDir = FS::cacheDir() . '/chromedriver'; - $executableFileName = $dir . '/' . $this->getExecutableFileName(); - - if (!(is_string($zipFilePathname) && is_file($zipFilePathname))) { - $downloadUrl = $this->fetchChromedriverVersionUrl(); - if (!is_dir($cacheDir) && !(mkdir($cacheDir, 0777, true) && is_dir($cacheDir))) { - throw new RuntimeException("Could not create Chromedriver cache directory $cacheDir."); - } - $zipFilePathname = rtrim($cacheDir, '\\/') . '/chromedriver.zip'; - if (is_file($zipFilePathname) && !unlink($zipFilePathname)) { - throw new RuntimeException( - "Could not remove existing zip file $zipFilePathname", - self::ERR_REMOVE_EXISTING_ZIP_FILE - ); - } - $this->output->writeln('Downloading Chromedriver to ' . $zipFilePathname . ' ...'); - $zipFilePathname = Download::fileFromUrl($downloadUrl, $zipFilePathname); - $this->output->writeln('Downloaded Chromedriver to ' . $zipFilePathname); - } - - if (is_file($executableFileName) && !unlink($executableFileName)) { - throw new RuntimeException( - "Could not remove existing executable file $executableFileName", - self::ERR_REMOVE_EXISTING_BINARY - ); - } - - Zip::extractFile($zipFilePathname, $this->getExecutableFileName(), $executableFileName); - - if (!chmod($executableFileName, 0755)) { - throw new RuntimeException( - "Could not make Chromedriver executable", - self::ERR_BINARY_CHMOD - ); - } - - $this->output->writeln("Installed Chromedriver to $executableFileName"); - - return $executableFileName; - } - - /** - * @throws RuntimeException - */ - private function detectVersion(): string - { - switch ($this->platform) { - case 'linux64': - case 'mac-x64': - case 'mac-arm64': - $process = new Process([$this->binary, ' --version']); - break; - case 'win32': - case 'win64': - $process = Process::fromShellCommandline( - 'reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version' - ); - break; - } - - $process->run(); - $chromeVersion = $process->getOutput(); - - if ($chromeVersion === '') { - throw new RuntimeException( - "Could not detect Chrome version from $this->binary", - self::ERR_VERSION_NOT_STRING - ); - } - - $matches = []; - if (!( - preg_match('/\s*\d+\.\d+\.\d+\.\d+\s*/', $chromeVersion, $matches) - && isset($matches[0]) && is_string($matches[0]) - )) { - throw new RuntimeException( - "Could not detect Chrome version from $this->binary", - self::ERR_INVALID_VERSION_FORMAT - ); - } - - return trim($matches[0]); - } - /** * @throws RuntimeException */ @@ -236,10 +126,40 @@ private function checkPlatform($platform): string ); } - /** @var 'linux64'|'mac-x64'|'mac-arm64'|'win32'|'win64' $platform */ + /** @var 'linux64'|'mac-arm64'|'mac-x64'|'win32'|'win64' $platform */ return $platform; } + /** + * @throws RuntimeException + */ + private function detectBinary(): string + { + switch ($this->platform) { + case 'linux64': + return $this->detectLinuxBinaryPath(); + case 'mac-x64': + case 'mac-arm64': + return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; + case 'win32': + case 'win64': + return $this->detectWindowsBinaryPath(); + } + } + + private function detectLinuxBinaryPath(): string + { + foreach (['chromium', 'google-chrome'] as $bin) { + $path = exec("which $bin"); + + if (!empty($path)) { + return $path; + } + } + + return '/usr/bin/google-chrome'; + } + private function detectWindowsBinaryPath(): string { $candidates = [ @@ -258,36 +178,84 @@ private function detectWindowsBinaryPath(): string } /** - * @throws RuntimeException + * @param mixed $binary */ - private function detectBinary(): string + private function checkBinary($binary): string + { + // Replace escaped spaces with spaces to check the binary. + if (!(is_string($binary) && is_executable(str_replace('\ ', ' ', $binary)))) { + throw new RuntimeException( + "Invalid Chrome binary: not executable or not existing.\n" . + "Checked paths: " . implode(', ', $this->getBinaryCandidateList()) . "\n", + self::ERR_INVALID_BINARY + ); + } + + return $binary; + } + + /** + * @return string[] + */ + private function getBinaryCandidateList(): array { switch ($this->platform) { case 'linux64': - return '/usr/bin/google-chrome'; + return ['chromium', 'google-chrome']; case 'mac-x64': case 'mac-arm64': - return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; + return ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome']; case 'win32': case 'win64': - return $this->detectWindowsBinaryPath(); + return [ + getenv('ProgramFiles') . '\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe', + getenv('ProgramFiles(x86)') . '\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe', + getenv('LOCALAPPDATA') . '\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe' + ]; } } /** - * @param mixed $binary + * @throws RuntimeException */ - private function checkBinary($binary): string + private function detectVersion(): string { - // Replace escaped spaces with spaces to check the binary. - if (!(is_string($binary) && is_executable(str_replace('\ ', ' ', $binary)))) { + switch ($this->platform) { + case 'linux64': + case 'mac-x64': + case 'mac-arm64': + $process = new Process([$this->binary, ' --version']); + break; + case 'win32': + case 'win64': + $process = Process::fromShellCommandline( + 'reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version' + ); + break; + } + + $process->run(); + $chromeVersion = $process->getOutput(); + + if ($chromeVersion === '') { throw new RuntimeException( - "Invalid Chrome binary: not executable or not existing.", - self::ERR_INVALID_BINARY + "Could not detect Chrome version from $this->binary", + self::ERR_VERSION_NOT_STRING ); } - return $binary; + $matches = []; + if (!( + preg_match('/\s*\d+\.\d+\.\d+\.\d+\s*/', $chromeVersion, $matches) + && isset($matches[0]) && is_string($matches[0]) + )) { + throw new RuntimeException( + "Could not detect Chrome version from $this->binary", + self::ERR_INVALID_VERSION_FORMAT + ); + } + + return trim($matches[0]); } /** @@ -306,6 +274,86 @@ private function checkVersion($version): string return $matches['major']; } + /** + * @throws JsonException + */ + public function install(string $dir = null): string + { + if ($dir === null) { + global $_composer_bin_dir; + $dir = $_composer_bin_dir; + $composerEnvBinDir = getenv('COMPOSER_BIN_DIR'); + if ($composerEnvBinDir && is_string($composerEnvBinDir) && is_dir($composerEnvBinDir)) { + $dir = $composerEnvBinDir; + } + } + + if (!is_dir($dir)) { + throw new InvalidArgumentException( + "The directory $dir does not exist.", + self::ERR_DESTINATION_NOT_DIR + ); + } + + $this->output->writeln("Fetching Chromedriver version URL ..."); + + $zipFilePathname = $this->useEnvZipFile ? + Env::get('WPBROWSER_CHROMEDRIVER_ZIP_FILE', null) + : null; + $cacheDir = FS::cacheDir() . '/chromedriver'; + $executableFileName = $dir . '/' . $this->getExecutableFileName(); + + if (!(is_string($zipFilePathname) && is_file($zipFilePathname))) { + $downloadUrl = $this->fetchChromedriverVersionUrl(); + if (!is_dir($cacheDir) && !(mkdir($cacheDir, 0777, true) && is_dir($cacheDir))) { + throw new RuntimeException("Could not create Chromedriver cache directory $cacheDir."); + } + $zipFilePathname = rtrim($cacheDir, '\\/') . '/chromedriver.zip'; + if (is_file($zipFilePathname) && !unlink($zipFilePathname)) { + throw new RuntimeException( + "Could not remove existing zip file $zipFilePathname", + self::ERR_REMOVE_EXISTING_ZIP_FILE + ); + } + $this->output->writeln('Downloading Chromedriver to ' . $zipFilePathname . ' ...'); + $zipFilePathname = Download::fileFromUrl($downloadUrl, $zipFilePathname); + $this->output->writeln('Downloaded Chromedriver to ' . $zipFilePathname); + } + + if (is_file($executableFileName) && !unlink($executableFileName)) { + throw new RuntimeException( + "Could not remove existing executable file $executableFileName", + self::ERR_REMOVE_EXISTING_BINARY + ); + } + + Zip::extractFile($zipFilePathname, $this->getExecutableFileName(), $executableFileName); + + if (!chmod($executableFileName, 0755)) { + throw new RuntimeException( + "Could not make Chromedriver executable", + self::ERR_BINARY_CHMOD + ); + } + + $this->output->writeln("Installed Chromedriver to $executableFileName"); + + return $executableFileName; + } + + private function getExecutableFileName(): string + { + switch ($this->platform) { + case 'linux64': + case 'mac-x64': + case 'mac-arm64': + return 'chromedriver'; + case 'win32': + case 'win64': + return 'chromedriver.exe'; + } + } + private function fetchChromedriverVersionUrl(): string { return useMemoString( @@ -349,7 +397,9 @@ private function unmemoizedFetchChromedriverVersionUrl(): string && is_array($decoded['milestones'][$this->milestone]['downloads']['chromedriver']) )) { throw new RuntimeException( - 'Failed to decode known good Chrome and Chromedriver versions with downloads.', + "Failed to find a version of Chromedriver to download for your platform and Chrome combination." . + "\nTry upgrading Chrome and making sure it is executable from one of the expected locations for your " . + "platform ({$this->platform}): " . implode(', ', $this->getBinaryCandidateList()), self::ERR_DECODE_MILESTONE_DOWNLOADS ); } @@ -374,19 +424,6 @@ private function unmemoizedFetchChromedriverVersionUrl(): string ); } - private function getExecutableFileName(): string - { - switch ($this->platform) { - case 'linux64': - case 'mac-x64': - case 'mac-arm64': - return 'chromedriver'; - case 'win32': - case 'win64': - return 'chromedriver.exe'; - } - } - public function getVersion(): string { return $this->milestone; diff --git a/src/Utils/MonkeyPatch.php b/src/Utils/MonkeyPatch.php index d1165c06f..7d2ba6448 100644 --- a/src/Utils/MonkeyPatch.php +++ b/src/Utils/MonkeyPatch.php @@ -5,13 +5,23 @@ use lucatume\WPBrowser\MonkeyPatch\FileStreamWrapper; use lucatume\WPBrowser\MonkeyPatch\Patchers\FileContentsReplacementPatcher; use lucatume\WPBrowser\MonkeyPatch\Patchers\FileReplacementPatcher; +use lucatume\WPBrowser\Utils\Filesystem as FS; class MonkeyPatch { - public static function redirectFileToFile(string $fromFile, string $toFile): void - { - FileStreamWrapper::setPatcherForFile($fromFile, new FileReplacementPatcher($toFile)); + public static function redirectFileToFile( + string $fromFile, + string $toFile, + bool $redirectOpenedPath = true, + string $context = null + ): void { + FileStreamWrapper::setPatcherForFile( + $fromFile, + new FileReplacementPatcher($toFile), + $redirectOpenedPath, + $context + ); } public static function dudFile(): string @@ -19,8 +29,29 @@ public static function dudFile(): string return dirname(__DIR__) . '/MonkeyPatch/dud-file.php'; } - public static function redirectFileContents(string $fromFile, string $fileContents):void + public static function redirectFileContents( + string $fromFile, + string $fileContents, + bool $redirectOpenedPath = true, + string $context = null + ): void { + FileStreamWrapper::setPatcherForFile( + $fromFile, + new FileContentsReplacementPatcher($fileContents), + $redirectOpenedPath, + $context + ); + } + + public static function getReplacementFileName(string $pathname, string $context): string + { + $mtime = (string)filemtime($pathname); + $hash = md5($pathname . $mtime . $context); + return FS::getTmpSubDir('_monkeypatch') . "/{$hash}.php"; + } + + public static function getCachePath(): string { - FileStreamWrapper::setPatcherForFile($fromFile, new FileContentsReplacementPatcher($fileContents)); + return FS::getTmpSubDir('_monkeypatch'); } } diff --git a/src/Utils/Random.php b/src/Utils/Random.php index f8c5079a1..27b37588b 100644 --- a/src/Utils/Random.php +++ b/src/Utils/Random.php @@ -15,11 +15,11 @@ class Random * @var string */ private static $saltChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' . - '!"#$%&()*+,-./:;<=>?@[]^_`{|}~'; + '!#$%&()*+,-./:;<>?@[]^_`{|}~'; /** * @var int */ - private static $saltCharsCount = 92; + private static $saltCharsCount = 90; /** * @var string */ diff --git a/src/deprecated-functions.php b/src/deprecated-functions.php new file mode 100644 index 000000000..1eec8d05e --- /dev/null +++ b/src/deprecated-functions.php @@ -0,0 +1,442 @@ + + * @deprecated Use \lucatume\WPBrowser\Utils\MysqlDatabase::dbDsnMap instead. + */ + function dbDsnMap(string $dbHost): array + { + return Db::dbDsnToMap($dbHost); + } + + /** + * @param array{ + * type: string, + * host: string, + * port: string, + * unix_socket: string, + * version: string, + * file: string, + * memory: bool + * } $dsn The database DSN map. + * @return array{ + * dsn: string, + * user: string, + * password: string + * } + * @deprecated Use \lucatume\WPBrowser\Utils\MysqlDatabase::dbCredentials instead. + */ + function dbCredentials(array $dsn, string $dbuser, string $dbpass, string $dbname = null): array + { + return Db::dbCredentials($dsn, $dbuser, $dbpass, $dbname); + } + + /** + * @param array{ + * type: string, + * host: string, + * port: string, + * unix_socket: string, + * dbname: string, + * file: string, + * version: string, + * memory: bool + * } $dbDsnMap + * + * @deprecated Use \lucatume\WPBrowser\Utils\MysqlDatabase::dbDsnString instead. + */ + function dbDsnString(array $dbDsnMap, bool $forDbHost = false): string + { + return Db::dbDsnString($dbDsnMap, $forDbHost); + } + + /** + * @deprecated Use \lucatume\WPBrowser\Utils\MysqlDatabase::isDsnString instead. + */ + function isDsnString(string $string): bool + { + return Db::isDsnString($string); + } + + /** + * @return array + * @deprecated Use \lucatume\WPBrowser\Utils\MysqlDatabase::dbDsnToMap instead. + */ + function dbDsnToMap(string $dsnString): array + { + return Db::dbDsnToMap($dsnString); + } + + /** + * @return array + * @deprecated Use \lucatume\WPBrowser\Utils\Env::envFile instead. + */ + function envFile(string $file): array + { + return Env::envFile($file); + } + + /** + * @deprecated Use \lucatume\WPBrowser\Utils\Env::os instead. + */ + function os(): string + { + return Env::os(); + } + + /** + * @param array $map + * @deprecated Use \lucatume\WPBrowser\Utils\Env::loadEnvMap instead. + */ + function loadEnvMap(array $map, bool $overwrite = true): void + { + Env::loadEnvMap($map, $overwrite); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::rrmdir` instead. + */ + function rrmdir(string $src): bool + { + return Filesystem::rrmdir($src); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::homeDir` instead. + */ + function homeDir(string $path = ''): string + { + return Filesystem::homeDir($path); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::resolvePath` instead. + * @return bool|string + */ + function resolvePath(string $path, string $root = null) + { + return Filesystem::resolvePath($path, $root); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::untrailslashit` instead. + */ + function untrailslashit(string $path): string + { + return Filesystem::untrailslashit($path); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::unleadslashit` instead. + */ + function unleadslashit(string $path): string + { + return Filesystem::unleadslashit($path); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::recurseCopy` instead. + */ + function recurseCopy(string $source, string $destination): bool + { + return Filesystem::recurseCopy($source, $destination); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::rrmdir` instead. + */ + function recurseRemoveDir(string $target): bool + { + return Filesystem::rrmdir($target); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::findHereOrInParentrmdir` instead. + * @return bool|string + */ + function findHereOrInParent(string $path, string $root) + { + return Filesystem::findHereOrInParent($path, $root); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::realpathish` instead. + * @return bool|string + */ + function realpathish(string $path) + { + return Filesystem::realpath($path); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Filesystem::mkdirp` instead. + * @param array>|string $contents + */ + function mkdirp(string $pathname, $contents = [], int $mode = 0777): void + { + Filesystem::mkdirp($pathname, $contents, $mode); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Events\Dispatcher::addListener` instead. + */ + function addListener(string $eventName, callable $listener, int $priority = 0): void + { + Dispatcher::addListener($eventName, $listener, $priority); + } + + /** + * @param array $context + * @deprecated Use `lucatume\WPBrowser\Events\Dispatcher::dispatch` instead. + * @param mixed $origin + */ + function dispatch(string $eventName, $origin = null, ?array $context = []): void + { + Dispatcher::dispatch($eventName, $origin, $context ?? []); + } + + + /** + * @param array $props + * @throws ReflectionException + * @deprecated Use `lucatume\WPBrowser\Utils\Property::setPropertiesForClass` instead. + * @param object $object + * @return object + */ + function setPropertiesForClass($object, string $class, array $props) + { + return Property::setPropertiesForClass($object, $class, $props); + } + + /** + * @param array $props + * @throws ReflectionException + * @deprecated Use `lucatume\WPBrowser\Utils\Property::setPrivateProperties` instead. + * @param object|string $object + */ + function setPrivateProperties($object, array $props): void + { + Property::setPrivateProperties($object, $props); + } + + /** + * @throws ReflectionException + * @deprecated Use `lucatume\WPBrowser\Utils\Property::readPrivate` instead. + * @param object|string $object + * @return mixed + */ + function readPrivateProperty($object, string $prop) + { + return Property::readPrivate($object, $prop); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::normalizeNewLine` instead. + */ + function normalizeNewLine(string $str): string + { + return Strings::normalizeNewLine($str); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::slug` instead. + */ + function slug(string $string, string $sep = '-', bool $let = false): string + { + return Strings::slug($string, $sep, $let); + } + + /** + * @param array $data + * @param array $fnArgs + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::renderString` instead. + */ + function renderString(string $template, array $data = [], array $fnArgs = []): string + { + return Strings::renderString($template, $data, $fnArgs); + } + + /** + * @return array{ + * fragment: string, + * host: string, + * pass: string, + * path: string, + * port: int, + * query: string, + * scheme: string, + * user: string + * } + * @deprecated Use `lucatume\WPBrowser\Utils\Url::parseUrl` instead. + */ + function parseUrl(string $url): array + { + return Url::parseUrl($url); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Url::isRegex` instead. + */ + function isRegex(string $string): bool + { + return Strings::isRegex($string); + } + + /** + * @param array $elements + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::andList` instead. + */ + function andList(array $elements): string + { + return Strings::andList($elements); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Url::getDomain` instead. + */ + function urlDomain(string $fullUrl): string + { + return Url::getDomain($fullUrl); + } + + /** + * @deprecated Use `Codeception\Util\Debug::isEnabled` instead. + */ + function isDebug(bool $activate = null): bool + { + return Debug::isEnabled(); + } + + /** + * @deprecated Use `codecept_debug` instead. + * @param mixed $message + */ + function debug($message): void + { + codecept_debug($message); + } + + /** + * @deprecated Use `PHPUnit\Framework\Assert:assertTrue` instead. + * @param mixed $condition + */ + function ensure($condition, string $message): void + { + Assert::assertTrue((bool)$condition, $message); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Composer::vendorDir` instead. + */ + function vendorDir(string $path = ''): string + { + return Composer::vendorDir($path); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\CorePHPUnit::path` instead. + */ + function includesDir(string $path = ''): string + { + return CorePHPUnit::path($path); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::stripTags` instead. + */ + function strip_all_tags(string $string, bool $removeBreaks = false): string + { + return Strings::stripTags($string, $removeBreaks); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::removeAccents` instead. + */ + function remove_accents(string $string): string + { + return Strings::removeAccents($string); + } + + /** + * @deprecated Use `lucatume\WPBrowser\Utils\Strings::sanitizeUsername` instead. + */ + function sanitize_user(string $username, bool $strict = false): string + { + return Strings::sanitizeUsername($username, $strict); + } + + /** + * @param array|null $tables + * @return array + * @deprecated Use `lucatume\WPBrowser\Utils\WP::dropWpTables` instead. + */ + function dropWpTables(wpdb $wpdb, array $tables = null): array + { + return WP::dropWpTables($wpdb, $tables); + } + + /** + * @param array|null $tables + * @return array + * @deprecated Use `lucatume\WPBrowser\Utils\WP::emptyWpTables` instead. + */ + function emptyWpTables(wpdb $wpdb, array $tables = null): array + { + return WP::emptyWpTables($wpdb, $tables); + } + + /** + * @deprecated Use `\PHPUnit\Runner\Version::id` instead. + */ + function phpunitVersion(): string + { + return Version::id(); + } +} diff --git a/src/version-4-aliases.php b/src/version-4-aliases.php index 7aa8004ba..d303cd2e3 100644 --- a/src/version-4-aliases.php +++ b/src/version-4-aliases.php @@ -2,7 +2,15 @@ namespace lucatume\WPBrowser; +use lucatume\WPBrowser\Command\GenerateWPAjax; +use lucatume\WPBrowser\Command\GenerateWPCanonical; +use lucatume\WPBrowser\Command\GenerateWPRestApi; +use lucatume\WPBrowser\Command\GenerateWPRestController; +use lucatume\WPBrowser\Command\GenerateWPRestPostTypeController; use lucatume\WPBrowser\Command\GenerateWPUnit; +use lucatume\WPBrowser\Command\GenerateWPXMLRPC; +use lucatume\WPBrowser\Extension\EventDispatcherBridge; +use lucatume\WPBrowser\Extension\IsolationSupport; use lucatume\WPBrowser\Module\WPBrowser; use lucatume\WPBrowser\Module\WPBrowserMethods; use lucatume\WPBrowser\Module\WPCLI; @@ -19,13 +27,11 @@ use lucatume\WPBrowser\TestCase\WPRestPostTypeControllerTestCase; use lucatume\WPBrowser\TestCase\WPTestCase; use lucatume\WPBrowser\TestCase\WPXMLRPCTestCase; + use function class_alias; /** * Defines a set of class aliases to allow referencing the framework classes with their previous versions' names. - */ - -/** * Calls to `class_alias` will immediately autoload the class in a eager fashion. * Using an autoloader will load them lazily. */ @@ -40,6 +46,12 @@ 'Codeception\\Module\\WPQueries' => WPQueries::class, 'Codeception\\Module\\WPWebDriver' => WPWebDriver::class, 'Codeception\\Command\\GenerateWPUnit' => GenerateWPUnit::class, + 'Codeception\\Command\\GenerateWPRestApi' => GenerateWPRestApi::class, + 'Codeception\\Command\\GenerateWPRestController' => GenerateWPRestController::class, + 'Codeception\\Command\\GenerateWPRestPostTypeController' => GenerateWPRestPostTypeController::class, + 'Codeception\\Command\\GenerateWPAjax' => GenerateWPAjax::class, + 'Codeception\\Command\\GenerateWPCanonical' => GenerateWPCanonical::class, + 'Codeception\\Command\\GenerateWPXMLRPC' => GenerateWPXMLRPC::class, 'Codeception\\Template\\Wpbrowser' => WpbrowserInitTemplate::class, 'Codeception\\TestCase\\WPTestCase' => WPTestCase::class, 'Codeception\\TestCase\\WPAjaxTestCase' => WPAjaxTestCase::class, @@ -48,6 +60,15 @@ 'Codeception\\TestCase\\WPRestControllerTestCase' => WPRestControllerTestCase::class, 'Codeception\\TestCase\\WPRestPostTypeControllerTestCase' => WPRestPostTypeControllerTestCase::class, 'Codeception\\TestCase\\WPXMLRPCTestCase' => WPXMLRPCTestCase::class, + 'tad\\WPBrowser\\Extension\\Events' => EventDispatcherBridge::class, + 'Codeception\\Extension\\IsolationSupport' => IsolationSupport::class, + 'tad\\WPBrowser\\Module\\WPLoader\\FactoryStore' => WPLoader\FactoryStore::class, + /* WordPress PHPUnit compatibility layer will require these classes removed in PHPUnit 10 */ + 'PHPUnit\\Framework\\Error\\Deprecated' => RemovedInPHPUnitVersion10::class, + 'PHPUnit\\Framework\\Error\\Notice' => RemovedInPHPUnitVersion10::class, + 'PHPUnit\\Framework\\Error\\Warning' => RemovedInPHPUnitVersion10::class, + 'PHPUnit\\Framework\\Warning' => RemovedInPHPUnitVersion10::class, + 'PHPUnit\\Framework\\TestListener' => RemovedInPHPUnitVersion10::class ]; $countDeprecated = count($deprecated); static $hits = 0; diff --git a/tests/_data/plugins/isolated-test-plugin-two/plugin.php b/tests/_data/plugins/isolated-test-plugin-two/plugin.php index 52f5cdf3b..ef007e3f5 100644 --- a/tests/_data/plugins/isolated-test-plugin-two/plugin.php +++ b/tests/_data/plugins/isolated-test-plugin-two/plugin.php @@ -53,10 +53,7 @@ function isolated_test_two_read($id): ?string return $wpdb->get_var($query); } -/** - * @return mixed[]|object|null - */ -function isolated_test_two_read_all() +function isolated_test_two_read_all(): array|object|null { global $wpdb; diff --git a/tests/_data/plugins/isolated-test-plugin/plugin.php b/tests/_data/plugins/isolated-test-plugin/plugin.php index 01eea27d3..5c8dc7410 100644 --- a/tests/_data/plugins/isolated-test-plugin/plugin.php +++ b/tests/_data/plugins/isolated-test-plugin/plugin.php @@ -53,10 +53,7 @@ function isolated_test_read($id): ?string return $wpdb->get_var($query); } -/** - * @return mixed[]|object|null - */ -function isolated_test_read_all() +function isolated_test_read_all(): array|object|null { global $wpdb; diff --git a/tests/_support/FSTemplates/BedrockProject.php b/tests/_support/FSTemplates/BedrockProject.php index 8962bbc32..3f90e83e8 100644 --- a/tests/_support/FSTemplates/BedrockProject.php +++ b/tests/_support/FSTemplates/BedrockProject.php @@ -11,18 +11,8 @@ class BedrockProject { - /** - * @var \lucatume\WPBrowser\WordPress\Database\MysqlDatabase - */ - private $db; - /** - * @var string - */ - private $home; - public function __construct(MysqlDatabase $db, string $home) + public function __construct(private MysqlDatabase $db, private string $home) { - $this->db = $db; - $this->home = $home; } public function scaffold(string $dir, string $version = 'latest'): string @@ -53,9 +43,7 @@ public function scaffold(string $dir, string $version = 'latest'): string ]; $envContents = str_replace( - array_map(function (string $key) { - return '{{' . $key . '}}'; - }, array_keys($replacements)), + array_map(fn(string $key) => '{{' . $key . '}}', array_keys($replacements)), $replacements, $envContents ); diff --git a/tests/_support/StubClassFactory.php b/tests/_support/StubClassFactory.php index 2a5b92aee..255b0c136 100644 --- a/tests/_support/StubClassFactory.php +++ b/tests/_support/StubClassFactory.php @@ -10,10 +10,7 @@ class StubClassFactory { - /** - * @var string - */ - private static $classTemplate = 'class %1$s extends %2$s + private static string $classTemplate = 'class %1$s extends %2$s { public function __construct(%3$s) { @@ -21,14 +18,8 @@ public function __construct(%3$s) %4$s::assertConstructorConditions("%1$s", func_get_args()); } }'; - /** - * @var mixed[] - */ - private static $stubParametersByClassName = []; - /** - * @var mixed[] - */ - private static $constructorAssertions = []; + private static array $stubParametersByClassName = []; + private static array $constructorAssertions = []; public static function tearDown(): void { @@ -38,9 +29,8 @@ public static function tearDown(): void /** * @throws Exception - * @param object $mock */ - public static function connectInvocationMocker($mock): void + public static function connectInvocationMocker(object $mock): void { $mockClassName = get_class($mock); [$class, $parameters] = self::$stubParametersByClassName[$mockClassName]; diff --git a/tests/_support/Traits/LoopIsolation.php b/tests/_support/Traits/LoopIsolation.php index 1b3881cad..a6cb9dde9 100644 --- a/tests/_support/Traits/LoopIsolation.php +++ b/tests/_support/Traits/LoopIsolation.php @@ -19,20 +19,26 @@ trait LoopIsolation * @throws WorkerException * @throws Throwable * @throws ProcessException - * @return mixed */ - protected function assertInIsolation(Closure $runAssertions, string $cwd = null, array $requireFiles = []) - { + protected function assertInIsolation( + Closure $runAssertions, + string $cwd = null, + array $requireFiles = [], + ): mixed { $options = ['cwd' => $cwd, 'rethrow' => false]; + $callerFile = (new ReflectionObject($this))->getFileName(); $options['requireFiles'] = $requireFiles ?: []; if ($callerFile !== false) { $options['requireFiles'][] = $callerFile; } + $options['cwd'] = !empty($options['cwd']) ? $options['cwd'] : getcwd(); + $timeout = Debug::isEnabled() ? PHP_INT_MAX : 30; $result = Loop::executeClosure($runAssertions, $timeout, $options); $returnValue = $result->getReturnValue(); + if ($returnValue instanceof Throwable) { // Update the stack trace to present the loop execution frame on top of the stack. $stackTrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); @@ -42,11 +48,13 @@ protected function assertInIsolation(Closure $runAssertions, string $cwd = null, ); throw $returnValue; } + if ($result->getExitCode() !== 0) { codecept_debug('STDOUT: ' . $result->getStdoutBuffer()); codecept_debug('STDERR: ' . $result->getStderrBuffer()); $this->fail('Loop execution failed with exit code ' . $result->getExitCode()); } + return $returnValue; } } diff --git a/tests/_support/Traits/UopzFunctions.php b/tests/_support/Traits/UopzFunctions.php index d5b9191c0..febd57907 100644 --- a/tests/_support/Traits/UopzFunctions.php +++ b/tests/_support/Traits/UopzFunctions.php @@ -8,26 +8,11 @@ trait UopzFunctions { - /** - * @var mixed[] - */ - protected static $uopzSetFunctionReturns = []; - /** - * @var mixed[] - */ - protected static $uopzSetStaticMethodReturns = []; - /** - * @var mixed[] - */ - protected static $uopzRedefinedConstants = []; - /** - * @var mixed[] - */ - protected static $uopzRedefinedClassConstants = []; - /** - * @var mixed[] - */ - protected static $uopzSetMocks = []; + protected static array $uopzSetFunctionReturns = []; + protected static array $uopzSetStaticMethodReturns = []; + protected static array $uopzRedefinedConstants = []; + protected static array $uopzRedefinedClassConstants = []; + protected static array $uopzSetMocks = []; protected function replacingWithUopz(array $what, callable $do): void { @@ -76,13 +61,10 @@ protected function uopzSetFunctionReturn(string $function, $return, bool $execut self::$uopzSetFunctionReturns[] = $function; } - /** - * @param mixed $return - */ protected function uopzSetStaticMethodReturn( string $class, string $method, - $return, + mixed $return, bool $execute = false ): void { if (!function_exists('uopz_set_return')) { @@ -93,10 +75,7 @@ protected function uopzSetStaticMethodReturn( self::$uopzSetStaticMethodReturns[] = $class . '::' . $method; } - /** - * @param string|int|bool|null $value - */ - protected function uopzRedefineConstant(string $constant, $value): void + protected function uopzRedefineConstant(string $constant, string|int|bool|null $value): void { if (!function_exists('uopz_set_return')) { $this->markTestSkipped('This test requires the uopz extension'); @@ -108,10 +87,7 @@ protected function uopzRedefineConstant(string $constant, $value): void self::$uopzRedefinedConstants[$constant] = [$wasDefined, $previousValue]; } - /** - * @param string|int|bool|null $value - */ - protected function uopzRedefinedClassConstant(string $class, string $constant, $value): void + protected function uopzRedefinedClassConstant(string $class, string $constant, string|int|bool|null $value): void { if (!function_exists('uopz_set_return')) { $this->markTestSkipped('This test requires the uopz extension'); @@ -179,10 +155,7 @@ protected function uopzUndefineConstant(string $constant): void uopz_undefine($constant); } - /** - * @param string|object $mock - */ - protected function uopzSetMock(string $class, $mock): void + protected function uopzSetMock(string $class, string|object $mock): void { if (!function_exists('uopz_set_return')) { $this->markTestSkipped('This test requires the uopz extension'); diff --git a/tests/_support/_generated/AcceptanceTesterActions.php b/tests/_support/_generated/AcceptanceTesterActions.php index 49eda7a32..94c78f425 100644 --- a/tests/_support/_generated/AcceptanceTesterActions.php +++ b/tests/_support/_generated/AcceptanceTesterActions.php @@ -1,4 +1,4 @@ - $pluginSlug The plugin slug, like "hello-dolly" or a list of plugin slugs. * @see \lucatume\WPBrowser\Module\WPBrowser::activatePlugin() */ - public function activatePlugin($pluginSlug): void { + public function activatePlugin(array|string $pluginSlug): void { $this->getScenario()->runStep(new \Codeception\Step\Action('activatePlugin', func_get_args())); } @@ -83,7 +83,7 @@ public function activatePlugin($pluginSlug): void { * @param string|array $pluginSlug The plugin slug, like "hello-dolly", or a list of plugin slugs. * @see \lucatume\WPBrowser\Module\WPBrowser::deactivatePlugin() */ - public function deactivatePlugin($pluginSlug): void { + public function deactivatePlugin(array|string $pluginSlug): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deactivatePlugin', func_get_args())); } @@ -787,9 +787,8 @@ public function cantSeeCurrentUrlMatches(string $uri): void { * $uri = $I->grabFromCurrentUrl(); * ``` * @see \Codeception\Lib\InnerBrowser::grabFromCurrentUrl() - * @return mixed */ - public function grabFromCurrentUrl(?string $uri = NULL) { + public function grabFromCurrentUrl(?string $uri = NULL): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); } @@ -1375,15 +1374,15 @@ public function fillField($field, $value): void { * * ``` php * selectOption('Which OS do you use?', array('Windows','Linux')); + * $I->selectOption('Which OS do you use?', ['Windows', 'Linux']); * ``` * * Or provide an associative array for the second argument to specifically define which selection method should be used: * * ``` php * selectOption('Which OS do you use?', array('text' => 'Windows')); // Only search by text 'Windows' - * $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only search by value 'windows' + * $I->selectOption('Which OS do you use?', ['text' => 'Windows']); // Only search by text 'Windows' + * $I->selectOption('Which OS do you use?', ['value' => 'windows']); // Only search by value 'windows' * ``` * @see \Codeception\Lib\InnerBrowser::selectOption() */ @@ -1531,9 +1530,8 @@ public function makeHtmlSnapshot(?string $name = NULL): void { * $value = $I->grabTextFrom('~getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); } @@ -1549,9 +1547,8 @@ public function grabTextFrom($cssOrXPathOrRegex) { * $I->grabAttributeFrom('#tooltip', 'title'); * ``` * @see \Codeception\Lib\InnerBrowser::grabAttributeFrom() - * @return mixed */ - public function grabAttributeFrom($cssOrXpath, string $attribute) { + public function grabAttributeFrom($cssOrXpath, string $attribute): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args())); } @@ -1599,9 +1596,8 @@ public function grabMultiple($cssOrXpath, ?string $attribute = NULL): array { * $name = $I->grabValueFrom(['name' => 'username']); * ``` * @see \Codeception\Lib\InnerBrowser::grabValueFrom() - * @return mixed */ - public function grabValueFrom($field) { + public function grabValueFrom($field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args())); } @@ -1632,9 +1628,8 @@ public function setCookie($name, $val, $params = []) { * You can set additional cookie params like `domain`, `path` in array passed as last argument. * If the cookie is set by an ajax request (XMLHttpRequest), there might be some delay caused by the browser, so try `$I->wait(0.1)`. * @see \Codeception\Lib\InnerBrowser::grabCookie() - * @return mixed */ - public function grabCookie(string $cookie, array $params = []) { + public function grabCookie(string $cookie, array $params = []): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); } @@ -2334,7 +2329,7 @@ public function setMaxRedirects(int $maxRedirects): void { * @throws ModuleException IF the current URI cannot be retrieved from the inner browser. * @see \lucatume\WPBrowser\Module\WPBrowser::logOut() */ - public function logOut($redirectTo = false): void { + public function logOut(string|bool $redirectTo = false): void { $this->getScenario()->runStep(new \Codeception\Step\Action('logOut', func_get_args())); } @@ -2636,7 +2631,7 @@ public function cantSeePluginInstalled(string $pluginSlug): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeErrorMessage() */ - public function seeErrorMessage($classes = ""): void { + public function seeErrorMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeErrorMessage', func_get_args())); } /** @@ -2661,7 +2656,7 @@ public function seeErrorMessage($classes = ""): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeErrorMessage() */ - public function canSeeErrorMessage($classes = ""): void { + public function canSeeErrorMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeErrorMessage', func_get_args())); } @@ -2727,7 +2722,7 @@ public function canSeeWpDiePage(): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeMessage() */ - public function seeMessage($classes = ""): void { + public function seeMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeMessage', func_get_args())); } /** @@ -2751,7 +2746,7 @@ public function seeMessage($classes = ""): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeMessage() */ - public function canSeeMessage($classes = ""): void { + public function canSeeMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeMessage', func_get_args())); } @@ -2817,7 +2812,7 @@ public function amOnAdminPage(string $page): void { * @param string|array $queryVars A string or array of query variables to append to the AJAX path. * @see \lucatume\WPBrowser\Module\WPBrowser::amOnAdminAjaxPage() */ - public function amOnAdminAjaxPage($queryVars = NULL): void { + public function amOnAdminAjaxPage(array|string|null $queryVars = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnAdminAjaxPage', func_get_args())); } @@ -2836,7 +2831,7 @@ public function amOnAdminAjaxPage($queryVars = NULL): void { * @param string|array $queryVars A string or array of query variables to append to the Cron path. * @see \lucatume\WPBrowser\Module\WPBrowser::amOnCronPage() */ - public function amOnCronPage($queryVars = NULL): void { + public function amOnCronPage(array|string|null $queryVars = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnCronPage', func_get_args())); } @@ -3040,7 +3035,7 @@ public function canSeeThemeActivated(string $slug): void { * @return int The inserted row ID. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteMetaInDatabase() */ - public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int { + public function haveSiteMetaInDatabase(int $blogId, string $string, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteMetaInDatabase', func_get_args())); } @@ -3066,7 +3061,7 @@ public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int * @throws Exception On unserialize failure. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteMetaFromDatabase() */ - public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) { + public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteMetaFromDatabase', func_get_args())); } @@ -3088,7 +3083,7 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field) { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -3134,14 +3129,14 @@ public function importSqlDumpFile(?string $dumpFile = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionInDatabase', func_get_args())); } /** @@ -3162,14 +3157,14 @@ public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function cantSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionInDatabase', func_get_args())); } @@ -3673,7 +3668,7 @@ public function grabLatestEntryByFromDatabase(string $tableName, string $idColum * @return int The inserted meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::havePostmetaInDatabase() */ - public function havePostmetaInDatabase(int $postId, string $meta_key, $meta_value): int { + public function havePostmetaInDatabase(int $postId, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('havePostmetaInDatabase', func_get_args())); } @@ -3721,7 +3716,7 @@ public function grabPostmetaTableName(): string { * @return int|false The matching term `term_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermIdFromDatabase() */ - public function grabTermIdFromDatabase(array $criteria) { + public function grabTermIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermIdFromDatabase', func_get_args())); } @@ -3825,7 +3820,7 @@ public function grabTermTaxonomyTableName(): string { * @return int The inserted term meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTermMetaInDatabase() */ - public function haveTermMetaInDatabase(int $term_id, string $meta_key, $meta_value): int { + public function haveTermMetaInDatabase(int $term_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTermMetaInDatabase', func_get_args())); } @@ -3872,7 +3867,7 @@ public function grabTermMetaTableName(): string { * @return int|false The matching term `term_taxonomy_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermTaxonomyIdFromDatabase() */ - public function grabTermTaxonomyIdFromDatabase(array $criteria) { + public function grabTermTaxonomyIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermTaxonomyIdFromDatabase', func_get_args())); } @@ -4491,7 +4486,7 @@ public function dontHaveUserMetaInDatabase(array $criteria): void { * @throws Exception If the search criteria is incoherent. * @see \lucatume\WPBrowser\Module\WPDb::grabUserMetaFromDatabase() */ - public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false) { + public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserMetaFromDatabase', func_get_args())); } @@ -4542,7 +4537,7 @@ public function grabAllFromDatabase(string $table, string $column, array $criter * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTransientInDatabase() */ - public function haveTransientInDatabase(string $transient, $value): int { + public function haveTransientInDatabase(string $transient, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTransientInDatabase', func_get_args())); } @@ -4567,7 +4562,7 @@ public function haveTransientInDatabase(string $transient, $value): int { * @return int The inserted option `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveOptionInDatabase() */ - public function haveOptionInDatabase(string $option_name, $option_value, string $autoload = "yes"): int { + public function haveOptionInDatabase(string $option_name, mixed $option_value, string $autoload = "yes"): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveOptionInDatabase', func_get_args())); } @@ -4605,10 +4600,10 @@ public function dontHaveTransientInDatabase(string $transient): void { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed if its value matches the passed one. + * @param mixed|null $value If set the option will only be removed if its value matches the passed one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveOptionInDatabase() */ - public function dontHaveOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveOptionInDatabase', func_get_args())); } @@ -4631,7 +4626,7 @@ public function dontHaveOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteOptionInDatabase() */ - public function haveSiteOptionInDatabase(string $key, $value): int { + public function haveSiteOptionInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteOptionInDatabase', func_get_args())); } @@ -4718,10 +4713,10 @@ public function grabBlogUrl(int $blogId = 1): string { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed it its value matches the specified one. + * @param mixed|null $value If set the option will only be removed it its value matches the specified one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveSiteOptionInDatabase() */ - public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveSiteOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveSiteOptionInDatabase', func_get_args())); } @@ -4745,7 +4740,7 @@ public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted transient `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveSiteTransientInDatabase() */ - public function haveSiteTransientInDatabase(string $key, $value): int { + public function haveSiteTransientInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteTransientInDatabase', func_get_args())); } @@ -4783,7 +4778,7 @@ public function dontHaveSiteTransientInDatabase(string $key): void { * @return mixed The value of the option stored in the database, unserialized if serialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteOptionFromDatabase() */ - public function grabSiteOptionFromDatabase(string $key) { + public function grabSiteOptionFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteOptionFromDatabase', func_get_args())); } @@ -4803,7 +4798,7 @@ public function grabSiteOptionFromDatabase(string $key) { * @return mixed The option value. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabOptionFromDatabase() */ - public function grabOptionFromDatabase(string $option_name) { + public function grabOptionFromDatabase(string $option_name): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabOptionFromDatabase', func_get_args())); } @@ -4824,7 +4819,7 @@ public function grabOptionFromDatabase(string $option_name) { * @return mixed The value of the site transient. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteTransientFromDatabase() */ - public function grabSiteTransientFromDatabase(string $key) { + public function grabSiteTransientFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteTransientFromDatabase', func_get_args())); } @@ -4843,12 +4838,12 @@ public function grabSiteTransientFromDatabase(string $key) { * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function seeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteSiteTransientInDatabase', func_get_args())); } /** @@ -4866,12 +4861,12 @@ public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function canSeeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteSiteTransientInDatabase', func_get_args())); } @@ -4893,14 +4888,14 @@ public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): v * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionInDatabase', func_get_args())); } /** @@ -4921,14 +4916,14 @@ public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionInDatabase', func_get_args())); } @@ -4947,14 +4942,14 @@ public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteOptionInDatabase', func_get_args())); } /** @@ -4972,14 +4967,14 @@ public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function canSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteOptionInDatabase', func_get_args())); } @@ -5225,7 +5220,7 @@ public function haveCommentInDatabase(int $comment_post_ID, array $data = []): i * @return int The inserted comment meta ID. * @see \lucatume\WPBrowser\Module\WPDb::haveCommentMetaInDatabase() */ - public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, $meta_value): int { + public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveCommentMetaInDatabase', func_get_args())); } @@ -5490,7 +5485,7 @@ public function haveManyUsersInDatabase(int $count, string $user_login, string $ * @see WPDb::haveUserCapabilitiesInDatabase() for the roles and caps options. * @see \lucatume\WPBrowser\Module\WPDb::haveUserInDatabase() */ - public function haveUserInDatabase(string $user_login, $role = "subscriber", array $overrides = []): int { + public function haveUserInDatabase(string $user_login, array|string $role = "subscriber", array $overrides = []): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserInDatabase', func_get_args())); } @@ -5581,7 +5576,7 @@ public function grabUsersTableName(): string { * @return array|int> An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserCapabilitiesInDatabase() */ - public function haveUserCapabilitiesInDatabase(int $userId, $role): array { + public function haveUserCapabilitiesInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserCapabilitiesInDatabase', func_get_args())); } @@ -5605,7 +5600,7 @@ public function haveUserCapabilitiesInDatabase(int $userId, $role): array { * @return array An array of inserted `umeta_id`s. * @see \lucatume\WPBrowser\Module\WPDb::haveUserMetaInDatabase() */ - public function haveUserMetaInDatabase(int $userId, string $meta_key, $meta_value): array { + public function haveUserMetaInDatabase(int $userId, string $meta_key, mixed $meta_value): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserMetaInDatabase', func_get_args())); } @@ -5660,7 +5655,7 @@ public function grabUsermetaTableName(): string { * @return array An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserLevelsInDatabase() */ - public function haveUserLevelsInDatabase(int $userId, $role): array { + public function haveUserLevelsInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserLevelsInDatabase', func_get_args())); } @@ -6420,7 +6415,7 @@ public function canSeeTermRelationshipInDatabase(array $criteria): void { * readable. * @see \lucatume\WPBrowser\Module\WPDb::haveAttachmentInDatabase() */ - public function haveAttachmentInDatabase(string $file, $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { + public function haveAttachmentInDatabase(string $file, string|int $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveAttachmentInDatabase', func_get_args())); } @@ -6582,7 +6577,7 @@ public function dontHaveAttachmentInDatabase(array $criteria, bool $purgeMeta = * @throws ModuleRequireException If the `WPFilesystem` module is not loaded in the suite. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveAttachmentFilesInDatabase() */ - public function dontHaveAttachmentFilesInDatabase($attachmentIds): void { + public function dontHaveAttachmentFilesInDatabase(array|int $attachmentIds): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveAttachmentFilesInDatabase', func_get_args())); } @@ -6737,7 +6732,7 @@ public function grabTablePrefix(): string { * @param bool $purgeMeta Whether the user meta should be purged alongside the user or not. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveUserInDatabase() */ - public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): void { + public function dontHaveUserInDatabase(string|int $userIdOrLogin, bool $purgeMeta = true): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveUserInDatabase', func_get_args())); } @@ -6757,7 +6752,7 @@ public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): * @return int|false The user ID or `false` if the user was not found. * @see \lucatume\WPBrowser\Module\WPDb::grabUserIdFromDatabase() */ - public function grabUserIdFromDatabase(string $userLogin) { + public function grabUserIdFromDatabase(string $userLogin): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserIdFromDatabase', func_get_args())); } @@ -6779,7 +6774,7 @@ public function grabUserIdFromDatabase(string $userLogin) { * @return mixed|array Either a single meta value or an array of all the available meta values. * @see \lucatume\WPBrowser\Module\WPDb::grabPostMetaFromDatabase() */ - public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false) { + public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostMetaFromDatabase', func_get_args())); } @@ -7075,14 +7070,14 @@ public function importSql(array $sql): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteOptionInDatabase', func_get_args())); } /** @@ -7101,14 +7096,14 @@ public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteOptionInDatabase', func_get_args())); } @@ -7130,7 +7125,7 @@ public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * * @see \lucatume\WPBrowser\Module\WPDb::grabTransientFromDatabase() */ - public function grabTransientFromDatabase(string $transient) { + public function grabTransientFromDatabase(string $transient): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTransientFromDatabase', func_get_args())); } @@ -7153,7 +7148,7 @@ public function grabTransientFromDatabase(string $transient) { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function dontSeeTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeTransientInDatabase', func_get_args())); } /** @@ -7175,7 +7170,7 @@ public function dontSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function cantSeeTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeTransientInDatabase', func_get_args())); } @@ -7199,7 +7194,7 @@ public function cantSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function seeTransientInDatabase(string $name, $value = NULL): void { + public function seeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeTransientInDatabase', func_get_args())); } /** @@ -7222,7 +7217,7 @@ public function seeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function canSeeTransientInDatabase(string $name, $value = NULL): void { + public function canSeeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeTransientInDatabase', func_get_args())); } @@ -7237,7 +7232,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7246,7 +7241,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteTransientInDatabase', func_get_args())); } /** @@ -7260,7 +7255,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7269,7 +7264,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteTransientInDatabase', func_get_args())); } @@ -7285,7 +7280,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7293,7 +7288,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function seeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function seeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteTransientInDatabase', func_get_args())); } /** @@ -7308,7 +7303,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7316,7 +7311,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function canSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function canSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteTransientInDatabase', func_get_args())); } @@ -7700,13 +7695,13 @@ public function updateInDatabase(string $table, array $data, array $criteria = [ * $I->seeFileFound('shop.log'); * ``` * - * @param string|null $path The path, relative to the site uploads folder. + * @param string|int|null $path The path, relative to the site uploads folder. * * * @throws Exception If the path is a date string and is not parsable by the `strtotime` function. * @see \lucatume\WPBrowser\Module\WPFilesystem::amInUploadsPath() */ - public function amInUploadsPath(?string $path = NULL): void { + public function amInUploadsPath(string|int|null $path = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amInUploadsPath', func_get_args())); } @@ -7732,7 +7727,7 @@ public function amInUploadsPath(?string $path = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeUploadedFileFound() */ - public function seeUploadedFileFound(string $filename, $date = NULL): void { + public function seeUploadedFileFound(string $filename, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeUploadedFileFound', func_get_args())); } /** @@ -7757,7 +7752,7 @@ public function seeUploadedFileFound(string $filename, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeUploadedFileFound() */ - public function canSeeUploadedFileFound(string $filename, $date = NULL): void { + public function canSeeUploadedFileFound(string $filename, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeUploadedFileFound', func_get_args())); } @@ -7776,7 +7771,7 @@ public function canSeeUploadedFileFound(string $filename, $date = NULL): void { * ``` * * @param string $file The file path, relative to the uploads folder. - * @param mixed $date A string compatible with `strtotime`, a Unix timestamp or a Date + * @param DateTimeInterface|string|int|null $date A string compatible with `strtotime`, a Unix timestamp or a Date * object. * * @return string The absolute path to an uploaded file. @@ -7784,7 +7779,7 @@ public function canSeeUploadedFileFound(string $filename, $date = NULL): void { * @throws Exception * @see \lucatume\WPBrowser\Module\WPFilesystem::getUploadsPath() */ - public function getUploadsPath(string $file = "", $date = NULL): string { + public function getUploadsPath(string $file = "", mixed $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('getUploadsPath', func_get_args())); } @@ -7809,7 +7804,7 @@ public function getUploadsPath(string $file = "", $date = NULL): string { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeUploadedFileFound() */ - public function dontSeeUploadedFileFound(string $file, $date = NULL): void { + public function dontSeeUploadedFileFound(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeUploadedFileFound', func_get_args())); } /** @@ -7833,7 +7828,7 @@ public function dontSeeUploadedFileFound(string $file, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeUploadedFileFound() */ - public function cantSeeUploadedFileFound(string $file, $date = NULL): void { + public function cantSeeUploadedFileFound(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeUploadedFileFound', func_get_args())); } @@ -7859,7 +7854,7 @@ public function cantSeeUploadedFileFound(string $file, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeInUploadedFile() */ - public function seeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function seeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInUploadedFile', func_get_args())); } /** @@ -7884,7 +7879,7 @@ public function seeInUploadedFile(string $file, string $contents, $date = NULL): * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeInUploadedFile() */ - public function canSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function canSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInUploadedFile', func_get_args())); } @@ -7908,7 +7903,7 @@ public function canSeeInUploadedFile(string $file, string $contents, $date = NUL * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeInUploadedFile() */ - public function dontSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function dontSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInUploadedFile', func_get_args())); } /** @@ -7931,7 +7926,7 @@ public function dontSeeInUploadedFile(string $file, string $contents, $date = NU * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeInUploadedFile() */ - public function cantSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function cantSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInUploadedFile', func_get_args())); } @@ -7957,7 +7952,7 @@ public function cantSeeInUploadedFile(string $file, string $contents, $date = NU * @throws ModuleException If the destination folder could not be removed. * @see \lucatume\WPBrowser\Module\WPFilesystem::deleteUploadedDir() */ - public function deleteUploadedDir(string $dir, $date = NULL): void { + public function deleteUploadedDir(string $dir, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deleteUploadedDir', func_get_args())); } @@ -7980,7 +7975,7 @@ public function deleteUploadedDir(string $dir, $date = NULL): void { * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::deleteUploadedFile() */ - public function deleteUploadedFile(string $file, $date = NULL): void { + public function deleteUploadedFile(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deleteUploadedFile', func_get_args())); } @@ -8004,7 +7999,7 @@ public function deleteUploadedFile(string $file, $date = NULL): void { * @param string|null $dir The path to the directory to delete, relative to the uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::cleanUploadsDir() */ - public function cleanUploadsDir(?string $dir = NULL, $date = NULL): void { + public function cleanUploadsDir(?string $dir = NULL, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('cleanUploadsDir', func_get_args())); } @@ -8029,7 +8024,7 @@ public function cleanUploadsDir(?string $dir = NULL, $date = NULL): void { * @param string $src The path to the source file, relative to the current uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::copyDirToUploads() */ - public function copyDirToUploads(string $src, string $dst, $date = NULL): void { + public function copyDirToUploads(string $src, string $dst, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('copyDirToUploads', func_get_args())); } @@ -8059,7 +8054,7 @@ public function copyDirToUploads(string $src, string $dst, $date = NULL): void { * file could not be written. * @see \lucatume\WPBrowser\Module\WPFilesystem::writeToUploadedFile() */ - public function writeToUploadedFile(string $filename, string $data, $date = NULL): string { + public function writeToUploadedFile(string $filename, string $data, \DateTime|string|int|null $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('writeToUploadedFile', func_get_args())); } @@ -8083,7 +8078,7 @@ public function writeToUploadedFile(string $filename, string $data, $date = NULL * @param string $filename The path to the file, relative to the current uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::openUploadedFile() */ - public function openUploadedFile(string $filename, $date = NULL): void { + public function openUploadedFile(string $filename, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('openUploadedFile', func_get_args())); } @@ -8932,7 +8927,7 @@ public function getWpRootFolder(): string { * @throws Exception If the date is not a valid format. * @see \lucatume\WPBrowser\Module\WPFilesystem::getBlogUploadsPath() */ - public function getBlogUploadsPath(int $blogId, string $file = "", $date = NULL): string { + public function getBlogUploadsPath(int $blogId, string $file = "", \DateTimeImmutable|\DateTime|string|null $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('getBlogUploadsPath', func_get_args())); } @@ -10626,9 +10621,8 @@ public function assertNull($actual, string $message = "") { * * Asserts that an object has a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() - * @param object $object */ - public function assertObjectHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); } @@ -10638,9 +10632,8 @@ public function assertObjectHasAttribute(string $attributeName, $object, string * * Asserts that an object does not have a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() - * @param object $object */ - public function assertObjectNotHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectNotHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); } diff --git a/tests/_support/_generated/ClimoduleTesterActions.php b/tests/_support/_generated/ClimoduleTesterActions.php index 5e587e298..ae7bc44d1 100644 --- a/tests/_support/_generated/ClimoduleTesterActions.php +++ b/tests/_support/_generated/ClimoduleTesterActions.php @@ -39,7 +39,7 @@ public function setCliEnv($key, $value) { * * @param string|array $command The command to execute. * @param array|null $env An array of environment variables to pass to the command. - * @param mixed $input The input to pass to the command, a stream resource or a \Traversable + * @param mixed|null $input The input to pass to the command, a stream resource or a \Traversable * instance. * * @return int The command exit value; `0` usually means success. @@ -47,7 +47,7 @@ public function setCliEnv($key, $value) { * @throws ModuleException If the command execution fails and the `throw` configuration option is set to `true`. * @see \lucatume\WPBrowser\Module\WPCLI::cli() */ - public function cli($command = ["core", "version"], ?array $env = NULL, $input = NULL): int { + public function cli(array|string $command = ["core", "version"], ?array $env = NULL, mixed $input = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('cli', func_get_args())); } @@ -124,7 +124,7 @@ public function grabLastShellErrorOutput(): string { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPCLI::cliToArray() */ - public function cliToArray(array $command, ?callable $splitCallback = NULL, ?array $env = NULL, $input = NULL): array { + public function cliToArray(array $command, ?callable $splitCallback = NULL, ?array $env = NULL, mixed $input = NULL): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('cliToArray', func_get_args())); } @@ -157,7 +157,7 @@ public function cliToArray(array $command, ?callable $splitCallback = NULL, ?arr * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPCLI::cliToString() */ - public function cliToString(array $command, ?array $env = NULL, $input = NULL): string { + public function cliToString(array $command, ?array $env = NULL, mixed $input = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('cliToString', func_get_args())); } @@ -465,7 +465,7 @@ public function changeWpcliPath(string $path): void { * @return int The inserted row ID. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteMetaInDatabase() */ - public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int { + public function haveSiteMetaInDatabase(int $blogId, string $string, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteMetaInDatabase', func_get_args())); } @@ -491,7 +491,7 @@ public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int * @throws Exception On unserialize failure. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteMetaFromDatabase() */ - public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) { + public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteMetaFromDatabase', func_get_args())); } @@ -513,7 +513,7 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field) { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -559,14 +559,14 @@ public function importSqlDumpFile(?string $dumpFile = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionInDatabase', func_get_args())); } /** @@ -587,14 +587,14 @@ public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function cantSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionInDatabase', func_get_args())); } @@ -1098,7 +1098,7 @@ public function grabLatestEntryByFromDatabase(string $tableName, string $idColum * @return int The inserted meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::havePostmetaInDatabase() */ - public function havePostmetaInDatabase(int $postId, string $meta_key, $meta_value): int { + public function havePostmetaInDatabase(int $postId, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('havePostmetaInDatabase', func_get_args())); } @@ -1146,7 +1146,7 @@ public function grabPostmetaTableName(): string { * @return int|false The matching term `term_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermIdFromDatabase() */ - public function grabTermIdFromDatabase(array $criteria) { + public function grabTermIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermIdFromDatabase', func_get_args())); } @@ -1250,7 +1250,7 @@ public function grabTermTaxonomyTableName(): string { * @return int The inserted term meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTermMetaInDatabase() */ - public function haveTermMetaInDatabase(int $term_id, string $meta_key, $meta_value): int { + public function haveTermMetaInDatabase(int $term_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTermMetaInDatabase', func_get_args())); } @@ -1297,7 +1297,7 @@ public function grabTermMetaTableName(): string { * @return int|false The matching term `term_taxonomy_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermTaxonomyIdFromDatabase() */ - public function grabTermTaxonomyIdFromDatabase(array $criteria) { + public function grabTermTaxonomyIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermTaxonomyIdFromDatabase', func_get_args())); } @@ -1916,7 +1916,7 @@ public function dontHaveUserMetaInDatabase(array $criteria): void { * @throws Exception If the search criteria is incoherent. * @see \lucatume\WPBrowser\Module\WPDb::grabUserMetaFromDatabase() */ - public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false) { + public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserMetaFromDatabase', func_get_args())); } @@ -1967,7 +1967,7 @@ public function grabAllFromDatabase(string $table, string $column, array $criter * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTransientInDatabase() */ - public function haveTransientInDatabase(string $transient, $value): int { + public function haveTransientInDatabase(string $transient, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTransientInDatabase', func_get_args())); } @@ -1992,7 +1992,7 @@ public function haveTransientInDatabase(string $transient, $value): int { * @return int The inserted option `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveOptionInDatabase() */ - public function haveOptionInDatabase(string $option_name, $option_value, string $autoload = "yes"): int { + public function haveOptionInDatabase(string $option_name, mixed $option_value, string $autoload = "yes"): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveOptionInDatabase', func_get_args())); } @@ -2030,10 +2030,10 @@ public function dontHaveTransientInDatabase(string $transient): void { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed if its value matches the passed one. + * @param mixed|null $value If set the option will only be removed if its value matches the passed one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveOptionInDatabase() */ - public function dontHaveOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveOptionInDatabase', func_get_args())); } @@ -2056,7 +2056,7 @@ public function dontHaveOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteOptionInDatabase() */ - public function haveSiteOptionInDatabase(string $key, $value): int { + public function haveSiteOptionInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteOptionInDatabase', func_get_args())); } @@ -2143,10 +2143,10 @@ public function grabBlogUrl(int $blogId = 1): string { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed it its value matches the specified one. + * @param mixed|null $value If set the option will only be removed it its value matches the specified one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveSiteOptionInDatabase() */ - public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveSiteOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveSiteOptionInDatabase', func_get_args())); } @@ -2170,7 +2170,7 @@ public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted transient `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveSiteTransientInDatabase() */ - public function haveSiteTransientInDatabase(string $key, $value): int { + public function haveSiteTransientInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteTransientInDatabase', func_get_args())); } @@ -2208,7 +2208,7 @@ public function dontHaveSiteTransientInDatabase(string $key): void { * @return mixed The value of the option stored in the database, unserialized if serialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteOptionFromDatabase() */ - public function grabSiteOptionFromDatabase(string $key) { + public function grabSiteOptionFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteOptionFromDatabase', func_get_args())); } @@ -2228,7 +2228,7 @@ public function grabSiteOptionFromDatabase(string $key) { * @return mixed The option value. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabOptionFromDatabase() */ - public function grabOptionFromDatabase(string $option_name) { + public function grabOptionFromDatabase(string $option_name): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabOptionFromDatabase', func_get_args())); } @@ -2249,7 +2249,7 @@ public function grabOptionFromDatabase(string $option_name) { * @return mixed The value of the site transient. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteTransientFromDatabase() */ - public function grabSiteTransientFromDatabase(string $key) { + public function grabSiteTransientFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteTransientFromDatabase', func_get_args())); } @@ -2268,12 +2268,12 @@ public function grabSiteTransientFromDatabase(string $key) { * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function seeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteSiteTransientInDatabase', func_get_args())); } /** @@ -2291,12 +2291,12 @@ public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function canSeeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteSiteTransientInDatabase', func_get_args())); } @@ -2318,14 +2318,14 @@ public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): v * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionInDatabase', func_get_args())); } /** @@ -2346,14 +2346,14 @@ public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionInDatabase', func_get_args())); } @@ -2372,14 +2372,14 @@ public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteOptionInDatabase', func_get_args())); } /** @@ -2397,14 +2397,14 @@ public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function canSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteOptionInDatabase', func_get_args())); } @@ -2650,7 +2650,7 @@ public function haveCommentInDatabase(int $comment_post_ID, array $data = []): i * @return int The inserted comment meta ID. * @see \lucatume\WPBrowser\Module\WPDb::haveCommentMetaInDatabase() */ - public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, $meta_value): int { + public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveCommentMetaInDatabase', func_get_args())); } @@ -2915,7 +2915,7 @@ public function haveManyUsersInDatabase(int $count, string $user_login, string $ * @see WPDb::haveUserCapabilitiesInDatabase() for the roles and caps options. * @see \lucatume\WPBrowser\Module\WPDb::haveUserInDatabase() */ - public function haveUserInDatabase(string $user_login, $role = "subscriber", array $overrides = []): int { + public function haveUserInDatabase(string $user_login, array|string $role = "subscriber", array $overrides = []): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserInDatabase', func_get_args())); } @@ -3006,7 +3006,7 @@ public function grabUsersTableName(): string { * @return array|int> An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserCapabilitiesInDatabase() */ - public function haveUserCapabilitiesInDatabase(int $userId, $role): array { + public function haveUserCapabilitiesInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserCapabilitiesInDatabase', func_get_args())); } @@ -3030,7 +3030,7 @@ public function haveUserCapabilitiesInDatabase(int $userId, $role): array { * @return array An array of inserted `umeta_id`s. * @see \lucatume\WPBrowser\Module\WPDb::haveUserMetaInDatabase() */ - public function haveUserMetaInDatabase(int $userId, string $meta_key, $meta_value): array { + public function haveUserMetaInDatabase(int $userId, string $meta_key, mixed $meta_value): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserMetaInDatabase', func_get_args())); } @@ -3085,7 +3085,7 @@ public function grabUsermetaTableName(): string { * @return array An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserLevelsInDatabase() */ - public function haveUserLevelsInDatabase(int $userId, $role): array { + public function haveUserLevelsInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserLevelsInDatabase', func_get_args())); } @@ -3845,7 +3845,7 @@ public function canSeeTermRelationshipInDatabase(array $criteria): void { * readable. * @see \lucatume\WPBrowser\Module\WPDb::haveAttachmentInDatabase() */ - public function haveAttachmentInDatabase(string $file, $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { + public function haveAttachmentInDatabase(string $file, string|int $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveAttachmentInDatabase', func_get_args())); } @@ -4007,7 +4007,7 @@ public function dontHaveAttachmentInDatabase(array $criteria, bool $purgeMeta = * @throws ModuleRequireException If the `WPFilesystem` module is not loaded in the suite. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveAttachmentFilesInDatabase() */ - public function dontHaveAttachmentFilesInDatabase($attachmentIds): void { + public function dontHaveAttachmentFilesInDatabase(array|int $attachmentIds): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveAttachmentFilesInDatabase', func_get_args())); } @@ -4162,7 +4162,7 @@ public function grabTablePrefix(): string { * @param bool $purgeMeta Whether the user meta should be purged alongside the user or not. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveUserInDatabase() */ - public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): void { + public function dontHaveUserInDatabase(string|int $userIdOrLogin, bool $purgeMeta = true): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveUserInDatabase', func_get_args())); } @@ -4182,7 +4182,7 @@ public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): * @return int|false The user ID or `false` if the user was not found. * @see \lucatume\WPBrowser\Module\WPDb::grabUserIdFromDatabase() */ - public function grabUserIdFromDatabase(string $userLogin) { + public function grabUserIdFromDatabase(string $userLogin): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserIdFromDatabase', func_get_args())); } @@ -4204,7 +4204,7 @@ public function grabUserIdFromDatabase(string $userLogin) { * @return mixed|array Either a single meta value or an array of all the available meta values. * @see \lucatume\WPBrowser\Module\WPDb::grabPostMetaFromDatabase() */ - public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false) { + public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostMetaFromDatabase', func_get_args())); } @@ -4500,14 +4500,14 @@ public function importSql(array $sql): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteOptionInDatabase', func_get_args())); } /** @@ -4526,14 +4526,14 @@ public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteOptionInDatabase', func_get_args())); } @@ -4555,7 +4555,7 @@ public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * * @see \lucatume\WPBrowser\Module\WPDb::grabTransientFromDatabase() */ - public function grabTransientFromDatabase(string $transient) { + public function grabTransientFromDatabase(string $transient): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTransientFromDatabase', func_get_args())); } @@ -4578,7 +4578,7 @@ public function grabTransientFromDatabase(string $transient) { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function dontSeeTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeTransientInDatabase', func_get_args())); } /** @@ -4600,7 +4600,7 @@ public function dontSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function cantSeeTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeTransientInDatabase', func_get_args())); } @@ -4624,7 +4624,7 @@ public function cantSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function seeTransientInDatabase(string $name, $value = NULL): void { + public function seeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeTransientInDatabase', func_get_args())); } /** @@ -4647,7 +4647,7 @@ public function seeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function canSeeTransientInDatabase(string $name, $value = NULL): void { + public function canSeeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeTransientInDatabase', func_get_args())); } @@ -4662,7 +4662,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4671,7 +4671,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteTransientInDatabase', func_get_args())); } /** @@ -4685,7 +4685,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4694,7 +4694,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteTransientInDatabase', func_get_args())); } @@ -4710,7 +4710,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4718,7 +4718,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function seeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function seeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteTransientInDatabase', func_get_args())); } /** @@ -4733,7 +4733,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4741,7 +4741,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function canSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function canSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteTransientInDatabase', func_get_args())); } @@ -5157,7 +5157,7 @@ public function grabCookiesWithPattern(string $cookiePattern): ?array { * @param string|array $pluginSlug The plugin slug, like "hello-dolly" or a list of plugin slugs. * @see \lucatume\WPBrowser\Module\WPBrowser::activatePlugin() */ - public function activatePlugin($pluginSlug): void { + public function activatePlugin(array|string $pluginSlug): void { $this->getScenario()->runStep(new \Codeception\Step\Action('activatePlugin', func_get_args())); } @@ -5184,7 +5184,7 @@ public function activatePlugin($pluginSlug): void { * @param string|array $pluginSlug The plugin slug, like "hello-dolly", or a list of plugin slugs. * @see \lucatume\WPBrowser\Module\WPBrowser::deactivatePlugin() */ - public function deactivatePlugin($pluginSlug): void { + public function deactivatePlugin(array|string $pluginSlug): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deactivatePlugin', func_get_args())); } @@ -5888,9 +5888,8 @@ public function cantSeeCurrentUrlMatches(string $uri): void { * $uri = $I->grabFromCurrentUrl(); * ``` * @see \Codeception\Lib\InnerBrowser::grabFromCurrentUrl() - * @return mixed */ - public function grabFromCurrentUrl(?string $uri = NULL) { + public function grabFromCurrentUrl(?string $uri = NULL): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); } @@ -6632,9 +6631,8 @@ public function makeHtmlSnapshot(?string $name = NULL): void { * $value = $I->grabTextFrom('~getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); } @@ -6650,9 +6648,8 @@ public function grabTextFrom($cssOrXPathOrRegex) { * $I->grabAttributeFrom('#tooltip', 'title'); * ``` * @see \Codeception\Lib\InnerBrowser::grabAttributeFrom() - * @return mixed */ - public function grabAttributeFrom($cssOrXpath, string $attribute) { + public function grabAttributeFrom($cssOrXpath, string $attribute): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args())); } @@ -6700,9 +6697,8 @@ public function grabMultiple($cssOrXpath, ?string $attribute = NULL): array { * $name = $I->grabValueFrom(['name' => 'username']); * ``` * @see \Codeception\Lib\InnerBrowser::grabValueFrom() - * @return mixed */ - public function grabValueFrom($field) { + public function grabValueFrom($field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args())); } @@ -6733,9 +6729,8 @@ public function setCookie($name, $val, $params = []) { * You can set additional cookie params like `domain`, `path` in array passed as last argument. * If the cookie is set by an ajax request (XMLHttpRequest), there might be some delay caused by the browser, so try `$I->wait(0.1)`. * @see \Codeception\Lib\InnerBrowser::grabCookie() - * @return mixed */ - public function grabCookie(string $cookie, array $params = []) { + public function grabCookie(string $cookie, array $params = []): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); } @@ -7435,7 +7430,7 @@ public function setMaxRedirects(int $maxRedirects): void { * @throws ModuleException IF the current URI cannot be retrieved from the inner browser. * @see \lucatume\WPBrowser\Module\WPBrowser::logOut() */ - public function logOut($redirectTo = false): void { + public function logOut(string|bool $redirectTo = false): void { $this->getScenario()->runStep(new \Codeception\Step\Action('logOut', func_get_args())); } @@ -7737,7 +7732,7 @@ public function cantSeePluginInstalled(string $pluginSlug): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeErrorMessage() */ - public function seeErrorMessage($classes = ""): void { + public function seeErrorMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeErrorMessage', func_get_args())); } /** @@ -7762,7 +7757,7 @@ public function seeErrorMessage($classes = ""): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeErrorMessage() */ - public function canSeeErrorMessage($classes = ""): void { + public function canSeeErrorMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeErrorMessage', func_get_args())); } @@ -7828,7 +7823,7 @@ public function canSeeWpDiePage(): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeMessage() */ - public function seeMessage($classes = ""): void { + public function seeMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeMessage', func_get_args())); } /** @@ -7852,7 +7847,7 @@ public function seeMessage($classes = ""): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPBrowser::seeMessage() */ - public function canSeeMessage($classes = ""): void { + public function canSeeMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeMessage', func_get_args())); } @@ -7918,7 +7913,7 @@ public function amOnAdminPage(string $page): void { * @param string|array $queryVars A string or array of query variables to append to the AJAX path. * @see \lucatume\WPBrowser\Module\WPBrowser::amOnAdminAjaxPage() */ - public function amOnAdminAjaxPage($queryVars = NULL): void { + public function amOnAdminAjaxPage(array|string|null $queryVars = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnAdminAjaxPage', func_get_args())); } @@ -7937,7 +7932,7 @@ public function amOnAdminAjaxPage($queryVars = NULL): void { * @param string|array $queryVars A string or array of query variables to append to the Cron path. * @see \lucatume\WPBrowser\Module\WPBrowser::amOnCronPage() */ - public function amOnCronPage($queryVars = NULL): void { + public function amOnCronPage(array|string|null $queryVars = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnCronPage', func_get_args())); } @@ -9432,9 +9427,8 @@ public function assertNull($actual, string $message = "") { * * Asserts that an object has a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() - * @param object $object */ - public function assertObjectHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); } @@ -9444,9 +9438,8 @@ public function assertObjectHasAttribute(string $attributeName, $object, string * * Asserts that an object does not have a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() - * @param object $object */ - public function assertObjectNotHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectNotHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); } diff --git a/tests/_support/_generated/FunctionalTesterActions.php b/tests/_support/_generated/FunctionalTesterActions.php index 730159e9c..79c391a51 100644 --- a/tests/_support/_generated/FunctionalTesterActions.php +++ b/tests/_support/_generated/FunctionalTesterActions.php @@ -31,7 +31,7 @@ abstract protected function getScenario(); * @return int The inserted row ID. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteMetaInDatabase() */ - public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int { + public function haveSiteMetaInDatabase(int $blogId, string $string, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteMetaInDatabase', func_get_args())); } @@ -57,7 +57,7 @@ public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int * @throws Exception On unserialize failure. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteMetaFromDatabase() */ - public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) { + public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteMetaFromDatabase', func_get_args())); } @@ -79,7 +79,7 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field) { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -125,14 +125,14 @@ public function importSqlDumpFile(?string $dumpFile = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionInDatabase', func_get_args())); } /** @@ -153,14 +153,14 @@ public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function cantSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionInDatabase', func_get_args())); } @@ -664,7 +664,7 @@ public function grabLatestEntryByFromDatabase(string $tableName, string $idColum * @return int The inserted meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::havePostmetaInDatabase() */ - public function havePostmetaInDatabase(int $postId, string $meta_key, $meta_value): int { + public function havePostmetaInDatabase(int $postId, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('havePostmetaInDatabase', func_get_args())); } @@ -712,7 +712,7 @@ public function grabPostmetaTableName(): string { * @return int|false The matching term `term_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermIdFromDatabase() */ - public function grabTermIdFromDatabase(array $criteria) { + public function grabTermIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermIdFromDatabase', func_get_args())); } @@ -816,7 +816,7 @@ public function grabTermTaxonomyTableName(): string { * @return int The inserted term meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTermMetaInDatabase() */ - public function haveTermMetaInDatabase(int $term_id, string $meta_key, $meta_value): int { + public function haveTermMetaInDatabase(int $term_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTermMetaInDatabase', func_get_args())); } @@ -863,7 +863,7 @@ public function grabTermMetaTableName(): string { * @return int|false The matching term `term_taxonomy_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermTaxonomyIdFromDatabase() */ - public function grabTermTaxonomyIdFromDatabase(array $criteria) { + public function grabTermTaxonomyIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermTaxonomyIdFromDatabase', func_get_args())); } @@ -1482,7 +1482,7 @@ public function dontHaveUserMetaInDatabase(array $criteria): void { * @throws Exception If the search criteria is incoherent. * @see \lucatume\WPBrowser\Module\WPDb::grabUserMetaFromDatabase() */ - public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false) { + public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserMetaFromDatabase', func_get_args())); } @@ -1533,7 +1533,7 @@ public function grabAllFromDatabase(string $table, string $column, array $criter * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTransientInDatabase() */ - public function haveTransientInDatabase(string $transient, $value): int { + public function haveTransientInDatabase(string $transient, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTransientInDatabase', func_get_args())); } @@ -1558,7 +1558,7 @@ public function haveTransientInDatabase(string $transient, $value): int { * @return int The inserted option `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveOptionInDatabase() */ - public function haveOptionInDatabase(string $option_name, $option_value, string $autoload = "yes"): int { + public function haveOptionInDatabase(string $option_name, mixed $option_value, string $autoload = "yes"): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveOptionInDatabase', func_get_args())); } @@ -1596,10 +1596,10 @@ public function dontHaveTransientInDatabase(string $transient): void { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed if its value matches the passed one. + * @param mixed|null $value If set the option will only be removed if its value matches the passed one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveOptionInDatabase() */ - public function dontHaveOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveOptionInDatabase', func_get_args())); } @@ -1622,7 +1622,7 @@ public function dontHaveOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteOptionInDatabase() */ - public function haveSiteOptionInDatabase(string $key, $value): int { + public function haveSiteOptionInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteOptionInDatabase', func_get_args())); } @@ -1709,10 +1709,10 @@ public function grabBlogUrl(int $blogId = 1): string { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed it its value matches the specified one. + * @param mixed|null $value If set the option will only be removed it its value matches the specified one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveSiteOptionInDatabase() */ - public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveSiteOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveSiteOptionInDatabase', func_get_args())); } @@ -1736,7 +1736,7 @@ public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted transient `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveSiteTransientInDatabase() */ - public function haveSiteTransientInDatabase(string $key, $value): int { + public function haveSiteTransientInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteTransientInDatabase', func_get_args())); } @@ -1774,7 +1774,7 @@ public function dontHaveSiteTransientInDatabase(string $key): void { * @return mixed The value of the option stored in the database, unserialized if serialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteOptionFromDatabase() */ - public function grabSiteOptionFromDatabase(string $key) { + public function grabSiteOptionFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteOptionFromDatabase', func_get_args())); } @@ -1794,7 +1794,7 @@ public function grabSiteOptionFromDatabase(string $key) { * @return mixed The option value. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabOptionFromDatabase() */ - public function grabOptionFromDatabase(string $option_name) { + public function grabOptionFromDatabase(string $option_name): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabOptionFromDatabase', func_get_args())); } @@ -1815,7 +1815,7 @@ public function grabOptionFromDatabase(string $option_name) { * @return mixed The value of the site transient. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteTransientFromDatabase() */ - public function grabSiteTransientFromDatabase(string $key) { + public function grabSiteTransientFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteTransientFromDatabase', func_get_args())); } @@ -1834,12 +1834,12 @@ public function grabSiteTransientFromDatabase(string $key) { * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function seeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteSiteTransientInDatabase', func_get_args())); } /** @@ -1857,12 +1857,12 @@ public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function canSeeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteSiteTransientInDatabase', func_get_args())); } @@ -1884,14 +1884,14 @@ public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): v * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionInDatabase', func_get_args())); } /** @@ -1912,14 +1912,14 @@ public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionInDatabase', func_get_args())); } @@ -1938,14 +1938,14 @@ public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteOptionInDatabase', func_get_args())); } /** @@ -1963,14 +1963,14 @@ public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function canSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteOptionInDatabase', func_get_args())); } @@ -2216,7 +2216,7 @@ public function haveCommentInDatabase(int $comment_post_ID, array $data = []): i * @return int The inserted comment meta ID. * @see \lucatume\WPBrowser\Module\WPDb::haveCommentMetaInDatabase() */ - public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, $meta_value): int { + public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveCommentMetaInDatabase', func_get_args())); } @@ -2481,7 +2481,7 @@ public function haveManyUsersInDatabase(int $count, string $user_login, string $ * @see WPDb::haveUserCapabilitiesInDatabase() for the roles and caps options. * @see \lucatume\WPBrowser\Module\WPDb::haveUserInDatabase() */ - public function haveUserInDatabase(string $user_login, $role = "subscriber", array $overrides = []): int { + public function haveUserInDatabase(string $user_login, array|string $role = "subscriber", array $overrides = []): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserInDatabase', func_get_args())); } @@ -2572,7 +2572,7 @@ public function grabUsersTableName(): string { * @return array|int> An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserCapabilitiesInDatabase() */ - public function haveUserCapabilitiesInDatabase(int $userId, $role): array { + public function haveUserCapabilitiesInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserCapabilitiesInDatabase', func_get_args())); } @@ -2596,7 +2596,7 @@ public function haveUserCapabilitiesInDatabase(int $userId, $role): array { * @return array An array of inserted `umeta_id`s. * @see \lucatume\WPBrowser\Module\WPDb::haveUserMetaInDatabase() */ - public function haveUserMetaInDatabase(int $userId, string $meta_key, $meta_value): array { + public function haveUserMetaInDatabase(int $userId, string $meta_key, mixed $meta_value): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserMetaInDatabase', func_get_args())); } @@ -2651,7 +2651,7 @@ public function grabUsermetaTableName(): string { * @return array An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserLevelsInDatabase() */ - public function haveUserLevelsInDatabase(int $userId, $role): array { + public function haveUserLevelsInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserLevelsInDatabase', func_get_args())); } @@ -3411,7 +3411,7 @@ public function canSeeTermRelationshipInDatabase(array $criteria): void { * readable. * @see \lucatume\WPBrowser\Module\WPDb::haveAttachmentInDatabase() */ - public function haveAttachmentInDatabase(string $file, $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { + public function haveAttachmentInDatabase(string $file, string|int $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveAttachmentInDatabase', func_get_args())); } @@ -3573,7 +3573,7 @@ public function dontHaveAttachmentInDatabase(array $criteria, bool $purgeMeta = * @throws ModuleRequireException If the `WPFilesystem` module is not loaded in the suite. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveAttachmentFilesInDatabase() */ - public function dontHaveAttachmentFilesInDatabase($attachmentIds): void { + public function dontHaveAttachmentFilesInDatabase(array|int $attachmentIds): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveAttachmentFilesInDatabase', func_get_args())); } @@ -3728,7 +3728,7 @@ public function grabTablePrefix(): string { * @param bool $purgeMeta Whether the user meta should be purged alongside the user or not. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveUserInDatabase() */ - public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): void { + public function dontHaveUserInDatabase(string|int $userIdOrLogin, bool $purgeMeta = true): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveUserInDatabase', func_get_args())); } @@ -3748,7 +3748,7 @@ public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): * @return int|false The user ID or `false` if the user was not found. * @see \lucatume\WPBrowser\Module\WPDb::grabUserIdFromDatabase() */ - public function grabUserIdFromDatabase(string $userLogin) { + public function grabUserIdFromDatabase(string $userLogin): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserIdFromDatabase', func_get_args())); } @@ -3770,7 +3770,7 @@ public function grabUserIdFromDatabase(string $userLogin) { * @return mixed|array Either a single meta value or an array of all the available meta values. * @see \lucatume\WPBrowser\Module\WPDb::grabPostMetaFromDatabase() */ - public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false) { + public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostMetaFromDatabase', func_get_args())); } @@ -4066,14 +4066,14 @@ public function importSql(array $sql): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteOptionInDatabase', func_get_args())); } /** @@ -4092,14 +4092,14 @@ public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteOptionInDatabase', func_get_args())); } @@ -4121,7 +4121,7 @@ public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * * @see \lucatume\WPBrowser\Module\WPDb::grabTransientFromDatabase() */ - public function grabTransientFromDatabase(string $transient) { + public function grabTransientFromDatabase(string $transient): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTransientFromDatabase', func_get_args())); } @@ -4144,7 +4144,7 @@ public function grabTransientFromDatabase(string $transient) { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function dontSeeTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeTransientInDatabase', func_get_args())); } /** @@ -4166,7 +4166,7 @@ public function dontSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function cantSeeTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeTransientInDatabase', func_get_args())); } @@ -4190,7 +4190,7 @@ public function cantSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function seeTransientInDatabase(string $name, $value = NULL): void { + public function seeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeTransientInDatabase', func_get_args())); } /** @@ -4213,7 +4213,7 @@ public function seeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function canSeeTransientInDatabase(string $name, $value = NULL): void { + public function canSeeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeTransientInDatabase', func_get_args())); } @@ -4228,7 +4228,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4237,7 +4237,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteTransientInDatabase', func_get_args())); } /** @@ -4251,7 +4251,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4260,7 +4260,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteTransientInDatabase', func_get_args())); } @@ -4276,7 +4276,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4284,7 +4284,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function seeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function seeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteTransientInDatabase', func_get_args())); } /** @@ -4299,7 +4299,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4307,7 +4307,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function canSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function canSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteTransientInDatabase', func_get_args())); } @@ -5990,9 +5990,8 @@ public function assertNull($actual, string $message = "") { * * Asserts that an object has a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() - * @param object $object */ - public function assertObjectHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); } @@ -6002,9 +6001,8 @@ public function assertObjectHasAttribute(string $attributeName, $object, string * * Asserts that an object does not have a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() - * @param object $object */ - public function assertObjectNotHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectNotHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); } @@ -6413,7 +6411,7 @@ public function amInUploadsPath(?string $path = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeUploadedFileFound() */ - public function seeUploadedFileFound(string $filename, $date = NULL): void { + public function seeUploadedFileFound(string $filename, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeUploadedFileFound', func_get_args())); } /** @@ -6438,7 +6436,7 @@ public function seeUploadedFileFound(string $filename, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeUploadedFileFound() */ - public function canSeeUploadedFileFound(string $filename, $date = NULL): void { + public function canSeeUploadedFileFound(string $filename, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeUploadedFileFound', func_get_args())); } @@ -6457,7 +6455,7 @@ public function canSeeUploadedFileFound(string $filename, $date = NULL): void { * ``` * * @param string $file The file path, relative to the uploads folder. - * @param mixed $date A string compatible with `strtotime`, a Unix timestamp or a Date + * @param DateTimeInterface|string|int|null $date A string compatible with `strtotime`, a Unix timestamp or a Date * object. * * @return string The absolute path to an uploaded file. @@ -6465,7 +6463,7 @@ public function canSeeUploadedFileFound(string $filename, $date = NULL): void { * @throws Exception * @see \lucatume\WPBrowser\Module\WPFilesystem::getUploadsPath() */ - public function getUploadsPath(string $file = "", $date = NULL): string { + public function getUploadsPath(string $file = "", mixed $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('getUploadsPath', func_get_args())); } @@ -6490,7 +6488,7 @@ public function getUploadsPath(string $file = "", $date = NULL): string { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeUploadedFileFound() */ - public function dontSeeUploadedFileFound(string $file, $date = NULL): void { + public function dontSeeUploadedFileFound(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeUploadedFileFound', func_get_args())); } /** @@ -6514,7 +6512,7 @@ public function dontSeeUploadedFileFound(string $file, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeUploadedFileFound() */ - public function cantSeeUploadedFileFound(string $file, $date = NULL): void { + public function cantSeeUploadedFileFound(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeUploadedFileFound', func_get_args())); } @@ -6540,7 +6538,7 @@ public function cantSeeUploadedFileFound(string $file, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeInUploadedFile() */ - public function seeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function seeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInUploadedFile', func_get_args())); } /** @@ -6565,7 +6563,7 @@ public function seeInUploadedFile(string $file, string $contents, $date = NULL): * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeInUploadedFile() */ - public function canSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function canSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInUploadedFile', func_get_args())); } @@ -6589,7 +6587,7 @@ public function canSeeInUploadedFile(string $file, string $contents, $date = NUL * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeInUploadedFile() */ - public function dontSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function dontSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInUploadedFile', func_get_args())); } /** @@ -6612,7 +6610,7 @@ public function dontSeeInUploadedFile(string $file, string $contents, $date = NU * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeInUploadedFile() */ - public function cantSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function cantSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInUploadedFile', func_get_args())); } @@ -6638,7 +6636,7 @@ public function cantSeeInUploadedFile(string $file, string $contents, $date = NU * @throws ModuleException If the destination folder could not be removed. * @see \lucatume\WPBrowser\Module\WPFilesystem::deleteUploadedDir() */ - public function deleteUploadedDir(string $dir, $date = NULL): void { + public function deleteUploadedDir(string $dir, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deleteUploadedDir', func_get_args())); } @@ -6661,7 +6659,7 @@ public function deleteUploadedDir(string $dir, $date = NULL): void { * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::deleteUploadedFile() */ - public function deleteUploadedFile(string $file, $date = NULL): void { + public function deleteUploadedFile(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deleteUploadedFile', func_get_args())); } @@ -6685,7 +6683,7 @@ public function deleteUploadedFile(string $file, $date = NULL): void { * @param string|null $dir The path to the directory to delete, relative to the uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::cleanUploadsDir() */ - public function cleanUploadsDir(?string $dir = NULL, $date = NULL): void { + public function cleanUploadsDir(?string $dir = NULL, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('cleanUploadsDir', func_get_args())); } @@ -6710,7 +6708,7 @@ public function cleanUploadsDir(?string $dir = NULL, $date = NULL): void { * @param string $src The path to the source file, relative to the current uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::copyDirToUploads() */ - public function copyDirToUploads(string $src, string $dst, $date = NULL): void { + public function copyDirToUploads(string $src, string $dst, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('copyDirToUploads', func_get_args())); } @@ -6740,7 +6738,7 @@ public function copyDirToUploads(string $src, string $dst, $date = NULL): void { * file could not be written. * @see \lucatume\WPBrowser\Module\WPFilesystem::writeToUploadedFile() */ - public function writeToUploadedFile(string $filename, string $data, $date = NULL): string { + public function writeToUploadedFile(string $filename, string $data, \DateTime|string|int|null $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('writeToUploadedFile', func_get_args())); } @@ -6764,7 +6762,7 @@ public function writeToUploadedFile(string $filename, string $data, $date = NULL * @param string $filename The path to the file, relative to the current uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::openUploadedFile() */ - public function openUploadedFile(string $filename, $date = NULL): void { + public function openUploadedFile(string $filename, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('openUploadedFile', func_get_args())); } @@ -7613,7 +7611,7 @@ public function getWpRootFolder(): string { * @throws Exception If the date is not a valid format. * @see \lucatume\WPBrowser\Module\WPFilesystem::getBlogUploadsPath() */ - public function getBlogUploadsPath(int $blogId, string $file = "", $date = NULL): string { + public function getBlogUploadsPath(int $blogId, string $file = "", \DateTimeImmutable|\DateTime|string|null $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('getBlogUploadsPath', func_get_args())); } diff --git a/tests/_support/_generated/UnitTesterActions.php b/tests/_support/_generated/UnitTesterActions.php index d57d3941f..885159a0f 100644 --- a/tests/_support/_generated/UnitTesterActions.php +++ b/tests/_support/_generated/UnitTesterActions.php @@ -1322,9 +1322,8 @@ public function assertNull($actual, string $message = "") { * * Asserts that an object has a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() - * @param object $object */ - public function assertObjectHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); } @@ -1334,9 +1333,8 @@ public function assertObjectHasAttribute(string $attributeName, $object, string * * Asserts that an object does not have a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() - * @param object $object */ - public function assertObjectNotHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectNotHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); } diff --git a/tests/_support/_generated/WebDriverTesterActions.php b/tests/_support/_generated/WebDriverTesterActions.php index 6308c000b..5b56f4815 100644 --- a/tests/_support/_generated/WebDriverTesterActions.php +++ b/tests/_support/_generated/WebDriverTesterActions.php @@ -158,7 +158,7 @@ public function grabFullUrl(): string { * @throws JsonException If there's an issue encoding the debug message. * @see \lucatume\WPBrowser\Module\WPWebDriver::deactivatePlugin() */ - public function deactivatePlugin($pluginSlug): void { + public function deactivatePlugin(array|string $pluginSlug): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deactivatePlugin', func_get_args())); } @@ -188,7 +188,7 @@ public function deactivatePlugin($pluginSlug): void { * @throws JsonException If there's an issue encoding the debug message. * @see \lucatume\WPBrowser\Module\WPWebDriver::activatePlugin() */ - public function activatePlugin($pluginSlug): void { + public function activatePlugin(array|string $pluginSlug): void { $this->getScenario()->runStep(new \Codeception\Step\Action('activatePlugin', func_get_args())); } @@ -410,9 +410,8 @@ public function resetCookie($cookie, array $params = [], bool $showDebug = true) * You can set additional cookie params like `domain`, `path` in array passed as last argument. * If the cookie is set by an ajax request (XMLHttpRequest), there might be some delay caused by the browser, so try `$I->wait(0.1)`. * @see \Codeception\Module\WebDriver::grabCookie() - * @return mixed */ - public function grabCookie($cookie, array $params = []) { + public function grabCookie($cookie, array $params = []): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); } @@ -1053,9 +1052,8 @@ public function cantSeeCurrentUrlMatches(string $uri): void { * $uri = $I->grabFromCurrentUrl(); * ``` * @see \Codeception\Module\WebDriver::grabFromCurrentUrl() - * @return mixed */ - public function grabFromCurrentUrl($uri = NULL) { + public function grabFromCurrentUrl($uri = NULL): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); } @@ -1602,9 +1600,8 @@ public function attachFile($field, string $filename): void { * $value = $I->grabTextFrom('~getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); } @@ -3080,7 +3077,7 @@ public function performOn($element, $actions, int $timeout = 10): void { * @throws ModuleException IF the current URI cannot be retrieved from the inner browser. * @see \lucatume\WPBrowser\Module\WPWebDriver::logOut() */ - public function logOut($redirectTo = false): void { + public function logOut(string|bool $redirectTo = false): void { $this->getScenario()->runStep(new \Codeception\Step\Action('logOut', func_get_args())); } @@ -3337,7 +3334,7 @@ public function cantSeePluginInstalled(string $pluginSlug): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPWebDriver::seeErrorMessage() */ - public function seeErrorMessage($classes = ""): void { + public function seeErrorMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeErrorMessage', func_get_args())); } /** @@ -3362,7 +3359,7 @@ public function seeErrorMessage($classes = ""): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPWebDriver::seeErrorMessage() */ - public function canSeeErrorMessage($classes = ""): void { + public function canSeeErrorMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeErrorMessage', func_get_args())); } @@ -3428,7 +3425,7 @@ public function canSeeWpDiePage(): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPWebDriver::seeMessage() */ - public function seeMessage($classes = ""): void { + public function seeMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeMessage', func_get_args())); } /** @@ -3452,7 +3449,7 @@ public function seeMessage($classes = ""): void { * @throws JsonException If there's any issue stringifying the selector. * @see \lucatume\WPBrowser\Module\WPWebDriver::seeMessage() */ - public function canSeeMessage($classes = ""): void { + public function canSeeMessage(array|string $classes = ""): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeMessage', func_get_args())); } @@ -3518,7 +3515,7 @@ public function amOnAdminPage(string $page): void { * @param string|array $queryVars A string or array of query variables to append to the AJAX path. * @see \lucatume\WPBrowser\Module\WPWebDriver::amOnAdminAjaxPage() */ - public function amOnAdminAjaxPage($queryVars = NULL): void { + public function amOnAdminAjaxPage(array|string|null $queryVars = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnAdminAjaxPage', func_get_args())); } @@ -3537,7 +3534,7 @@ public function amOnAdminAjaxPage($queryVars = NULL): void { * @param string|array $queryVars A string or array of query variables to append to the Cron path. * @see \lucatume\WPBrowser\Module\WPWebDriver::amOnCronPage() */ - public function amOnCronPage($queryVars = NULL): void { + public function amOnCronPage(array|string|null $queryVars = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnCronPage', func_get_args())); } @@ -3741,7 +3738,7 @@ public function canSeeThemeActivated(string $slug): void { * @return int The inserted row ID. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteMetaInDatabase() */ - public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int { + public function haveSiteMetaInDatabase(int $blogId, string $string, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteMetaInDatabase', func_get_args())); } @@ -3767,7 +3764,7 @@ public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int * @throws Exception On unserialize failure. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteMetaFromDatabase() */ - public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) { + public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteMetaFromDatabase', func_get_args())); } @@ -3789,7 +3786,7 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field) { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -3835,14 +3832,14 @@ public function importSqlDumpFile(?string $dumpFile = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionInDatabase', func_get_args())); } /** @@ -3863,14 +3860,14 @@ public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function cantSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionInDatabase', func_get_args())); } @@ -4374,7 +4371,7 @@ public function grabLatestEntryByFromDatabase(string $tableName, string $idColum * @return int The inserted meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::havePostmetaInDatabase() */ - public function havePostmetaInDatabase(int $postId, string $meta_key, $meta_value): int { + public function havePostmetaInDatabase(int $postId, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('havePostmetaInDatabase', func_get_args())); } @@ -4422,7 +4419,7 @@ public function grabPostmetaTableName(): string { * @return int|false The matching term `term_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermIdFromDatabase() */ - public function grabTermIdFromDatabase(array $criteria) { + public function grabTermIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermIdFromDatabase', func_get_args())); } @@ -4526,7 +4523,7 @@ public function grabTermTaxonomyTableName(): string { * @return int The inserted term meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTermMetaInDatabase() */ - public function haveTermMetaInDatabase(int $term_id, string $meta_key, $meta_value): int { + public function haveTermMetaInDatabase(int $term_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTermMetaInDatabase', func_get_args())); } @@ -4573,7 +4570,7 @@ public function grabTermMetaTableName(): string { * @return int|false The matching term `term_taxonomy_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermTaxonomyIdFromDatabase() */ - public function grabTermTaxonomyIdFromDatabase(array $criteria) { + public function grabTermTaxonomyIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermTaxonomyIdFromDatabase', func_get_args())); } @@ -5192,7 +5189,7 @@ public function dontHaveUserMetaInDatabase(array $criteria): void { * @throws Exception If the search criteria is incoherent. * @see \lucatume\WPBrowser\Module\WPDb::grabUserMetaFromDatabase() */ - public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false) { + public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserMetaFromDatabase', func_get_args())); } @@ -5243,7 +5240,7 @@ public function grabAllFromDatabase(string $table, string $column, array $criter * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTransientInDatabase() */ - public function haveTransientInDatabase(string $transient, $value): int { + public function haveTransientInDatabase(string $transient, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTransientInDatabase', func_get_args())); } @@ -5268,7 +5265,7 @@ public function haveTransientInDatabase(string $transient, $value): int { * @return int The inserted option `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveOptionInDatabase() */ - public function haveOptionInDatabase(string $option_name, $option_value, string $autoload = "yes"): int { + public function haveOptionInDatabase(string $option_name, mixed $option_value, string $autoload = "yes"): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveOptionInDatabase', func_get_args())); } @@ -5306,10 +5303,10 @@ public function dontHaveTransientInDatabase(string $transient): void { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed if its value matches the passed one. + * @param mixed|null $value If set the option will only be removed if its value matches the passed one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveOptionInDatabase() */ - public function dontHaveOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveOptionInDatabase', func_get_args())); } @@ -5332,7 +5329,7 @@ public function dontHaveOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteOptionInDatabase() */ - public function haveSiteOptionInDatabase(string $key, $value): int { + public function haveSiteOptionInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteOptionInDatabase', func_get_args())); } @@ -5419,10 +5416,10 @@ public function grabBlogUrl(int $blogId = 1): string { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed it its value matches the specified one. + * @param mixed|null $value If set the option will only be removed it its value matches the specified one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveSiteOptionInDatabase() */ - public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveSiteOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveSiteOptionInDatabase', func_get_args())); } @@ -5446,7 +5443,7 @@ public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted transient `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveSiteTransientInDatabase() */ - public function haveSiteTransientInDatabase(string $key, $value): int { + public function haveSiteTransientInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteTransientInDatabase', func_get_args())); } @@ -5484,7 +5481,7 @@ public function dontHaveSiteTransientInDatabase(string $key): void { * @return mixed The value of the option stored in the database, unserialized if serialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteOptionFromDatabase() */ - public function grabSiteOptionFromDatabase(string $key) { + public function grabSiteOptionFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteOptionFromDatabase', func_get_args())); } @@ -5504,7 +5501,7 @@ public function grabSiteOptionFromDatabase(string $key) { * @return mixed The option value. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabOptionFromDatabase() */ - public function grabOptionFromDatabase(string $option_name) { + public function grabOptionFromDatabase(string $option_name): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabOptionFromDatabase', func_get_args())); } @@ -5525,7 +5522,7 @@ public function grabOptionFromDatabase(string $option_name) { * @return mixed The value of the site transient. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteTransientFromDatabase() */ - public function grabSiteTransientFromDatabase(string $key) { + public function grabSiteTransientFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteTransientFromDatabase', func_get_args())); } @@ -5544,12 +5541,12 @@ public function grabSiteTransientFromDatabase(string $key) { * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function seeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteSiteTransientInDatabase', func_get_args())); } /** @@ -5567,12 +5564,12 @@ public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function canSeeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteSiteTransientInDatabase', func_get_args())); } @@ -5594,14 +5591,14 @@ public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): v * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionInDatabase', func_get_args())); } /** @@ -5622,14 +5619,14 @@ public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionInDatabase', func_get_args())); } @@ -5648,14 +5645,14 @@ public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteOptionInDatabase', func_get_args())); } /** @@ -5673,14 +5670,14 @@ public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function canSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteOptionInDatabase', func_get_args())); } @@ -5926,7 +5923,7 @@ public function haveCommentInDatabase(int $comment_post_ID, array $data = []): i * @return int The inserted comment meta ID. * @see \lucatume\WPBrowser\Module\WPDb::haveCommentMetaInDatabase() */ - public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, $meta_value): int { + public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveCommentMetaInDatabase', func_get_args())); } @@ -6191,7 +6188,7 @@ public function haveManyUsersInDatabase(int $count, string $user_login, string $ * @see WPDb::haveUserCapabilitiesInDatabase() for the roles and caps options. * @see \lucatume\WPBrowser\Module\WPDb::haveUserInDatabase() */ - public function haveUserInDatabase(string $user_login, $role = "subscriber", array $overrides = []): int { + public function haveUserInDatabase(string $user_login, array|string $role = "subscriber", array $overrides = []): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserInDatabase', func_get_args())); } @@ -6282,7 +6279,7 @@ public function grabUsersTableName(): string { * @return array|int> An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserCapabilitiesInDatabase() */ - public function haveUserCapabilitiesInDatabase(int $userId, $role): array { + public function haveUserCapabilitiesInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserCapabilitiesInDatabase', func_get_args())); } @@ -6306,7 +6303,7 @@ public function haveUserCapabilitiesInDatabase(int $userId, $role): array { * @return array An array of inserted `umeta_id`s. * @see \lucatume\WPBrowser\Module\WPDb::haveUserMetaInDatabase() */ - public function haveUserMetaInDatabase(int $userId, string $meta_key, $meta_value): array { + public function haveUserMetaInDatabase(int $userId, string $meta_key, mixed $meta_value): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserMetaInDatabase', func_get_args())); } @@ -6361,7 +6358,7 @@ public function grabUsermetaTableName(): string { * @return array An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserLevelsInDatabase() */ - public function haveUserLevelsInDatabase(int $userId, $role): array { + public function haveUserLevelsInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserLevelsInDatabase', func_get_args())); } @@ -7121,7 +7118,7 @@ public function canSeeTermRelationshipInDatabase(array $criteria): void { * readable. * @see \lucatume\WPBrowser\Module\WPDb::haveAttachmentInDatabase() */ - public function haveAttachmentInDatabase(string $file, $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { + public function haveAttachmentInDatabase(string $file, string|int $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveAttachmentInDatabase', func_get_args())); } @@ -7283,7 +7280,7 @@ public function dontHaveAttachmentInDatabase(array $criteria, bool $purgeMeta = * @throws ModuleRequireException If the `WPFilesystem` module is not loaded in the suite. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveAttachmentFilesInDatabase() */ - public function dontHaveAttachmentFilesInDatabase($attachmentIds): void { + public function dontHaveAttachmentFilesInDatabase(array|int $attachmentIds): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveAttachmentFilesInDatabase', func_get_args())); } @@ -7438,7 +7435,7 @@ public function grabTablePrefix(): string { * @param bool $purgeMeta Whether the user meta should be purged alongside the user or not. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveUserInDatabase() */ - public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): void { + public function dontHaveUserInDatabase(string|int $userIdOrLogin, bool $purgeMeta = true): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveUserInDatabase', func_get_args())); } @@ -7458,7 +7455,7 @@ public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): * @return int|false The user ID or `false` if the user was not found. * @see \lucatume\WPBrowser\Module\WPDb::grabUserIdFromDatabase() */ - public function grabUserIdFromDatabase(string $userLogin) { + public function grabUserIdFromDatabase(string $userLogin): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserIdFromDatabase', func_get_args())); } @@ -7480,7 +7477,7 @@ public function grabUserIdFromDatabase(string $userLogin) { * @return mixed|array Either a single meta value or an array of all the available meta values. * @see \lucatume\WPBrowser\Module\WPDb::grabPostMetaFromDatabase() */ - public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false) { + public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostMetaFromDatabase', func_get_args())); } @@ -7776,14 +7773,14 @@ public function importSql(array $sql): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteOptionInDatabase', func_get_args())); } /** @@ -7802,14 +7799,14 @@ public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteOptionInDatabase', func_get_args())); } @@ -7831,7 +7828,7 @@ public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * * @see \lucatume\WPBrowser\Module\WPDb::grabTransientFromDatabase() */ - public function grabTransientFromDatabase(string $transient) { + public function grabTransientFromDatabase(string $transient): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTransientFromDatabase', func_get_args())); } @@ -7854,7 +7851,7 @@ public function grabTransientFromDatabase(string $transient) { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function dontSeeTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeTransientInDatabase', func_get_args())); } /** @@ -7876,7 +7873,7 @@ public function dontSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function cantSeeTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeTransientInDatabase', func_get_args())); } @@ -7900,7 +7897,7 @@ public function cantSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function seeTransientInDatabase(string $name, $value = NULL): void { + public function seeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeTransientInDatabase', func_get_args())); } /** @@ -7923,7 +7920,7 @@ public function seeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function canSeeTransientInDatabase(string $name, $value = NULL): void { + public function canSeeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeTransientInDatabase', func_get_args())); } @@ -7938,7 +7935,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7947,7 +7944,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteTransientInDatabase', func_get_args())); } /** @@ -7961,7 +7958,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7970,7 +7967,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteTransientInDatabase', func_get_args())); } @@ -7986,7 +7983,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -7994,7 +7991,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function seeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function seeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteTransientInDatabase', func_get_args())); } /** @@ -8009,7 +8006,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -8017,7 +8014,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function canSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function canSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteTransientInDatabase', func_get_args())); } @@ -8433,7 +8430,7 @@ public function amInUploadsPath(?string $path = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeUploadedFileFound() */ - public function seeUploadedFileFound(string $filename, $date = NULL): void { + public function seeUploadedFileFound(string $filename, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeUploadedFileFound', func_get_args())); } /** @@ -8458,7 +8455,7 @@ public function seeUploadedFileFound(string $filename, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeUploadedFileFound() */ - public function canSeeUploadedFileFound(string $filename, $date = NULL): void { + public function canSeeUploadedFileFound(string $filename, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeUploadedFileFound', func_get_args())); } @@ -8477,7 +8474,7 @@ public function canSeeUploadedFileFound(string $filename, $date = NULL): void { * ``` * * @param string $file The file path, relative to the uploads folder. - * @param mixed $date A string compatible with `strtotime`, a Unix timestamp or a Date + * @param DateTimeInterface|string|int|null $date A string compatible with `strtotime`, a Unix timestamp or a Date * object. * * @return string The absolute path to an uploaded file. @@ -8485,7 +8482,7 @@ public function canSeeUploadedFileFound(string $filename, $date = NULL): void { * @throws Exception * @see \lucatume\WPBrowser\Module\WPFilesystem::getUploadsPath() */ - public function getUploadsPath(string $file = "", $date = NULL): string { + public function getUploadsPath(string $file = "", mixed $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('getUploadsPath', func_get_args())); } @@ -8510,7 +8507,7 @@ public function getUploadsPath(string $file = "", $date = NULL): string { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeUploadedFileFound() */ - public function dontSeeUploadedFileFound(string $file, $date = NULL): void { + public function dontSeeUploadedFileFound(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeUploadedFileFound', func_get_args())); } /** @@ -8534,7 +8531,7 @@ public function dontSeeUploadedFileFound(string $file, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeUploadedFileFound() */ - public function cantSeeUploadedFileFound(string $file, $date = NULL): void { + public function cantSeeUploadedFileFound(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeUploadedFileFound', func_get_args())); } @@ -8560,7 +8557,7 @@ public function cantSeeUploadedFileFound(string $file, $date = NULL): void { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeInUploadedFile() */ - public function seeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function seeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInUploadedFile', func_get_args())); } /** @@ -8585,7 +8582,7 @@ public function seeInUploadedFile(string $file, string $contents, $date = NULL): * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPFilesystem::seeInUploadedFile() */ - public function canSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function canSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInUploadedFile', func_get_args())); } @@ -8609,7 +8606,7 @@ public function canSeeInUploadedFile(string $file, string $contents, $date = NUL * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeInUploadedFile() */ - public function dontSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function dontSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInUploadedFile', func_get_args())); } /** @@ -8632,7 +8629,7 @@ public function dontSeeInUploadedFile(string $file, string $contents, $date = NU * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::dontSeeInUploadedFile() */ - public function cantSeeInUploadedFile(string $file, string $contents, $date = NULL): void { + public function cantSeeInUploadedFile(string $file, string $contents, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInUploadedFile', func_get_args())); } @@ -8658,7 +8655,7 @@ public function cantSeeInUploadedFile(string $file, string $contents, $date = NU * @throws ModuleException If the destination folder could not be removed. * @see \lucatume\WPBrowser\Module\WPFilesystem::deleteUploadedDir() */ - public function deleteUploadedDir(string $dir, $date = NULL): void { + public function deleteUploadedDir(string $dir, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deleteUploadedDir', func_get_args())); } @@ -8681,7 +8678,7 @@ public function deleteUploadedDir(string $dir, $date = NULL): void { * @param int|string|null $date A string compatible with `strtotime` or a Unix timestamp. * @see \lucatume\WPBrowser\Module\WPFilesystem::deleteUploadedFile() */ - public function deleteUploadedFile(string $file, $date = NULL): void { + public function deleteUploadedFile(string $file, string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('deleteUploadedFile', func_get_args())); } @@ -8705,7 +8702,7 @@ public function deleteUploadedFile(string $file, $date = NULL): void { * @param string|null $dir The path to the directory to delete, relative to the uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::cleanUploadsDir() */ - public function cleanUploadsDir(?string $dir = NULL, $date = NULL): void { + public function cleanUploadsDir(?string $dir = NULL, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('cleanUploadsDir', func_get_args())); } @@ -8730,7 +8727,7 @@ public function cleanUploadsDir(?string $dir = NULL, $date = NULL): void { * @param string $src The path to the source file, relative to the current uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::copyDirToUploads() */ - public function copyDirToUploads(string $src, string $dst, $date = NULL): void { + public function copyDirToUploads(string $src, string $dst, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('copyDirToUploads', func_get_args())); } @@ -8760,7 +8757,7 @@ public function copyDirToUploads(string $src, string $dst, $date = NULL): void { * file could not be written. * @see \lucatume\WPBrowser\Module\WPFilesystem::writeToUploadedFile() */ - public function writeToUploadedFile(string $filename, string $data, $date = NULL): string { + public function writeToUploadedFile(string $filename, string $data, \DateTime|string|int|null $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('writeToUploadedFile', func_get_args())); } @@ -8784,7 +8781,7 @@ public function writeToUploadedFile(string $filename, string $data, $date = NULL * @param string $filename The path to the file, relative to the current uploads folder. * @see \lucatume\WPBrowser\Module\WPFilesystem::openUploadedFile() */ - public function openUploadedFile(string $filename, $date = NULL): void { + public function openUploadedFile(string $filename, \DateTime|string|int|null $date = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('openUploadedFile', func_get_args())); } @@ -9633,7 +9630,7 @@ public function getWpRootFolder(): string { * @throws Exception If the date is not a valid format. * @see \lucatume\WPBrowser\Module\WPFilesystem::getBlogUploadsPath() */ - public function getBlogUploadsPath(int $blogId, string $file = "", $date = NULL): string { + public function getBlogUploadsPath(int $blogId, string $file = "", \DateTimeImmutable|\DateTime|string|null $date = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('getBlogUploadsPath', func_get_args())); } diff --git a/tests/_support/_generated/Wpcli_moduleTesterActions.php b/tests/_support/_generated/Wpcli_moduleTesterActions.php index c25dc8175..28baa3450 100644 --- a/tests/_support/_generated/Wpcli_moduleTesterActions.php +++ b/tests/_support/_generated/Wpcli_moduleTesterActions.php @@ -31,7 +31,7 @@ abstract protected function getScenario(); * @return int The inserted row ID. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteMetaInDatabase() */ - public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int { + public function haveSiteMetaInDatabase(int $blogId, string $string, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteMetaInDatabase', func_get_args())); } @@ -57,7 +57,7 @@ public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int * @throws Exception On unserialize failure. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteMetaFromDatabase() */ - public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) { + public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteMetaFromDatabase', func_get_args())); } @@ -79,7 +79,7 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field) { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -125,14 +125,14 @@ public function importSqlDumpFile(?string $dumpFile = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionInDatabase', func_get_args())); } /** @@ -153,14 +153,14 @@ public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function cantSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionInDatabase', func_get_args())); } @@ -664,7 +664,7 @@ public function grabLatestEntryByFromDatabase(string $tableName, string $idColum * @return int The inserted meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::havePostmetaInDatabase() */ - public function havePostmetaInDatabase(int $postId, string $meta_key, $meta_value): int { + public function havePostmetaInDatabase(int $postId, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('havePostmetaInDatabase', func_get_args())); } @@ -712,7 +712,7 @@ public function grabPostmetaTableName(): string { * @return int|false The matching term `term_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermIdFromDatabase() */ - public function grabTermIdFromDatabase(array $criteria) { + public function grabTermIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermIdFromDatabase', func_get_args())); } @@ -816,7 +816,7 @@ public function grabTermTaxonomyTableName(): string { * @return int The inserted term meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTermMetaInDatabase() */ - public function haveTermMetaInDatabase(int $term_id, string $meta_key, $meta_value): int { + public function haveTermMetaInDatabase(int $term_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTermMetaInDatabase', func_get_args())); } @@ -863,7 +863,7 @@ public function grabTermMetaTableName(): string { * @return int|false The matching term `term_taxonomy_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermTaxonomyIdFromDatabase() */ - public function grabTermTaxonomyIdFromDatabase(array $criteria) { + public function grabTermTaxonomyIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermTaxonomyIdFromDatabase', func_get_args())); } @@ -1482,7 +1482,7 @@ public function dontHaveUserMetaInDatabase(array $criteria): void { * @throws Exception If the search criteria is incoherent. * @see \lucatume\WPBrowser\Module\WPDb::grabUserMetaFromDatabase() */ - public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false) { + public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserMetaFromDatabase', func_get_args())); } @@ -1533,7 +1533,7 @@ public function grabAllFromDatabase(string $table, string $column, array $criter * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTransientInDatabase() */ - public function haveTransientInDatabase(string $transient, $value): int { + public function haveTransientInDatabase(string $transient, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTransientInDatabase', func_get_args())); } @@ -1558,7 +1558,7 @@ public function haveTransientInDatabase(string $transient, $value): int { * @return int The inserted option `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveOptionInDatabase() */ - public function haveOptionInDatabase(string $option_name, $option_value, string $autoload = "yes"): int { + public function haveOptionInDatabase(string $option_name, mixed $option_value, string $autoload = "yes"): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveOptionInDatabase', func_get_args())); } @@ -1596,10 +1596,10 @@ public function dontHaveTransientInDatabase(string $transient): void { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed if its value matches the passed one. + * @param mixed|null $value If set the option will only be removed if its value matches the passed one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveOptionInDatabase() */ - public function dontHaveOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveOptionInDatabase', func_get_args())); } @@ -1622,7 +1622,7 @@ public function dontHaveOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteOptionInDatabase() */ - public function haveSiteOptionInDatabase(string $key, $value): int { + public function haveSiteOptionInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteOptionInDatabase', func_get_args())); } @@ -1709,10 +1709,10 @@ public function grabBlogUrl(int $blogId = 1): string { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed it its value matches the specified one. + * @param mixed|null $value If set the option will only be removed it its value matches the specified one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveSiteOptionInDatabase() */ - public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveSiteOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveSiteOptionInDatabase', func_get_args())); } @@ -1736,7 +1736,7 @@ public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted transient `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveSiteTransientInDatabase() */ - public function haveSiteTransientInDatabase(string $key, $value): int { + public function haveSiteTransientInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteTransientInDatabase', func_get_args())); } @@ -1774,7 +1774,7 @@ public function dontHaveSiteTransientInDatabase(string $key): void { * @return mixed The value of the option stored in the database, unserialized if serialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteOptionFromDatabase() */ - public function grabSiteOptionFromDatabase(string $key) { + public function grabSiteOptionFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteOptionFromDatabase', func_get_args())); } @@ -1794,7 +1794,7 @@ public function grabSiteOptionFromDatabase(string $key) { * @return mixed The option value. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabOptionFromDatabase() */ - public function grabOptionFromDatabase(string $option_name) { + public function grabOptionFromDatabase(string $option_name): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabOptionFromDatabase', func_get_args())); } @@ -1815,7 +1815,7 @@ public function grabOptionFromDatabase(string $option_name) { * @return mixed The value of the site transient. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteTransientFromDatabase() */ - public function grabSiteTransientFromDatabase(string $key) { + public function grabSiteTransientFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteTransientFromDatabase', func_get_args())); } @@ -1834,12 +1834,12 @@ public function grabSiteTransientFromDatabase(string $key) { * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function seeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteSiteTransientInDatabase', func_get_args())); } /** @@ -1857,12 +1857,12 @@ public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function canSeeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteSiteTransientInDatabase', func_get_args())); } @@ -1884,14 +1884,14 @@ public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): v * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionInDatabase', func_get_args())); } /** @@ -1912,14 +1912,14 @@ public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionInDatabase', func_get_args())); } @@ -1938,14 +1938,14 @@ public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteOptionInDatabase', func_get_args())); } /** @@ -1963,14 +1963,14 @@ public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function canSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteOptionInDatabase', func_get_args())); } @@ -2216,7 +2216,7 @@ public function haveCommentInDatabase(int $comment_post_ID, array $data = []): i * @return int The inserted comment meta ID. * @see \lucatume\WPBrowser\Module\WPDb::haveCommentMetaInDatabase() */ - public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, $meta_value): int { + public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveCommentMetaInDatabase', func_get_args())); } @@ -2481,7 +2481,7 @@ public function haveManyUsersInDatabase(int $count, string $user_login, string $ * @see WPDb::haveUserCapabilitiesInDatabase() for the roles and caps options. * @see \lucatume\WPBrowser\Module\WPDb::haveUserInDatabase() */ - public function haveUserInDatabase(string $user_login, $role = "subscriber", array $overrides = []): int { + public function haveUserInDatabase(string $user_login, array|string $role = "subscriber", array $overrides = []): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserInDatabase', func_get_args())); } @@ -2572,7 +2572,7 @@ public function grabUsersTableName(): string { * @return array|int> An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserCapabilitiesInDatabase() */ - public function haveUserCapabilitiesInDatabase(int $userId, $role): array { + public function haveUserCapabilitiesInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserCapabilitiesInDatabase', func_get_args())); } @@ -2596,7 +2596,7 @@ public function haveUserCapabilitiesInDatabase(int $userId, $role): array { * @return array An array of inserted `umeta_id`s. * @see \lucatume\WPBrowser\Module\WPDb::haveUserMetaInDatabase() */ - public function haveUserMetaInDatabase(int $userId, string $meta_key, $meta_value): array { + public function haveUserMetaInDatabase(int $userId, string $meta_key, mixed $meta_value): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserMetaInDatabase', func_get_args())); } @@ -2651,7 +2651,7 @@ public function grabUsermetaTableName(): string { * @return array An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserLevelsInDatabase() */ - public function haveUserLevelsInDatabase(int $userId, $role): array { + public function haveUserLevelsInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserLevelsInDatabase', func_get_args())); } @@ -3411,7 +3411,7 @@ public function canSeeTermRelationshipInDatabase(array $criteria): void { * readable. * @see \lucatume\WPBrowser\Module\WPDb::haveAttachmentInDatabase() */ - public function haveAttachmentInDatabase(string $file, $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { + public function haveAttachmentInDatabase(string $file, string|int $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveAttachmentInDatabase', func_get_args())); } @@ -3573,7 +3573,7 @@ public function dontHaveAttachmentInDatabase(array $criteria, bool $purgeMeta = * @throws ModuleRequireException If the `WPFilesystem` module is not loaded in the suite. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveAttachmentFilesInDatabase() */ - public function dontHaveAttachmentFilesInDatabase($attachmentIds): void { + public function dontHaveAttachmentFilesInDatabase(array|int $attachmentIds): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveAttachmentFilesInDatabase', func_get_args())); } @@ -3728,7 +3728,7 @@ public function grabTablePrefix(): string { * @param bool $purgeMeta Whether the user meta should be purged alongside the user or not. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveUserInDatabase() */ - public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): void { + public function dontHaveUserInDatabase(string|int $userIdOrLogin, bool $purgeMeta = true): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveUserInDatabase', func_get_args())); } @@ -3748,7 +3748,7 @@ public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): * @return int|false The user ID or `false` if the user was not found. * @see \lucatume\WPBrowser\Module\WPDb::grabUserIdFromDatabase() */ - public function grabUserIdFromDatabase(string $userLogin) { + public function grabUserIdFromDatabase(string $userLogin): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserIdFromDatabase', func_get_args())); } @@ -3770,7 +3770,7 @@ public function grabUserIdFromDatabase(string $userLogin) { * @return mixed|array Either a single meta value or an array of all the available meta values. * @see \lucatume\WPBrowser\Module\WPDb::grabPostMetaFromDatabase() */ - public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false) { + public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostMetaFromDatabase', func_get_args())); } @@ -4066,14 +4066,14 @@ public function importSql(array $sql): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteOptionInDatabase', func_get_args())); } /** @@ -4092,14 +4092,14 @@ public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteOptionInDatabase', func_get_args())); } @@ -4121,7 +4121,7 @@ public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * * @see \lucatume\WPBrowser\Module\WPDb::grabTransientFromDatabase() */ - public function grabTransientFromDatabase(string $transient) { + public function grabTransientFromDatabase(string $transient): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTransientFromDatabase', func_get_args())); } @@ -4144,7 +4144,7 @@ public function grabTransientFromDatabase(string $transient) { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function dontSeeTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeTransientInDatabase', func_get_args())); } /** @@ -4166,7 +4166,7 @@ public function dontSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function cantSeeTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeTransientInDatabase', func_get_args())); } @@ -4190,7 +4190,7 @@ public function cantSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function seeTransientInDatabase(string $name, $value = NULL): void { + public function seeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeTransientInDatabase', func_get_args())); } /** @@ -4213,7 +4213,7 @@ public function seeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function canSeeTransientInDatabase(string $name, $value = NULL): void { + public function canSeeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeTransientInDatabase', func_get_args())); } @@ -4228,7 +4228,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4237,7 +4237,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteTransientInDatabase', func_get_args())); } /** @@ -4251,7 +4251,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4260,7 +4260,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteTransientInDatabase', func_get_args())); } @@ -4276,7 +4276,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4284,7 +4284,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function seeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function seeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteTransientInDatabase', func_get_args())); } /** @@ -4299,7 +4299,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4307,7 +4307,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function canSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function canSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteTransientInDatabase', func_get_args())); } @@ -4695,7 +4695,7 @@ public function updateInDatabase(string $table, array $data, array $criteria = [ * * @param string|array $command The command to execute. * @param array|null $env An array of environment variables to pass to the command. - * @param mixed $input The input to pass to the command, a stream resource or a \Traversable + * @param mixed|null $input The input to pass to the command, a stream resource or a \Traversable * instance. * * @return int The command exit value; `0` usually means success. @@ -4703,7 +4703,7 @@ public function updateInDatabase(string $table, array $data, array $criteria = [ * @throws ModuleException If the command execution fails and the `throw` configuration option is set to `true`. * @see \lucatume\WPBrowser\Module\WPCLI::cli() */ - public function cli($command = ["core", "version"], ?array $env = NULL, $input = NULL): int { + public function cli(array|string $command = ["core", "version"], ?array $env = NULL, mixed $input = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('cli', func_get_args())); } @@ -4780,7 +4780,7 @@ public function grabLastShellErrorOutput(): string { * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPCLI::cliToArray() */ - public function cliToArray(array $command, ?callable $splitCallback = NULL, ?array $env = NULL, $input = NULL): array { + public function cliToArray(array $command, ?callable $splitCallback = NULL, ?array $env = NULL, mixed $input = NULL): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('cliToArray', func_get_args())); } @@ -4813,7 +4813,7 @@ public function cliToArray(array $command, ?callable $splitCallback = NULL, ?arr * @throws ModuleException * @see \lucatume\WPBrowser\Module\WPCLI::cliToString() */ - public function cliToString(array $command, ?array $env = NULL, $input = NULL): string { + public function cliToString(array $command, ?array $env = NULL, mixed $input = NULL): string { return $this->getScenario()->runStep(new \Codeception\Step\Action('cliToString', func_get_args())); } @@ -6412,9 +6412,8 @@ public function assertNull($actual, string $message = "") { * * Asserts that an object has a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() - * @param object $object */ - public function assertObjectHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); } @@ -6424,9 +6423,8 @@ public function assertObjectHasAttribute(string $attributeName, $object, string * * Asserts that an object does not have a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() - * @param object $object */ - public function assertObjectNotHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectNotHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); } diff --git a/tests/_support/_generated/WploaderTesterActions.php b/tests/_support/_generated/WploaderTesterActions.php index 9c489023a..bf0e9a02b 100644 --- a/tests/_support/_generated/WploaderTesterActions.php +++ b/tests/_support/_generated/WploaderTesterActions.php @@ -1,4 +1,4 @@ -getPluginsFolder(); * $hello = $this->getPluginsFolder('hello.php'); * ``` * + * @param string $path A relative path to append to te plugins directory absolute path. + * + * @return string The absolute path to the `pluginsFolder` path or the same with a relative path appended if `$path` + * is provided. * @see \lucatume\WPBrowser\Module\WPLoader::getPluginsFolder() */ public function getPluginsFolder(string $path = ""): string { @@ -69,16 +69,16 @@ public function getPluginsFolder(string $path = ""): string { * * Returns the absolute path to the themes directory. * - * @param string $path A relative path to append to te themes directory absolute path. - * - * @return string The absolute path to the `themesFolder` path or the same with a relative path appended if `$path` - * is provided. * @example * ```php * $themes = $this->getThemesFolder(); * $twentytwenty = $this->getThemesFolder('/twentytwenty'); * ``` * + * @param string $path A relative path to append to te themes directory absolute path. + * + * @return string The absolute path to the `themesFolder` path or the same with a relative path appended if `$path` + * is provided. * @see \lucatume\WPBrowser\Module\WPLoader::getThemesFolder() */ public function getThemesFolder(string $path = ""): string { @@ -93,15 +93,15 @@ public function getThemesFolder(string $path = ""): string { * This method gives access to the same factories provided by the * [Core test suite](https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/). * - * @return FactoryStore A factory store, proxy to get hold of the Core suite object - * factories. - * * @example * ```php * $postId = $I->factory()->post->create(); * $userId = $I->factory()->user->create(['role' => 'administrator']); * ``` * + * @return FactoryStore A factory store, proxy to get hold of the Core suite object + * factories. + * * @link https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/ * @see \lucatume\WPBrowser\Module\WPLoader::factory() */ @@ -115,9 +115,6 @@ public function factory(): \lucatume\WPBrowser\Module\WPLoader\FactoryStore { * * Returns the absolute path to the WordPress content directory. * - * @param string $path An optional path to append to the content directory absolute path. - * - * @return string The content directory absolute path, or a path in it. * @example * ```php * $content = $this->getContentFolder(); @@ -125,6 +122,9 @@ public function factory(): \lucatume\WPBrowser\Module\WPLoader\FactoryStore { * $twentytwenty = $this->getContentFolder('themes/twentytwenty'); * ``` * + * @param string $path An optional path to append to the content directory absolute path. + * + * @return string The content directory absolute path, or a path in it. * @see \lucatume\WPBrowser\Module\WPLoader::getContentFolder() */ public function getContentFolder(string $path = ""): string { diff --git a/tests/_support/_generated/Wploader_wpdb_interactionTesterActions.php b/tests/_support/_generated/Wploader_wpdb_interactionTesterActions.php index 9d2368964..4f6177233 100644 --- a/tests/_support/_generated/Wploader_wpdb_interactionTesterActions.php +++ b/tests/_support/_generated/Wploader_wpdb_interactionTesterActions.php @@ -150,7 +150,7 @@ public function getInstallation(): \lucatume\WPBrowser\WordPress\Installation { * @return int The inserted row ID. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteMetaInDatabase() */ - public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int { + public function haveSiteMetaInDatabase(int $blogId, string $string, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteMetaInDatabase', func_get_args())); } @@ -176,7 +176,7 @@ public function haveSiteMetaInDatabase(int $blogId, string $string, $value): int * @throws Exception On unserialize failure. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteMetaFromDatabase() */ - public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) { + public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteMetaFromDatabase', func_get_args())); } @@ -198,7 +198,7 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field) { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -244,14 +244,14 @@ public function importSqlDumpFile(?string $dumpFile = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionInDatabase', func_get_args())); } /** @@ -272,14 +272,14 @@ public function dontSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's an issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeOptionInDatabase() */ - public function cantSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionInDatabase', func_get_args())); } @@ -783,7 +783,7 @@ public function grabLatestEntryByFromDatabase(string $tableName, string $idColum * @return int The inserted meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::havePostmetaInDatabase() */ - public function havePostmetaInDatabase(int $postId, string $meta_key, $meta_value): int { + public function havePostmetaInDatabase(int $postId, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('havePostmetaInDatabase', func_get_args())); } @@ -831,7 +831,7 @@ public function grabPostmetaTableName(): string { * @return int|false The matching term `term_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermIdFromDatabase() */ - public function grabTermIdFromDatabase(array $criteria) { + public function grabTermIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermIdFromDatabase', func_get_args())); } @@ -935,7 +935,7 @@ public function grabTermTaxonomyTableName(): string { * @return int The inserted term meta `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTermMetaInDatabase() */ - public function haveTermMetaInDatabase(int $term_id, string $meta_key, $meta_value): int { + public function haveTermMetaInDatabase(int $term_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTermMetaInDatabase', func_get_args())); } @@ -982,7 +982,7 @@ public function grabTermMetaTableName(): string { * @return int|false The matching term `term_taxonomy_id` or `false` if not found. * @see \lucatume\WPBrowser\Module\WPDb::grabTermTaxonomyIdFromDatabase() */ - public function grabTermTaxonomyIdFromDatabase(array $criteria) { + public function grabTermTaxonomyIdFromDatabase(array $criteria): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTermTaxonomyIdFromDatabase', func_get_args())); } @@ -1601,7 +1601,7 @@ public function dontHaveUserMetaInDatabase(array $criteria): void { * @throws Exception If the search criteria is incoherent. * @see \lucatume\WPBrowser\Module\WPDb::grabUserMetaFromDatabase() */ - public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false) { + public function grabUserMetaFromDatabase(int $userId, string $meta_key, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserMetaFromDatabase', func_get_args())); } @@ -1652,7 +1652,7 @@ public function grabAllFromDatabase(string $table, string $column, array $criter * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveTransientInDatabase() */ - public function haveTransientInDatabase(string $transient, $value): int { + public function haveTransientInDatabase(string $transient, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveTransientInDatabase', func_get_args())); } @@ -1677,7 +1677,7 @@ public function haveTransientInDatabase(string $transient, $value): int { * @return int The inserted option `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveOptionInDatabase() */ - public function haveOptionInDatabase(string $option_name, $option_value, string $autoload = "yes"): int { + public function haveOptionInDatabase(string $option_name, mixed $option_value, string $autoload = "yes"): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveOptionInDatabase', func_get_args())); } @@ -1715,10 +1715,10 @@ public function dontHaveTransientInDatabase(string $transient): void { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed if its value matches the passed one. + * @param mixed|null $value If set the option will only be removed if its value matches the passed one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveOptionInDatabase() */ - public function dontHaveOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveOptionInDatabase', func_get_args())); } @@ -1741,7 +1741,7 @@ public function dontHaveOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted option `option_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveSiteOptionInDatabase() */ - public function haveSiteOptionInDatabase(string $key, $value): int { + public function haveSiteOptionInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteOptionInDatabase', func_get_args())); } @@ -1828,10 +1828,10 @@ public function grabBlogUrl(int $blogId = 1): string { * ``` * * @param string $key The option name. - * @param mixed $value If set the option will only be removed it its value matches the specified one. + * @param mixed|null $value If set the option will only be removed it its value matches the specified one. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveSiteOptionInDatabase() */ - public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { + public function dontHaveSiteOptionInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveSiteOptionInDatabase', func_get_args())); } @@ -1855,7 +1855,7 @@ public function dontHaveSiteOptionInDatabase(string $key, $value = NULL): void { * @return int The inserted transient `option_id` * @see \lucatume\WPBrowser\Module\WPDb::haveSiteTransientInDatabase() */ - public function haveSiteTransientInDatabase(string $key, $value): int { + public function haveSiteTransientInDatabase(string $key, mixed $value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveSiteTransientInDatabase', func_get_args())); } @@ -1893,7 +1893,7 @@ public function dontHaveSiteTransientInDatabase(string $key): void { * @return mixed The value of the option stored in the database, unserialized if serialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteOptionFromDatabase() */ - public function grabSiteOptionFromDatabase(string $key) { + public function grabSiteOptionFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteOptionFromDatabase', func_get_args())); } @@ -1913,7 +1913,7 @@ public function grabSiteOptionFromDatabase(string $key) { * @return mixed The option value. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabOptionFromDatabase() */ - public function grabOptionFromDatabase(string $option_name) { + public function grabOptionFromDatabase(string $option_name): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabOptionFromDatabase', func_get_args())); } @@ -1934,7 +1934,7 @@ public function grabOptionFromDatabase(string $option_name) { * @return mixed The value of the site transient. If the value is serialized it will be unserialized. * @see \lucatume\WPBrowser\Module\WPDb::grabSiteTransientFromDatabase() */ - public function grabSiteTransientFromDatabase(string $key) { + public function grabSiteTransientFromDatabase(string $key): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabSiteTransientFromDatabase', func_get_args())); } @@ -1953,12 +1953,12 @@ public function grabSiteTransientFromDatabase(string $key) { * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function seeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteSiteTransientInDatabase', func_get_args())); } /** @@ -1976,12 +1976,12 @@ public function seeSiteSiteTransientInDatabase(string $key, $value = NULL): void * ``` * * @param string $key The name of the transient to check for, w/o the `_site_transient_` prefix. - * @param mixed $value If provided then the assertion will include the value. + * @param mixed|null $value If provided then the assertion will include the value. * * @throws JsonException * @see \lucatume\WPBrowser\Module\WPDb::seeSiteSiteTransientInDatabase() */ - public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): void { + public function canSeeSiteSiteTransientInDatabase(string $key, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteSiteTransientInDatabase', func_get_args())); } @@ -2003,14 +2003,14 @@ public function canSeeSiteSiteTransientInDatabase(string $key, $value = NULL): v * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionInDatabase', func_get_args())); } /** @@ -2031,14 +2031,14 @@ public function seeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeOptionInDatabase() */ - public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionInDatabase', func_get_args())); } @@ -2057,14 +2057,14 @@ public function canSeeOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function seeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteOptionInDatabase', func_get_args())); } /** @@ -2082,14 +2082,14 @@ public function seeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the failure. * @see \lucatume\WPBrowser\Module\WPDb::seeSiteOptionInDatabase() */ - public function canSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function canSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteOptionInDatabase', func_get_args())); } @@ -2335,7 +2335,7 @@ public function haveCommentInDatabase(int $comment_post_ID, array $data = []): i * @return int The inserted comment meta ID. * @see \lucatume\WPBrowser\Module\WPDb::haveCommentMetaInDatabase() */ - public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, $meta_value): int { + public function haveCommentMetaInDatabase(int $comment_id, string $meta_key, mixed $meta_value): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveCommentMetaInDatabase', func_get_args())); } @@ -2600,7 +2600,7 @@ public function haveManyUsersInDatabase(int $count, string $user_login, string $ * @see WPDb::haveUserCapabilitiesInDatabase() for the roles and caps options. * @see \lucatume\WPBrowser\Module\WPDb::haveUserInDatabase() */ - public function haveUserInDatabase(string $user_login, $role = "subscriber", array $overrides = []): int { + public function haveUserInDatabase(string $user_login, array|string $role = "subscriber", array $overrides = []): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserInDatabase', func_get_args())); } @@ -2691,7 +2691,7 @@ public function grabUsersTableName(): string { * @return array|int> An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserCapabilitiesInDatabase() */ - public function haveUserCapabilitiesInDatabase(int $userId, $role): array { + public function haveUserCapabilitiesInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserCapabilitiesInDatabase', func_get_args())); } @@ -2715,7 +2715,7 @@ public function haveUserCapabilitiesInDatabase(int $userId, $role): array { * @return array An array of inserted `umeta_id`s. * @see \lucatume\WPBrowser\Module\WPDb::haveUserMetaInDatabase() */ - public function haveUserMetaInDatabase(int $userId, string $meta_key, $meta_value): array { + public function haveUserMetaInDatabase(int $userId, string $meta_key, mixed $meta_value): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserMetaInDatabase', func_get_args())); } @@ -2770,7 +2770,7 @@ public function grabUsermetaTableName(): string { * @return array An array of inserted `meta_id`. * @see \lucatume\WPBrowser\Module\WPDb::haveUserLevelsInDatabase() */ - public function haveUserLevelsInDatabase(int $userId, $role): array { + public function haveUserLevelsInDatabase(int $userId, array|string $role): array { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveUserLevelsInDatabase', func_get_args())); } @@ -3530,7 +3530,7 @@ public function canSeeTermRelationshipInDatabase(array $criteria): void { * readable. * @see \lucatume\WPBrowser\Module\WPDb::haveAttachmentInDatabase() */ - public function haveAttachmentInDatabase(string $file, $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { + public function haveAttachmentInDatabase(string $file, string|int $date = "now", array $overrides = [], ?array $imageSizes = NULL): int { return $this->getScenario()->runStep(new \Codeception\Step\Action('haveAttachmentInDatabase', func_get_args())); } @@ -3692,7 +3692,7 @@ public function dontHaveAttachmentInDatabase(array $criteria, bool $purgeMeta = * @throws ModuleRequireException If the `WPFilesystem` module is not loaded in the suite. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveAttachmentFilesInDatabase() */ - public function dontHaveAttachmentFilesInDatabase($attachmentIds): void { + public function dontHaveAttachmentFilesInDatabase(array|int $attachmentIds): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveAttachmentFilesInDatabase', func_get_args())); } @@ -3847,7 +3847,7 @@ public function grabTablePrefix(): string { * @param bool $purgeMeta Whether the user meta should be purged alongside the user or not. * @see \lucatume\WPBrowser\Module\WPDb::dontHaveUserInDatabase() */ - public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): void { + public function dontHaveUserInDatabase(string|int $userIdOrLogin, bool $purgeMeta = true): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontHaveUserInDatabase', func_get_args())); } @@ -3867,7 +3867,7 @@ public function dontHaveUserInDatabase($userIdOrLogin, bool $purgeMeta = true): * @return int|false The user ID or `false` if the user was not found. * @see \lucatume\WPBrowser\Module\WPDb::grabUserIdFromDatabase() */ - public function grabUserIdFromDatabase(string $userLogin) { + public function grabUserIdFromDatabase(string $userLogin): int|false { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabUserIdFromDatabase', func_get_args())); } @@ -3889,7 +3889,7 @@ public function grabUserIdFromDatabase(string $userLogin) { * @return mixed|array Either a single meta value or an array of all the available meta values. * @see \lucatume\WPBrowser\Module\WPDb::grabPostMetaFromDatabase() */ - public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false) { + public function grabPostMetaFromDatabase(int $postId, string $metaKey, bool $single = false): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostMetaFromDatabase', func_get_args())); } @@ -4185,14 +4185,14 @@ public function importSql(array $sql): void { * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function dontSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteOptionInDatabase', func_get_args())); } /** @@ -4211,14 +4211,14 @@ public function dontSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * ``` * * @param array|string $criteriaOrName An array of search criteria or the option name. - * @param mixed $value The optional value to try and match, only used if the option + * @param mixed|null $value The optional value to try and match, only used if the option * name is provided. * * * @throws JsonException If there's any issue debugging the query. * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteOptionInDatabase() */ - public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): void { + public function cantSeeSiteOptionInDatabase(array|string $criteriaOrName, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteOptionInDatabase', func_get_args())); } @@ -4240,7 +4240,7 @@ public function cantSeeSiteOptionInDatabase($criteriaOrName, $value = NULL): voi * * @see \lucatume\WPBrowser\Module\WPDb::grabTransientFromDatabase() */ - public function grabTransientFromDatabase(string $transient) { + public function grabTransientFromDatabase(string $transient): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTransientFromDatabase', func_get_args())); } @@ -4263,7 +4263,7 @@ public function grabTransientFromDatabase(string $transient) { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function dontSeeTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeTransientInDatabase', func_get_args())); } /** @@ -4285,7 +4285,7 @@ public function dontSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeTransientInDatabase() */ - public function cantSeeTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeTransientInDatabase', func_get_args())); } @@ -4309,7 +4309,7 @@ public function cantSeeTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function seeTransientInDatabase(string $name, $value = NULL): void { + public function seeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeTransientInDatabase', func_get_args())); } /** @@ -4332,7 +4332,7 @@ public function seeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::seeTransientInDatabase() */ - public function canSeeTransientInDatabase(string $name, $value = NULL): void { + public function canSeeTransientInDatabase(string $name, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeTransientInDatabase', func_get_args())); } @@ -4347,7 +4347,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4356,7 +4356,7 @@ public function canSeeTransientInDatabase(string $name, $value = NULL): void { * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function dontSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeSiteTransientInDatabase', func_get_args())); } /** @@ -4370,7 +4370,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->dontSeeSiteTransientInDatabase('foo'); * $I->dontSeeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4379,7 +4379,7 @@ public function dontSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::dontSeeSiteTransientInDatabase() */ - public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function cantSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeSiteTransientInDatabase', func_get_args())); } @@ -4395,7 +4395,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4403,7 +4403,7 @@ public function cantSeeSiteTransientInDatabase(string $transient, $value = NULL) * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function seeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function seeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeSiteTransientInDatabase', func_get_args())); } /** @@ -4418,7 +4418,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * $I->seeSiteTransientInDatabase('foo'); * $I->seeSiteTransientInDatabase('foo', 23); * ``` - * @param mixed $value The optional value to try and match. + * @param mixed|null $value The optional value to try and match. * * @param string $transient The transient name. * @return void @@ -4426,7 +4426,7 @@ public function seeSiteTransientInDatabase(string $transient, $value = NULL): vo * * @see \lucatume\WPBrowser\Module\WPDb::seeSiteTransientInDatabase() */ - public function canSeeSiteTransientInDatabase(string $transient, $value = NULL): void { + public function canSeeSiteTransientInDatabase(string $transient, mixed $value = NULL): void { $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeSiteTransientInDatabase', func_get_args())); } @@ -6108,9 +6108,8 @@ public function assertNull($actual, string $message = "") { * * Asserts that an object has a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() - * @param object $object */ - public function assertObjectHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); } @@ -6120,9 +6119,8 @@ public function assertObjectHasAttribute(string $attributeName, $object, string * * Asserts that an object does not have a specified attribute. * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() - * @param object $object */ - public function assertObjectNotHasAttribute(string $attributeName, $object, string $message = "") { + public function assertObjectNotHasAttribute(string $attributeName, object $object, string $message = "") { return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); } diff --git a/tests/climodule/BasicOperationsCest.php b/tests/climodule/BasicOperationsCest.php index 18b714b20..d291f1459 100644 --- a/tests/climodule/BasicOperationsCest.php +++ b/tests/climodule/BasicOperationsCest.php @@ -8,10 +8,7 @@ class BasicOperationsCest { - /** - * @var mixed[] - */ - private $tmpCleanup = []; + private array $tmpCleanup = []; public function _after(): void { diff --git a/tests/unit/Codeception/Template/WpbrowserTest.php b/tests/unit/Codeception/Template/WpbrowserTest.php index 97ea97389..9235e1109 100644 --- a/tests/unit/Codeception/Template/WpbrowserTest.php +++ b/tests/unit/Codeception/Template/WpbrowserTest.php @@ -41,7 +41,7 @@ private function mockComposerBin(string $directory): void private function replaceRandomPorts(array $expected, array $actual, string $file): array { - if (substr_compare($file, 'tests/.env', -strlen('tests/.env')) !== 0) { + if (!str_ends_with($file, 'tests/.env')) { return [$expected, $actual]; } @@ -122,9 +122,7 @@ public function should_scaffold_for_plugin_with_plugin_php_file(): void // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/plugin_89', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -189,9 +187,7 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file(): void // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/plugin_89', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -249,9 +245,7 @@ public function should_scaffold_for_plugin_with_plugin_php_file_custom(): void // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/plugin_89', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -308,9 +302,7 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file_custom(): vo // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/plugin_89', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -375,9 +367,7 @@ public function should_scaffold_for_theme_correctly(): void // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/theme_23', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -399,13 +389,12 @@ public function should_scaffold_for_child_theme_correctly(): void $projectDir = FS::tmpDir('setup_', [ 'theme_23' => [ - 'style.css' => << <<< EOT /* Theme Name: Theme 23 Template: twentytwenty */ -EOT -, +EOT, 'composer.json' => $composerFileCode, 'vendor' => [ 'bin' => [ @@ -448,9 +437,7 @@ public function should_scaffold_for_child_theme_correctly(): void // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/theme_23', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -472,12 +459,11 @@ public function should_scaffold_for_theme_custom_correctly(): void $projectDir = FS::tmpDir('setup_', [ 'theme_23' => [ - 'style.css' => << <<< EOT /* Theme Name: Theme 23 */ -EOT -, +EOT, 'composer.json' => $composerFileCode, 'vendor' => [ 'bin' => [ @@ -514,9 +500,7 @@ public function should_scaffold_for_theme_custom_correctly(): void // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/theme_23', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } @@ -551,7 +535,14 @@ public function should_scaffold_for_single_site_correctly(): void $dbPassword = Env::get('WORDPRESS_DB_PASSWORD'); $db = new MysqlDatabase($dbName, $dbUser, $dbPassword, $dbHost, 'test_'); Installation::scaffold($projectDir . '/site') - ->configure($db)->install('https://the-project.local', 'admin', 'secret', 'admin@the-project.local', 'The Project'); + ->configure($db) + ->install( + 'https://the-project.local', + 'admin', + 'secret', + 'admin@the-project.local', + 'The Project', + ); $this->mockComposerBin($projectDir . '/site'); @@ -625,7 +616,14 @@ public function should_scaffold_for_multi_site_correctly(): void $dbPassword = Env::get('WORDPRESS_DB_PASSWORD'); $db = new MysqlDatabase($dbName, $dbUser, $dbPassword, $dbHost, 'test_'); Installation::scaffold($projectDir . '/site') - ->configure($db, InstallationStateInterface::MULTISITE_SUBDOMAIN)->install('https://the-project.local', 'admin', 'secret', 'admin@the-project.local', 'The Project'); + ->configure($db, InstallationStateInterface::MULTISITE_SUBDOMAIN) + ->install( + 'https://the-project.local', + 'admin', + 'secret', + 'admin@the-project.local', + 'The Project', + ); $this->mockComposerBin($projectDir . '/site'); @@ -710,9 +708,7 @@ public function should_scaffold_correctly_on_site_with_non_default_structure(): // Random ports will change: visit the data to replace the random ports with a placeholder. $this->assertMatchesDirectorySnapshot( $projectDir . '/tests', - function () { - return $this->replaceRandomPorts(...func_get_args()); - } + fn() => $this->replaceRandomPorts(...func_get_args()) ); } } diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_child_theme_correctly__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_child_theme_correctly__0.snapshot index 60a5492fc..609f26756 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_child_theme_correctly__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_child_theme_correctly__0.snapshot @@ -314,6 +314,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear - lucatume\WPBrowser\Command\DevStart - lucatume\WPBrowser\Command\DevStop - lucatume\WPBrowser\Command\DevInfo diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__0.snapshot.txt b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__0.snapshot.txt index 50b6051f1..39a0c43b7 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__0.snapshot.txt +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__0.snapshot.txt @@ -32,6 +32,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear - lucatume\WPBrowser\Command\DevStart - lucatume\WPBrowser\Command\DevStop - lucatume\WPBrowser\Command\DevInfo diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file__0.snapshot index 59ccd8e85..9a6067d55 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file__0.snapshot @@ -322,6 +322,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear - lucatume\WPBrowser\Command\DevStart - lucatume\WPBrowser\Command\DevStop - lucatume\WPBrowser\Command\DevInfo diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file_custom__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file_custom__0.snapshot index 09562cdd2..67cbbad11 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file_custom__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_non_plugin_php_file_custom__0.snapshot @@ -242,6 +242,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear <<< /codeception.yml <<< diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file__0.snapshot index 0c39dbd48..7aa3fe7ba 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file__0.snapshot @@ -327,6 +327,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear - lucatume\WPBrowser\Command\DevStart - lucatume\WPBrowser\Command\DevStop - lucatume\WPBrowser\Command\DevInfo diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file_custom__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file_custom__0.snapshot index 96c42e650..a155e1b89 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file_custom__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_plugin_with_plugin_php_file_custom__0.snapshot @@ -242,6 +242,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear <<< /codeception.yml <<< diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__0.snapshot.txt b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__0.snapshot.txt index 50b6051f1..39a0c43b7 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__0.snapshot.txt +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__0.snapshot.txt @@ -32,6 +32,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear - lucatume\WPBrowser\Command\DevStart - lucatume\WPBrowser\Command\DevStop - lucatume\WPBrowser\Command\DevInfo diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_correctly__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_correctly__0.snapshot index f5533da6c..d1dbc2fef 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_correctly__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_correctly__0.snapshot @@ -314,6 +314,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear - lucatume\WPBrowser\Command\DevStart - lucatume\WPBrowser\Command\DevStop - lucatume\WPBrowser\Command\DevInfo diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_custom_correctly__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_custom_correctly__0.snapshot index cd4dd2356..328b5421a 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_custom_correctly__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_theme_custom_correctly__0.snapshot @@ -244,6 +244,8 @@ extensions: - lucatume\WPBrowser\Command\GenerateWPUnit - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\MonkeyCacheClear <<< /codeception.yml <<< diff --git a/tests/unit/UnitTester.php b/tests/unit/UnitTester.php index d1df8f594..6cab03698 100644 --- a/tests/unit/UnitTester.php +++ b/tests/unit/UnitTester.php @@ -35,7 +35,7 @@ class UnitTester extends Actor * @return mixed * @see \Codeception\Module\Asserts::assertEquals() */ - public function assertEquals($expected, $actual, $message = null) + public function assertEquals($expected, $actual, $message = null): mixed { return $this->scenario->runStep(new Action('assertEquals', func_get_args())); } diff --git a/tests/unit/lucatume/WPBrowser/Command/DevInfoTest.php b/tests/unit/lucatume/WPBrowser/Command/DevInfoTest.php index 6fce4e81b..f59ad8da6 100644 --- a/tests/unit/lucatume/WPBrowser/Command/DevInfoTest.php +++ b/tests/unit/lucatume/WPBrowser/Command/DevInfoTest.php @@ -53,9 +53,7 @@ public function should_print_information_about_each_service_extension_found_in_c '__construct' => function () use (&$builtInServerControllerBuildArgs) { $builtInServerControllerBuildArgs = func_get_args(); }, - 'getPrettyName' => function () { - return 'BuiltInServer'; - }, + 'getPrettyName' => fn() => 'BuiltInServer', 'getInfo' => function () { return [ 'name' => 'BuiltInServerController', @@ -71,9 +69,7 @@ public function should_print_information_about_each_service_extension_found_in_c '__construct' => function () use (&$dockerComposeControllerBuildArgs) { $dockerComposeControllerBuildArgs = func_get_args(); }, - 'getPrettyName' => function () { - return 'DockerCompose'; - }, + 'getPrettyName' => fn() => 'DockerCompose', 'getInfo' => function () { return [ 'name' => 'DockerComposeController', @@ -89,9 +85,7 @@ public function should_print_information_about_each_service_extension_found_in_c '__construct' => function () use (&$chromeDriverControllerBuildArgs) { $chromeDriverControllerBuildArgs = func_get_args(); }, - 'getPrettyName' => function () { - return 'ChromeDriver'; - }, + 'getPrettyName' => fn() => 'ChromeDriver', 'getInfo' => function () { return [ 'name' => 'ChromeDriverController', diff --git a/tests/unit/lucatume/WPBrowser/Command/MonkeyCacheClearTest.php b/tests/unit/lucatume/WPBrowser/Command/MonkeyCacheClearTest.php new file mode 100644 index 000000000..645ceb4c1 --- /dev/null +++ b/tests/unit/lucatume/WPBrowser/Command/MonkeyCacheClearTest.php @@ -0,0 +1,65 @@ +assertDirectoryExists(MonkeyPatch::getCachePath()); + touch(MonkeyPatch::getCachePath() . '/some-file.txt'); + $this->assertFileExists(MonkeyPatch::getCachePath() . '/some-file.txt'); + mkdir(MonkeyPatch::getCachePath() . '/some-dir'); + touch(MonkeyPatch::getCachePath() . '/some-dir/some-file.txt'); + $this->assertFileExists(MonkeyPatch::getCachePath() . '/some-dir/some-file.txt'); + + $command = new MonkeyCacheClear(); + $command->execute($input, $output); + + $this->assertDirectoryExists(MonkeyPatch::getCachePath()); + $this->assertCount(0, (array)glob(MonkeyPatch::getCachePath() . '/*')); + $this->assertDirectoryDoesNotExist(MonkeyPatch::getCachePath() . '/some-dir'); + $this->assertEquals("Monkey patch cache cleared.\n", $output->fetch()); + } + + /** + * It should correctly clean cache with porcelain output + * + * @test + */ + public function should_correctly_clean_cache_with_porcelain_output(): void + { + $input = new StringInput('--porcelain'); + $output = new BufferedOutput(); + + $this->assertDirectoryExists(MonkeyPatch::getCachePath()); + touch(MonkeyPatch::getCachePath() . '/some-file.txt'); + $this->assertFileExists(MonkeyPatch::getCachePath() . '/some-file.txt'); + mkdir(MonkeyPatch::getCachePath() . '/some-dir'); + touch(MonkeyPatch::getCachePath() . '/some-dir/some-file.txt'); + $this->assertFileExists(MonkeyPatch::getCachePath() . '/some-dir/some-file.txt'); + + $command = new MonkeyCacheClear(); + $input->bind($command->getDefinition()); + $command->execute($input, $output); + + $this->assertDirectoryExists(MonkeyPatch::getCachePath()); + $this->assertCount(0, (array)glob(MonkeyPatch::getCachePath() . '/*')); + $this->assertDirectoryDoesNotExist(MonkeyPatch::getCachePath() . '/some-dir'); + $this->assertEquals('', $output->fetch()); + } +} diff --git a/tests/unit/lucatume/WPBrowser/Command/MonkeyCachePathTest.php b/tests/unit/lucatume/WPBrowser/Command/MonkeyCachePathTest.php new file mode 100644 index 000000000..b5bb104a0 --- /dev/null +++ b/tests/unit/lucatume/WPBrowser/Command/MonkeyCachePathTest.php @@ -0,0 +1,55 @@ +bind($command->getDefinition()); + $exitCode = $command->execute($input, $output); + + $this->assertEquals(0, $exitCode); + $this->assertEquals(MonkeyPatch::getCachePath() . "\n", $output->fetch()); + + $command = new MonkeyCachePath(); + $input = new StringInput('--porcelain'); + $input->bind($command->getDefinition()); + $exitCode = $command->execute($input, $output); + + $this->assertEquals(0, $exitCode); + $this->assertEquals(MonkeyPatch::getCachePath() . "\n", $output->fetch()); + } + + /** + * It should provide pretty output correctly + * + * @test + */ + public function should_provide_pretty_output_correctly(): void + { + $input = new StringInput(''); + $output = new BufferedOutput(); + + $command = new MonkeyCachePath(); + $exitCode = $command->execute($input, $output); + + $this->assertEquals(0, $exitCode); + $this->assertEquals('Monkey patch cache path: ' . MonkeyPatch::getCachePath() . "\n", $output->fetch()); + } +} diff --git a/tests/unit/lucatume/WPBrowser/Command/RunAllTest.php b/tests/unit/lucatume/WPBrowser/Command/RunAllTest.php index e889f0ec3..419b4175d 100644 --- a/tests/unit/lucatume/WPBrowser/Command/RunAllTest.php +++ b/tests/unit/lucatume/WPBrowser/Command/RunAllTest.php @@ -46,12 +46,8 @@ public function should_invoke_codecept_bin_once_for_each_suite(): void ]; Assert::assertEquals($expectedCommand, $command); }, - 'getIterator' => function () { - return yield from ["Running suite\n", "Done\n"]; - }, - 'isSuccessful' => function () { - return true; - }, + 'getIterator' => fn() => yield from ["Running suite\n", "Done\n"], + 'isSuccessful' => fn() => true, ]; $this->uopzSetMock(Process::class, $this->makeEmptyClass(Process::class, $mockParams)); $this->uopzSetStaticMethodReturn(Configuration::class, 'suites', ['suite-1', 'suite-2', 'suite-3']); @@ -83,9 +79,7 @@ public function should_return_1_if_any_suite_fails(int $failingSuite, string $ex { $currentSuite = 1; $mockParams = [ - 'getIterator' => function () { - return yield from ['.', '.', '.']; - }, + 'getIterator' => fn() => yield from ['.', '.', '.'], // Fail on the 2nd call. 'isSuccessful' => function () use ($failingSuite, &$currentSuite) { return $currentSuite++ !== $failingSuite; @@ -111,9 +105,7 @@ public function should_return_1_if_failing_to_build_process(): void { $this->uopzSetMock(Process::class, $this->makeEmptyClass(Process::class, [ - '__construct' => function () { - throw new Exception('Failed to build process.'); - } + '__construct' => fn() => throw new Exception('Failed to build process.') ])); $this->uopzSetStaticMethodReturn(Configuration::class, 'suites', ['suite-1', 'suite-2', 'suite-3']); diff --git a/tests/unit/lucatume/WPBrowser/Events/DispatcherTest.php b/tests/unit/lucatume/WPBrowser/Events/DispatcherTest.php index 909a94728..05af2c6a9 100644 --- a/tests/unit/lucatume/WPBrowser/Events/DispatcherTest.php +++ b/tests/unit/lucatume/WPBrowser/Events/DispatcherTest.php @@ -13,10 +13,7 @@ class DispatcherTest extends Unit { use UopzFunctions; - /** - * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface - */ - private $backupGlobalDispatcher; + private \Symfony\Component\EventDispatcher\EventDispatcherInterface $backupGlobalDispatcher; public function _before(): void { @@ -94,7 +91,7 @@ function should_return_a_purposely_built_dispatcher_when_the_codeception_instanc Dispatcher::setEventDispatcher(); - $this->assertInstanceOf(\Symfony\Component\EventDispatcher\EventDispatcherInterface::class, Dispatcher::getEventDispatcher()); + $this->assertInstanceOf(EventDispatcherInterface::class, Dispatcher::getEventDispatcher()); $this->assertNotSame($previousDispatcher, Dispatcher::getEventDispatcher()); $callStack = []; diff --git a/tests/unit/lucatume/WPBrowser/Events/Module/WPLoader/FiltersTest.php b/tests/unit/lucatume/WPBrowser/Events/Module/WPLoader/FiltersTest.php new file mode 100644 index 000000000..06fc0170d --- /dev/null +++ b/tests/unit/lucatume/WPBrowser/Events/Module/WPLoader/FiltersTest.php @@ -0,0 +1,200 @@ + [ + [ 'some-filter', 'some_callback', 23 ], + [ 'some-other-filter', 'some_callback' ], + [ 'some-filter', 'some_callback' ], + ] + ]); + + $removed = []; + $sut->removeWith(function ($tag, $callback, $priority) use (&$removed) { + $removed[] = [ $tag, $callback, $priority ]; + + return true; + }); + + $sut->toRemove()->remove(); + + $this->assertEquals([ + [ 'some-filter', 'some_callback', 23 ], + [ 'some-other-filter', 'some_callback', 10 ], + [ 'some-filter', 'some_callback', 10 ], + ], $removed); + } + + /** + * It should allow readding removed filters + * + * @test + */ + public function should_allow_readding_removed_filters() + { + $sut = new Filters([ + 'remove' => [ + [ 'some-filter', 'some_callback', 23 ], + [ 'some-other-filter', 'some_callback', 10, 2 ], + [ 'some-filter', 'some_callback' ], + ] + ]); + + $added = []; + $sut->removeWith(function ($tag, $callback, $priority) { + }); + $sut->addWith(function ($tag, $callback, $priority, $acceptedArgs) use (&$added) { + $added[] = [ $tag, $callback, $priority, $acceptedArgs ]; + }); + + $sut->toRemove()->add(); + + $this->assertEquals([ + [ 'some-filter', 'some_callback', 23, 1 ], + [ 'some-other-filter', 'some_callback', 10, 2 ], + [ 'some-filter', 'some_callback', 10, 1 ], + ], $added); + } + + /** + * It should allow setting filters to add + * + * @test + */ + public function should_allow_setting_filters_to_add() + { + $sut = new Filters([ + 'add' => [ + [ 'some-filter', 'some_callback', 23 ], + [ 'some-other-filter', 'some_callback' ], + [ 'some-filter', 'some_callback', 12, 3 ], + ] + ]); + + $added = []; + $sut->addWith(function ($tag, $callback, $priority, $acceptedArgs) use (&$added) { + $added[] = [ $tag, $callback, $priority, $acceptedArgs ]; + + return true; + }); + + $sut->toAdd()->add(); + + $this->assertEquals([ + [ 'some-filter', 'some_callback', 23, 1 ], + [ 'some-other-filter', 'some_callback', 10, 1 ], + [ 'some-filter', 'some_callback', 12, 3 ], + ], $added); + } + + /** + * It should allow removing added filters + * + * @test + */ + public function should_allow_removing_added_filters() + { + $sut = new Filters([ + 'add' => [ + [ 'some-filter', 'some_callback', 23 ], + [ 'some-other-filter', 'some_callback' ], + [ 'some-filter', 'some_callback', 12, 3 ], + ] + ]); + + $removed = []; + $sut->addWith(function () { + }); + $sut->removeWith(function ($tag, $callback, $priority) use (&$removed) { + $removed[] = [ $tag, $callback, $priority ]; + }); + + $sut->toAdd()->remove(); + + $this->assertEquals([ + [ 'some-filter', 'some_callback', 23 ], + [ 'some-other-filter', 'some_callback', 10 ], + [ 'some-filter', 'some_callback', 12 ], + ], $removed); + } + + /** + * It should allow formatting the filters + * + * @test + */ + public function should_allow_formatting_the_filters() + { + $formatted = Filters::format([ + 'foo' => 'bar', + 'add' => [ + [ 'one', 'foo', 11 ], + [ 'one', 'bar' ], + [ 'two', 'foo', 23, 2 ], + ], + 'remove' => [ + [ 'one', 'foo', 11 ], + [ 'one', 'bar' ], + [ 'two', 'foo', 23, 2 ], + ] + ]); + + $this->assertEquals([ + 'remove' => [ + [ 'one', 'foo', 11, 1 ], + [ 'one', 'bar', 10, 1 ], + [ 'two', 'foo', 23, 2 ], + ], + 'add' => [ + [ 'one', 'foo', 11, 1 ], + [ 'one', 'bar', 10, 1 ], + [ 'two', 'foo', 23, 2 ], + ] + ], $formatted); + } + + public function badFilters(): array + { + return [ + [ [ 'foo', new stdClass() ] ], + [ [ new stdClass(), 'foo' ] ], + [ [ '', new stdClass() ] ], + [ [ '', '' ] ], + [ [ '' ] ], + [ [] ], + [ [ 'foo', [ 'bar' ] ] ], + [ [ 'foo', [ 'bar', new stdClass() ] ] ], + [ [ 'foo', [ new stdClass(), 'bar' ] ] ], + [ [ 'foo', 'bar', 10, 12, 23 ] ], + ]; + } + + /** + * It should throw if filters information is not correct + * + * @test + * + * @dataProvider badFilters + */ + public function should_throw_if_filters_information_is_not_correct(array $filters) + { + $this->expectException(ModuleException::class); + new Filters([ + 'remove' => [ $filters ] + ]); + } +} diff --git a/tests/unit/lucatume/WPBrowser/Events/Module/WPLoaderTest.php b/tests/unit/lucatume/WPBrowser/Events/Module/WPLoaderTest.php index 090902dfb..47cc6d073 100644 --- a/tests/unit/lucatume/WPBrowser/Events/Module/WPLoaderTest.php +++ b/tests/unit/lucatume/WPBrowser/Events/Module/WPLoaderTest.php @@ -197,8 +197,8 @@ public function should_allow_specifying_the_wp_root_folder_as_a_relative_path_to $this->assertInIsolation(static function () use ($rootDir, $wpLoader1) { chdir($rootDir); $wpLoader1->_initialize(); - Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader1->_getConfig('wpRootFolder')); - Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader1->getWpRootFolder()); + Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader1->_getConfig('wpRootFolder')); + Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader1->getWpRootFolder()); }, $rootDir); $this->config = [ @@ -214,8 +214,8 @@ public function should_allow_specifying_the_wp_root_folder_as_a_relative_path_to $this->assertInIsolation(static function () use ($rootDir, $wpLoader2) { chdir($rootDir); $wpLoader2->_initialize(); - Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader2->_getConfig('wpRootFolder')); - Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader2->getWpRootFolder()); + Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader2->_getConfig('wpRootFolder')); + Assert::assertEquals($rootDir . '/test/wordpress/', $wpLoader2->getWpRootFolder()); }, $rootDir); } @@ -244,8 +244,8 @@ public function should_allow_specifying_the_wp_root_folder_including_the_home_sy $_SERVER['HOME'] = $homeDir; $wpLoader->_initialize(); - Assert::assertEquals($homeDir . '/projects/work/acme/wordpress/', $wpLoader->_getConfig('wpRootFolder')); - Assert::assertEquals($homeDir . '/projects/work/acme/wordpress/', $wpLoader->getWpRootFolder()); + Assert::assertEquals($homeDir . '/projects/work/acme/wordpress/', $wpLoader->_getConfig('wpRootFolder')); + Assert::assertEquals($homeDir . '/projects/work/acme/wordpress/', $wpLoader->getWpRootFolder()); }); } @@ -271,8 +271,8 @@ public function should_allow_specifying_the_wp_root_folder_as_an_absolute_path() $this->assertInIsolation(static function () use ($wpRootDir, $wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals($wpRootDir . '/', $wpLoader->_getConfig('wpRootFolder')); - Assert::assertEquals($wpRootDir . '/', $wpLoader->getWpRootFolder()); + Assert::assertEquals($wpRootDir . '/', $wpLoader->_getConfig('wpRootFolder')); + Assert::assertEquals($wpRootDir . '/', $wpLoader->getWpRootFolder()); }); } @@ -298,8 +298,8 @@ public function should_allow_specifying_the_wp_root_folder_as_absolute_path_with $this->assertInIsolation(static function () use ($wpRootDir, $wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals($wpRootDir . '/Word Press/', $wpLoader->_getConfig('wpRootFolder')); - Assert::assertEquals($wpRootDir . '/Word Press/', $wpLoader->getWpRootFolder()); + Assert::assertEquals($wpRootDir . '/Word Press/', $wpLoader->_getConfig('wpRootFolder')); + Assert::assertEquals($wpRootDir . '/Word Press/', $wpLoader->getWpRootFolder()); }); } @@ -324,7 +324,7 @@ public function should_scaffold_the_installation_if_the_wp_root_folder_is_empty( $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertInstanceOf(Scaffolded::class, $wpLoader->getInstallation()->getState()); + Assert::assertInstanceOf(Scaffolded::class, $wpLoader->getInstallation()->getState()); }); } @@ -356,14 +356,14 @@ public function should_read_salts_from_configured_installation(): void $wpLoader->_initialize(); $installation = $wpLoader->getInstallation(); - Assert::assertEquals($installation->getAuthKey(), $wpLoader->_getConfig('AUTH_KEY')); - Assert::assertEquals($installation->getSecureAuthKey(), $wpLoader->_getConfig('SECURE_AUTH_KEY')); - Assert::assertEquals($installation->getLoggedInKey(), $wpLoader->_getConfig('LOGGED_IN_KEY')); - Assert::assertEquals($installation->getNonceKey(), $wpLoader->_getConfig('NONCE_KEY')); - Assert::assertEquals($installation->getAuthSalt(), $wpLoader->_getConfig('AUTH_SALT')); - Assert::assertEquals($installation->getSecureAuthSalt(), $wpLoader->_getConfig('SECURE_AUTH_SALT')); - Assert::assertEquals($installation->getLoggedInSalt(), $wpLoader->_getConfig('LOGGED_IN_SALT')); - Assert::assertEquals($installation->getNonceSalt(), $wpLoader->_getConfig('NONCE_SALT')); + Assert::assertEquals($installation->getAuthKey(), $wpLoader->_getConfig('AUTH_KEY')); + Assert::assertEquals($installation->getSecureAuthKey(), $wpLoader->_getConfig('SECURE_AUTH_KEY')); + Assert::assertEquals($installation->getLoggedInKey(), $wpLoader->_getConfig('LOGGED_IN_KEY')); + Assert::assertEquals($installation->getNonceKey(), $wpLoader->_getConfig('NONCE_KEY')); + Assert::assertEquals($installation->getAuthSalt(), $wpLoader->_getConfig('AUTH_SALT')); + Assert::assertEquals($installation->getSecureAuthSalt(), $wpLoader->_getConfig('SECURE_AUTH_SALT')); + Assert::assertEquals($installation->getLoggedInSalt(), $wpLoader->_getConfig('LOGGED_IN_SALT')); + Assert::assertEquals($installation->getNonceSalt(), $wpLoader->_getConfig('NONCE_SALT')); }); } @@ -389,9 +389,9 @@ public function should_allow_getting_paths_from_the_wp_root_folder(): void $this->assertInIsolation(static function () use ($wpRootDir, $wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals($wpRootDir . '/foo-bar', $wpLoader->getWpRootFolder('foo-bar')); - Assert::assertEquals($wpRootDir . '/foo-bar/baz', $wpLoader->getWpRootFolder('foo-bar/baz')); - Assert::assertEquals($wpRootDir . '/wp-config.php', $wpLoader->getWpRootFolder('wp-config.php')); + Assert::assertEquals($wpRootDir . '/foo-bar', $wpLoader->getWpRootFolder('foo-bar')); + Assert::assertEquals($wpRootDir . '/foo-bar/baz', $wpLoader->getWpRootFolder('foo-bar/baz')); + Assert::assertEquals($wpRootDir . '/wp-config.php', $wpLoader->getWpRootFolder('wp-config.php')); }); } @@ -428,9 +428,9 @@ public function should_set_some_default_values_for_salt_keys(): void ]; foreach ($var as $i => $key) { if ($i > 0) { - Assert::assertNotEquals($var[$i - 1], $wpLoader->_getConfig($key)); + Assert::assertNotEquals($var[$i - 1], $wpLoader->_getConfig($key)); } - Assert::assertEquals(64, strlen($wpLoader->_getConfig($key))); + Assert::assertEquals(64, strlen($wpLoader->_getConfig($key))); } }); } @@ -456,7 +456,7 @@ public function should_load_config_files_if_set(): void $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals('test_file_001.php', getenv('LOADED')); + Assert::assertEquals('test_file_001.php', getenv('LOADED')); }); $this->config = [ @@ -476,8 +476,8 @@ public function should_load_config_files_if_set(): void $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals(getenv('LOADED_2'), 'test_file_002.php'); - Assert::assertEquals(getenv('LOADED_3'), 'test_file_003.php'); + Assert::assertEquals(getenv('LOADED_2'), 'test_file_002.php'); + Assert::assertEquals(getenv('LOADED_3'), 'test_file_003.php'); }); } @@ -505,10 +505,10 @@ public function should_throw_if_config_files_do_not_exist(): void try { $wpLoader->_initialize(); } catch (Exception $e) { - Assert::assertInstanceOf(ModuleConfigException::class, $e); + Assert::assertInstanceOf(ModuleConfigException::class, $e); $captured = true; } - Assert::assertTrue($captured); + Assert::assertTrue($captured); }); $this->config = [ @@ -651,7 +651,7 @@ public function should_throw_if_load_only_and_word_press_not_installed(): void $this->assertInIsolation(static function () use ($wpRootDir, $wpLoader) { $wpLoader->_initialize(); - Dispatcher::dispatch(Events::SUITE_BEFORE); + Dispatcher::dispatch(Events::SUITE_INIT); }); } @@ -693,8 +693,8 @@ public function should_load_word_press_before_suite_if_load_only_w_config_files( $this->assertInIsolation(static function () use ($wpRootDir, $wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals('', getenv('LOADED_2')); - Assert::assertFalse(defined('ABSPATH')); + Assert::assertEquals('', getenv('LOADED_2')); + Assert::assertFalse(defined('ABSPATH')); $actions = []; Dispatcher::addListener(WPLoader::EVENT_BEFORE_LOADONLY, static function () use (&$actions) { @@ -704,15 +704,15 @@ public function should_load_word_press_before_suite_if_load_only_w_config_files( $actions[] = WPLoader::EVENT_AFTER_LOADONLY; }); - Dispatcher::dispatch(Events::SUITE_BEFORE); + Dispatcher::dispatch(Events::SUITE_INIT); - Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); - Assert::assertEquals($wpRootDir . '/', ABSPATH); - Assert::assertEquals([ + Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); + Assert::assertEquals($wpRootDir . '/', ABSPATH); + Assert::assertEquals([ WPLoader::EVENT_BEFORE_LOADONLY, WPLoader::EVENT_AFTER_LOADONLY, ], $actions); - Assert::assertInstanceOf(FactoryStore::class, $wpLoader->factory()); + Assert::assertInstanceOf(FactoryStore::class, $wpLoader->factory()); }); } @@ -794,9 +794,9 @@ public function should_not_throw_when_load_only_true_and_using_db_module( $this->assertInIsolation(static function () use ($wpLoader, $wpRootDir) { $wpLoader->_initialize(); - Dispatcher::dispatch(Events::SUITE_BEFORE); + Dispatcher::dispatch(Events::SUITE_INIT); - Assert::assertEquals($wpRootDir . '/', ABSPATH); + Assert::assertEquals($wpRootDir . '/', ABSPATH); }); } @@ -937,11 +937,11 @@ public function should_should_install_and_bootstrap_single_site_using_constants_ $this->assertInIsolation(static function () use ($wpLoader, $wpRootDir) { $wpLoader->_initialize(); - Assert::assertEquals('test_file_001.php', getenv('LOADED')); - Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); - Assert::assertEquals($wpRootDir . '/', ABSPATH); - Assert::assertTrue(defined('WP_DEBUG')); - Assert::assertTrue(WP_DEBUG); + Assert::assertEquals('test_file_001.php', getenv('LOADED')); + Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); + Assert::assertEquals($wpRootDir . '/', ABSPATH); + Assert::assertTrue(defined('WP_DEBUG')); + Assert::assertTrue(WP_DEBUG); }); } @@ -1031,31 +1031,31 @@ public function should_install_and_bootstrap_single_installation(): void if (PHP_VERSION >= 7.4) { $expectedActivePlugins[] = 'woocommerce/woocommerce.php'; } - Assert::assertEquals($expectedActivePlugins, get_option('active_plugins')); - Assert::assertEquals([ + Assert::assertEquals($expectedActivePlugins, get_option('active_plugins')); + Assert::assertEquals([ 'before_install', 'after_install', ], $actions); - Assert::assertEquals('twentytwenty', get_option('template')); - Assert::assertEquals('twentytwenty', get_option('stylesheet')); - Assert::assertEquals('test_file_001.php', getenv('LOADED')); - Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); - Assert::assertEquals($wpRootDir . '/', ABSPATH); - Assert::assertTrue(defined('WP_DEBUG')); - Assert::assertTrue(WP_DEBUG); - Assert::assertInstanceOf(\wpdb::class, $GLOBALS['wpdb']); - Assert::assertFalse(is_multisite()); - Assert::assertEquals($wpRootDir . '/wp-content/', $wpLoader->getContentFolder()); - Assert::assertEquals($wpRootDir . '/wp-content/some/path', $wpLoader->getContentFolder('some/path')); - Assert::assertEquals( + Assert::assertEquals('twentytwenty', get_option('template')); + Assert::assertEquals('twentytwenty', get_option('stylesheet')); + Assert::assertEquals('test_file_001.php', getenv('LOADED')); + Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); + Assert::assertEquals($wpRootDir . '/', ABSPATH); + Assert::assertTrue(defined('WP_DEBUG')); + Assert::assertTrue(WP_DEBUG); + Assert::assertInstanceOf(\wpdb::class, $GLOBALS['wpdb']); + Assert::assertFalse(is_multisite()); + Assert::assertEquals($wpRootDir . '/wp-content/', $wpLoader->getContentFolder()); + Assert::assertEquals($wpRootDir . '/wp-content/some/path', $wpLoader->getContentFolder('some/path')); + Assert::assertEquals( $wpRootDir . '/wp-content/some/path/some-file.php', $wpLoader->getContentFolder('some/path/some-file.php') ); - Assert::assertEquals( + Assert::assertEquals( $wpRootDir . '/wp-content/plugins/some-file.php', $wpLoader->getPluginsFolder('/some-file.php') ); - Assert::assertEquals( + Assert::assertEquals( $wpRootDir . '/wp-content/themes/some-file.php', $wpLoader->getThemesFolder('/some-file.php') ); @@ -1122,32 +1122,32 @@ public function should_install_and_bootstrap_multisite_installation(): void if (PHP_VERSION >= 7.4) { $expectedActivePlugins[] = 'woocommerce/woocommerce.php'; } - Assert::assertEquals($expectedActivePlugins, array_keys(get_site_option('active_sitewide_plugins'))); - Assert::assertEquals([ + Assert::assertEquals($expectedActivePlugins, array_keys(get_site_option('active_sitewide_plugins'))); + Assert::assertEquals([ 'before_install', 'after_install', ], $actions); - Assert::assertEquals('twentytwenty', get_option('template')); - Assert::assertEquals('twentytwenty', get_option('stylesheet')); - Assert::assertEquals(['twentytwenty' => true], WP_Theme::get_allowed()); - Assert::assertEquals('test_file_001.php', getenv('LOADED')); - Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); - Assert::assertEquals($wpRootDir . '/', ABSPATH); - Assert::assertTrue(defined('WP_DEBUG')); - Assert::assertTrue(WP_DEBUG); - Assert::assertInstanceOf(\wpdb::class, $GLOBALS['wpdb']); - Assert::assertTrue(is_multisite()); - Assert::assertEquals($wpRootDir . '/wp-content/', $wpLoader->getContentFolder()); - Assert::assertEquals($wpRootDir . '/wp-content/some/path', $wpLoader->getContentFolder('some/path')); - Assert::assertEquals( + Assert::assertEquals('twentytwenty', get_option('template')); + Assert::assertEquals('twentytwenty', get_option('stylesheet')); + Assert::assertEquals(['twentytwenty' => true], WP_Theme::get_allowed()); + Assert::assertEquals('test_file_001.php', getenv('LOADED')); + Assert::assertEquals('test_file_002.php', getenv('LOADED_2')); + Assert::assertEquals($wpRootDir . '/', ABSPATH); + Assert::assertTrue(defined('WP_DEBUG')); + Assert::assertTrue(WP_DEBUG); + Assert::assertInstanceOf(\wpdb::class, $GLOBALS['wpdb']); + Assert::assertTrue(is_multisite()); + Assert::assertEquals($wpRootDir . '/wp-content/', $wpLoader->getContentFolder()); + Assert::assertEquals($wpRootDir . '/wp-content/some/path', $wpLoader->getContentFolder('some/path')); + Assert::assertEquals( $wpRootDir . '/wp-content/some/path/some-file.php', $wpLoader->getContentFolder('some/path/some-file.php') ); - Assert::assertEquals( + Assert::assertEquals( $wpRootDir . '/wp-content/plugins/some-file.php', $wpLoader->getPluginsFolder('/some-file.php') ); - Assert::assertEquals( + Assert::assertEquals( $wpRootDir . '/wp-content/themes/some-file.php', $wpLoader->getThemesFolder('/some-file.php') ); @@ -1413,8 +1413,8 @@ public function should_correctly_activate_child_theme_in_single_installation(): $installationOutput = $this->assertInIsolation(static function () use ($wpLoader, $wpRootDir) { $wpLoader->_initialize(); - Assert::assertEquals('twentytwenty', get_option('template')); - Assert::assertEquals('some-child-theme', get_option('stylesheet')); + Assert::assertEquals('twentytwenty', get_option('template')); + Assert::assertEquals('some-child-theme', get_option('stylesheet')); return [ 'bootstrapOutput' => $wpLoader->_getBootstrapOutput(), @@ -1481,8 +1481,8 @@ public function should_correctly_activate_child_theme_in_multisite_installation( $installationOutput = $this->assertInIsolation(static function () use ($wpLoader, $wpRootDir) { $wpLoader->_initialize(); - Assert::assertEquals('twentytwenty', get_option('template')); - Assert::assertEquals('twentytwenty-child', get_option('stylesheet')); + Assert::assertEquals('twentytwenty', get_option('template')); + Assert::assertEquals('twentytwenty-child', get_option('stylesheet')); return [ 'bootstrapOutput' => $wpLoader->_getBootstrapOutput(), @@ -1613,7 +1613,7 @@ public function should_allow_loading_a_database_dump_before_tests(): void $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals('value_1', get_option('option_1')); + Assert::assertEquals('value_1', get_option('option_1')); }); } @@ -1648,9 +1648,9 @@ public function should_allow_loading_multiple_database_dumps_before_the_tests(): $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals('value_1', get_option('option_1')); - Assert::assertEquals('value_2', get_option('option_2')); - Assert::assertEquals('value_3', get_option('option_3')); + Assert::assertEquals('value_1', get_option('option_1')); + Assert::assertEquals('value_2', get_option('option_2')); + Assert::assertEquals('value_3', get_option('option_3')); }); } @@ -1716,7 +1716,7 @@ public function should_place_sq_lite_dropin_if_using_sq_lite_database_for_tests( $this->assertInIsolation(static function () use ($wpRootDir, $wpLoader) { $wpLoader->_initialize(); - Assert::assertFileExists($wpRootDir . '/wp-content/db.php'); + Assert::assertFileExists($wpRootDir . '/wp-content/db.php'); }); } @@ -1743,8 +1743,8 @@ public function should_initialize_correctly_with_sqlite_database(): void $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); - Assert::assertInstanceOf(\WP_User::class, wp_get_current_user()); + Assert::assertTrue(function_exists('do_action')); + Assert::assertInstanceOf(\WP_User::class, wp_get_current_user()); }); } @@ -1779,10 +1779,10 @@ public function should_initialize_correctly_with_sqlite_database_in_load_only_mo $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Dispatcher::dispatch(Events::SUITE_BEFORE); + Dispatcher::dispatch(Events::SUITE_INIT); - Assert::assertTrue(function_exists('do_action')); - Assert::assertInstanceOf(\WP_User::class, wp_get_current_user()); + Assert::assertTrue(function_exists('do_action')); + Assert::assertInstanceOf(\WP_User::class, wp_get_current_user()); }); } @@ -1854,12 +1854,12 @@ function plugin_2_canary() {} $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); - Assert::assertTrue(function_exists('plugin_1_canary')); - Assert::assertTrue(is_plugin_active('plugin-1/plugin.php')); - Assert::assertTrue(function_exists('plugin_2_canary')); - Assert::assertTrue(is_plugin_active('plugin-2/plugin.php')); - Assert::assertEquals('theme-1', wp_get_theme()->get_stylesheet()); + Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('plugin_1_canary')); + Assert::assertTrue(is_plugin_active('plugin-1/plugin.php')); + Assert::assertTrue(function_exists('plugin_2_canary')); + Assert::assertTrue(is_plugin_active('plugin-2/plugin.php')); + Assert::assertEquals('theme-1', wp_get_theme()->get_stylesheet()); }); } @@ -1910,18 +1910,68 @@ public function should_correctly_load_with_different_database_names(string $dbNa $this->assertInIsolation(static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); - Assert::assertInstanceOf(\WP_User::class, wp_get_current_user()); + Assert::assertTrue(function_exists('do_action')); + Assert::assertInstanceOf(\WP_User::class, wp_get_current_user()); return $wpLoader->getInstallation()->getDb()->getDbName(); }) ); } + /** + * It should not backup globals by default + * + * @test + * @group backup-globals + */ + public function should_not_backup_globals_by_default(): void + { + $wpRootDir = FS::tmpDir('wploader_'); + $installation = Installation::scaffold($wpRootDir); + $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, 'test_'); + $db->drop(); + $installation->configure($db); + $installation->install( + 'https://wp.local', + 'admin', + 'password', + 'admin@wp.local', + 'Test' + ); + $testcaseFile = codecept_data_dir('files/BackupControlTestCase.php'); + $overridingTestCaseFile = codecept_data_dir('files/BackupControlTestCaseOverridingTestCase.php'); + + // Do not set`WPLoader.backupGlobals`, let the default value kick in. + $this->config = [ + 'wpRootFolder' => $wpRootDir, + 'dbUrl' => $db->getDbUrl(), + ]; + $wpLoader = $this->module(); + + $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { + $wpLoader->_initialize(); + + Assert::assertTrue(function_exists('do_action')); + + require_once $testcaseFile; + + $testCase = new \BackupControlTestCase('testBackupGlobalsIsFalse'); + /** @var TestResult $result */ + $result = $testCase->run(); + + Assert::assertTrue($result->wasSuccessful()); + }); + } + /** * It should allow controlling the backup of global variables in the WPTestCase * * @test + * @group backup-globals */ public function should_allow_controlling_the_backup_of_global_variables_in_the_wp_test_case(): void { @@ -1955,7 +2005,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $testcaseFile; @@ -1963,7 +2013,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); }); // Set `WPLoader.backupGlobals` to `true`. @@ -1977,7 +2027,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $testcaseFile; @@ -1985,11 +2035,10 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); }); - // Do not set `WPLoader.backupGlobals`, but use the default value. - // Set `WPLoader.backupGlobals` to `true`. + // Do not set `WPLoader.backupGlobals`, but use the default value of `false`. $this->config = [ 'wpRootFolder' => $wpRootDir, 'dbUrl' => $db->getDbUrl(), @@ -1999,15 +2048,15 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $testcaseFile; - $testCase = new \BackupControlTestCase('testBackupGlobalsIsTrue'); + $testCase = new \BackupControlTestCase('testBackupGlobalsIsFalse'); /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); }); // Set `WPLoader.backupGlobals` to `true`, but use a use-case that sets it explicitly to `false`. @@ -2021,7 +2070,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w $this->assertInIsolation(static function () use ($wpLoader, $overridingTestCaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $overridingTestCaseFile; @@ -2029,7 +2078,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); }); $this->config = [ @@ -2038,11 +2087,11 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w ]; $wpLoader = $this->module(); - // Test that globals defined before the test runs should be backed up by default. + // Test that globals defined before the test runs should not be backed up by default. $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); // Set the initial value of the global variable. global $_wpbrowser_test_global_var; @@ -2054,10 +2103,10 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); // Check that the value of the global variable has been updated. - Assert::assertEquals('initial_value', $_wpbrowser_test_global_var); + Assert::assertEquals('updated_value', $_wpbrowser_test_global_var); }); $this->config = [ @@ -2071,7 +2120,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); // Set the initial value of the global variable. global $_wpbrowser_test_global_var; @@ -2083,10 +2132,10 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); // Check that the value of the global variable has been updated. - Assert::assertEquals('updated_value', $_wpbrowser_test_global_var); + Assert::assertEquals('updated_value', $_wpbrowser_test_global_var); }); } @@ -2094,6 +2143,7 @@ public function should_allow_controlling_the_backup_of_global_variables_in_the_w * It should allow controlling the backup of static attributes in the WPTestCase * * @test + * @group backup-globals */ public function should_allow_controlling_the_backup_of_static_attributes_in_the_wp_test_case(): void { @@ -2127,7 +2177,7 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $testcaseFile; @@ -2135,12 +2185,12 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); - Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttribute); + Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttribute); }); - // Don't set`WPLoader.backupStaticAttributes`, it should be `true` by default. + // Don't set`WPLoader.backupStaticAttributes`, it should be `false` by default. $this->config = [ 'wpRootFolder' => $wpRootDir, 'dbUrl' => $db->getDbUrl() @@ -2150,7 +2200,7 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ $this->assertInIsolation(static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $testcaseFile; @@ -2158,9 +2208,9 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); - Assert::assertEquals('initial_value', \BackupControlTestCaseStore::$staticAttribute); + Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttribute); }); // Set the value of `WPLoader.backupStaticAttributes` to `true`, but use a use-case that sets it explicitly to `false`. @@ -2174,7 +2224,7 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ $this->assertInIsolation(static function () use ($wpLoader, $overridingTestCaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $overridingTestCaseFile; @@ -2182,15 +2232,16 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); - Assert::assertEquals('updated_value', \BackupControlTestCaseOverridingStore::$staticAttribute); + Assert::assertEquals('updated_value', \BackupControlTestCaseOverridingStore::$staticAttribute); }); // Set the value of the `WPLoader.backupStaticAttributesExcludeList` to not back up the static attribute. $this->config = [ 'wpRootFolder' => $wpRootDir, 'dbUrl' => $db->getDbUrl(), + 'backupStaticAttributes' => true, 'backupStaticAttributesExcludeList' => [ \BackupControlTestCaseStore::class => ['staticAttribute', 'staticAttributeThree'], \BackupControlTestCaseStoreTwo::class => ['staticAttributeFour'], @@ -2202,7 +2253,7 @@ public function should_allow_controlling_the_backup_of_static_attributes_in_the_ static function () use ($wpLoader, $testcaseFile) { $wpLoader->_initialize(); - Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue(function_exists('do_action')); require_once $testcaseFile; @@ -2210,16 +2261,16 @@ static function () use ($wpLoader, $testcaseFile) { /** @var TestResult $result */ $result = $testCase->run(); - Assert::assertTrue($result->wasSuccessful()); + Assert::assertTrue($result->wasSuccessful()); - Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttribute); - Assert::assertEquals('initial_value', \BackupControlTestCaseStore::$staticAttributeTwo); - Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttributeThree); - Assert::assertEquals('initial_value', \BackupControlTestCaseStore::$staticAttributeFour); - Assert::assertEquals('initial_value', \BackupControlTestCaseStoreTwo::$staticAttribute); - Assert::assertEquals('initial_value', \BackupControlTestCaseStoreTwo::$staticAttributeTwo); - Assert::assertEquals('initial_value', \BackupControlTestCaseStoreTwo::$staticAttributeThree); - Assert::assertEquals('updated_value', \BackupControlTestCaseStoreTwo::$staticAttributeFour); + Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttribute); + Assert::assertEquals('initial_value', \BackupControlTestCaseStore::$staticAttributeTwo); + Assert::assertEquals('updated_value', \BackupControlTestCaseStore::$staticAttributeThree); + Assert::assertEquals('initial_value', \BackupControlTestCaseStore::$staticAttributeFour); + Assert::assertEquals('initial_value', \BackupControlTestCaseStoreTwo::$staticAttribute); + Assert::assertEquals('initial_value', \BackupControlTestCaseStoreTwo::$staticAttributeTwo); + Assert::assertEquals('initial_value', \BackupControlTestCaseStoreTwo::$staticAttributeThree); + Assert::assertEquals('updated_value', \BackupControlTestCaseStoreTwo::$staticAttributeFour); } ); } @@ -2240,6 +2291,7 @@ public function notABooleanProvider(): array * * @test * @dataProvider notABooleanProvider + * @group backup-globals */ public function should_throw_if_backup_globals_is_not_a_boolean($notABoolean): void { @@ -2276,6 +2328,7 @@ public function notArrayOfStringsProvider(): array * * @test * @dataProvider notArrayOfStringsProvider + * @group backup-globals */ public function should_throw_if_backup_globals_exclude_list_is_not_an_array_of_strings($input): void { @@ -2297,6 +2350,7 @@ public function should_throw_if_backup_globals_exclude_list_is_not_an_array_of_s * * @test * @dataProvider notABooleanProvider + * @group backup-globals */ public function should_throw_if_backup_static_attributes_is_not_a_boolean($notABoolean): void { @@ -2333,6 +2387,7 @@ public function notStaticAttributeExcludeListProvider(): array * * @test * @dataProvider notStaticAttributeExcludeListProvider + * @group backup-globals */ public function should_throw_if_backup_static_attributes_exclude_list_is_not_in_the_correct_format($input): void { @@ -2424,14 +2479,14 @@ static function () use ($wpLoader, $moduleSplObjectHash) { $activePlugins = $wpdb->get_var( "SELECT option_value FROM {$wpdb->options} WHERE option_name = 'active_plugins'" ); - Assert::assertEquals(['woocommerce/woocommerce.php'], unserialize($activePlugins)); - Assert::assertNotEquals('1', getenv('WP_TESTS_SKIP_INSTALL')); - Assert::assertTrue(function_exists('do_action')); - Assert::assertTrue($beforeInstallCalled); - Assert::assertTrue($afterInstallCalled); - Assert::assertTrue($afterBootstrapCalled); - Assert::assertTrue(function_exists('wc_get_product')); - Assert::assertEquals('twentytwenty', wp_get_theme()->get_stylesheet()); + Assert::assertEquals(['woocommerce/woocommerce.php'], unserialize($activePlugins)); + Assert::assertNotEquals('1', getenv('WP_TESTS_SKIP_INSTALL')); + Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue($beforeInstallCalled); + Assert::assertTrue($afterInstallCalled); + Assert::assertTrue($afterBootstrapCalled); + Assert::assertTrue(function_exists('wc_get_product')); + Assert::assertEquals('twentytwenty', wp_get_theme()->get_stylesheet()); // Set a canary value. update_option('canary', $moduleSplObjectHash); @@ -2471,15 +2526,15 @@ static function () use ($moduleSplObjectHash, $wpLoader) { $activePlugins = $wpdb->get_var( "SELECT option_value FROM {$wpdb->options} WHERE option_name = 'active_plugins'" ); - Assert::assertEquals(['woocommerce/woocommerce.php'], unserialize($activePlugins)); - Assert::assertEquals('1', getenv('WP_TESTS_SKIP_INSTALL')); - Assert::assertTrue(function_exists('do_action')); - Assert::assertTrue($beforeInstallCalled); - Assert::assertTrue($afterInstallCalled); - Assert::assertTrue($afterBootstrapCalled); - Assert::assertTrue(function_exists('wc_get_product')); - Assert::assertEquals('twentytwenty', wp_get_theme()->get_stylesheet()); - Assert::assertEquals($moduleSplObjectHash, get_option('canary')); + Assert::assertEquals(['woocommerce/woocommerce.php'], unserialize($activePlugins)); + Assert::assertEquals('1', getenv('WP_TESTS_SKIP_INSTALL')); + Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue($beforeInstallCalled); + Assert::assertTrue($afterInstallCalled); + Assert::assertTrue($afterBootstrapCalled); + Assert::assertTrue(function_exists('wc_get_product')); + Assert::assertEquals('twentytwenty', wp_get_theme()->get_stylesheet()); + Assert::assertEquals($moduleSplObjectHash, get_option('canary')); } ); @@ -2508,15 +2563,15 @@ static function () use ($wpLoader) { $activePlugins = $wpdb->get_var( "SELECT option_value FROM {$wpdb->options} WHERE option_name = 'active_plugins'" ); - Assert::assertEquals(['woocommerce/woocommerce.php'], unserialize($activePlugins)); - Assert::assertNotEquals('1', getenv('WP_TESTS_SKIP_INSTALL')); - Assert::assertTrue(function_exists('do_action')); - Assert::assertTrue($beforeInstallCalled); - Assert::assertTrue($afterInstallCalled); - Assert::assertTrue($afterBootstrapCalled); - Assert::assertTrue(function_exists('wc_get_product')); - Assert::assertEquals('twentytwenty', wp_get_theme()->get_stylesheet()); - Assert::assertEquals( + Assert::assertEquals(['woocommerce/woocommerce.php'], unserialize($activePlugins)); + Assert::assertNotEquals('1', getenv('WP_TESTS_SKIP_INSTALL')); + Assert::assertTrue(function_exists('do_action')); + Assert::assertTrue($beforeInstallCalled); + Assert::assertTrue($afterInstallCalled); + Assert::assertTrue($afterBootstrapCalled); + Assert::assertTrue(function_exists('wc_get_product')); + Assert::assertEquals('twentytwenty', wp_get_theme()->get_stylesheet()); + Assert::assertEquals( '', get_option('canary'), 'The value set in the previous installation should be gone.' @@ -2676,8 +2731,8 @@ function activate_my_plugin(){ static function () use ($wpLoader) { $wpLoader->_initialize(); - Assert::assertEquals('', get_option('my_plugin_activated')); - Assert::assertEquals('__loaded__', get_option('my_plugin_loaded')); + Assert::assertEquals('', get_option('my_plugin_activated')); + Assert::assertEquals('__loaded__', get_option('my_plugin_loaded')); } ); } diff --git a/tests/unit/lucatume/WPBrowser/Extension/BuiltInServerControllerTest.php b/tests/unit/lucatume/WPBrowser/Extension/BuiltInServerControllerTest.php index 2d1956b9a..4323e5c66 100644 --- a/tests/unit/lucatume/WPBrowser/Extension/BuiltInServerControllerTest.php +++ b/tests/unit/lucatume/WPBrowser/Extension/BuiltInServerControllerTest.php @@ -18,10 +18,7 @@ class PhpBuiltInServerMock extends PhpBuiltInServer { - /** - * @var mixed[] - */ - public static $lastInstanceArgs; + public static array $lastInstanceArgs; public function __construct(string $docRoot, int $port = 0, array $env = []) { @@ -43,20 +40,27 @@ class BuiltInServerControllerTest extends Unit use UopzFunctions; use SnapshotAssertions; + private Output $output; + /** - * @var \Codeception\Lib\Console\Output + * @before */ - private $output; + public function backupPidFile():void{ + $pidFile = PhpBuiltInServer::getPidFile(); + + if (is_file($pidFile)) { + rename($pidFile, $pidFile.'.bak'); + } + } /** - * @before * @after */ - public function removePidFiles(): void - { + public static function restorePidFile():void{ $pidFile = PhpBuiltInServer::getPidFile(); - if (is_file($pidFile)) { - unlink($pidFile); + + if (is_file($pidFile .'.bak')) { + rename($pidFile.'.bak', $pidFile); } } @@ -88,9 +92,8 @@ public function notArrayOfStringsProvider(): array * * @test * @dataProvider notArrayOfStringsProvider - * @param mixed $suites */ - public function should_throw_if_suite_configuration_parameter_is_not_array_of_strings($suites): void + public function should_throw_if_suite_configuration_parameter_is_not_array_of_strings(mixed $suites): void { $config = ['suites' => $suites]; $options = []; @@ -121,9 +124,8 @@ public function notIntGreaterThanZeroProvider(): array * * @test * @dataProvider notIntGreaterThanZeroProvider - * @param mixed $port */ - public function should_throw_if_config_port_is_not_int_greater_than_0($port): void + public function should_throw_if_config_port_is_not_int_greater_than_0(mixed $port): void { $config = [ 'docroot' => __DIR__, @@ -158,9 +160,8 @@ public function notValidDirectoryProvider(): array * * @test * @dataProvider notValidDirectoryProvider - * @param mixed $docroot */ - public function should_throw_if_config_docroot_is_not_existing_directory($docroot): void + public function should_throw_if_config_docroot_is_not_existing_directory(mixed $docroot): void { $config = ['docroot' => $docroot]; $options = []; @@ -179,9 +180,8 @@ public function should_throw_if_config_docroot_is_not_existing_directory($docroo * * @test * @dataProvider notIntGreaterThanZeroProvider - * @param mixed $workers */ - public function should_throw_if_config_workers_is_not_int_greater_than_0($workers): void + public function should_throw_if_config_workers_is_not_int_greater_than_0(mixed $workers): void { $config = [ 'docroot' => __DIR__, @@ -218,9 +218,8 @@ public function notAssociativeArrayWithStringsProvider(): array * * @test * @dataProvider notAssociativeArrayWithStringsProvider - * @param mixed $env */ - public function should_throw_if_config_env_is_not_associative_array_with_string_keys($env): void + public function should_throw_if_config_env_is_not_associative_array_with_string_keys(mixed $env): void { $config = [ 'docroot' => __DIR__, diff --git a/tests/unit/lucatume/WPBrowser/Extension/ChromeDriverControllerTest.php b/tests/unit/lucatume/WPBrowser/Extension/ChromeDriverControllerTest.php index 683b74ed9..036e1354d 100644 --- a/tests/unit/lucatume/WPBrowser/Extension/ChromeDriverControllerTest.php +++ b/tests/unit/lucatume/WPBrowser/Extension/ChromeDriverControllerTest.php @@ -20,10 +20,7 @@ class ChromeDriverControllerTest extends Unit use UopzFunctions; use SnapshotAssertions; - /** - * @var \Codeception\Lib\Console\Output - */ - private $output; + private Output $output; /** * @before @@ -47,6 +44,28 @@ public function _before() $this->uopzSetMock(Output::class, $this->output); } + /** + * @before + */ + public function backupPidFile():void{ + $pidFile = ChromeDriver::getPidFile(); + + if (is_file($pidFile)) { + rename($pidFile, $pidFile.'.bak'); + } + } + + /** + * @after + */ + public static function restorePidFile():void{ + $pidFile = ChromeDriver::getPidFile(); + + if (is_file($pidFile .'.bak')) { + rename($pidFile.'.bak', $pidFile); + } + } + public function notArrayOfStringsProvider(): array { return [ @@ -65,9 +84,8 @@ public function notArrayOfStringsProvider(): array * * @test * @dataProvider notArrayOfStringsProvider - * @param mixed $suites */ - public function should_throw_if_suite_configuration_parameter_is_not_array_of_strings($suites): void + public function should_throw_if_suite_configuration_parameter_is_not_array_of_strings(mixed $suites): void { $config = ['suites' => $suites]; $options = []; @@ -98,9 +116,8 @@ public function notIntGreaterThanZeroProvider(): array * * @test * @dataProvider notIntGreaterThanZeroProvider - * @param mixed $port */ - public function should_throw_if_config_port_is_not_int_greater_than_0($port): void + public function should_throw_if_config_port_is_not_int_greater_than_0(mixed $port): void { $config = ['port' => $port]; $options = []; diff --git a/tests/unit/lucatume/WPBrowser/Extension/DockerComposeControllerTest.php b/tests/unit/lucatume/WPBrowser/Extension/DockerComposeControllerTest.php index 736049862..21e88448e 100644 --- a/tests/unit/lucatume/WPBrowser/Extension/DockerComposeControllerTest.php +++ b/tests/unit/lucatume/WPBrowser/Extension/DockerComposeControllerTest.php @@ -50,6 +50,30 @@ public function _before() $this->uopzSetMock(Output::class, $this->output); } + /** + * @before + */ + public static function backupRunFile(): void + { + $runFile = DockerComposeController::getRunningFile(); + + if (is_file($runFile)) { + rename($runFile, $runFile . '.bak'); + } + } + + /** + * @after + */ + public static function restoreRunFile(): void + { + $runFile = DockerComposeController::getRunningFile(); + + if (is_file($runFile . '.bak')) { + rename($runFile . '.bak', $runFile); + } + } + public function notArrayOfStringsProvider(): array { return [ diff --git a/tests/unit/lucatume/WPBrowser/Extension/EventDispatcherBridgeTest.php b/tests/unit/lucatume/WPBrowser/Extension/EventDispatcherBridgeTest.php index db4abf0c7..33413e4a1 100644 --- a/tests/unit/lucatume/WPBrowser/Extension/EventDispatcherBridgeTest.php +++ b/tests/unit/lucatume/WPBrowser/Extension/EventDispatcherBridgeTest.php @@ -53,7 +53,7 @@ public function should_set_global_event_dispatcher_to_application_one(): void $this->uopzSetStaticMethodReturn(Dispatcher::class, 'getEventDispatcher', null); $this->uopzSetStaticMethodReturn(Dispatcher::class, 'setEventDispatcher', - function (\Symfony\Component\EventDispatcher\EventDispatcherInterface $setEventDispatcher) use ( + function (EventDispatcherInterface $setEventDispatcher) use ( $eventDispatcher ) { Assert::assertSame($eventDispatcher, $setEventDispatcher); diff --git a/tests/unit/lucatume/WPBrowser/Lib/Generator/GenerationCommandsTest.php b/tests/unit/lucatume/WPBrowser/Lib/Generator/GenerationCommandsTest.php new file mode 100644 index 000000000..e4a07def4 --- /dev/null +++ b/tests/unit/lucatume/WPBrowser/Lib/Generator/GenerationCommandsTest.php @@ -0,0 +1,96 @@ +testCaseFile)) { + return; + } + + if (!unlink($this->testCaseFile)) { + throw new \RuntimeException('Cannot remove test case file.'); + } + } + + /** + * @return array + */ + public function commandsProvider(): array + { + return [ + GenerateWPAjax::class => ['GenerateWPAjax', GenerateWPAjax::getCommandName()], + GenerateWPCanonical::class => ['GenerateWPCanonical', GenerateWPCanonical::getCommandName()], + GenerateWPRestApi::class => ['GenerateWPRestApi', GenerateWPRestApi::getCommandName()], + GenerateWPRestController::class => ['GenerateWPRestController', GenerateWPRestController::getCommandName()], + GenerateWPRestPostTypeController::class => [ + 'GenerateWPRestPostTypeController', + GenerateWPRestPostTypeController::getCommandName() + ], + GenerateWPUnit::class => ['GenerateWPUnit', GenerateWPUnit::getCommandName()], + GenerateWPXML::class => ['GenerateWPXML', GenerateWPXML::getCommandName()], + GenerateWPXMLRPC::class => ['GenerateWPXMLRPC', GenerateWPXMLRPC::getCommandName()], + ]; + } + + /** + * @dataProvider commandsProvider + */ + public function test_testcase_generation(string $commandClass, string $commandName): void + { + $codeceptionBin = FS::realpath('vendor/bin/codecept'); + + $suite = static::$suite; + + // Generate the test example. + (new Process([PHP_BINARY, $codeceptionBin, $commandName, $suite, $commandClass]))->mustRun(); + + $testCaseFileRelativePath = "tests/{$suite}/{$commandClass}Test.php"; + $testCaseFile = codecept_root_dir($testCaseFileRelativePath); + + $this->assertFileExists($testCaseFile); + + $this->testCaseFile = $testCaseFile; + + $runProcess = new Process( + [PHP_BINARY, $codeceptionBin, 'codeception:run', $testCaseFileRelativePath] + ); + $runProcess->run(); + $exitCode = $runProcess->getExitCode(); + + if ($exitCode !== 0) { + $this->testCaseFile = null; + } + + $this->assertEquals(0, $exitCode, $this->formatRunProcessOutput($runProcess)); + } + + private function formatRunProcessOutput(Process $runProcess): string + { + return sprintf( + "\nSTDOUT\n---\n%s\nSTDERR\n---\n%s\n", + preg_replace('/^/mu', '> ', $runProcess->getOutput()), + preg_replace('/^/mu', '> ', $runProcess->getErrorOutput()) + ); + } +} diff --git a/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_correctly_add_the_tester_property_if_actor_is_set_in_the_settings__0.snapshot.php b/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_correctly_add_the_tester_property_if_actor_is_set_in_the_settings__0.snapshot.php index 3ce3aadec..da7e47391 100644 --- a/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_correctly_add_the_tester_property_if_actor_is_set_in_the_settings__0.snapshot.php +++ b/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_correctly_add_the_tester_property_if_actor_is_set_in_the_settings__0.snapshot.php @@ -32,4 +32,4 @@ public function test_factory() :void $this->assertInstanceOf(\WP_Post::class, $post); } -} +} \ No newline at end of file diff --git a/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_scaffold_the_test_case__0.snapshot.php b/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_scaffold_the_test_case__0.snapshot.php index f2d9d0323..321af87a3 100644 --- a/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_scaffold_the_test_case__0.snapshot.php +++ b/tests/unit/lucatume/WPBrowser/Lib/Generator/__snapshots__/WPUnitTest__should_scaffold_the_test_case__0.snapshot.php @@ -28,4 +28,4 @@ public function test_factory() :void $this->assertInstanceOf(\WP_Post::class, $post); } -} +} \ No newline at end of file diff --git a/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php b/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php index 35c32262a..f6cdc5bfd 100644 --- a/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php +++ b/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php @@ -123,7 +123,7 @@ public function should_throw_if_pif_file_cannot_be_written_on_start(): void $this->expectException(RuntimeException::class); $this->expectExceptionCode(ManagedProcessInterface::ERR_PID_FILE); - $this->uopzSetFunctionReturn('file_put_contents', function (string $file) { + $this->uopzSetFunctionReturn('file_put_contents', function (string $file): false|int { return $file === ChromeDriver::getPidFile() ? false : 0; }, true); diff --git a/tests/unit/lucatume/WPBrowser/ManagedProcess/PhpBuiltInServerTest.php b/tests/unit/lucatume/WPBrowser/ManagedProcess/PhpBuiltInServerTest.php index cbbcb2ed9..d8d7157d3 100644 --- a/tests/unit/lucatume/WPBrowser/ManagedProcess/PhpBuiltInServerTest.php +++ b/tests/unit/lucatume/WPBrowser/ManagedProcess/PhpBuiltInServerTest.php @@ -12,19 +12,13 @@ class PhpBuiltinServerProcessMock extends Process { - /** - * @var mixed[] - */ - public static $instances = []; + public static array $instances = []; - /** - * @param mixed $input - */ public function __construct( array $command, string $cwd = null, array $env = null, - $input = null, + mixed $input = null, ?float $timeout = 60 ) { parent::__construct($command, $cwd, $env, $input, $timeout); @@ -100,9 +94,8 @@ public function notAssociativeArrayProvider(): array * * @test * @dataProvider notAssociativeArrayProvider - * @param mixed $env */ - public function should_throw_if_env_is_not_associative_array($env): void + public function should_throw_if_env_is_not_associative_array(mixed $env): void { $this->expectException(RuntimeException::class); $this->expectExceptionCode(PhpBuiltInServer::ERR_ENV); diff --git a/tests/unit/lucatume/WPBrowser/ManagedProcess/Polyfills/Dotenv/DotenvTest.php b/tests/unit/lucatume/WPBrowser/ManagedProcess/Polyfills/Dotenv/DotenvTest.php new file mode 100644 index 000000000..d74bb02a1 --- /dev/null +++ b/tests/unit/lucatume/WPBrowser/ManagedProcess/Polyfills/Dotenv/DotenvTest.php @@ -0,0 +1,57 @@ +load(); + + $expected = [ + 'TEST_ENV_2_VAR_INT' => 23, + 'TEST_ENV_2_VAR_FLOAT' => 23.89, + 'TEST_ENV_2_VAR_SINGLE_STRING' => 'lorem', + 'TEST_ENV_2_VAR_SINGLE_MULTI_STRING' => 'lorem dolor sit', + 'TEST_ENV_2_VAR_SINGLE_MULTI_STRING_W_QUOTES' => 'lorem dolor sit' + ]; + + foreach ($expected as $key => $value) { + $this->assertEquals($value, getenv($key)); + $this->assertEquals($value, $_ENV[ $key ]); + $this->assertEquals($value, $_SERVER[ $key ]); + } + } + + /** + * It should throw if the root dir does not exist + * + * @test + */ + public function should_throw_if_the_root_dir_does_not_exist() + { + $this->expectException(InvalidArgumentException::class); + + new Dotenv(codecept_data_dir('foo/bar')); + } + + /** + * It should throw if the env file does not exist + * + * @test + */ + public function should_throw_if_the_env_file_does_not_exist() + { + $this->expectException(InvalidArgumentException::class); + + new Dotenv(codecept_data_dir('envFiles'), '.foo.bar'); + } +} diff --git a/tests/unit/lucatume/WPBrowser/Process/Protocol/ControlTest.php b/tests/unit/lucatume/WPBrowser/Process/Protocol/ControlTest.php index fcfa80f63..bda2e5eeb 100644 --- a/tests/unit/lucatume/WPBrowser/Process/Protocol/ControlTest.php +++ b/tests/unit/lucatume/WPBrowser/Process/Protocol/ControlTest.php @@ -13,14 +13,8 @@ class ControlTest extends Unit { use UopzFunctions; - /** - * @var string|null - */ - private $composerAutoloadPath; - /** - * @var string|null - */ - private $composerBinDir; + private ?string $composerAutoloadPath = null; + private ?string $composerBinDir = null; /** * @before diff --git a/tests/unit/lucatume/WPBrowser/Process/Protocol/ParserTest.php b/tests/unit/lucatume/WPBrowser/Process/Protocol/ParserTest.php index 659d76828..681fc4fdb 100644 --- a/tests/unit/lucatume/WPBrowser/Process/Protocol/ParserTest.php +++ b/tests/unit/lucatume/WPBrowser/Process/Protocol/ParserTest.php @@ -207,9 +207,8 @@ public function decodePartialDataProvider(): Generator /** * @dataProvider decodePartialDataProvider - * @param mixed $expected */ - public function testDecodePartial(string $input, int $offset, int $count, $expected): void + public function testDecodePartial(string $input, int $offset, int $count, mixed $expected): void { $parsed = Parser::decode($input, $offset, $count); $this->assertEquals($expected, $parsed); diff --git a/tests/unit/lucatume/WPBrowser/Process/StderrStreamTest.php b/tests/unit/lucatume/WPBrowser/Process/StderrStreamTest.php index fcd4a0a7b..9e6f87159 100644 --- a/tests/unit/lucatume/WPBrowser/Process/StderrStreamTest.php +++ b/tests/unit/lucatume/WPBrowser/Process/StderrStreamTest.php @@ -270,10 +270,7 @@ public function testParsesStreamCorrectly( $stderrStream = new StderrStream($stream, StderrStream::RELATIVE_PATHNAMES, $currentDateTime); $errors = $stderrStream->getParsed(); - $encoded = json_encode($errors, JSON_PRETTY_PRINT); - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \Exception(json_last_error_msg()); - } + $encoded = json_encode($errors, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR); codecept_debug($encoded); $this->assertMatchesJsonSnapshot($encoded); if ($expectedThrowableClass) { diff --git a/tests/unit/lucatume/WPBrowser/Project/PluginProjectTest.php b/tests/unit/lucatume/WPBrowser/Project/PluginProjectTest.php index f6cb57996..b86e52721 100644 --- a/tests/unit/lucatume/WPBrowser/Project/PluginProjectTest.php +++ b/tests/unit/lucatume/WPBrowser/Project/PluginProjectTest.php @@ -8,8 +8,13 @@ use lucatume\WPBrowser\Tests\Traits\CliCommandTestingTools; use lucatume\WPBrowser\Tests\Traits\TmpFilesCleanup; use lucatume\WPBrowser\Tests\Traits\UopzFunctions; +use lucatume\WPBrowser\Utils\Env; use lucatume\WPBrowser\Utils\Filesystem as FS; +use lucatume\WPBrowser\Utils\Random; +use lucatume\WPBrowser\WordPress\Database\MysqlDatabase; +use lucatume\WPBrowser\WordPress\Installation; use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\NullOutput; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; @@ -67,7 +72,56 @@ public function should_build_on_plugin_directory_correctly(): void $output = new NullOutput(); $pluginProject = new PluginProject($input, $output, $pluginDir); + $this->assertEquals('Acme Plugin', $pluginProject->getName()); $this->assertEquals($pluginDir . '/plugin.php', $pluginProject->getPluginFilePathName()); } + + /** + * It should provide information about the failure to activate due to error + * + * @test + */ + public function should_provide_information_about_the_failure_to_activate_due_to_error(): void + { + $wpRootDir = FS::tmpDir('plugin_project_'); + $dbName = Random::dbName(); + $db = new MysqlDatabase( + $dbName, + Env::get('WORDPRESS_DB_USER'), + Env::get('WORDPRESS_DB_PASSWORD'), + Env::get('WORDPRESS_DB_HOST') + ); + Installation::scaffold($wpRootDir) + ->configure($db) + ->install( + 'http://localhost:1234', + 'admin', + 'password', + 'admin@example.com', + 'Test' + ); + FS::mkdirp($wpRootDir . '/wp-content/plugins/acme-plugin', [ + 'plugin.php' => <<< PHP +assertFalse($pluginProject->activate($wpRootDir, 1234)); + $expected = "Could not activate plugin: Something went wrong. \n" . + "{{wp_root_dir}}/wp-content/plugins/acme-plugin/plugin.php:3\n" . + "This might happen because the plugin has unmet dependencies; wp-browser configuration will continue, " . + "but you will need to manually activate the plugin and update the dump in tests/Support/Data/dump.sql."; + $this->assertEquals( + $expected, + trim(str_replace($wpRootDir, '{{wp_root_dir}}', $output->fetch())) + ); + } } diff --git a/tests/unit/lucatume/WPBrowser/Project/SiteProjectTest.php b/tests/unit/lucatume/WPBrowser/Project/SiteProjectTest.php index 36150dbe6..917013894 100644 --- a/tests/unit/lucatume/WPBrowser/Project/SiteProjectTest.php +++ b/tests/unit/lucatume/WPBrowser/Project/SiteProjectTest.php @@ -43,11 +43,11 @@ public function should_throw_if_trying_scaffold_on_site_that_is_empty(): void } /** - * It should throw if trying to scaffol on site that is not configured + * It should throw if trying to scaffold on site that is not configured * * @test */ - public function should_throw_if_trying_to_scaffol_on_site_that_is_not_configured(): void + public function should_throw_if_trying_to_scaffold_on_site_that_is_not_configured(): void { $composerFileCode = <<< EOT { diff --git a/tests/unit/lucatume/WPBrowser/Project/ThemeProjectTest.php b/tests/unit/lucatume/WPBrowser/Project/ThemeProjectTest.php index 726005399..5a44e6719 100644 --- a/tests/unit/lucatume/WPBrowser/Project/ThemeProjectTest.php +++ b/tests/unit/lucatume/WPBrowser/Project/ThemeProjectTest.php @@ -8,10 +8,15 @@ use lucatume\WPBrowser\Tests\Traits\CliCommandTestingTools; use lucatume\WPBrowser\Tests\Traits\TmpFilesCleanup; use lucatume\WPBrowser\Tests\Traits\UopzFunctions; +use lucatume\WPBrowser\Utils\Env; +use lucatume\WPBrowser\Utils\Filesystem as FS; +use lucatume\WPBrowser\Utils\Random; +use lucatume\WPBrowser\WordPress\Database\MysqlDatabase; +use lucatume\WPBrowser\WordPress\Installation; use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\NullOutput; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use lucatume\WPBrowser\Utils\Filesystem as FS; class ThemeProjectTest extends Unit { @@ -113,4 +118,54 @@ public function should_build_correctly_on_child_theme_directory(): void $this->assertEquals('Some Theme', $themeProject->getName()); $this->assertEquals('theme', $themeProject->getType()); } + + /** + * It should provide information about the failure to activate due to error + * + * @test + */ + public function should_provide_information_about_the_failure_to_activate_due_to_error(): void + { + $wpRootDir = FS::tmpDir('theme_project_'); + $dbName = Random::dbName(); + $db = new MysqlDatabase( + $dbName, + Env::get('WORDPRESS_DB_USER'), + Env::get('WORDPRESS_DB_PASSWORD'), + Env::get('WORDPRESS_DB_HOST') + ); + Installation::scaffold($wpRootDir) + ->configure($db) + ->install( + 'http://localhost:1234', + 'admin', + 'password', + 'admin@example.com', + 'Test' + ); + FS::mkdirp($wpRootDir . '/wp-content/themes/acme-theme', [ + 'style.css' => <<< PHP + ' 'assertFalse($themeProject->activate($wpRootDir, 1234)); + $expected = "Could not activate theme: Error: Current PHP version does not meet minimum requirements for Acme Theme. \n" . + "This might happen because the theme has unmet dependencies; wp-browser configuration will continue, " . + "but you will need to manually activate the theme and update the dump in tests/Support/Data/dump.sql."; + $this->assertEquals( + $expected, + trim(str_replace($wpRootDir, '{{wp_root_dir}}', $output->fetch())) + ); + } } diff --git a/tests/unit/lucatume/WPBrowser/Utils/ArrTest.php b/tests/unit/lucatume/WPBrowser/Utils/ArrTest.php index f39d03207..93b3865b0 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ArrTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ArrTest.php @@ -52,9 +52,8 @@ public function searchWithCallbackDataProvider(): array /** * @dataProvider searchWithCallbackDataProvider - * @param int|string|false $expected */ - public function testSearchWithCallback(callable $isNeedle, array $hastack, $expected): void + public function testSearchWithCallback(callable $isNeedle, array $hastack, int|string|false $expected): void { $actual = Arr::searchWithCallback($isNeedle, $hastack); $this->assertEquals($expected, $actual); @@ -93,11 +92,8 @@ public function firstFromDataProvider(): array /** * @dataProvider firstFromDataProvider - * @param mixed $value - * @param mixed $default - * @param mixed $expected */ - public function test_firstFrom($value, $default, $expected): void + public function test_firstFrom(mixed $value, mixed $default, mixed $expected): void { $actual = Arr::firstFrom($value, $default); $this->assertEquals($expected, $actual); @@ -144,37 +140,27 @@ public function hasShapeDataProvider(): array 'array has mixed shape, 3rd type is Closure' => [ 'array' => [new stdClass, 2, '3'], 'expected' => true, - ['stdClass', 'int', function (string $value) : bool { - return $value === '3'; - }] + ['stdClass', 'int', fn(string $value): bool => $value === '3'] ], 'array has mixed shape, 3rd type is Closure, misses one' => [ 'array' => [new stdClass, 2], 'expected' => false, - ['stdClass', 'int', function (string $value) : bool { - return $value === '3'; - }] + ['stdClass', 'int', fn(string $value): bool => $value === '3'] ], 'array has mixed shape with associative type' => [ 'array' => ['a' => new stdClass, 'b' => 2, 'c' => '3'], 'expected' => true, - ['a' => 'stdClass', 'b' => 'int', 'c' => function (string $value) : bool { - return $value === '3'; - }] + ['a' => 'stdClass', 'b' => 'int', 'c' => fn(string $value): bool => $value === '3'] ], 'array shape does not match mixed types' => [ 'array' => ['a' => new stdClass, 'b' => 2, 'c' => '3'], 'expected' => false, - ['a' => 'stdClass', 'b' => 'int', 'c' => function (string $value) : bool { - return $value === '4'; - }] + ['a' => 'stdClass', 'b' => 'int', 'c' => fn(string $value): bool => $value === '4'] ], 'array shape matches in different order' => [ 'array' => ['a' => new stdClass, 'b' => 2, 'c' => '3'], 'expected' => true, - ['b' => 'int', 'c' => function (string $value) : bool { - return $value === '3'; - }, 'a' => 'stdClass'] + ['b' => 'int', 'c' => fn(string $value): bool => $value === '3', 'a' => 'stdClass'] ], ]; } @@ -218,16 +204,12 @@ public function containsOnlyDataProvider(): array ], 'array of integers, type is Closure' => [ 'array' => [1, 2, 3], - 'type' => function (int $value) { - return $value > 0; - }, + 'type' => fn(int $value) => $value > 0, 'expected' => true ], 'array of integers, type is Closure, no match' => [ 'array' => [1, 2, 3], - 'type' => function (int $value) { - return $value > 23; - }, + 'type' => fn(int $value) => $value > 23, 'expected' => false ], ]; @@ -235,9 +217,8 @@ public function containsOnlyDataProvider(): array /** * @dataProvider containsOnlyDataProvider - * @param callable|string $type */ - public function test_containsOnly(array $array, $type, bool $expected): void + public function test_containsOnly(array $array, callable|string $type, bool $expected): void { $actual = Arr::containsOnly($array, $type); $this->assertEquals($expected, $actual); diff --git a/tests/unit/lucatume/WPBrowser/Utils/ChromedriverInstallerTest.php b/tests/unit/lucatume/WPBrowser/Utils/ChromedriverInstallerTest.php index 314fd1abb..e3e687608 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ChromedriverInstallerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ChromedriverInstallerTest.php @@ -42,14 +42,61 @@ public function should_throw_if_specified_platform_is_not_supported(): void } /** - * It should throw if binary cannot be found + * It should throw if specified binary cannot be found * * @test */ - public function should_throw_if_binary_cannot_be_found(): void + public function should_throw_if_specified_binary_cannot_be_found(): void + { + $this->uopzSetFunctionReturn('is_file', fn(string $file) => !str_contains($file, 'chrome'), true); + $this->expectException(RuntimeException::class); + $this->expectExceptionCode(ChromedriverInstaller::ERR_INVALID_BINARY); + + new ChromedriverInstaller(null, 'win32', '/path/to/chrome.exe'); + } + + /** + * @return string[] + */ + public function platforms_provider(): array + { + return [ + 'win32' => ['win32', 'chrome'], + 'win64' => ['win64', 'chrome'], + 'linux64' => ['linux64', 'chrom'], + 'mac-x64' => ['mac-x64', 'Chrome'], + 'mac-arm64' => ['mac-arm64', 'Chrome'], + ]; + } + + /** + * It should throw if binary cannot be found in default paths for platform + * + * @test + * @dataProvider platforms_provider + */ + public function should_throw_if_binary_cannot_be_found_in_default_paths_for_platform( + string $platform, + string $binNamePattern + ): void { + $isNotAnExecutableFile = fn(string $file) => !str_contains($file, $binNamePattern); + $this->uopzSetFunctionReturn('is_file', $isNotAnExecutableFile, true); + $this->uopzSetFunctionReturn('is_executable', $isNotAnExecutableFile, true); + $this->expectException(RuntimeException::class); + $this->expectExceptionCode(ChromedriverInstaller::ERR_INVALID_BINARY); + + new ChromedriverInstaller(null, $platform); + } + + /** + * It should throw if binary cannot be executed + * + * @test + */ + public function should_throw_if_binary_cannot_be_executed(): void { $this->uopzSetFunctionReturn('is_executable', function (string $file): bool { - return strpos($file, 'chrome') === false && is_executable($file); + return !str_contains($file, 'chrome') && is_executable($file); }, true); $this->expectException(RuntimeException::class); @@ -66,15 +113,17 @@ public function should_throw_if_binary_cannot_be_found(): void public function should_throw_if_specified_binary_is_not_valid(): void { $this->uopzSetFunctionReturn('is_executable', function (string $file): bool { - return strpos($file, 'Chromium') === false && is_executable($file); + return !str_contains($file, 'Chromium') && is_executable($file); }, true); $this->expectException(RuntimeException::class); $this->expectExceptionCode(ChromedriverInstaller::ERR_INVALID_BINARY); - new ChromedriverInstaller('1.2.3.4', + new ChromedriverInstaller( + '1.2.3.4', 'mac-arm64', - '/Applications/Chromium.app/Contents/MacOS/Chromium'); + '/Applications/Chromium.app/Contents/MacOS/Chromium' + ); } /** @@ -87,9 +136,11 @@ public function should_throw_if_version_from_binary_is_not_a_string(): void $this->expectException(RuntimeException::class); $this->expectExceptionCode(ChromedriverInstaller::ERR_VERSION_NOT_STRING); - new ChromedriverInstaller(null, + new ChromedriverInstaller( + null, null, - codecept_data_dir('bins/chrome-version-not-string')); + codecept_data_dir('bins/chrome-version-not-string') + ); } /** @@ -99,7 +150,7 @@ public function should_throw_if_version_from_binary_is_not_a_string(): void */ public function should_throw_if_version_from_binary_has_not_correct_format(): void { - $this->uopzSetFunctionReturn('exec','Could not start Google Chrome.'); + $this->uopzSetFunctionReturn('exec', 'Could not start Google Chrome.'); $this->expectException(RuntimeException::class); $this->expectExceptionCode(ChromedriverInstaller::ERR_INVALID_VERSION_FORMAT); @@ -155,8 +206,8 @@ public function should_throw_if_trying_to_install_to_non_existing_directory(): v */ public function should_throw_if_it_cannot_get_milestone_downloads(): void { - $this->uopzSetFunctionReturn('file_get_contents', function (string $file) { - return strpos($file, 'chrome-for-testing') !== false ? false : file_get_contents($file); + $this->uopzSetFunctionReturn('file_get_contents', function (string $file): string|false { + return str_contains($file, 'chrome-for-testing') ? false : file_get_contents($file); }, true); $ci = new ChromedriverInstaller(null, 'linux64', codecept_data_dir('bins/chrome-mock')); @@ -175,8 +226,8 @@ public function should_throw_if_it_cannot_get_milestone_downloads(): void */ public function should_throw_if_response_is_not_valid_json(): void { - $this->uopzSetFunctionReturn('file_get_contents', function (string $file) { - return strpos($file, 'chrome-for-testing') !== false ? '{}' : file_get_contents($file); + $this->uopzSetFunctionReturn('file_get_contents', function (string $file): string|false { + return str_contains($file, 'chrome-for-testing') ? '{}' : file_get_contents($file); }, true); $ci = new ChromedriverInstaller(null, 'linux64', codecept_data_dir('bins/chrome-mock')); @@ -184,6 +235,9 @@ public function should_throw_if_response_is_not_valid_json(): void $this->expectException(RuntimeException::class); $this->expectExceptionCode(ChromedriverInstaller::ERR_DECODE_MILESTONE_DOWNLOADS); + $this->expectExceptionMessage("Failed to find a version of Chromedriver to download for your platform and " . + "Chrome combination.\nTry upgrading Chrome and making sure it is executable from one of the expected " . + "locations for your platform (linux64): chromium, google-chrome"); $ci->install(__DIR__); } @@ -195,10 +249,10 @@ public function should_throw_if_response_is_not_valid_json(): void */ public function should_throw_if_download_url_for_chrome_version_cannot_be_found_in_milestone_downloads(): void { - $this->uopzSetFunctionReturn('file_get_contents', function (string $file) { - return strpos($file, 'chrome-for-testing') !== false ? - '{"milestones":{"116": {"downloads":{"chrome":{},"chromedriver":{}}}}}' - : file_get_contents($file); + $this->uopzSetFunctionReturn('file_get_contents', function (string $file): string|false { + return str_contains($file, 'chrome-for-testing') ? + '{"milestones":{"116": {"downloads":{"chrome":{},"chromedriver":{}}}}}' + : file_get_contents($file); }, true); $ci = new ChromedriverInstaller(null, 'linux64', codecept_data_dir('bins/chrome-mock')); @@ -219,7 +273,7 @@ public function should_throw_if_existing_zip_file_cannot_be_removed(): void { $this->uopzSetFunctionReturn('sys_get_temp_dir', codecept_output_dir()); $this->uopzSetFunctionReturn('unlink', function (string $file): bool { - return preg_match('~chromedriver\\.zip$~' ,$file) ? false : unlink($file); + return preg_match('~chromedriver\\.zip$~', $file) ? false : unlink($file); }, true); $ci = new ChromedriverInstaller(null, 'linux64', codecept_data_dir('bins/chrome-mock')); diff --git a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php index c3ead7425..c4a13d62b 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php @@ -137,12 +137,8 @@ public function should_allow_updating_the_composer_file(): void Assert::assertEquals(['composer', 'update', '--no-interaction'], func_get_args()[0]); $built++; }, - 'run' => function () { - return 0; - }, - 'getExitCode' => function () { - return 0; - }, + 'run' => fn() => 0, + 'getExitCode' => fn() => 0, ])); $hash = md5(microtime()); $testFile = sys_get_temp_dir() . "/$hash-composer.json"; @@ -167,12 +163,8 @@ public function should_allow_updating_the_composer_file_for_a_specific_package() Assert::assertEquals(['composer', 'update', '--no-interaction', 'foo/baz'], func_get_args()[0]); $built++; }, - 'run' => function () { - return 0; - }, - 'getExitCode' => function () { - return 0; - }, + 'run' => fn() => 0, + 'getExitCode' => fn() => 0, ])); $tmpDir = FS::tmpDir('composer_', [ 'composer.json' => file_get_contents(codecept_data_dir('composer-files/test-1-composer.json')), @@ -196,12 +188,8 @@ public function should_throw_if_update_fails(): void '__construct' => function () { Assert::assertEquals(['composer', 'update', '--no-interaction'], func_get_args()[0]); }, - 'run' => function () { - return 1; - }, - 'getExitCode' => function () { - return 1; - }, + 'run' => fn() => 1, + 'getExitCode' => fn() => 1, ])); $hash = md5(microtime()); $testFile = sys_get_temp_dir() . "/$hash-composer.json"; diff --git a/tests/unit/lucatume/WPBrowser/Utils/FilesystemTest.php b/tests/unit/lucatume/WPBrowser/Utils/FilesystemTest.php index f76c765d5..05053fa5e 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/FilesystemTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/FilesystemTest.php @@ -165,15 +165,9 @@ public function test_mkdirp_creates_nested_trees_wo_specifying_content(): void public function relativePathDataSet(): Generator { - yield 'empty' => [function () { - return ['', '', '/', '']; - }]; - yield 'empty from, absolute to' => [function () { - return ['', __DIR__, '/', __DIR__]; - }]; - yield 'empty to' => [function () { - return [__DIR__, '', '/', '']; - }]; + yield 'empty' => [fn() => ['', '', '/', '']]; + yield 'empty from, absolute to' => [fn() => ['', __DIR__, '/', __DIR__]]; + yield 'empty to' => [fn() => [__DIR__, '', '/', '']]; $makeTmpDir = static function (): string { $tmpDir = Filesystem::tmpDir(); diff --git a/tests/unit/lucatume/WPBrowser/Utils/PropertyTest.php b/tests/unit/lucatume/WPBrowser/Utils/PropertyTest.php index e806086c0..60d82a101 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/PropertyTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/PropertyTest.php @@ -7,58 +7,25 @@ class PropertyAccessTestTarget { - /** - * @var int - */ - private $private = 23; - /** - * @var int - */ - protected $protected = 89; - /** - * @var int - */ - public $public = 2389; - /** - * @var int - */ - private static $privateStatic = 23; - /** - * @var int - */ - protected static $protectedStatic = 89; - /** - * @var int - */ - public static $publicStatic = 2389; + private int $private = 23; + protected int $protected = 89; + public int $public = 2389; + private static int $privateStatic = 23; + protected static int $protectedStatic = 89; + public static int $publicStatic = 2389; } class PropertyAccessTestTargetChild extends PropertyAccessTestTarget { - /** - * @var int - */ - private $private = 42; - /** - * @var int - */ - protected $protected = 0; - /** - * @var int - */ - public static $publicStatic = 0; + private int $private = 42; + protected int $protected = 0; + public static int $publicStatic = 0; } class PropertyAccessTestTargetGrandchild extends PropertyAccessTestTargetChild { - /** - * @var int - */ - private $private = 17; - /** - * @var int - */ - public static $publicStatic = 1731; + private int $private = 17; + public static int $publicStatic = 1731; } class PropertyTest extends Unit diff --git a/tests/unit/lucatume/WPBrowser/Utils/SerializerTest.php b/tests/unit/lucatume/WPBrowser/Utils/SerializerTest.php index 45d1bc0d9..2beee5d73 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/SerializerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/SerializerTest.php @@ -15,14 +15,8 @@ class TestSerializableObject { - /** - * @var string - */ - public $foo = 'bar'; - /** - * @var int - */ - public $number = 23; + public string $foo = 'bar'; + public int $number = 23; public function __serialize(): array { @@ -140,9 +134,8 @@ public function isSerializedDataProvider(): Generator /** * @dataProvider isSerializedDataProvider - * @param mixed $input */ - public function test_isSerialized($input, bool $expected): void + public function test_isSerialized(mixed $input, bool $expected): void { $this->assertEquals($expected, Serializer::isSerialized($input)); } @@ -201,10 +194,8 @@ public function maybeSerializeDataProvider(): Generator /** * @dataProvider maybeSerializeDataProvider - * @param mixed $input - * @param mixed $expected */ - public function test_maybeSerialize($input, $expected): void + public function test_maybeSerialize(mixed $input, mixed $expected): void { $this->assertEquals($expected, Serializer::maybeSerialize($input)); } diff --git a/tests/unit/lucatume/WPBrowser/Utils/StringsTest.php b/tests/unit/lucatume/WPBrowser/Utils/StringsTest.php index 1b1367c86..b8bccce01 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/StringsTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/StringsTest.php @@ -131,9 +131,7 @@ public function renderStringDataProvider(): array 'empty_w_data_and_seed' => ['',['name'=>'luca'],['session'=>'test'],''], 'template_w_data_and_seed' => [ '{{session}}_{{name}}', - [ 'name' => 'luca', 'session' => static function ($session) { - return 'xyz_' . $session; - }], + [ 'name' => 'luca', 'session' => static fn($session) => 'xyz_' . $session], [ 'session' => 'test' ], 'xyz_test_luca' ] diff --git a/tests/unit/lucatume/WPBrowser/WordPress/Database/SqliteDatabaseTest.php b/tests/unit/lucatume/WPBrowser/WordPress/Database/SqliteDatabaseTest.php index 06edf8f99..86419fcdc 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/Database/SqliteDatabaseTest.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/Database/SqliteDatabaseTest.php @@ -126,7 +126,7 @@ public function should_delete_the_db_file_on_drop(): void $this->assertFileExists($dir . '/' . $file); $db->drop(); $this->assertFalse($db->exists()); - $this->assertFileNotExists($dir . '/' . $file); + $this->assertFileDoesNotExist($dir . '/' . $file); } /** diff --git a/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ConfiguredTest.php b/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ConfiguredTest.php index 5caa77c06..0399bf959 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ConfiguredTest.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ConfiguredTest.php @@ -848,7 +848,13 @@ public function should_allow_changing_the_db_from_mysql_to_sqlite(): void $this->assertEquals($sqliteDb, $withSqliteDb->getDb()); - $installedOnSqlite = $withSqliteDb->install('http://wp.local', 'admin', 'password', 'admin@wp.local', 'Test Blog'); + $installedOnSqlite = $withSqliteDb->install( + 'http://wp.local', + 'admin', + 'password', + 'admin@wp.local', + 'Test Blog', + ); $this->assertFileExists($wpRootDir . '/wp-content/db.sqlite'); $this->assertEquals('http://wp.local', $sqliteDb->getOption('siteurl')); diff --git a/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ScaffoldedTest.php b/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ScaffoldedTest.php index 60c15c551..9a15d9d4c 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ScaffoldedTest.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/ScaffoldedTest.php @@ -657,7 +657,7 @@ public function should_throw_if_sqlite_plugin_db_copy_file_cannot_be_read(): voi $scaffolded = new Scaffolded($wpRootDir); $this->uopzSetFunctionReturn('file_get_contents', function (string $file) { - if (substr_compare($file, 'db.copy', -strlen('db.copy')) === 0) { + if (str_ends_with($file, 'db.copy')) { return false; } return file_get_contents(...func_get_args()); @@ -682,7 +682,7 @@ public function should_throw_if_sqlite_drop_in_placement_fails(): void $scaffolded = new Scaffolded($wpRootDir); $this->uopzSetFunctionReturn('file_put_contents', function (string $file) { - if (substr_compare($file, 'db.php', -strlen('db.php')) === 0) { + if (str_ends_with($file, 'db.php')) { return false; } return file_put_contents(...func_get_args()); diff --git a/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/__snapshots__/ScaffoldedTest__3.5__should_allow_configuring_an_installation_using_custom_configuration__0.snapshot.php b/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/__snapshots__/ScaffoldedTest__3.5__should_allow_configuring_an_installation_using_custom_configuration__0.snapshot.php index 0dc37ca22..5925fa7e4 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/__snapshots__/ScaffoldedTest__3.5__should_allow_configuring_an_installation_using_custom_configuration__0.snapshot.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/InstallationState/__snapshots__/ScaffoldedTest__3.5__should_allow_configuring_an_installation_using_custom_configuration__0.snapshot.php @@ -29,7 +29,7 @@ define( 'DB_PASSWORD', 'password' ); /** Database hostname */ -define( 'DB_HOST', '127.0.0.1:3591' ); +define( 'DB_HOST', '127.0.0.1:2391' ); /** Database charset to use in creating database tables. */ define( 'DB_CHARSET', 'utf8' ); diff --git a/tests/unit/lucatume/WPBrowser/WordPress/InstallationTest.php b/tests/unit/lucatume/WPBrowser/WordPress/InstallationTest.php index b0de7451a..3a3a27998 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/InstallationTest.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/InstallationTest.php @@ -47,9 +47,7 @@ public function should_throw_when_building_on_non_writable_root_directory(): voi { $tmpDir = FS::tmpDir('installation_'); $this->uopzSetFunctionReturn('is_writable', - function (string $dir) use ($tmpDir) { - return !($dir === $tmpDir . '/') && is_writable($dir); - }, + fn(string $dir) => !($dir === $tmpDir . '/') && is_writable($dir), true ); @@ -68,9 +66,7 @@ public function should_throw_when_building_on_non_readable_root_directory() { $tmpDir = FS::tmpDir('installation_'); $this->uopzSetFunctionReturn('is_readable', - function (string $dir) use ($tmpDir) { - return !($dir === $tmpDir . '/') && is_readable($dir); - }, + fn(string $dir) => !($dir === $tmpDir . '/') && is_readable($dir), true ); @@ -459,7 +455,7 @@ public function should_support_complex_plugin_load_in_sqlite_context(): void { $wpRoot = FS::tmpDir('installation_'); $db = new SQLiteDatabase($wpRoot, 'db.sqlite'); - $installation = Installation::scaffold($wpRoot, '6.1.1') + $installation = Installation::scaffold($wpRoot) ->configure($db) ->install( 'https://localhost:2389', diff --git a/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_contents_provided_db_and_configuration_data__0.snapshot.php b/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_contents_provided_db_and_configuration_data__0.snapshot.php index f3367b6d1..c78729263 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_contents_provided_db_and_configuration_data__0.snapshot.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_contents_provided_db_and_configuration_data__0.snapshot.php @@ -29,7 +29,7 @@ define( 'DB_PASSWORD', 'password' ); /** Database hostname */ -define( 'DB_HOST', '127.0.0.1:3591' ); +define( 'DB_HOST', '127.0.0.1:2391' ); /** Database charset to use in creating database tables. */ define( 'DB_CHARSET', 'utf8' ); diff --git a/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_with_custom_constants__0.snapshot.php b/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_with_custom_constants__0.snapshot.php index feea0e5b9..83e0c8aa4 100644 --- a/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_with_custom_constants__0.snapshot.php +++ b/tests/unit/lucatume/WPBrowser/WordPress/__snapshots__/WpConfigFileGeneratorTest__3.5__should_correctly_produce_a_wp_config_php_file_with_custom_constants__0.snapshot.php @@ -29,7 +29,7 @@ define( 'DB_PASSWORD', 'password' ); /** Database hostname */ -define( 'DB_HOST', '127.0.0.1:3591' ); +define( 'DB_HOST', '127.0.0.1:2391' ); /** Database charset to use in creating database tables. */ define( 'DB_CHARSET', 'utf8' ); diff --git a/tests/wploadersuite.suite.dist.yml b/tests/wploadersuite.suite.dist.yml index 829bc562b..67c4829ce 100644 --- a/tests/wploadersuite.suite.dist.yml +++ b/tests/wploadersuite.suite.dist.yml @@ -24,5 +24,3 @@ modules: - 'woocommerce/woocommerce.php' installationTableHandling: drop booststrapActions: [] - backupGlobalsExcludeList: - - wc_container diff --git a/tests/wploadersuite/AjaxTest.php b/tests/wploadersuite/AjaxTest.php index ff61a149e..c5399bdb4 100644 --- a/tests/wploadersuite/AjaxTest.php +++ b/tests/wploadersuite/AjaxTest.php @@ -1,9 +1,12 @@ suppress_errors = true; // Due to a WooCommerce activation issue in older versions. $this->_handleAjax('test_ajax_action'); - } catch (\WPAjaxDieContinueException $exception) { + } catch (\WPAjaxDieContinueException) { $response = json_decode($this->_last_response); } diff --git a/tests/wploadersuite/DynamicPropertyTest.php b/tests/wploadersuite/DynamicPropertyTest.php new file mode 100644 index 000000000..e0f03fdd7 --- /dev/null +++ b/tests/wploadersuite/DynamicPropertyTest.php @@ -0,0 +1,39 @@ +assertFalse(isset($this->testDynamicProperty)); + $this->assertNull($this->testDynamicProperty); + + $this->testDynamicProperty = 23; + + $this->assertTrue(isset($this->testDynamicProperty)); + $this->assertEquals(23,$this->testDynamicProperty); + + $this->testDynamicProperty = 89; + + $this->assertTrue(isset($this->testDynamicProperty)); + $this->assertEquals(89,$this->testDynamicProperty); + + unset($this->testDynamicProperty); + + $this->assertFalse(isset($this->testDynamicProperty)); + $this->assertNull($this->testDynamicProperty); + } +} diff --git a/tests/wploadersuite/RunInSeparateProcessAnnotationTest.php b/tests/wploadersuite/RunInSeparateProcessAnnotationTest.php new file mode 100644 index 000000000..ccdc731e4 --- /dev/null +++ b/tests/wploadersuite/RunInSeparateProcessAnnotationTest.php @@ -0,0 +1,62 @@ + [23], + 'case two' => [89] + ]; + } + + /** + * @dataProvider isolation_data_provider + * @runInSeparateProcess + */ + public function test_isolation_works(int $number): void + { + define('TEST_CONST', $number); + + $this->assertTrue(defined('TEST_CONST')); + $this->assertEquals($number, TEST_CONST); + } + + public function test_state_not_leaked_from_isolated_test(): void + { + $this->assertFalse(defined('TEST_CONST')); + } + + public function closures_provider(): Generator + { + yield 'empty return closure' => [ + fn() => null, + fn($value) => is_null($value) + ]; + + yield 'numeric return closure' => [ + fn() => 23, + fn($value) => is_int($value) + ]; + + yield 'post returning closure' => [ + fn() => static::factory()->post->create(), + fn($value) => get_post($value) instanceof WP_Post + ]; + } + + /** + * @test + * @runInSeparateProcess + * @dataProvider closures_provider + */ + public function should_correctly_serialize_closures(Closure $createCurrent, Closure $check): void + { + $this->assertTrue($check($createCurrent())); + } +} diff --git a/tests/wploadersuite/RunInSeparateProcessAttributeTest.php b/tests/wploadersuite/RunInSeparateProcessAttributeTest.php new file mode 100644 index 000000000..6d5557e70 --- /dev/null +++ b/tests/wploadersuite/RunInSeparateProcessAttributeTest.php @@ -0,0 +1,88 @@ + [23], + 'case two' => [89] + ]; + } + + #[DataProvider('isolation_data_provider')] + #[RunInSeparateProcess] + public function test_isolation_works(int $number): void + { + define('TEST_CONST', $number); + + $this->assertTrue(defined('TEST_CONST')); + $this->assertEquals($number, TEST_CONST); + } + + public function test_state_not_leaked_from_isolated_test(): void + { + $this->assertFalse(defined('TEST_CONST')); + } + + /** + * @test + */ + public function it_works(): void + { + $this->assertEquals(23, 23); + } + + /** + * @test + * @runInSeparateProcess + */ + public function it_works_2(): void + { + $this->assertEquals(23, 23); + } + + /** + * @runInSeparateProcess + * @test + */ + public function it_works_3(): void + { + $this->assertEquals(23, 23); + } + + /** + * @test + */ + #[RunInSeparateProcess] + public function it_works_4(): void + { + $this->assertEquals(23, 23); + } + + #[RunInSeparateProcess] + public function it_works_5(): void + { + $this->assertEquals(23, 23); + } + + #[RunInSeparateProcess] + /** + * @test + */ + #[DataProvider('isolation_data_provider')] + + public function it_works_6(int $number): void + { + define('TEST_CONST', $number); + + $this->assertTrue(defined('TEST_CONST')); + $this->assertEquals($number, TEST_CONST); + } +} diff --git a/tests/wploadersuite/RunTestsInSeparateProcessesAnnotationTest.php b/tests/wploadersuite/RunTestsInSeparateProcessesAnnotationTest.php new file mode 100644 index 000000000..156a95b55 --- /dev/null +++ b/tests/wploadersuite/RunTestsInSeparateProcessesAnnotationTest.php @@ -0,0 +1,32 @@ +assertEquals(23, TEST_CONST); + } + + public function test_setting_another_constant(): void + { + define('TEST_CONST_2', 89); + + $this->assertFalse(defined('TEST_CONST')); + $this->assertEquals(89, TEST_CONST_2); + } + + public function test_using_post_factory(): void + { + $post = static::factory()->post->create(); + + $this->assertInstanceOf(\WP_Post::class, get_post($post)); + } +} diff --git a/tests/wploadersuite/RunTestsInSeparateProcessesAttributeTest.php b/tests/wploadersuite/RunTestsInSeparateProcessesAttributeTest.php new file mode 100644 index 000000000..1d232778d --- /dev/null +++ b/tests/wploadersuite/RunTestsInSeparateProcessesAttributeTest.php @@ -0,0 +1,35 @@ + [23], + 'case two' => [89] + ]; + } + + #[DataProvider('isolation_data_provider')] + /** + * @dataProvider isolation_data_provider + */ + public function test_isolation_works(int $number): void + { + define('TEST_CONST', $number); + + $this->assertTrue(defined('TEST_CONST')); + $this->assertEquals($number, TEST_CONST); + } + + public function test_state_not_leaked_from_isolated_test(): void + { + $this->assertFalse(defined('TEST_CONST')); + } +} diff --git a/tests/wploadersuite/_bootstrap.php b/tests/wploadersuite/_bootstrap.php index 51e29508d..b38454ff0 100644 --- a/tests/wploadersuite/_bootstrap.php +++ b/tests/wploadersuite/_bootstrap.php @@ -5,3 +5,12 @@ if (!class_exists(WP_Post::class)) { throw new RuntimeException('WP_Post class not found'); } + +// Work around WooCommerce enqueueing this only on admin requests. +if (!function_exists('wc_get_page_screen_id')) { + function wc_get_page_screen_id(): string + { + return ''; + } +} +