In a previous post I’ve presented a WordPress plugin requirement check baked into the wp-utils package and while that’s on the production side I want to be able to test the behaviours related to missing or incomplete requirements as well.
Codeception makes it easy using a cest
format test and the fact that WordPress will consider a plugin “installed” when a .php
file with a proper header is found in the plugins folder or in a first level sub-folder; that means that simply renaming a plugin main file removing the .php
extension “uninstalls it” when it comes to WordPress logic.
The scenario
Plugin B requires Plugin A to work and I want to test that an helpful wp_die
message is shown to the administrator when he tries to activate Plugin B while Plugin A is not installed.
Since that’s a test I need a reliable and programmatic way to “install” and “uninstall” a plugin on a per-test-method base without having to do any manual operations.
The code
I will use a cest
test file format here to leverage the possibility offered by the _before
and _after
methods (PHPUnit equivalent of setUp
and tearDown
methods).
<?php
class ActivationAndInstallationRequirementsCest
{
protected $shouldRestorePluginAMainFile = false;
protected $pluginAMainFile;
public function _before()
{
$this->pluginAMainFile = dirname(__FILE__) . '/../../../Plugin-A/plugin-A';
}
public function _after()
{
if(!file_exists($this->pluginAMainFile . '.php')){
$this->shouldRestorePluginAMainFile = true;
}
if($this->shouldRestorePluginAMainFile){
rename($this->pluginAMainFile, $this->pluginAMainFile. '.php');
}
}
public function shouldShowWpDiePageIfPluginANotInstalled(AcceptanceTester $I)
{
// setup
$this->disinstallPluginAPlugin();
$I->loginAsAdmin();
$I->amOnPluginsPage();
$I->dontSeePluginInstalled('plugin-a');
// exercise
$I->activatePlugin('plugin-b');
// verify
$I->seeWpDiePage();
// make sure the wp_die page contains a link to install Plugin A
$I->seeElement('a#plugin-a-installation-link');
}
protected function disinstallPluginAPlugin(){
if(file_exists($this->pluginAMainFile . '.php')){
$this->shouldRestorePluginAMainFile = rename($this->pluginAMainFile . '.php', $this->pluginAMainFile);
}
}
}
That’s all self explanatory and I could get rid of the _before
method entirely hardcoding the path to the required plugin main file to slim down the test case further.