Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event Form Handler Unit Tests #383

Draft
wants to merge 19 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 32 additions & 28 deletions includes/event/event-form-handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,35 @@ public function __construct( DateTimeImmutable $now, Event_Repository $event_rep
}

public function handle( array $form_data ): void {
$response = $this->process_form( $form_data );
if ( is_wp_error( $response ) ) {
$status_code = $response->get_error_data( 'status' );
wp_send_json_error( $response->get_error_message(), $status_code );
}
wp_send_json_success( $response );
}

public function process_form( array $form_data ) {
if ( ! is_user_logged_in() ) {
wp_send_json_error( esc_html__( 'The user must be logged in.', 'gp-translation-events' ), 403 );
return new WP_Error( 'not_logged_in', esc_html__( 'The user must be logged in.', 'gp-translation-events' ), array( 'status' => 403 ) );
}

$action = isset( $form_data['form_name'] ) ? sanitize_text_field( wp_unslash( $form_data['form_name'] ) ) : '';
if ( ! in_array( $action, array( 'create_event', 'edit_event', 'trash_event' ), true ) ) {
wp_send_json_error( esc_html__( 'Invalid form name.', 'gp-translation-events' ), 403 );
return new WP_Error( 'form_name_error', esc_html__( 'Invalid form name.', 'gp-translation-events' ), array( 'status' => 403 ) );
}

$event_id = isset( $form_data['event_id'] ) ? intval( sanitize_text_field( wp_unslash( $form_data['event_id'] ) ) ) : 0;
$event = null;

if ( 'create_event' === $action && ( ! current_user_can( 'create_translation_event' ) ) ) {
wp_send_json_error( esc_html__( 'You do not have permissions to create events.', 'gp-translation-events' ), 403 );
return new WP_Error( 'permission_error', esc_html__( 'You do not have permissions to create events.', 'gp-translation-events' ), array( 'status' => 403 ) );
}
if ( 'edit_event' === $action && ( ! current_user_can( 'edit_translation_event', $event_id ) ) ) {
wp_send_json_error( esc_html__( 'You do not have permissions to edit this event.', 'gp-translation-events' ), 403 );
return new WP_Error( 'permission_error', esc_html__( 'You do not have permissions to edit this event.', 'gp-translation-events' ), array( 'status' => 403 ) );
}
if ( 'trash_event' === $action && ( ! current_user_can( 'trash_translation_event', $event_id ) ) ) {
wp_send_json_error( esc_html__( 'You do not have permissions to delete this event.', 'gp-translation-events' ), 403 );
return new WP_Error( 'permission_error', esc_html__( 'You do not have permissions to delete this event.', 'gp-translation-events' ), array( 'status' => 403 ) );
}

$is_nonce_valid = false;
Expand All @@ -52,7 +61,7 @@ public function handle( array $form_data ): void {
}
}
if ( ! $is_nonce_valid ) {
wp_send_json_error( esc_html__( 'Nonce verification failed.', 'gp-translation-events' ), 403 );
return new WP_Error( 'invalid_nonce', esc_html__( 'Nonce verification failed.', 'gp-translation-events' ), array( 'status' => 403 ) );
}

