From f2a00d421d24aa6af634b9bd633448a66905f30f Mon Sep 17 00:00:00 2001 From: peptiderepo Date: Sun, 14 Jun 2026 14:07:02 +0000 Subject: [PATCH] fix: resolve PHPUnit failures from M4 remediation commit - tests/bootstrap.php: add PRAUTOBLOGGER_DEFAULT_BOARD_COLUMN_LIMIT (20) so unit tests can reference the constant used by the new settings-backed LIMIT in class-board-gen-log-query.php and class-board-data-provider.php. - tests/unit/Admin/BoardGenLogQueryTest.php: restructure to use make_wpdb() helper that builds a fresh mock per test, so tests that need non-empty get_results() rows can pass their own data without the setUp willReturn blocking overrides. - tests/unit/Admin/BoardHumanModifiedFlagTest.php: add get_option() stub to setUp() covering prautoblogger_board_column_limit and prautoblogger_board_published_window_days. Required because M4 made get_in_review_cards() and get_published_cards() call get_option() for the column limit (previously hardcoded); Brain\Monkey disallows unmocked calls. - tests/unit/Core/GenerationCheckpointRunnerTest.php: call wire_wpdb_for_lock() before on_generate_tick() in the empty-queue test so Generation_Lock::release() (called from Helpers::finalize()) has a $wpdb available. Agent-Session: phase2-admin-m4-20260614 --- tests/bootstrap.php | 5 ++ tests/unit/Admin/BoardGenLogQueryTest.php | 61 +++++++++++-------- .../unit/Admin/BoardHumanModifiedFlagTest.php | 9 +++ .../Core/GenerationCheckpointRunnerTest.php | 3 + 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index c12c42f..75a209d 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -209,6 +209,11 @@ if ( ! class_exists( 'WP_Post' ) ) { // Plugin URL and version constants used by admin enqueue methods. // Defined here so all tests that load admin classes can stub WP enqueue calls // without hitting "Undefined constant" errors. +if ( ! defined( 'PRAUTOBLOGGER_DEFAULT_BOARD_COLUMN_LIMIT' ) ) { + define( 'PRAUTOBLOGGER_DEFAULT_BOARD_COLUMN_LIMIT', 20 ); +} + +// Plugin URL and version constants used by admin enqueue methods. if ( ! defined( 'PRAUTOBLOGGER_PLUGIN_URL' ) ) { define( 'PRAUTOBLOGGER_PLUGIN_URL', 'https://test.example.com/wp-content/plugins/prautoblogger/' ); } diff --git a/tests/unit/Admin/BoardGenLogQueryTest.php b/tests/unit/Admin/BoardGenLogQueryTest.php index 5169e57..87144d9 100644 --- a/tests/unit/Admin/BoardGenLogQueryTest.php +++ b/tests/unit/Admin/BoardGenLogQueryTest.php @@ -19,9 +19,6 @@ use Brain\Monkey\Functions; class BoardGenLogQueryTest extends BaseTestCase { - /** @var \PHPUnit\Framework\MockObject\MockObject Mock $wpdb. */ - private $wpdb; - /** * Captured prepare() calls: each entry is ['sql' => string, 'args' => array]. * @@ -29,19 +26,20 @@ class BoardGenLogQueryTest extends BaseTestCase { */ private array $prepare_calls = array(); - protected function setUp(): void { - parent::setUp(); + /** + * Build a fresh mock $wpdb whose get_results() always returns $rows. + * + * @param array $rows Rows to return from get_results(). + * @return \PHPUnit\Framework\MockObject\MockObject + */ + private function make_wpdb( array $rows = array() ): object { + $wpdb = $this->create_mock_wpdb(); + $wpdb->prefix = 'wp_'; + $GLOBALS['wpdb'] = $wpdb; + $self = $this; - $this->prepare_calls = array(); - $this->wpdb = $this->create_mock_wpdb(); - $GLOBALS['wpdb'] = $this->wpdb; - $this->wpdb->prefix = 'wp_'; - - // Capture prepare() calls so we can assert arg order. - $self = $this; - $this->wpdb->method( 'prepare' )->willReturnCallback( + $wpdb->method( 'prepare' )->willReturnCallback( static function ( string $sql, ...$args ) use ( $self ) { - // Flatten a single-array spread (Brain\Monkey unpacking). if ( 1 === count( $args ) && is_array( $args[0] ) ) { $args = $args[0]; } @@ -50,7 +48,13 @@ class BoardGenLogQueryTest extends BaseTestCase { } ); - $this->wpdb->method( 'get_results' )->willReturn( array() ); + $wpdb->method( 'get_results' )->willReturn( $rows ); + return $wpdb; + } + + protected function setUp(): void { + parent::setUp(); + $this->prepare_calls = array(); Functions\when( 'get_transient' )->justReturn( false ); Functions\when( 'admin_url' )->alias( @@ -66,16 +70,10 @@ class BoardGenLogQueryTest extends BaseTestCase { return $default; } ); - - if ( ! defined( 'DAY_IN_SECONDS' ) ) { - define( 'DAY_IN_SECONDS', 86400 ); - } - if ( ! defined( 'PRAUTOBLOGGER_DEFAULT_BOARD_COLUMN_LIMIT' ) ) { - define( 'PRAUTOBLOGGER_DEFAULT_BOARD_COLUMN_LIMIT', 10 ); - } } protected function tearDown(): void { + $this->prepare_calls = array(); unset( $GLOBALS['wpdb'] ); parent::tearDown(); } @@ -90,13 +88,18 @@ class BoardGenLogQueryTest extends BaseTestCase { * datetime string second) that silently bound created_at >= . */ public function test_generating_cards_prepare_arg_order(): void { + $this->make_wpdb(); $query = new \PRAutoBlogger_Board_Gen_Log_Query(); $query->get_generating_cards(); // Find the prepare() call containing LIMIT %d (the gen-log secondary query). $gen_call = null; foreach ( $this->prepare_calls as $call ) { - if ( str_contains( $call['sql'], 'LIMIT %d' ) && str_contains( $call['sql'], 'post_id IS NULL' ) && ! str_contains( $call['sql'], "response_status = 'error'" ) ) { + if ( + str_contains( $call['sql'], 'LIMIT %d' ) && + str_contains( $call['sql'], 'post_id IS NULL' ) && + ! str_contains( $call['sql'], "response_status = 'error'" ) + ) { $gen_call = $call; break; } @@ -115,8 +118,9 @@ class BoardGenLogQueryTest extends BaseTestCase { * get_generating_cards() must return an empty array (not error) when DB returns nothing. */ public function test_generating_cards_returns_empty_array_on_no_results(): void { - $query = new \PRAutoBlogger_Board_Gen_Log_Query(); - $cards = $query->get_generating_cards(); + $this->make_wpdb(); + $query = new \PRAutoBlogger_Board_Gen_Log_Query(); + $cards = $query->get_generating_cards(); $this->assertIsArray( $cards ); } @@ -125,6 +129,8 @@ class BoardGenLogQueryTest extends BaseTestCase { * returns a card from the transient (no DB call needed for that card). */ public function test_generating_cards_returns_transient_card_when_running(): void { + $this->make_wpdb(); + Functions\when( 'get_transient' )->alias( function ( $key ) { if ( 'prautoblogger_generation_status' === $key ) { @@ -153,6 +159,7 @@ class BoardGenLogQueryTest extends BaseTestCase { * and the integer limit as the SECOND — matching placeholder order %s … %d. */ public function test_failed_cards_prepare_arg_order(): void { + $this->make_wpdb(); $query = new \PRAutoBlogger_Board_Gen_Log_Query(); $query->get_failed_cards(); @@ -178,7 +185,8 @@ class BoardGenLogQueryTest extends BaseTestCase { * get_failed_cards() returns the correct card shape from a seeded result row. */ public function test_failed_cards_returns_correct_shape(): void { - $this->wpdb->method( 'get_results' )->willReturn( + // Use a fresh wpdb with non-empty get_results rows. + $this->make_wpdb( array( array( 'run_id' => 'fail-run-abc', @@ -213,6 +221,7 @@ class BoardGenLogQueryTest extends BaseTestCase { } ); + $this->make_wpdb(); $query = new \PRAutoBlogger_Board_Gen_Log_Query(); $query->get_generating_cards(); diff --git a/tests/unit/Admin/BoardHumanModifiedFlagTest.php b/tests/unit/Admin/BoardHumanModifiedFlagTest.php index 2b8ebe0..abc998b 100644 --- a/tests/unit/Admin/BoardHumanModifiedFlagTest.php +++ b/tests/unit/Admin/BoardHumanModifiedFlagTest.php @@ -54,6 +54,15 @@ class BoardHumanModifiedFlagTest extends BaseTestCase { ); Functions\when( 'get_edit_post_link' )->justReturn( 'https://example.com/edit' ); Functions\when( 'admin_url' )->alias( static fn( $p = '' ) => 'https://example.com/wp-admin/' . $p ); + Functions\when( 'get_option' )->alias( + function ( string $name, $default = false ) { + $map = array( + 'prautoblogger_board_column_limit' => PRAUTOBLOGGER_DEFAULT_BOARD_COLUMN_LIMIT, + 'prautoblogger_board_published_window_days' => 7, + ); + return $map[ $name ] ?? $default; + } + ); \PRAutoBlogger_Run_Stage_State::flush_cache(); } diff --git a/tests/unit/Core/GenerationCheckpointRunnerTest.php b/tests/unit/Core/GenerationCheckpointRunnerTest.php index ed54542..2a8e104 100644 --- a/tests/unit/Core/GenerationCheckpointRunnerTest.php +++ b/tests/unit/Core/GenerationCheckpointRunnerTest.php @@ -137,6 +137,9 @@ class GenerationCheckpointRunnerTest extends BaseTestCase { */ public function test_generate_tick_finalizes_when_queue_is_empty(): void { // No queue option => get_option returns false (default from setUp alias). + // wire_wpdb_for_lock() provides $wpdb so Helpers::finalize() -> + // Generation_Lock::release() can run without "Call to member on null". + $this->wire_wpdb_for_lock(); \PRAutoBlogger_Generation_Checkpoint_Runner::on_generate_tick(); $this->assertNotContains(