Table of Contents
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 );
}
}
Laisser un commentaire