test_trainers[] = $this->factory->user->create( array( 'role' => 'hvac_trainer', 'user_login' => 'trainer_' . $i, 'user_email' => 'trainer' . $i . '@example.com', 'display_name' => 'Trainer ' . $i, ) ); } // Add capabilities HVAC_Announcements_Permissions::add_capabilities(); // Create test announcement $this->test_announcement = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Test Announcement for Email', 'post_content' => 'This is the content of the test announcement.', 'post_excerpt' => 'Test excerpt', 'post_status' => 'draft', 'post_author' => $this->test_trainers[0], ) ); } /** * Teardown after each test */ public function tearDown() { parent::tearDown(); // Clean up test announcement if ( $this->test_announcement ) { wp_delete_post( $this->test_announcement, true ); } // Clean up test users foreach ( $this->test_trainers as $user_id ) { wp_delete_user( $user_id ); } // Remove capabilities HVAC_Announcements_Permissions::remove_capabilities(); } /** * Test email status tracking */ public function test_email_status_tracking() { // Initially no email sent $status = HVAC_Announcements_Email::get_email_status( $this->test_announcement ); $this->assertFalse( $status['sent'] ); $this->assertEquals( 0, $status['total_recipients'] ); $this->assertEquals( 0, $status['successful'] ); $this->assertEquals( 0, $status['failed'] ); // Mark as sent update_post_meta( $this->test_announcement, '_hvac_announcement_email_sent', true ); update_post_meta( $this->test_announcement, '_hvac_announcement_email_recipients', $this->test_trainers ); $status = HVAC_Announcements_Email::get_email_status( $this->test_announcement ); $this->assertTrue( $status['sent'] ); $this->assertEquals( 3, $status['total_recipients'] ); } /** * Test email validation in headers */ public function test_email_header_validation() { // Mock invalid admin email update_option( 'admin_email', 'invalid-email' ); $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $method = $reflection->getMethod( 'get_email_headers' ); $method->setAccessible( true ); $headers = $method->invoke( $email_handler ); // Should have Content-Type header $this->assertContains( 'Content-Type: text/html; charset=UTF-8', $headers ); // Should have From header with fallback email $from_header = $headers[1]; $this->assertStringContainsString( 'From:', $from_header ); // Restore original admin email update_option( 'admin_email', 'admin@example.com' ); } /** * Test batch size filter */ public function test_batch_size_filter() { // Test default batch size $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $batch_size_prop = $reflection->getProperty( 'batch_size' ); $batch_size_prop->setAccessible( true ); $default_batch_size = $batch_size_prop->getValue( $email_handler ); $this->assertEquals( 50, $default_batch_size ); // Test filter add_filter( 'hvac_announcement_email_batch_size', function() { return 25; } ); // Create new instance to apply filter $reflection_constructor = $reflection->getConstructor(); $new_instance = $reflection->newInstanceWithoutConstructor(); $reflection_constructor->invoke( $new_instance ); $filtered_batch_size = $batch_size_prop->getValue( $new_instance ); $this->assertEquals( 25, $filtered_batch_size ); // Remove filter remove_all_filters( 'hvac_announcement_email_batch_size' ); } /** * Test email subject generation */ public function test_email_subject() { $post = get_post( $this->test_announcement ); $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $method = $reflection->getMethod( 'get_email_subject' ); $method->setAccessible( true ); $subject = $method->invoke( $email_handler, $post ); $this->assertStringContainsString( 'Upskill HVAC Trainer Announcement:', $subject ); $this->assertStringContainsString( 'Test Announcement for Email', $subject ); } /** * Test email body generation */ public function test_email_body() { $post = get_post( $this->test_announcement ); $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $method = $reflection->getMethod( 'get_email_body' ); $method->setAccessible( true ); $body = $method->invoke( $email_handler, $post ); // Should contain HTML structure $this->assertStringContainsString( '', $body ); $this->assertStringContainsString( '', $body ); $this->assertStringContainsString( '', $body ); // Should contain announcement title $this->assertStringContainsString( 'Test Announcement for Email', $body ); // Should contain announcement content $this->assertStringContainsString( 'This is the content of the test announcement.', $body ); } /** * Test fallback email body */ public function test_fallback_email_body() { $post = get_post( $this->test_announcement ); $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $method = $reflection->getMethod( 'get_fallback_email_body' ); $method->setAccessible( true ); $body = $method->invoke( $email_handler, $post ); // Should contain HTML structure $this->assertStringContainsString( '', $body ); $this->assertStringContainsString( 'Upskill HVAC Trainer Announcement', $body ); $this->assertStringContainsString( 'Test Announcement for Email', $body ); $this->assertStringContainsString( 'You received this email because you are registered as an HVAC Trainer', $body ); } /** * Test email logging */ public function test_email_logging() { $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $method = $reflection->getMethod( 'log_email_send' ); $method->setAccessible( true ); // Log successful send $method->invoke( $email_handler, $this->test_announcement, $this->test_trainers[0], 'success' ); // Log failed send $method->invoke( $email_handler, $this->test_announcement, $this->test_trainers[1], 'failed' ); // Check log $log = get_post_meta( $this->test_announcement, '_hvac_announcement_email_log', true ); $this->assertIsArray( $log ); $this->assertCount( 2, $log ); $this->assertEquals( $this->test_trainers[0], $log[0]['user_id'] ); $this->assertEquals( 'success', $log[0]['status'] ); $this->assertEquals( $this->test_trainers[1], $log[1]['user_id'] ); $this->assertEquals( 'failed', $log[1]['status'] ); } /** * Test retry mechanism */ public function test_retry_mechanism() { $email_handler = HVAC_Announcements_Email::get_instance(); $reflection = new ReflectionClass( $email_handler ); $method = $reflection->getMethod( 'maybe_schedule_retry' ); $method->setAccessible( true ); // First retry $method->invoke( $email_handler, $this->test_announcement, $this->test_trainers[0] ); $retry_count = get_user_meta( $this->test_trainers[0], '_hvac_announcement_email_retry_' . $this->test_announcement, true ); $this->assertEquals( 1, $retry_count ); // Second retry $method->invoke( $email_handler, $this->test_announcement, $this->test_trainers[0] ); $retry_count = get_user_meta( $this->test_trainers[0], '_hvac_announcement_email_retry_' . $this->test_announcement, true ); $this->assertEquals( 2, $retry_count ); // Third retry $method->invoke( $email_handler, $this->test_announcement, $this->test_trainers[0] ); $retry_count = get_user_meta( $this->test_trainers[0], '_hvac_announcement_email_retry_' . $this->test_announcement, true ); $this->assertEquals( 3, $retry_count ); // Fourth retry should not increase (max 3) $method->invoke( $email_handler, $this->test_announcement, $this->test_trainers[0] ); $retry_count = get_user_meta( $this->test_trainers[0], '_hvac_announcement_email_retry_' . $this->test_announcement, true ); $this->assertEquals( 3, $retry_count ); } /** * Test singleton pattern */ public function test_singleton_pattern() { $instance1 = HVAC_Announcements_Email::get_instance(); $instance2 = HVAC_Announcements_Email::get_instance(); $this->assertSame( $instance1, $instance2 ); } }