user->create( [ 'role' => 'hvac_trainer', ] ); // Ensure The Events Calendar core classes are loaded if needed // Note: This might require adjustments based on how TEC is loaded in bootstrap.php if ( ! class_exists( 'Tribe__Events__Main' ) && defined( 'TRIBE_EVENTS_FILE' ) ) { require_once dirname( TRIBE_EVENTS_FILE ) . '/src/Tribe/Main.php'; } } /** * Set up the test environment before each test method runs. */ public function set_up() { parent::set_up(); // Set the current user to the test trainer for permission-based tests wp_set_current_user( self::$trainer_user_id ); } /** * Tear down the test environment after each test method runs. */ public function tear_down() { // Reset the current user wp_set_current_user( 0 ); parent::tear_down(); } // --- Test Cases --- /** * Test that event creation fails if required data (e.g., title) is missing. * @test */ public function test_event_creation_requires_valid_data() { // Assume TEC CE handler doesn't exist or fails for this test path if ( class_exists( 'Tribe__Events__Community__Main' ) ) { $this->markTestSkipped('Skipping manual fallback test when TEC CE is active.'); } // 1. Prepare POST data missing the title $_POST = [ 'action' => 'hvac_save_event', 'event_id' => 0, '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), 'event_title' => '', // Missing title 'event_description' => 'Description without title.', // Add other fields like dates if they are validated in the fallback ]; // 2. Instantiate handler and call method (expecting wp_die or error handling) $handler = HVAC_Event_Handler::get_instance(); ob_start(); @$handler->process_event_submission(); $output = ob_get_clean(); // Capture potential wp_die output // 3. Assert no event was created $args = [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_status' => 'any', 'post_content' => 'Description without title.', // Search by content as title is empty 'posts_per_page' => 1, ]; $events = get_posts( $args ); $this->assertCount( 0, $events, 'No event should have been created with missing title.' ); // Optional: Check output for expected error message if wp_die was caught // $this->assertStringContainsString( 'Event Title is required', $output ); // TODO: Add more scenarios for other invalid data (e.g., invalid dates) // Clean up unset( $_POST ); } /** * Test successful event creation with valid data using the fallback logic. * @test */ public function test_event_creation_success() { // Assume TEC CE handler doesn't exist or fails for this test path if ( class_exists( 'Tribe__Events__Community__Main' ) ) { $this->markTestSkipped('Skipping manual fallback test when TEC CE is active.'); } // 1. Create dependencies $venue_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::VENUE_POST_TYPE, 'post_title' => 'Test Venue', 'post_status' => 'publish', ] ); $organizer_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::ORGANIZER_POST_TYPE, 'post_title' => 'Test Organizer', 'post_status' => 'publish', ] ); // 2. Prepare mock POST data (using common TEC field names) $start_date = date( 'Y-m-d H:i:s', strtotime( '+1 day' ) ); $end_date = date( 'Y-m-d H:i:s', strtotime( '+1 day +2 hours' ) ); $_POST = [ 'action' => 'hvac_save_event', 'event_id' => 0, // Creating new event '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), // Generate a valid nonce 'event_title' => 'My Test Event', 'event_description' => 'This is the event description.', // TEC Date fields (adjust names if needed based on actual form) 'EventStartDate' => date( 'Y-m-d', strtotime( $start_date ) ), 'EventStartTime' => date( 'h:i A', strtotime( $start_date ) ), 'EventEndDate' => date( 'Y-m-d', strtotime( $end_date ) ), 'EventEndTime' => date( 'h:i A', strtotime( $end_date ) ), // TEC Venue/Organizer fields (adjust names if needed) 'venue' => [ 'VenueID' => $venue_id ], 'organizer' => [ 'OrganizerID' => $organizer_id ], // Add other necessary fields like cost, categories etc. if required by fallback logic ]; // 3. Instantiate handler and call method $handler = HVAC_Event_Handler::get_instance(); // Use output buffering to catch potential wp_die output if redirection fails ob_start(); // We expect this to redirect, so catch potential headers already sent errors/output @$handler->process_event_submission(); ob_end_clean(); // Discard output buffer // 4. Assertions $args = [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_status' => 'publish', // Assuming fallback publishes directly 'title' => 'My Test Event', 'author' => self::$trainer_user_id, 'posts_per_page' => 1, ]; $events = get_posts( $args ); $this->assertCount( 1, $events, 'Expected one event to be created.' ); $created_event_id = $events[0]->ID; // Assert basic post data $this->assertEquals( 'My Test Event', $events[0]->post_title ); $this->assertEquals( 'This is the event description.', $events[0]->post_content ); $this->assertEquals( self::$trainer_user_id, $events[0]->post_author ); // Assert meta data (requires fallback logic in handler to save these) $this->assertEquals( $start_date, get_post_meta( $created_event_id, '_EventStartDate', true ) ); $this->assertEquals( $end_date, get_post_meta( $created_event_id, '_EventEndDate', true ) ); $this->assertEquals( $venue_id, get_post_meta( $created_event_id, '_EventVenueID', true ) ); $this->assertEquals( $organizer_id, get_post_meta( $created_event_id, '_EventOrganizerID', true ) ); // $this->markTestIncomplete( 'Meta data assertions depend on fallback save logic implementation.' ); // Removed // Clean up post variable unset( $_POST ); } /** * Test successful event modification with valid data using the fallback logic. * @test */ public function test_event_modification_success() { // Assume TEC CE handler doesn't exist or fails for this test path if ( class_exists( 'Tribe__Events__Community__Main' ) ) { $this->markTestSkipped('Skipping manual fallback test when TEC CE is active.'); } // 1. Create initial event, venue, organizer $initial_venue_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::VENUE_POST_TYPE, 'post_title' => 'Initial Venue', 'post_status' => 'publish' ] ); $initial_organizer_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::ORGANIZER_POST_TYPE, 'post_title' => 'Initial Organizer', 'post_status' => 'publish' ] ); $event_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_title' => 'Initial Event Title', 'post_content' => 'Initial description.', 'post_status' => 'publish', 'post_author' => self::$trainer_user_id, // TODO: Set initial meta if needed for comparison ] ); // Set initial meta (assuming fallback logic would have done this) // update_post_meta( $event_id, '_EventVenueID', $initial_venue_id ); // update_post_meta( $event_id, '_EventOrganizerID', $initial_organizer_id ); // 2. Prepare mock POST data for modification $new_start_date = date( 'Y-m-d H:i:s', strtotime( '+2 day' ) ); $new_end_date = date( 'Y-m-d H:i:s', strtotime( '+2 day +3 hours' ) ); $new_venue_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::VENUE_POST_TYPE, 'post_title' => 'New Venue', 'post_status' => 'publish' ] ); $_POST = [ 'action' => 'hvac_save_event', 'event_id' => $event_id, // Modifying existing event '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), 'event_title' => 'Updated Test Event Title', 'event_description' => 'Updated event description.', // TEC Date fields 'EventStartDate' => date( 'Y-m-d', strtotime( $new_start_date ) ), 'EventStartTime' => date( 'h:i A', strtotime( $new_start_date ) ), 'EventEndDate' => date( 'Y-m-d', strtotime( $new_end_date ) ), 'EventEndTime' => date( 'h:i A', strtotime( $new_end_date ) ), // TEC Venue/Organizer fields 'venue' => [ 'VenueID' => $new_venue_id ], // Change venue 'organizer' => [ 'OrganizerID' => $initial_organizer_id ], // Keep organizer // Add other fields as needed ]; // 3. Instantiate handler and call method $handler = HVAC_Event_Handler::get_instance(); ob_start(); @$handler->process_event_submission(); ob_end_clean(); // 4. Assertions $updated_event = get_post( $event_id ); $this->assertNotNull( $updated_event, 'Event post should still exist.' ); $this->assertEquals( 'Updated Test Event Title', $updated_event->post_title ); $this->assertEquals( 'Updated event description.', $updated_event->post_content ); $this->assertEquals( self::$trainer_user_id, $updated_event->post_author ); // Author should not change // Assert meta data (requires fallback logic in handler to save these) $this->assertEquals( $new_start_date, get_post_meta( $event_id, '_EventStartDate', true ) ); $this->assertEquals( $new_end_date, get_post_meta( $event_id, '_EventEndDate', true ) ); $this->assertEquals( $new_venue_id, get_post_meta( $event_id, '_EventVenueID', true ) ); $this->assertEquals( $initial_organizer_id, get_post_meta( $event_id, '_EventOrganizerID', true ) ); // Ensure organizer didn't change unexpectedly // $this->markTestIncomplete( 'Meta data assertions depend on fallback save logic implementation.' ); // Removed // Clean up post variable unset( $_POST ); } /** * Test that a user without the correct role/capabilities cannot create an event. * @test */ public function test_unauthorized_user_cannot_create_event() { // 1. Set user to subscriber $subscriber_id = $this->factory()->user->create( [ 'role' => 'subscriber' ] ); wp_set_current_user( $subscriber_id ); // 2. Prepare minimal POST data $_POST = [ 'action' => 'hvac_save_event', 'event_id' => 0, '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), 'event_title' => 'Unauthorized Event Attempt', // Other fields not strictly necessary for permission check ]; // 3. Instantiate handler and call method (expecting wp_die) $handler = HVAC_Event_Handler::get_instance(); ob_start(); // Use @ to suppress expected wp_die output/error @$handler->process_event_submission(); $output = ob_get_clean(); // Capture output in case we want to check it later // 4. Assert no event was created $args = [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_status' => 'any', // Check all statuses 'title' => 'Unauthorized Event Attempt', 'posts_per_page' => 1, ]; $events = get_posts( $args ); $this->assertCount( 0, $events, 'No event should have been created by an unauthorized user.' ); // Optional: Check output for expected error message if wp_die was caught // $this->assertStringContainsString( 'You do not have permission', $output ); // This might be fragile // Clean up unset( $_POST ); wp_set_current_user( self::$trainer_user_id ); // Reset user for subsequent tests } /** * Test that a user cannot modify an event they don't own (even if they have the trainer role). * @test */ public function test_unauthorized_user_cannot_modify_event() { // 1. Create initial event owned by the main test trainer $initial_title = 'Event Owned By Trainer 1'; $event_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_title' => $initial_title, 'post_status' => 'publish', 'post_author' => self::$trainer_user_id, ] ); // 2. Create a second trainer user $other_trainer_id = $this->factory()->user->create( [ 'role' => 'hvac_trainer' ] ); wp_set_current_user( $other_trainer_id ); // 3. Prepare POST data attempting modification $_POST = [ 'action' => 'hvac_save_event', 'event_id' => $event_id, // Target the first trainer's event '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), 'event_title' => 'Attempted Update By Trainer 2', // Other fields... ]; // 4. Instantiate handler and call method (expecting wp_die) $handler = HVAC_Event_Handler::get_instance(); ob_start(); @$handler->process_event_submission(); ob_end_clean(); // 5. Assert the event was NOT modified $event_post = get_post( $event_id ); $this->assertNotNull( $event_post, 'Event post should still exist.' ); $this->assertEquals( $initial_title, $event_post->post_title, 'Event title should not have been changed by another trainer.' ); // Clean up unset( $_POST ); wp_set_current_user( self::$trainer_user_id ); // Reset user } /** * Test that venue information is correctly associated with the created event (fallback logic). * @test */ public function test_event_venue_association() { // Assume TEC CE handler doesn't exist or fails for this test path if ( class_exists( 'Tribe__Events__Community__Main' ) ) { $this->markTestSkipped('Skipping manual fallback test when TEC CE is active.'); } // 1. Create dependencies $venue_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::VENUE_POST_TYPE, 'post_title' => 'Associated Venue', 'post_status' => 'publish' ] ); $organizer_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::ORGANIZER_POST_TYPE, 'post_title' => 'Associated Organizer', 'post_status' => 'publish' ] ); // 2. Prepare mock POST data $start_date = date( 'Y-m-d H:i:s', strtotime( '+3 day' ) ); $end_date = date( 'Y-m-d H:i:s', strtotime( '+3 day +2 hours' ) ); $_POST = [ 'action' => 'hvac_save_event', 'event_id' => 0, '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), 'event_title' => 'Event With Venue', 'event_description' => 'Testing venue association.', 'EventStartDate' => date( 'Y-m-d', strtotime( $start_date ) ), 'EventStartTime' => date( 'h:i A', strtotime( $start_date ) ), 'EventEndDate' => date( 'Y-m-d', strtotime( $end_date ) ), 'EventEndTime' => date( 'h:i A', strtotime( $end_date ) ), 'venue' => [ 'VenueID' => $venue_id ], // Key field 'organizer' => [ 'OrganizerID' => $organizer_id ], ]; // 3. Instantiate handler and call method $handler = HVAC_Event_Handler::get_instance(); ob_start(); @$handler->process_event_submission(); ob_end_clean(); // 4. Assertions $args = [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_status' => 'publish', 'title' => 'Event With Venue', 'posts_per_page' => 1, ]; $events = get_posts( $args ); $this->assertCount( 1, $events, 'Expected event to be created.' ); $created_event_id = $events[0]->ID; // Assert meta data (requires fallback logic in handler to save these) $this->assertEquals( $venue_id, get_post_meta( $created_event_id, '_EventVenueID', true ) ); // $this->markTestIncomplete( 'Venue meta assertion depends on fallback save logic implementation.' ); // Removed // Clean up unset( $_POST ); } /** * Test that organizer information is correctly associated with the created event (fallback logic). * @test */ public function test_event_organizer_association() { // Assume TEC CE handler doesn't exist or fails for this test path if ( class_exists( 'Tribe__Events__Community__Main' ) ) { $this->markTestSkipped('Skipping manual fallback test when TEC CE is active.'); } // 1. Create dependencies $venue_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::VENUE_POST_TYPE, 'post_title' => 'Associated Venue 2', 'post_status' => 'publish' ] ); $organizer_id = $this->factory()->post->create( [ 'post_type' => Tribe__Events__Main::ORGANIZER_POST_TYPE, 'post_title' => 'Associated Organizer 2', 'post_status' => 'publish' ] ); // 2. Prepare mock POST data $start_date = date( 'Y-m-d H:i:s', strtotime( '+4 day' ) ); $end_date = date( 'Y-m-d H:i:s', strtotime( '+4 day +2 hours' ) ); $_POST = [ 'action' => 'hvac_save_event', 'event_id' => 0, '_hvac_event_nonce' => wp_create_nonce( 'hvac_save_event_nonce' ), 'event_title' => 'Event With Organizer', 'event_description' => 'Testing organizer association.', 'EventStartDate' => date( 'Y-m-d', strtotime( $start_date ) ), 'EventStartTime' => date( 'h:i A', strtotime( $start_date ) ), 'EventEndDate' => date( 'Y-m-d', strtotime( $end_date ) ), 'EventEndTime' => date( 'h:i A', strtotime( $end_date ) ), 'venue' => [ 'VenueID' => $venue_id ], 'organizer' => [ 'OrganizerID' => $organizer_id ], // Key field ]; // 3. Instantiate handler and call method $handler = HVAC_Event_Handler::get_instance(); ob_start(); @$handler->process_event_submission(); ob_end_clean(); // 4. Assertions $args = [ 'post_type' => Tribe__Events__Main::POSTTYPE, 'post_status' => 'publish', 'title' => 'Event With Organizer', 'posts_per_page' => 1, ]; $events = get_posts( $args ); $this->assertCount( 1, $events, 'Expected event to be created.' ); $created_event_id = $events[0]->ID; // Assert meta data (requires fallback logic in handler to save these) $this->assertEquals( $organizer_id, get_post_meta( $created_event_id, '_EventOrganizerID', true ) ); // $this->markTestIncomplete( 'Organizer meta assertion depends on fallback save logic implementation.' ); // Removed // Clean up unset( $_POST ); } }