manager = HVAC_Announcements_Manager::get_instance(); // Create test roles if they don't exist if ( !get_role( 'hvac_master_trainer' ) ) { add_role( 'hvac_master_trainer', 'HVAC Master Trainer', array( 'read' => true, 'edit_posts' => true, 'delete_posts' => true, ) ); } if ( !get_role( 'hvac_trainer' ) ) { add_role( 'hvac_trainer', 'HVAC Trainer', array( 'read' => true, ) ); } // Run activation to set up capabilities HVAC_Announcements_Manager::activate(); // Create test users $this->master_trainer = $this->factory->user->create( array( 'role' => 'hvac_master_trainer', 'user_login' => 'master_workflow', 'user_email' => 'master@workflow.com', 'display_name' => 'Master Trainer', ) ); $this->regular_trainer = $this->factory->user->create( array( 'role' => 'hvac_trainer', 'user_login' => 'trainer_workflow', 'user_email' => 'trainer@workflow.com', 'display_name' => 'Regular Trainer', ) ); $this->subscriber = $this->factory->user->create( array( 'role' => 'subscriber', 'user_login' => 'subscriber_workflow', 'user_email' => 'subscriber@workflow.com', ) ); } /** * Teardown after each test */ public function tearDown() { parent::tearDown(); // Clean up users wp_delete_user( $this->master_trainer ); wp_delete_user( $this->regular_trainer ); wp_delete_user( $this->subscriber ); // Run deactivation HVAC_Announcements_Manager::deactivate(); } /** * Test complete announcement creation and display workflow */ public function test_complete_announcement_workflow() { // Step 1: Master trainer creates announcement wp_set_current_user( $this->master_trainer ); $announcement_id = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Workflow Test Announcement', 'post_content' => '

This is a test announcement for the workflow.

