WordPress integration test: Ajax request

In some occasions it is essential to use Ajax request inside your plugin.

In that article we will see how it is possible to test your Ajax requests using integration tests.

In case you don’t know yet how to setup integration tests on your project, you can check my previous article on the topic.

Overall plan

Theory behind testing ajax request

A test concerning an Ajax request always follow the same plan.

First, we will prepare WordPress state to setup the initial state from the test.

Next, we will send a request to WordPress to execute the logic we want to test.

Finally, we will assert that the state we are in after the response is the one expected and for that we will assert the Ajax response is correct.

The example

To better picture the process, it is necessary to use some code that will be tested rather than just keep the code in that tutorial abstract and generic.

That is why we will be testing the following code:

add_action('wp_ajax_update_post', 'update_post_title');

function update_post_title() {
   if(! isset($_GET['_wpnonce']) || ! isset($_GET['post_id']) || ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'update_post_title' . (int) $_GET['post_id'] ) ) {
     return wp_die();
   }

   if( ! isset( $_POST['post_title'] ) ) {
    return wp_die();
   }

   $post_title = sanitize_key( $_GET['post_title'] );

   $post_id = $_POST['post_id'];

   $post = get_post( $post_id );

   if( ! $post ) {
     return wp_send_json( [] );
   }

   $post->title = $post_title;

   wp_update_post($post);

   return wp_send_json( [
     'title' => $post_title
   ] );
}

The objective from that code is to update the title from a post and return the updated title.

This example is quite complete as it is covering all the different interactions we can have with the Ajax request.

Creating the testcase

The best way to create an Ajax testcase is to extend from the class AjaxTestCase:

use WPMedia\PHPUnit\Integration\AjaxTestCase;

class MyTest extends AjaxTestCase {

}

Creating the test method

For that it is necessary to create a public method with the world test inside it.

In this example, that will be testShouldDoAsExpected:

use WPMedia\PHPUnit\Integration\AjaxTestCase;

class MyTest extends AjaxTestCase {
   public function testShouldDoAsExpected() {
  
   }
}

Setup the initial WordPress state

In our scenario we will be testing the ideal scenario where everything is working fine.

Due to that we need to create the post that we will be modification.

For that we will have to write the following code inside the test method:

$post_id = $this->factory()->post->create([
   'title' => 'old title'
]);

You can notice that we are creating the post using a factory to create the post.

It is an easy to be able different standard WordPress entities as such as users, posts or categories.

Initializing the request

The next step is to setup the request that will be sent to the the Ajax action.

For that it is possible to directly affect values to the $_GET global variable that will be automatically reset.

In that example there are three things to setup:

  • The nonce: Check if the request is from an authorize user.
  • The post ID: The ID from the post that will be generated.
  • The new post title: The new title from the post.
$_GET['_wpnonce'] = wp_create_nonce( 'update_post_title'.$post_id );
$_GET['post_id'] = $post_id;
$_GET['post_title'] = 'New title';

The next thing to setup is the action the request will be sent to with the following code:

$this->action = 'update_post';

Sending the Ajax request

Once the Ajax request is ready it is then time to send it.

For that it is possible to use the method callAjaxAction:

$response = $this->callAjaxAction();

Assert on the response

When the logic to test is executed it is time to make sure the results from the request are the ones expected.

For it is possible to make assertions on response from the request which is provided as return from the method callAjaxAction:

$this->assertTrue( $response->success );
$this->assertSame( 'New title', $response->data->title );

Inside this example it is possible to make sure the request is successful by checking the property success and then check if the data is returned inside data.title.

Assert the final state

The last thing to do in the test is to make sure that the WordPress website is in the right final state.

In that example, it is possible by checking the current title from the post:

$post = get_post( $post_id );
$this->assertSame( 'New title', $post->title );

Overall code

It can be sometimes hard to follow code that is exploded in many pieces, this is why a full version from the code is available here:

use WPMedia\PHPUnit\Integration\AjaxTestCase;

class MyTest extends AjaxTestCase {
   public function testShouldDoAsExpected() {
     $post_id = $this->factory()->post->create([
      'title' => 'old title'
     ]);

     $_GET['_wpnonce'] = wp_create_nonce( 'update_post_title'.$post_id );
     $_GET['post_id'] = $post_id;
     $_GET['post_title'] = 'New title';

     $this->action = 'update_post';

     $response = $this->callAjaxAction();

    $this->assertTrue( $response->success );
    $this->assertSame( 'New title', $response->data->title );

    $post = get_post( $post_id );
    $this->assertSame( 'New title', $post->title );
   }
}

Join my newsletter

Never miss a single article and receive a free ebook “Bug hunting for small companies”.


Leave a Reply

Your email address will not be published. Required fields are marked *