A WordPress functional testing module 04

Redirection and other intricacies of a functional test.

The story so far

I’ve been working, for the last two weeks, to the development of a WordPress-specific functional testing module for Codeception.
The module is part of the wp-browser package and will cover the unanswered need for a real functional test module.
Functional tests are similar to acceptance tests but without the web server requirement and will test a WordPress installation handling of an HTTP request asserting its final state and/or response.
Where an acceptance test hits a URL like http://local.dev a functional test directly runs a PHP file like /var/www/wordpress/index.php.
My last update did see me succeed in running a test like this:

/**
 * @test
 * it should be able to navigate to main page
 */
public function it_should_be_able_to_navigate_to_main_page(WpmoduleTester $I)
{
    $I->amOnPage('/');
}

which was not much but yet took quite some time to work out.

Going further

I’ve moved the development forward to the point where I could run a test involving database manipulation like the one below:

/**
 * @test
 * it should be able to insert a post in the database and see it on the homepage
 */
public function it_should_be_able_to_insert_a_post_in_the_database_and_see_it_on_the_homepage(WpmoduleTester $I)
{
    $I->havePostInDatabase(['post_type' => 'post', 'post_title' => 'A post', 'post_status' => 'publish']);
    $I->amOnPage('/');
    $I->see('A post');
}

The WordPress module requires the WPDb one to work and this means that a functional test will be able to rely on its methods like the havePostInDatabase one used above.
This also means that database dumps are a fundamental part of a functional test fixture set up process.

Beyond the front page

Navigating to the front page has been relatively easy but getting the module to “navigate” to other URIs proved to be more challenging. At this point the module is able to navigate the site similarly to what a user would do and will do so with “ugly” and “pretty” permalinks alike:

/**
 * @test
 * it should be able to navigate to a post using ugly permalinks
 */
public function it_should_be_able_to_navigate_to_a_post_using_ugly_permalinks(WpmoduleTester $I)
{
    $post_id = $I->havePostInDatabase(['post_type' => 'post', 'post_title' => 'A post', 'post_status' => 'publish']);
    $I->amOnPage('/?p=' . $post_id);
    $I->seeElement('body.single');
}

/**
 * @test
 * it should be able to navigate to a post single using pretty permalinks
 */
public function it_should_be_able_to_navigate_to_a_post_single_using_pretty_permalinks(WpmoduleTester $I)
{
    $I->havePostInDatabase(['post_type' => 'post', 'post_title' => 'A post', 'post_status' => 'publish', 'post_name' => 'a-post']);
    $I->amOnPage('/a-post');
    $I->seeElement('body.single');
}

The “pretty” permalink navigation is possible only if the database fixture powering the tests was generated from a WordPress installation with pretty permalinks activated.
Relying on the WPDb module means that the database will be cleaned up before each test starts.

And then the administration area

WordPress has two macro areas for handling requests: the front-end embodied mainly by the root index.php file and the administration area.
The latter has more than one file that can be directly hit and the module does account for that.
While I’ve had to find a way to deal with WordPress use of exit, die and headers I’ve been able to run, finally, the test below:

/**
 * @test
 * it should be able to visit the admin area when unlogged
 */
public function it_should_be_able_to_visit_the_admin_area_when_unlogged(WpmoduleTester $I)
{
    $I->amOnAdminPage('/');
    $I->seeElement('body.login');
}

The test code is diminutive in size but handling redirections in a CLI application required some work.

Next

Next natural step is to allow for user log in and log out and for the module to make direct GET, POST, PUT and DELETE requests similarly to what a user, the front-end or other applications might do.