master_trainer = $this->factory->user->create( array( 'role' => 'hvac_master_trainer', 'user_login' => 'master_trainer', 'user_email' => 'master@example.com', ) ); $this->regular_trainer = $this->factory->user->create( array( 'role' => 'hvac_trainer', 'user_login' => 'regular_trainer', 'user_email' => 'trainer@example.com', ) ); // Add capabilities HVAC_Announcements_Permissions::add_capabilities(); // Create test announcements with different statuses $this->test_announcements['published'] = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Published Announcement', 'post_content' => 'This is published content.', 'post_excerpt' => 'Published excerpt', 'post_status' => 'publish', 'post_author' => $this->master_trainer, ) ); $this->test_announcements['draft'] = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Draft Announcement', 'post_content' => 'This is draft content.', 'post_status' => 'draft', 'post_author' => $this->master_trainer, ) ); // Get display handler instance $this->display_handler = HVAC_Announcements_Display::get_instance(); } /** * Teardown after each test */ public function tearDown() { parent::tearDown(); // Clean up test announcements foreach ( $this->test_announcements as $post_id ) { wp_delete_post( $post_id, true ); } // Clean up test users wp_delete_user( $this->master_trainer ); wp_delete_user( $this->regular_trainer ); // Remove capabilities HVAC_Announcements_Permissions::remove_capabilities(); } /** * Test shortcode registration */ public function test_shortcodes_registered() { global $shortcode_tags; $this->assertArrayHasKey( 'hvac_announcements_timeline', $shortcode_tags ); $this->assertArrayHasKey( 'hvac_announcements_list', $shortcode_tags ); $this->assertArrayHasKey( 'hvac_google_drive_embed', $shortcode_tags ); } /** * Test timeline shortcode output for authorized user */ public function test_timeline_shortcode_authorized() { wp_set_current_user( $this->regular_trainer ); $output = do_shortcode( '[hvac_announcements_timeline posts_per_page="5"]' ); // Should contain the wrapper div $this->assertStringContainsString( 'hvac-announcements-timeline', $output ); // Should contain the published announcement $this->assertStringContainsString( 'Published Announcement', $output ); // Should NOT contain draft announcement for regular trainer $this->assertStringNotContainsString( 'Draft Announcement', $output ); // Should contain modal structure $this->assertStringContainsString( 'announcement-modal', $output ); } /** * Test timeline shortcode output for unauthorized user */ public function test_timeline_shortcode_unauthorized() { // Create non-trainer user $subscriber = $this->factory->user->create( array( 'role' => 'subscriber', ) ); wp_set_current_user( $subscriber ); $output = do_shortcode( '[hvac_announcements_timeline]' ); // Should show permission denied message $this->assertStringContainsString( 'You do not have permission to view announcements', $output ); // Clean up wp_delete_user( $subscriber ); } /** * Test list shortcode attributes */ public function test_list_shortcode_attributes() { wp_set_current_user( $this->regular_trainer ); // Test with show_excerpt="no" $output = do_shortcode( '[hvac_announcements_list show_excerpt="no" show_date="yes"]' ); // Should contain the list wrapper $this->assertStringContainsString( 'hvac-announcements-list', $output ); // Should contain announcement title $this->assertStringContainsString( 'Published Announcement', $output ); } /** * Test Google Drive embed shortcode */ public function test_google_drive_shortcode() { wp_set_current_user( $this->regular_trainer ); $output = do_shortcode( '[hvac_google_drive_embed url="https://drive.google.com/drive/folders/16uDRkFcaEqKUxfBek9VbfbAIeFV77nZG" height="500"]' ); // Should contain iframe $this->assertStringContainsString( 'assertStringContainsString( 'height="500"', $output ); // Should contain embed URL $this->assertStringContainsString( 'embeddedfolderview', $output ); } /** * Test Google Drive URL conversion */ public function test_drive_url_conversion() { $reflection = new ReflectionClass( $this->display_handler ); $method = $reflection->getMethod( 'convert_drive_url_to_embed' ); $method->setAccessible( true ); // Test folder URL conversion $sharing_url = 'https://drive.google.com/drive/folders/16uDRkFcaEqKUxfBek9VbfbAIeFV77nZG?usp=drive_link'; $embed_url = $method->invoke( $this->display_handler, $sharing_url ); $this->assertEquals( 'https://drive.google.com/embeddedfolderview?id=16uDRkFcaEqKUxfBek9VbfbAIeFV77nZG#list', $embed_url ); // Test invalid URL returns original $invalid_url = 'https://example.com/not-a-drive-url'; $result = $method->invoke( $this->display_handler, $invalid_url ); $this->assertEquals( $invalid_url, $result ); } /** * Test get_announcement_content with permissions */ public function test_get_announcement_content_permissions() { // Test as regular trainer viewing published announcement wp_set_current_user( $this->regular_trainer ); $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['published'] ); $this->assertStringContainsString( 'Published Announcement', $content ); $this->assertStringContainsString( 'This is published content.', $content ); // Test as regular trainer viewing draft announcement (should be empty) $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['draft'] ); $this->assertEmpty( $content ); // Test as master trainer viewing draft announcement wp_set_current_user( $this->master_trainer ); $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['draft'] ); $this->assertStringContainsString( 'Draft Announcement', $content ); } /** * Test output escaping in get_announcement_content */ public function test_output_escaping() { // Create announcement with special characters $test_id = wp_insert_post( array( 'post_type' => HVAC_Announcements_CPT::get_post_type(), 'post_title' => 'Test & Title with characters', 'post_content' => 'Content with & and < > characters', 'post_status' => 'publish', 'post_author' => $this->master_trainer, ) ); wp_set_current_user( $this->regular_trainer ); $content = HVAC_Announcements_Display::get_announcement_content( $test_id ); // Title should be escaped $this->assertStringContainsString( 'Test & Title with <special> characters', $content ); // Clean up wp_delete_post( $test_id, true ); } /** * Test categories and tags display */ public function test_categories_and_tags_display() { // Add category and tags to announcement $category_id = wp_insert_term( 'Test Category', HVAC_Announcements_CPT::get_category_taxonomy() ); wp_set_post_terms( $this->test_announcements['published'], array( $category_id['term_id'] ), HVAC_Announcements_CPT::get_category_taxonomy() ); wp_set_post_terms( $this->test_announcements['published'], array( 'tag1', 'tag2' ), HVAC_Announcements_CPT::get_tag_taxonomy() ); wp_set_current_user( $this->regular_trainer ); $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['published'] ); // Should contain categories and tags $this->assertStringContainsString( 'Categories:', $content ); $this->assertStringContainsString( 'Test Category', $content ); $this->assertStringContainsString( 'Tags:', $content ); $this->assertStringContainsString( 'tag1', $content ); $this->assertStringContainsString( 'tag2', $content ); // Clean up wp_delete_term( $category_id['term_id'], HVAC_Announcements_CPT::get_category_taxonomy() ); } /** * Test singleton pattern */ public function test_singleton_pattern() { $instance1 = HVAC_Announcements_Display::get_instance(); $instance2 = HVAC_Announcements_Display::get_instance(); $this->assertSame( $instance1, $instance2 ); } }