$response_message = '';
Expand All @@ -63,17 +72,17 @@ public function handle( array $form_data ): void {
if ( 'trash_event' === $action ) {
// Trash event.
if ( ! $event ) {
wp_send_json_error( esc_html__( 'Event does not exist.', 'gp-translation-events' ), 404 );
return new WP_Error( 'inexistent_event', esc_html__( 'Event does not exist.', 'gp-translation-events' ), array( 'status' => 404 ) );
}

$stats_calculator = new Stats_Calculator();
try {
$event_stats = $stats_calculator->for_event( $event->id() );
} catch ( Exception $e ) {
wp_send_json_error( esc_html__( 'Failed to calculate event stats.', 'gp-translation-events' ), 500 );
return new WP_Error( 'stats_calculation_error', esc_html__( 'Failed to calculate event stats.', 'gp-translation-events' ), array( 'status' => 500 ) );
}
if ( ! empty( $event_stats->rows() ) ) {
wp_send_json_error( esc_html__( 'Event has stats so it cannot be deleted.', 'gp-translation-events' ), 422 );
return new WP_Error( 'cannot_delete_event', esc_html__( 'Event has stats so it cannot be deleted.', 'gp-translation-events' ), array( 'status' => 422 ) );
}

if ( false === $this->event_repository->trash_event( $event ) ) {
Expand All @@ -90,43 +99,38 @@ public function handle( array $form_data ): void {
try {
$new_event = $this->parse_form_data( $form_data );
} catch ( InvalidTimeZone $e ) {
wp_send_json_error( esc_html__( 'Invalid time zone.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'invalid_timezone', esc_html__( 'Invalid time zone.', 'gp-translation-events' ), array( 'status' => 422 ) );
} catch ( InvalidStart $e ) {
wp_send_json_error( esc_html__( 'Invalid start date.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'invalid_start_date', esc_html__( 'Invalid start date.', 'gp-translation-events' ), array( 'status' => 422 ) );
} catch ( InvalidEnd $e ) {
wp_send_json_error( esc_html__( 'Invalid end date.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'invalid_end_date', esc_html__( 'Invalid end date.', 'gp-translation-events' ), array( 'status' => 422 ) );
} catch ( InvalidStatus $e ) {
wp_send_json_error( esc_html__( 'Invalid status.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'invalid_status', esc_html__( 'Invalid status.', 'gp-translation-events' ), array( 'status' => 422 ) );
}

if ( empty( $new_event->title() ) ) {
wp_send_json_error( esc_html__( 'Invalid title.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'invalid_title', esc_html__( 'Invalid title.', 'gp-translation-events' ), array( 'status' => 422 ) );
}

// This is a list of slugs that are not allowed, as they conflict with the event URLs.
$invalid_slugs = array( 'new', 'edit', 'attend', 'my-events' );
if ( in_array( sanitize_title( $new_event->title() ), $invalid_slugs, true ) ) {
wp_send_json_error( esc_html__( 'Invalid slug.', 'gp-translation-events' ), 422 );
return new WP_Error( 'invalid_slug', esc_html__( 'Invalid slug.', 'gp-translation-events' ), array( 'status' => 422 ) );
}

if ( 'create_event' === $action ) {
$result = $this->event_repository->insert_event( $new_event );
if ( $result instanceof WP_Error ) {
wp_send_json_error( esc_html__( 'Failed to create event.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'cannot_create_event', esc_html__( 'Failed to create event.', 'gp-translation-events' ), array( 'status' => 422 ) );

}
$response_message = esc_html__( 'Event created successfully.', 'gp-translation-events' );
$this->notifications_schedule->schedule_emails( $result );
}
if ( 'edit_event' === $action ) {
$event = $this->event_repository->get_event( $new_event->id() );
if ( ! $event ) {
wp_send_json_error( esc_html__( 'Event does not exist.', 'gp-translation-events' ), 404 );
return new WP_Error( 'inexistent_event', esc_html__( 'Event does not exist.', 'gp-translation-events' ), array( 'status' => 404 ) );
}

try {
Expand All @@ -153,14 +157,14 @@ public function handle( array $form_data ): void {
$event->set_attendance_mode( $new_event->attendance_mode() );
}
} catch ( Exception $e ) {
wp_send_json_error( esc_html__( 'Failed to update event.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'cannot_update_event', esc_html__( 'Failed to update event.', 'gp-translation-events' ), array( 'status' => 422 ) );

}

$result = $this->event_repository->update_event( $event );
if ( $result instanceof WP_Error ) {
wp_send_json_error( esc_html__( 'Failed to update event.', 'gp-translation-events' ), 422 );
return;
return new WP_Error( 'cannot_update_event', esc_html__( 'Failed to update event.', 'gp-translation-events' ), array( 'status' => 422 ) );

}
$response_message = esc_html__( 'Event updated successfully', 'gp-translation-events' );
$this->notifications_schedule->schedule_emails( $result );
Expand All @@ -170,7 +174,7 @@ public function handle( array $form_data ): void {
$event_status = $new_event->status();
}

wp_send_json_success(
return(
array(
'message' => $response_message,
'eventId' => $event_id,
Expand Down
103 changes: 103 additions & 0 deletions tests/event/event-form-handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

namespace Wporg\Tests\Event;

use Wporg\Tests\Base_Test;
use Wporg\TranslationEvents\Attendee\Attendee_Repository;
use Wporg\TranslationEvents\Event\Event_Repository;
use Wporg\TranslationEvents\Event\Event_Form_Handler;
use Wporg\TranslationEvents\Tests\Event_Form_Handler_Factory;

class Event_Form_Handler_Test extends Base_Test {
private Event_Repository $event_repository;
private Attendee_Repository $attendee_repository;
private Event_Form_Handler $event_form_handler;
private Event_Form_Handler_Factory $event_form_handler_factory;

public function setUp(): void {
parent::setUp();
$this->attendee_repository = new Attendee_Repository();
$this->event_repository = new Event_Repository( $this->now, $this->attendee_repository );
$this->event_form_handler = new Event_Form_Handler( $this->now, $this->event_repository );
$this->event_form_handler_factory = new Event_Form_Handler_Factory();
$this->set_normal_user_as_current();
}

/**
* Test that the user must be logged in to create an event.
*
* @return void
*/
public function test_user_is_not_logged_in() {
wp_set_current_user( 0 );
$form_data = $this->event_form_handler_factory->future_inactive_event_form_data( 'create_event', $this->now );
$response = $this->event_form_handler->process_form( $form_data );

$this->assertEquals( 'The user must be logged in.', $response->get_error_message() );
}

public function test_form_name_is_invalid() {
$form_data = $this->event_form_handler_factory->future_inactive_event_form_data( 'invalid_form_name', $this->now );
$response = $this->event_form_handler->process_form( $form_data );

$this->assertEquals( 'Invalid form name.', $response->get_error_message() );
}

public function test_invalid_permissions() {
$event_id = 9999;
$form_data_1 = $this->event_form_handler_factory->future_inactive_event_form_data( 'create_event', $this->now );
$response_1 = $this->event_form_handler->process_form( $form_data_1 );
$this->assertEquals( 'You do not have permissions to create events.', $response_1->get_error_message() );

$form_data_2 = $this->event_form_handler_factory->future_inactive_event_form_data( 'edit_event', $this->now, $event_id );
$response_2 = $this->event_form_handler->process_form( $form_data_2 );
$this->assertEquals( 'You do not have permissions to edit this event.', $response_2->get_error_message() );

$form_data_3 = $this->event_form_handler_factory->future_inactive_event_form_data( 'trash_event', $this->now, $event_id );
$response_3 = $this->event_form_handler->process_form( $form_data_3 );
$this->assertEquals( 'You do not have permissions to delete this event.', $response_3->get_error_message() );
}

public function test_invalid_nonce() {
add_filter( 'gp_translation_events_can_crud_event', '__return_true' );
$form_data = $this->event_form_handler_factory->future_inactive_event_form_data( 'create_event', $this->now );
$form_data['_event_nonce'] = wp_create_nonce( 'invalid_nonce' );
$response = $this->event_form_handler->process_form( $form_data );

$this->assertArrayHasKey( 'invalid_nonce', $response->error_data );
$this->assertEquals( 'Nonce verification failed.', $response->get_error_message() );
}

/**
* @dataProvider emptyFormDataProvider
*/
public function test_empty_form_fields( $action, $field, $error_key ) {
add_filter( 'gp_translation_events_can_crud_event', '__return_true' );
$form_data = $this->event_form_handler_factory->future_inactive_event_form_data( $action, $this->now );
$form_data[ $field ] = '';
$response = $this->event_form_handler->process_form( $form_data );

$this->assertArrayHasKey( $error_key, $response->error_data );

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 7.4

Failed asserting that an array has the key 'invalid_title'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 7.4

Failed asserting that an array has the key 'invalid_title'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 7.4

Failed asserting that an array has the key 'invalid_start_date'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 7.4

Failed asserting that an array has the key 'invalid_end_date'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 7.4

Failed asserting that an array has the key 'invalid_timezone'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 7.4

Failed asserting that an array has the key 'invalid event_attendance_mode'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 8.3

Failed asserting that an array has the key 'invalid_title'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 8.3

Failed asserting that an array has the key 'invalid_title'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 8.3

Failed asserting that an array has the key 'invalid_start_date'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 8.3

Failed asserting that an array has the key 'invalid_end_date'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 8.3

Failed asserting that an array has the key 'invalid_timezone'.

Check failure on line 80 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / PHPUnit 8.3

Failed asserting that an array has the key 'invalid event_attendance_mode'.
}

/**
* Data provider for invalid form data test cases.
*/
public function emptyFormDataProvider() {
return array(
array( 'create_event', 'event_title', 'invalid_title' ),
array( 'create_event', 'event_description', 'invalid_title' ),
array( 'create_event', 'event_start', 'invalid_start_date' ),
array( 'create_event', 'event_end', 'invalid_end_date' ),
array( 'create_event', 'event_timezone', 'invalid_timezone' ),
array( 'create_event', 'event_attendance_mode', 'invalid event_attendance_mode' ),
array( 'edit_event', 'event_title', 'invalid_title' ),
array( 'edit_event', 'event_description', 'invalid_title' ),
array( 'edit_event', 'event_start', 'invalid_start_date' ),
array( 'edit_event', 'event_end', 'invalid_end_date' ),
array( 'edit_event', 'event_timezone', 'invalid_timezone' ),
array( 'edit_event', 'event_attendance_mode', 'invalid event_attendance_mode' ),
);
}

}

Check failure on line 103 in tests/event/event-form-handler.php

View workflow job for this annotation

GitHub Actions / phpcs

The closing brace for the class must go on the next line after the body
32 changes: 32 additions & 0 deletions tests/lib/event-form-handler-factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Wporg\TranslationEvents\Tests;

use DateTimeImmutable;
use DateTimeZone;

class Event_Form_Handler_Factory {

public function future_inactive_event_form_data( $form_name, DateTimeImmutable $now, $event_id = 0 ): array {
$timezone = 'Europe/Lisbon';
$event_title = 'Foo title';
$event_description = 'Foo description';
$event_attendance_mode = 'hybrid';
$_event_id = isset( $event_id ) ? $event_id : 0;
$event_nonce = wp_create_nonce( '_event_nonce' );

return array(
'action' => 'submit_event_ajax',
'form_name' => $form_name,
'event_id' => $_event_id,
'event_form_action' => 'publish',
'event_title' => $event_title,
'event_description' => $event_description,
'event_start' => $now->modify( '+1 month' )->format( 'Y-m-d H:i:s' ),
'event_end' => $now->modify( '+2 month' )->format( 'Y-m-d H:i:s' ),
'event_timezone' => $timezone,
'event_attendance_mode' => $event_attendance_mode,
'_event_nonce' => $event_nonce,
);
}
}
Loading