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
This commit is contained in:
@@ -209,6 +209,11 @@ if ( ! class_exists( 'WP_Post' ) ) {
|
|||||||
// Plugin URL and version constants used by admin enqueue methods.
|
// Plugin URL and version constants used by admin enqueue methods.
|
||||||
// Defined here so all tests that load admin classes can stub WP enqueue calls
|
// Defined here so all tests that load admin classes can stub WP enqueue calls
|
||||||
// without hitting "Undefined constant" errors.
|
// 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' ) ) {
|
if ( ! defined( 'PRAUTOBLOGGER_PLUGIN_URL' ) ) {
|
||||||
define( 'PRAUTOBLOGGER_PLUGIN_URL', 'https://test.example.com/wp-content/plugins/prautoblogger/' );
|
define( 'PRAUTOBLOGGER_PLUGIN_URL', 'https://test.example.com/wp-content/plugins/prautoblogger/' );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ use Brain\Monkey\Functions;
|
|||||||
|
|
||||||
class BoardGenLogQueryTest extends BaseTestCase {
|
class BoardGenLogQueryTest extends BaseTestCase {
|
||||||
|
|
||||||
/** @var \PHPUnit\Framework\MockObject\MockObject Mock $wpdb. */
|
|
||||||
private $wpdb;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Captured prepare() calls: each entry is ['sql' => string, 'args' => array].
|
* Captured prepare() calls: each entry is ['sql' => string, 'args' => array].
|
||||||
*
|
*
|
||||||
@@ -29,19 +26,20 @@ class BoardGenLogQueryTest extends BaseTestCase {
|
|||||||
*/
|
*/
|
||||||
private array $prepare_calls = array();
|
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();
|
$wpdb->method( 'prepare' )->willReturnCallback(
|
||||||
$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(
|
|
||||||
static function ( string $sql, ...$args ) use ( $self ) {
|
static function ( string $sql, ...$args ) use ( $self ) {
|
||||||
// Flatten a single-array spread (Brain\Monkey unpacking).
|
|
||||||
if ( 1 === count( $args ) && is_array( $args[0] ) ) {
|
if ( 1 === count( $args ) && is_array( $args[0] ) ) {
|
||||||
$args = $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( 'get_transient' )->justReturn( false );
|
||||||
Functions\when( 'admin_url' )->alias(
|
Functions\when( 'admin_url' )->alias(
|
||||||
@@ -66,16 +70,10 @@ class BoardGenLogQueryTest extends BaseTestCase {
|
|||||||
return $default;
|
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 {
|
protected function tearDown(): void {
|
||||||
|
$this->prepare_calls = array();
|
||||||
unset( $GLOBALS['wpdb'] );
|
unset( $GLOBALS['wpdb'] );
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
@@ -90,13 +88,18 @@ class BoardGenLogQueryTest extends BaseTestCase {
|
|||||||
* datetime string second) that silently bound created_at >= <int>.
|
* datetime string second) that silently bound created_at >= <int>.
|
||||||
*/
|
*/
|
||||||
public function test_generating_cards_prepare_arg_order(): void {
|
public function test_generating_cards_prepare_arg_order(): void {
|
||||||
|
$this->make_wpdb();
|
||||||
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
||||||
$query->get_generating_cards();
|
$query->get_generating_cards();
|
||||||
|
|
||||||
// Find the prepare() call containing LIMIT %d (the gen-log secondary query).
|
// Find the prepare() call containing LIMIT %d (the gen-log secondary query).
|
||||||
$gen_call = null;
|
$gen_call = null;
|
||||||
foreach ( $this->prepare_calls as $call ) {
|
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;
|
$gen_call = $call;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -115,8 +118,9 @@ class BoardGenLogQueryTest extends BaseTestCase {
|
|||||||
* get_generating_cards() must return an empty array (not error) when DB returns nothing.
|
* 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 {
|
public function test_generating_cards_returns_empty_array_on_no_results(): void {
|
||||||
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
$this->make_wpdb();
|
||||||
$cards = $query->get_generating_cards();
|
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
||||||
|
$cards = $query->get_generating_cards();
|
||||||
$this->assertIsArray( $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).
|
* returns a card from the transient (no DB call needed for that card).
|
||||||
*/
|
*/
|
||||||
public function test_generating_cards_returns_transient_card_when_running(): void {
|
public function test_generating_cards_returns_transient_card_when_running(): void {
|
||||||
|
$this->make_wpdb();
|
||||||
|
|
||||||
Functions\when( 'get_transient' )->alias(
|
Functions\when( 'get_transient' )->alias(
|
||||||
function ( $key ) {
|
function ( $key ) {
|
||||||
if ( 'prautoblogger_generation_status' === $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.
|
* and the integer limit as the SECOND — matching placeholder order %s … %d.
|
||||||
*/
|
*/
|
||||||
public function test_failed_cards_prepare_arg_order(): void {
|
public function test_failed_cards_prepare_arg_order(): void {
|
||||||
|
$this->make_wpdb();
|
||||||
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
||||||
$query->get_failed_cards();
|
$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.
|
* get_failed_cards() returns the correct card shape from a seeded result row.
|
||||||
*/
|
*/
|
||||||
public function test_failed_cards_returns_correct_shape(): void {
|
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(
|
||||||
array(
|
array(
|
||||||
'run_id' => 'fail-run-abc',
|
'run_id' => 'fail-run-abc',
|
||||||
@@ -213,6 +221,7 @@ class BoardGenLogQueryTest extends BaseTestCase {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->make_wpdb();
|
||||||
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
$query = new \PRAutoBlogger_Board_Gen_Log_Query();
|
||||||
$query->get_generating_cards();
|
$query->get_generating_cards();
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,15 @@ class BoardHumanModifiedFlagTest extends BaseTestCase {
|
|||||||
);
|
);
|
||||||
Functions\when( 'get_edit_post_link' )->justReturn( 'https://example.com/edit' );
|
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( '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();
|
\PRAutoBlogger_Run_Stage_State::flush_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,9 @@ class GenerationCheckpointRunnerTest extends BaseTestCase {
|
|||||||
*/
|
*/
|
||||||
public function test_generate_tick_finalizes_when_queue_is_empty(): void {
|
public function test_generate_tick_finalizes_when_queue_is_empty(): void {
|
||||||
// No queue option => get_option returns false (default from setUp alias).
|
// 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();
|
\PRAutoBlogger_Generation_Checkpoint_Runner::on_generate_tick();
|
||||||
|
|
||||||
$this->assertNotContains(
|
$this->assertNotContains(
|
||||||
|
|||||||
Reference in New Issue
Block a user