', 'post_excerpt' => 'Test excerpt for workflow', 'post_status' => 'draft', 'post_author' => $this->master_trainer, ) ); $this->assertNotEquals( 0, $announcement_id ); // Step 2: Add categories and tags $category = wp_insert_term( 'Workflow Category', HVAC_Announcements_CPT::get_category_taxonomy() ); $this->assertFalse( is_wp_error( $category ) ); wp_set_post_terms( $announcement_id, array( $category['term_id'] ), HVAC_Announcements_CPT::get_category_taxonomy() ); wp_set_post_terms( $announcement_id, array( 'workflow', 'test', 'integration' ), HVAC_Announcements_CPT::get_tag_taxonomy() ); // Step 3: Add featured image $attachment_id = $this->factory->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg', $announcement_id ); set_post_thumbnail( $announcement_id, $attachment_id ); // Step 4: Verify draft is not visible to regular trainer wp_set_current_user( $this->regular_trainer ); $content = HVAC_Announcements_Display::get_announcement_content( $announcement_id ); $this->assertEmpty( $content, 'Draft should not be visible to regular trainer' ); // Step 5: Publish announcement wp_set_current_user( $this->master_trainer ); wp_update_post( array( 'ID' => $announcement_id, 'post_status' => 'publish', ) ); // Step 6: Verify published announcement is visible to regular trainer wp_set_current_user( $this->regular_trainer ); $content = HVAC_Announcements_Display::get_announcement_content( $announcement_id ); $this->assertNotEmpty( $content, 'Published announcement should be visible to regular trainer' ); $this->assertStringContainsString( 'Workflow Test Announcement', $content ); $this->assertStringContainsString( 'test announcement', $content ); // Step 7: Verify categories and tags are displayed $this->assertStringContainsString( 'Workflow Category', $content ); $this->assertStringContainsString( 'workflow', $content ); // Step 8: Test timeline shortcode display $timeline_output = do_shortcode( '[hvac_announcements_timeline posts_per_page="5"]' ); $this->assertStringContainsString( 'hvac-announcements-timeline', $timeline_output ); $this->assertStringContainsString( 'Workflow Test Announcement', $timeline_output ); $this->assertStringContainsString( 'announcement-link', $timeline_output ); $this->assertStringContainsString( 'data-id="' . $announcement_id . '"', $timeline_output ); // Step 9: Test list shortcode display $list_output = do_shortcode( '[hvac_announcements_list posts_per_page="5" show_excerpt="yes"]' ); $this->assertStringContainsString( 'hvac-announcements-list', $list_output ); $this->assertStringContainsString( 'Workflow Test Announcement', $list_output ); $this->assertStringContainsString( 'Test excerpt for workflow', $list_output ); // Step 10: Verify subscriber cannot view announcements wp_set_current_user( $this->subscriber ); $content = HVAC_Announcements_Display::get_announcement_content( $announcement_id ); $this->assertEmpty( $content, 'Subscriber should not be able to view announcements' ); $timeline_output = do_shortcode( '[hvac_announcements_timeline]' ); $this->assertStringContainsString( 'You do not have permission', $timeline_output ); // Clean up wp_delete_post( $announcement_id, true ); wp_delete_attachment( $attachment_id, true ); wp_delete_term( $category['term_id'], HVAC_Announcements_CPT::get_category_taxonomy() ); } /** * Test email notification workflow */ public function test_email_notification_workflow() { // Create additional trainers to receive emails $trainer_ids = array(); for ( $i = 1; $i <= 5; $i++ ) { $trainer_ids[] = $this->factory->user->create( array( 'role' => 'hvac_trainer', 'user_login' => 'email_trainer_' . $i, 'user_email' => 'trainer' . $i . '@test.com', ) ); } // Step 1: Create announcement as draft wp_set_current_user( $this->master_trainer ); $announcement_id = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Email Test Announcement', 'post_content' => 'This announcement will trigger emails.', 'post_status' => 'draft', ) ); // Step 2: Verify no emails sent for draft $email_status = HVAC_Announcements_Email::get_email_status( $announcement_id ); $this->assertFalse( $email_status['sent'] ); $this->assertEquals( 0, $email_status['total_recipients'] ); // Step 3: Publish announcement wp_update_post( array( 'ID' => $announcement_id, 'post_status' => 'publish', ) ); // Manually trigger the status transition handler $email_handler = HVAC_Announcements_Email::get_instance(); $email_handler->handle_status_transition( 'publish', 'draft', get_post( $announcement_id ) ); // Step 4: Verify emails were queued $recipients = get_post_meta( $announcement_id, '_hvac_announcement_email_recipients', true ); $this->assertNotEmpty( $recipients ); $this->assertGreaterThanOrEqual( 6, count( $recipients ) ); // 5 new + regular trainer // Step 5: Simulate email batch processing $reflection = new ReflectionClass( $email_handler ); $send_batch_method = $reflection->getMethod( 'send_email_batch' ); $send_batch_method->setAccessible( true ); // Note: We can't actually send emails in tests, but we can verify the process $test_batch = array_slice( $recipients, 0, 2 ); // Mock email sending by logging foreach ( $test_batch as $user_id ) { $log_method = $reflection->getMethod( 'log_email_send' ); $log_method->setAccessible( true ); $log_method->invoke( $email_handler, $announcement_id, $user_id, 'success' ); } // Step 6: Verify email log $log = get_post_meta( $announcement_id, '_hvac_announcement_email_log', true ); $this->assertNotEmpty( $log ); $this->assertGreaterThanOrEqual( 2, count( $log ) ); // Clean up wp_delete_post( $announcement_id, true ); foreach ( $trainer_ids as $id ) { wp_delete_user( $id ); } } /** * Test permission enforcement throughout workflow */ public function test_permission_enforcement_workflow() { // Step 1: Regular trainer cannot create announcements wp_set_current_user( $this->regular_trainer ); $this->assertFalse( HVAC_Announcements_Permissions::current_user_can_create() ); // Step 2: Master trainer can create announcements wp_set_current_user( $this->master_trainer ); $this->assertTrue( HVAC_Announcements_Permissions::current_user_can_create() ); // Create announcement $announcement_id = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Permission Test', 'post_status' => 'publish', 'post_author' => $this->master_trainer, ) ); // Step 3: Regular trainer cannot edit announcement wp_set_current_user( $this->regular_trainer ); $this->assertFalse( HVAC_Announcements_Permissions::current_user_can_edit( $announcement_id ) ); $this->assertFalse( HVAC_Announcements_Permissions::current_user_can_delete( $announcement_id ) ); // Step 4: Master trainer can edit own announcement wp_set_current_user( $this->master_trainer ); $this->assertTrue( HVAC_Announcements_Permissions::current_user_can_edit( $announcement_id ) ); $this->assertTrue( HVAC_Announcements_Permissions::current_user_can_delete( $announcement_id ) ); // Step 5: Create another master trainer $another_master = $this->factory->user->create( array( 'role' => 'hvac_master_trainer', 'user_login' => 'another_master', 'user_email' => 'another@master.com', ) ); // Step 6: Other master trainer can edit announcement wp_set_current_user( $another_master ); $this->assertTrue( HVAC_Announcements_Permissions::current_user_can_edit( $announcement_id ) ); $this->assertTrue( HVAC_Announcements_Permissions::current_user_can_delete( $announcement_id ) ); // Clean up wp_delete_post( $announcement_id, true ); wp_delete_user( $another_master ); } /** * Test caching throughout workflow */ public function test_caching_workflow() { // Step 1: Create multiple announcements wp_set_current_user( $this->master_trainer ); $announcement_ids = array(); for ( $i = 1; $i <= 5; $i++ ) { $announcement_ids[] = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Cache Test ' . $i, 'post_status' => 'publish', 'post_date' => date( 'Y-m-d H:i:s', strtotime( '-' . $i . ' hours' ) ), ) ); } // Step 2: First query should miss cache $cache_key = 'test_workflow_cache'; wp_cache_delete( $cache_key, 'hvac_announcements' ); $cached = wp_cache_get( $cache_key, 'hvac_announcements' ); $this->assertFalse( $cached ); // Simulate caching the query result $query_result = array( 'announcements' => $announcement_ids, 'total' => 5 ); wp_cache_set( $cache_key, $query_result, 'hvac_announcements', 120 ); // Step 3: Second query should hit cache $cached = wp_cache_get( $cache_key, 'hvac_announcements' ); $this->assertNotFalse( $cached ); $this->assertEquals( $query_result, $cached ); // Step 4: Creating new announcement should clear cache $ajax_handler = HVAC_Announcements_Ajax::get_instance(); $ajax_handler->clear_announcements_cache(); // Version should be incremented $version = wp_cache_get( 'announcements_cache_version', 'hvac_announcements' ); $this->assertGreaterThan( 0, $version ); // Step 5: Test user cache $active_trainers = HVAC_Announcements_Permissions::get_active_trainers(); $this->assertNotEmpty( $active_trainers ); // Second call should use cache $cached_trainers = HVAC_Announcements_Permissions::get_active_trainers(); $this->assertEquals( $active_trainers, $cached_trainers ); // Clean up foreach ( $announcement_ids as $id ) { wp_delete_post( $id, true ); } } /** * Test Google Drive integration */ public function test_google_drive_integration() { wp_set_current_user( $this->regular_trainer ); // Test shortcode $output = do_shortcode( '[hvac_google_drive_embed url="https://drive.google.com/drive/folders/test123" height="400" width="100%"]' ); $this->assertStringContainsString( 'assertStringContainsString( 'height="400"', $output ); $this->assertStringContainsString( 'width="100%"', $output ); $this->assertStringContainsString( 'embeddedfolderview?id=test123', $output ); // Test permission check wp_set_current_user( $this->subscriber ); $output = do_shortcode( '[hvac_google_drive_embed]' ); $this->assertStringContainsString( 'You do not have permission to view training resources', $output ); } }