HTTP Tests
Introduction
Mantle provides a fluent HTTP Request interface to make it easier to write feature/integration tests using PHPUnit and WordPress. This library is a derivative work of Laravel's testing framework, customized to work with WordPress.
In short, this library allows one to mimic a request to WordPress, and it sets
up WordPress' global state as if it were handling that request (e.g. sets up
superglobals and other WordPress-specific globals, sets up and executes the main
query, loads the appropriate template file, etc.). It then creates a new
Test_Response
object which stores the details of the HTTP response, including
headers and body content. The response object allows the developer to make
assertions against the observable response data, for instance asserting that
some content is present in the response body or that some header was set.
For example, here's a simple test that asserts that a given post's title is present on the page:
namespace Tests\Feature;
use Tests\TestCase;
class Example_Test extends TestCase {
/**
* A basic test example.
*
* @return void
*/
public function test_basic_test() {
$post = static::factory()->post->create_and_get( [
'post_title' => 'Hello World',
] );
$this->get( $post->permalink() )
->assertOk()
->assertSee( 'Hello World' );
}
}
The get
method makes a GET
requests to the given URI, and the assertSee
method asserts that the given string is present in the response body. All HTTP
methods are available to use including get
, post
, put
, patch
, delete
and options
.
Making Requests
As a basic example, here we create a post via its factory, then request it and assert we see the post's name (title):
$post = static::factory()->post->create_and_get();
$this->get( $post )
->assertSee( $post->post_title );
In this example, here we request a non-existing resource and assert that it yields a 404 Not Found response:
$this->get( '/this/resource/does/not/exist/' )
->assertNotFound();
Lastly, here's an example of POSTing some data to an endpoint, and after following a redirect, asserting that it sees a success message:
$this->following_redirects()
->post( '/profile/', [ 'some_data' => 'hello' ] )
->assertSee( 'Success!' );
Request Cookies
Requests can have cookies included with them using the with_cookie
and
with_cookies
methods:
$this->with_cookie( 'session', 'cookie-value' )->get( '/endpoint' );
// Pass multiple cookies.
$this->with_cookies( [
'key' => 'value',
'another' => 'value',
] )
->get( '/example' );
Request Headers
Request headers can be set for requests using the with_header
and
with_headers
methods:
$this->with_header( 'api-key', '<value>' )->get( '/example' );
$this->with_headers( [
'API-Key' => '<value>',
'X-Nonce' => 'nonce',
] )
->get( '/example' );
The with_header
/with_headers
methods can be used to set headers for any
request but will only be used for that request you are chaining them to. If you
want to set headers for all requests, you can use the add_default_header
method to set a default header that will be used for all requests:
$this->add_default_header( 'X-Header-Name', 'header-value' );
$this->add_default_header( [
'X-Header-Name' => 'header-value',
'X-Another-Header' => 'another-value',
] );
You can remove the default headers using the flush_default_headers
method:
$this->flush_default_headers();
Request Referrer
The request referrer can be passed using the from
method:
$this->from( 'https://wordpress.org/' )->get( '/example' );
✨ Experimental ✨: Request Hosts
By default, core and Mantle's testing framework will use the WP_TESTS_DOMAIN
constant as the host for all requests. There is an experimental feature that
allows you to set the host relative to the value of the home_url()
function/home
option. This can be useful to make the request match the home
URL you have setup in your test environment.
To enable this feature, you can set the MANTLE_EXPERIMENTAL_TESTING_USE_HOME_URL_HOST
environment variable to true
or you can call the with_experimental_testing_url_host()
method on the installation manager in your bootstrap file.
Example of a test that would previously have failed:
class Example_Test extends TestCase {
public function test_example() {
update_option( 'home', 'https://alley.com' );
$this->get( '/about/' );
// Without this feature flag, the HTTP_HOST would be `example.org'.
$this->assertEquals( 'alley.com', $_SERVER['HTTP_HOST'] );
$this->assertEquals( 'on', $_SERVER['HTTPS'] );
}
}
HTTPS Request
Requests will be made "unsecure" by default. The means that the HTTPS
server
variable will not be set. You can force the request to be made over HTTPS by
using the with_https
method:
$this->with_https()->get( '/example' );
You can also make all requests use HTTPS by setting the site's home URL to
include https://
and opt-in to the experimental feature to use the home URL
host as the request host when testing.