Coming up in wp-browser

A taste of the things to come for wp-browser.

Codeception 2.3 compatibility

The base package for wp-browser, Codeception, has just been updated to version 2.3; here is the change log.
Among the new features is PhpUnit 6 compatibility, without dropping compatibility with previous versions, and templates.
The first opens the door for a world of testing tools that will soon make the switch and only support PHPUnit version 6; Codeception does not live in a bubble and, while these tools are not so many to justify the transition now, they will grow in number in the future.
Templates are a new feature that will allow third-party developers to build and ship templates customized to the setup work at hand; wp-browser is directly affected by it as it relies on Codeception templating system to provide helper commands like wpcept bootstrap or wpcept generate:wpunit <suite> <class>.
I’ve released version 1.20.1 of wp-browser to address this requirement, now missing, exactly: Codeception installation, managed by wp-browser, will install the latest 2.2 version for the time being.
The new templating system will allow me to drop the “hacky” approach the wpcept command provided, changing the very first step of each wp-browser based installation from this:

wpcept bootstrap --interactive

To this:

codecept init wpbrowser

See Codeception own initialization templates in action.
I’m thiking of dropping the non interactive bootstrap command in favour of a new step by step process, like the one Codeception now offers for some functionalities, to guide users in the setup; scaffolding the four default suites (acceptance, functional, integration and unit) the quality and quantity of settings one has to configure manually across files might prove confusing and prone to error.
As a wp-browser user myself, I always use --interactive mode so it makes sense to make it the default behaviour.

WPFilesystem

Over time I’ve created a WP<module> version of any applicable Codeception modules; think of WPDb and Db, WPBrowser and PhpBrowser.
This is because the WordPress handling of some functionalities, like the database or the filesystem, is so reliable that modules can be built on it without risking fast deprecation.
So far the missing piece has been a WordPress dedicated filesystem module; to start it would provide some basic filesystem navigation functionalities like these:

// moving around in the uploads folder
$I->amInUploadsPath(); // root uploads folder
$I->amInUploadsPath('2017/04'); // specific uploads folder

// specific uploads folder but calculate Year and Month for me
$I->amInUploadsPath('today'); 
$I->amInUploadsPath('-4 weeks'); 

// check for files in the uploads
$I->seeUploadedFileFound('file.txt');
$I->seeUploadedFileFound('file.txt','2017/04');
$I->dontSeeUploadedFileFound('file.txt');
$I->dontSeeUploadedFileFound('file.txt','2017/04');

// check for an uploaded file contents
$I->seeInUploadedFile('file.txt', 'needle');
$I->seeInUploadedFile('file.txt', 'needle', '2017/04');
$I->dontSeeInUploadedFile('file.txt', 'needle');
$I->dontSeeInUploadedFile('file.txt', 'needle', '2017/04');

// file operations
$I->deleteUploadsDir('folder');
$I->deleteUploadsDir('folder', '2017/04');
$I->deleteUploadsFile('file.txt');
$I->deleteUploadsFile('file.txt', '2017/04');
$I->cleanUploadsDir();
$I->cleanUploadsDir('2017/4');

// putting files and folders in uploads
$I->copyDirToUploads($src,$destination);
$I->copyDirToUploads($src,$destination, '2017/04');
$I->writeToUploadedFile($filename, $data);
$I->writeToUploadedFile($filename, $data, '2017/04');

// focusing on an uploads file
$I->openUploadedFile($file);
$I->openUploadedFile($file, '2017/04');

The same would apply to plugins and themes:

// moving around in plugins...
$I->amInPluginPath('posts-to-posts');

// ...and themes
$I->amInThemePath('twentyseventeen');

Since plugins and themes can have any kind of custom file structure I’m stopping here; the methods provided so far should suffice; as I keep working on it, I will surely come up with new methods.

Attachment support

While not ground breaking I’m adding explicit support for attachments to the WPDb module; adding attachments into the database is already possible using a combination of WPDb provided methods but TDD makes me lazy; soon, in a new version, these methods will be available:

// adding attachments from a test file
$id = $I->haveAttachmentInDatabase($filePath);

// checking attachments
$I->seeAttachmentInDatabase($criteria);
$I->dontSeeAttachmentInDatabase($criteria);

// attachment meta
$I->seeAttachmentMetaInDatabase($criteria);
$I->dontSeeAttachmentMetaInDatabase($criteria);

// attaching media to posts directly
$I->haveFileAttachedToPostInDatabase($file, $postId);
$I->havePostThumbnailInDatabase($file, $postId);

// checking post attachments
$I->seePostAttachmentInDatabase($postId, $attachmentId);
$I->dontSeePostAttachmentInDatabase($postId, $attachmentId);

More methods will pop up as I go still this is a good start that removes more boilerplate code from the equation.

Scaffold test themes and plugins

I very much believe “the truth is in code” and really hate when I have to infer the test fixture from a SQL dump file, some plugin and theme combination and so on.
While this is not avoidable, the pain can be lessened to a point ; this is what I’m trying to achieve with a new module, WPScaffolds, the objective of which is to provide methods to quickly scaffold single use and test specific WordPress “building blocks”: plugins and themes.
As an example, I might need to test that I can properly authenticate in the WordPress REST API using a fancy new authentication method; in the context of an acceptance or functional test to do so, beyond my test setup, I need a plugin that will register a dummy ‘/wp-json/test/whoami’ endpoint.
The only thing the plugin will do is to return the user ID; here’s the needed code:

<?php
/*
Plugin Name: Test
Plugin URI: https://wordpress.org/plugins/test/
Description: whoami
Version: 0.1.0
Author: Luca Tumedei
Author URI: http://theaveragedev.local
*/


To do this now I should create the plugin file in the _data folder and then copy it over when needed.
This is not a big deal, still I think it could be improved to allow me to write something like this in a test and let go of the boilerplate and sudo files and headers I have to write every time:

$code = <<< CODE
add_action('rest_api_init', function () {
    register_rest_route('test', 'whoami',[
        'methods' => 'GET',
        'callback' => 'get_current_user_id'
    ] );
});
CODE;

$I->havePlugin('test/plugin.php', $code);

On the same line a test theme:

$code = <<< CODE
echo "Hello " . test_current_user_name());
CODE;

$functionsCode = <<< CODE
function test_current_user_name(){
    $currentUser = get_current_user_id();
    echo 0 == $currentUser ? 'Stranger' : $currentUser->display_name;
}
CODE;

// theme slug, content of index.php file, content of functions.php file
$I->haveTheme('test', $code, $functionsCode);

The theme code would end up in the index.php and functions.php files, the suite should take care of creating the needed style.css file for me.
While this approach does not make sense for long and complex code it makes sense for many scenarios where smaller and specific pieces of code are needed.

Next

I’m not guaranteeing I will tackle the list in the above order, yet it’s all in the “to do” list I keep.