From ece032efe5c07b87fc029514d7fc488e2adac3c1 Mon Sep 17 00:00:00 2001 From: peptiderepo Date: Sun, 12 Apr 2026 08:05:43 +0700 Subject: [PATCH] fix: add missing WordPress function stubs to unit tests - ContentAnalyzerTest: pass Cost_Tracker as 2nd constructor arg - IdeaScorerTest: stub get_option for topic_exclusions - CostTrackerTest: stub get_option for monthly_budget_usd - OpenRouterPricingTest: stub get_transient with cached model data - OpenRouterProviderTest: stub get_option for API key + get_transient Co-Authored-By: Claude Opus 4.6 --- tests/unit/Core/ContentAnalyzerTest.php | 29 +++++- tests/unit/Core/CostTrackerTest.php | 8 ++ tests/unit/Core/IdeaScorerTest.php | 9 ++ .../unit/Providers/OpenRouterPricingTest.php | 31 +++++++ .../unit/Providers/OpenRouterProviderTest.php | 88 +++++++++---------- 5 files changed, 118 insertions(+), 47 deletions(-) diff --git a/tests/unit/Core/ContentAnalyzerTest.php b/tests/unit/Core/ContentAnalyzerTest.php index 1b4187a..3befc73 100644 --- a/tests/unit/Core/ContentAnalyzerTest.php +++ b/tests/unit/Core/ContentAnalyzerTest.php @@ -20,18 +20,43 @@ class ContentAnalyzerTest extends BaseTestCase { */ private $mock_provider; + /** + * @var \PHPUnit\Framework\MockObject\MockObject Mock cost tracker. + */ + private $mock_cost_tracker; + protected function setUp(): void { parent::setUp(); // Create a mock that implements the LLM Provider Interface. $this->mock_provider = $this->createMock( \PRAutoBlogger_LLM_Provider_Interface::class ); + + // Create a mock cost tracker — ContentAnalyzer requires both provider and tracker. + $this->mock_cost_tracker = $this->createMock( \PRAutoBlogger_Cost_Tracker::class ); + + // Stub WordPress functions used internally by ContentAnalyzer. + $this->stub_get_option( [ + 'prautoblogger_monthly_budget_usd' => '50.00', + ] ); + + // Stub $wpdb for any database calls. + $wpdb = $this->create_mock_wpdb(); + $wpdb->method( 'prepare' )->willReturn( 'prepared' ); + $wpdb->method( 'get_var' )->willReturn( '0' ); + $wpdb->method( 'get_results' )->willReturn( [] ); + $GLOBALS['wpdb'] = $wpdb; + } + + protected function tearDown(): void { + unset( $GLOBALS['wpdb'] ); + parent::tearDown(); } /** * Test that ContentAnalyzer can be instantiated. */ public function test_content_analyzer_instantiation(): void { - $analyzer = new \PRAutoBlogger_Content_Analyzer( $this->mock_provider ); + $analyzer = new \PRAutoBlogger_Content_Analyzer( $this->mock_provider, $this->mock_cost_tracker ); $this->assertInstanceOf( \PRAutoBlogger_Content_Analyzer::class, $analyzer ); } @@ -53,7 +78,7 @@ class ContentAnalyzerTest extends BaseTestCase { $this->mock_provider->method( 'get_available_models' ) ->willReturn( [ 'model/test' ] ); - $analyzer = new \PRAutoBlogger_Content_Analyzer( $this->mock_provider ); + $analyzer = new \PRAutoBlogger_Content_Analyzer( $this->mock_provider, $this->mock_cost_tracker ); // analyze_recent_data takes no parameters. $result = $analyzer->analyze_recent_data(); diff --git a/tests/unit/Core/CostTrackerTest.php b/tests/unit/Core/CostTrackerTest.php index 6f2a47c..d60128c 100644 --- a/tests/unit/Core/CostTrackerTest.php +++ b/tests/unit/Core/CostTrackerTest.php @@ -25,6 +25,14 @@ class CostTrackerTest extends BaseTestCase { $this->wpdb = $this->create_mock_wpdb(); $GLOBALS['wpdb'] = $this->wpdb; + + // CostTracker methods call get_option for budget settings. + $this->stub_get_option( [ + 'prautoblogger_monthly_budget_usd' => '50.00', + ] ); + + // Stub current_time used in date-based queries. + $this->stub_current_time( '2026-04-12 10:00:00' ); } protected function tearDown(): void { diff --git a/tests/unit/Core/IdeaScorerTest.php b/tests/unit/Core/IdeaScorerTest.php index 61917bd..a7d238c 100644 --- a/tests/unit/Core/IdeaScorerTest.php +++ b/tests/unit/Core/IdeaScorerTest.php @@ -14,6 +14,15 @@ use Brain\Monkey\Functions; class IdeaScorerTest extends BaseTestCase { + protected function setUp(): void { + parent::setUp(); + + // IdeaScorer::score_and_rank() calls get_option('prautoblogger_topic_exclusions', '[]'). + $this->stub_get_option( [ + 'prautoblogger_topic_exclusions' => '[]', + ] ); + } + /** * Test Idea Scorer can be instantiated. */ diff --git a/tests/unit/Providers/OpenRouterPricingTest.php b/tests/unit/Providers/OpenRouterPricingTest.php index b842404..0dfd0f6 100644 --- a/tests/unit/Providers/OpenRouterPricingTest.php +++ b/tests/unit/Providers/OpenRouterPricingTest.php @@ -10,9 +10,40 @@ namespace PRAutoBlogger\Tests\Providers; use PRAutoBlogger\Tests\BaseTestCase; +use Brain\Monkey\Functions; class OpenRouterPricingTest extends BaseTestCase { + protected function setUp(): void { + parent::setUp(); + + // OpenRouterPricing::get_available_models() calls get_transient() to check cache. + // Return a valid cached model list so it doesn't try to make HTTP calls. + Functions\when( 'get_transient' )->alias( + function ( string $key ) { + if ( 'prautoblogger_openrouter_models' === $key ) { + return [ + [ + 'id' => 'google/gemini-2.0-flash-001', + 'name' => 'Gemini 2.0 Flash', + 'context_length' => 32768, + 'pricing' => [ 'prompt' => 0.10, 'completion' => 0.40 ], + ], + [ + 'id' => 'anthropic/claude-sonnet-4', + 'name' => 'Claude Sonnet 4', + 'context_length' => 200000, + 'pricing' => [ 'prompt' => 3.00, 'completion' => 15.00 ], + ], + ]; + } + return false; + } + ); + + Functions\when( 'set_transient' )->justReturn( true ); + } + /** * Test Pricing can be instantiated. */ diff --git a/tests/unit/Providers/OpenRouterProviderTest.php b/tests/unit/Providers/OpenRouterProviderTest.php index bdb013d..dd46c9e 100644 --- a/tests/unit/Providers/OpenRouterProviderTest.php +++ b/tests/unit/Providers/OpenRouterProviderTest.php @@ -15,15 +15,53 @@ use Brain\Monkey\Functions; class OpenRouterProviderTest extends BaseTestCase { + protected function setUp(): void { + parent::setUp(); + + // Stub get_option — provider calls get_option('prautoblogger_openrouter_api_key', '') + // for API key retrieval via private get_api_key() method. + $this->stub_get_option( [ + 'prautoblogger_openrouter_api_key' => 'test_encrypted_key', + ] ); + + // Stub get_transient/set_transient — used by OpenRouter_Pricing (called internally). + Functions\when( 'get_transient' )->alias( + function ( string $key ) { + if ( 'prautoblogger_openrouter_models' === $key ) { + return [ + [ + 'id' => 'model/test', + 'name' => 'Test Model', + 'context_length' => 4096, + 'pricing' => [ 'prompt' => 1.00, 'completion' => 2.00 ], + ], + ]; + } + return false; + } + ); + Functions\when( 'set_transient' )->justReturn( true ); + + // Stub HTTP functions for API calls. + Functions\when( 'wp_remote_post' )->justReturn( [ + 'body' => '{"choices":[{"message":{"content":"test"},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":5,"total_tokens":15}}', + 'response' => [ 'code' => 200 ], + ] ); + Functions\when( 'wp_remote_get' )->justReturn( [ + 'body' => '{}', + 'response' => [ 'code' => 200 ], + ] ); + Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); + Functions\when( 'wp_remote_retrieve_body' )->justReturn( + '{"choices":[{"message":{"content":"test"},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":5,"total_tokens":15}}' + ); + Functions\when( 'is_wp_error' )->justReturn( false ); + } + /** * Test OpenRouter Provider can be instantiated. */ public function test_openrouter_provider_instantiation(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $this->assertInstanceOf( \PRAutoBlogger_OpenRouter_Provider::class, $provider ); @@ -33,11 +71,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test that provider implements LLM Provider Interface. */ public function test_provider_implements_interface(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $this->assertInstanceOf( \PRAutoBlogger_LLM_Provider_Interface::class, $provider ); @@ -47,11 +80,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test send_chat_completion method is callable. */ public function test_send_chat_completion_method_exists(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $this->assertTrue( method_exists( $provider, 'send_chat_completion' ) ); @@ -61,11 +89,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test get_available_models returns array. */ public function test_get_available_models_returns_array(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $models = $provider->get_available_models(); @@ -76,11 +99,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test estimate_cost returns float. */ public function test_estimate_cost_returns_float(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $cost = $provider->estimate_cost( 'model/test', 1000, 500 ); @@ -91,11 +109,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test get_provider_name returns string. */ public function test_get_provider_name_returns_string(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $name = $provider->get_provider_name(); @@ -107,11 +120,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test validate_credentials returns boolean. */ public function test_validate_credentials_returns_boolean(): void { - Functions\when( 'wp_remote_post' )->justReturn( [] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $valid = $provider->validate_credentials(); @@ -122,11 +130,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test send_chat_completion returns array. */ public function test_send_chat_completion_returns_array(): void { - Functions\when( 'wp_remote_post' )->justReturn( [ 'body' => '{}' ] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $messages = [ @@ -142,11 +145,6 @@ class OpenRouterProviderTest extends BaseTestCase { * Test send_chat_completion with options. */ public function test_send_chat_completion_with_options(): void { - Functions\when( 'wp_remote_post' )->justReturn( [ 'body' => '{}' ] ); - Functions\when( 'wp_remote_retrieve_response_code' )->justReturn( 200 ); - Functions\when( 'wp_remote_retrieve_body' )->justReturn( '{}' ); - Functions\when( 'is_wp_error' )->justReturn( false ); - $provider = new \PRAutoBlogger_OpenRouter_Provider(); $messages = [