2024-06-04 13:10:56 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Tests\Modules\Plugins;
|
|
|
|
|
|
|
|
use App\Entities\Episode;
|
|
|
|
use App\Entities\Podcast;
|
2024-12-17 15:06:08 +00:00
|
|
|
use App\Libraries\HtmlHead;
|
2024-12-15 17:34:36 +00:00
|
|
|
use App\Libraries\RssFeed;
|
2024-06-04 13:10:56 +00:00
|
|
|
use CodeIgniter\Test\CIUnitTestCase;
|
|
|
|
use CodeIgniter\Test\DatabaseTestTrait;
|
|
|
|
use Modules\Plugins\Config\Plugins as PluginsConfig;
|
|
|
|
use Modules\Plugins\Core\Plugins;
|
|
|
|
use Modules\Plugins\Core\PluginStatus;
|
|
|
|
use Override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
final class PluginsTest extends CIUnitTestCase
|
|
|
|
{
|
|
|
|
use DatabaseTestTrait;
|
|
|
|
|
|
|
|
protected $migrate = true;
|
|
|
|
|
|
|
|
protected $migrateOnce = false;
|
|
|
|
|
|
|
|
protected $refresh = true;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string|null
|
|
|
|
*/
|
|
|
|
protected $namespace;
|
|
|
|
|
|
|
|
protected static Plugins $plugins;
|
|
|
|
|
|
|
|
#[Override]
|
|
|
|
public static function setUpBeforeClass(): void
|
|
|
|
{
|
|
|
|
$pluginsConfig = new PluginsConfig();
|
|
|
|
$pluginsConfig->folder = __DIR__ . '/mocks/plugins' . DIRECTORY_SEPARATOR;
|
|
|
|
|
|
|
|
self::$plugins = new Plugins($pluginsConfig);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testRegister(): void
|
|
|
|
{
|
|
|
|
$this->assertCount(7, self::$plugins->getAllPlugins());
|
|
|
|
$this->assertEquals(7, self::$plugins->getInstalledCount());
|
|
|
|
$this->assertEquals(0, self::$plugins->getActiveCount());
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testActivateDeactivate(): void
|
|
|
|
{
|
|
|
|
$this->assertEquals(0, self::$plugins->getActiveCount());
|
|
|
|
|
|
|
|
$plugin = self::$plugins->getAllPlugins()[0];
|
|
|
|
|
|
|
|
// get first plugin and activate it
|
|
|
|
self::$plugins->activate($plugin);
|
|
|
|
|
|
|
|
$this->assertEquals(1, self::$plugins->getActiveCount());
|
|
|
|
$this->assertEquals(PluginStatus::ACTIVE, $plugin->getStatus());
|
|
|
|
$this->seeInDatabase('settings', [
|
|
|
|
'class' => PluginsConfig::class,
|
|
|
|
'key' => 'active',
|
|
|
|
'value' => '1',
|
|
|
|
'type' => 'boolean',
|
|
|
|
'context' => 'plugin:' . $plugin->getKey(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
// get first plugin and deactivate it
|
|
|
|
self::$plugins->deactivate($plugin);
|
|
|
|
|
|
|
|
$this->assertEquals(0, self::$plugins->getActiveCount());
|
|
|
|
$this->assertEquals(PluginStatus::INACTIVE, $plugin->getStatus());
|
|
|
|
$this->seeInDatabase('settings', [
|
|
|
|
'class' => PluginsConfig::class,
|
|
|
|
'key' => 'active',
|
|
|
|
'value' => '0',
|
|
|
|
'type' => 'boolean',
|
|
|
|
'context' => 'plugin:' . $plugin->getKey(),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testRunHooksActive(): void
|
|
|
|
{
|
|
|
|
$acmeAllHooksPlugin = self::$plugins->getPlugin('acme', 'all-hooks');
|
|
|
|
|
|
|
|
self::$plugins->activate($acmeAllHooksPlugin);
|
|
|
|
|
|
|
|
$this->assertEquals(1, self::$plugins->getActiveCount());
|
|
|
|
|
|
|
|
$podcast = new Podcast();
|
|
|
|
$this->assertEquals('', $podcast->title);
|
|
|
|
self::$plugins->runHook('rssBeforeChannel', [$podcast]);
|
|
|
|
$this->assertEquals('Podcast test', $podcast->title);
|
|
|
|
|
2024-12-15 17:34:36 +00:00
|
|
|
$channel = new RssFeed('<channel></channel>');
|
2024-06-04 13:10:56 +00:00
|
|
|
$this->assertTrue(empty($channel->foo));
|
|
|
|
self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]);
|
|
|
|
$this->assertFalse(empty($channel->foo));
|
|
|
|
|
|
|
|
$episode = new Episode();
|
|
|
|
$this->assertEquals('', $episode->title);
|
|
|
|
self::$plugins->runHook('rssBeforeItem', [$episode]);
|
|
|
|
$this->assertEquals('Episode test', $episode->title);
|
|
|
|
|
2024-12-15 17:34:36 +00:00
|
|
|
$item = new RssFeed('<item></item>');
|
2024-06-04 13:10:56 +00:00
|
|
|
$this->assertTrue(empty($item->efoo));
|
|
|
|
self::$plugins->runHook('rssAfterItem', [$episode, $item]);
|
|
|
|
$this->assertFalse(empty($item->efoo));
|
|
|
|
|
2024-12-17 15:06:08 +00:00
|
|
|
$head = new HtmlHead();
|
|
|
|
self::$plugins->runHook('siteHead', [$head]);
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
(string) $head,
|
2024-12-18 16:05:25 +00:00
|
|
|
'<head> <title >foo</title> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <link rel="icon" type="image/x-icon" href="' . base_url(
|
|
|
|
'favicon.ico'
|
|
|
|
) . '"/> <link rel="apple-touch-icon" href="' . base_url(
|
|
|
|
'icon-180.png'
|
|
|
|
) . '"/> <link rel="manifest" href="/manifest.webmanifest"/> <meta name="theme-color" content="#009486"/> <link rel="stylesheet" type="text/css" href="/themes/colors"/> <title >foo</title> <script>
|
2024-12-17 15:06:08 +00:00
|
|
|
// Check that service workers are supported
|
|
|
|
if (\'serviceWorker\' in navigator) {
|
|
|
|
// Use the window load event to keep the page load performant
|
|
|
|
window.addEventListener(\'load\', () => {
|
|
|
|
navigator.serviceWorker.register(\'/sw.js\');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
</script></head>'
|
|
|
|
);
|
2024-06-04 13:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testRunHooksInactive(): void
|
|
|
|
{
|
|
|
|
$acmeAllHooksPlugin = self::$plugins->getPlugin('acme', 'all-hooks');
|
|
|
|
|
|
|
|
self::$plugins->deactivate($acmeAllHooksPlugin);
|
|
|
|
|
|
|
|
$this->assertEquals(0, self::$plugins->getActiveCount());
|
|
|
|
|
|
|
|
// nothing should change when running hooks as the plugin is inactive
|
|
|
|
|
|
|
|
$podcast = new Podcast();
|
|
|
|
$this->assertEquals('', $podcast->title);
|
|
|
|
self::$plugins->runHook('rssBeforeChannel', [$podcast]);
|
|
|
|
$this->assertEquals('', $podcast->title);
|
|
|
|
|
2024-12-15 17:34:36 +00:00
|
|
|
$channel = new RssFeed('<channel></channel>');
|
2024-06-04 13:10:56 +00:00
|
|
|
$this->assertTrue(empty($channel->foo));
|
|
|
|
self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]);
|
|
|
|
$this->assertTrue(empty($channel->foo));
|
|
|
|
|
|
|
|
$episode = new Episode();
|
|
|
|
$this->assertEquals('', $episode->title);
|
|
|
|
self::$plugins->runHook('rssBeforeItem', [$episode]);
|
|
|
|
$this->assertEquals('', $episode->title);
|
|
|
|
|
2024-12-15 17:34:36 +00:00
|
|
|
$item = new RssFeed('<item></item>');
|
2024-06-04 13:10:56 +00:00
|
|
|
$this->assertTrue(empty($item->efoo));
|
|
|
|
self::$plugins->runHook('rssAfterItem', [$episode, $item]);
|
|
|
|
$this->assertTrue(empty($item->efoo));
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
self::$plugins->runHook('siteHead', []);
|
|
|
|
$result = ob_get_contents();
|
|
|
|
ob_end_clean(); //Discard output buffer
|
|
|
|
$this->assertEquals('', $result);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testRunUndeclaredHook(): void
|
|
|
|
{
|
|
|
|
$acmeUndeclaredHookPlugin = self::$plugins->getPlugin('acme', 'undeclared-hook');
|
|
|
|
|
|
|
|
self::$plugins->activate($acmeUndeclaredHookPlugin);
|
|
|
|
|
|
|
|
$podcast = new Podcast();
|
|
|
|
$this->assertEquals('', $podcast->title);
|
|
|
|
self::$plugins->runHook('rssBeforeChannel', [$podcast]);
|
|
|
|
$this->assertEquals('Podcast test undeclared', $podcast->title);
|
|
|
|
|
|
|
|
// rssAfterChannel has not been declared in plugin manifest, should not be running
|
2024-12-15 17:34:36 +00:00
|
|
|
$channel = new RssFeed('<channel></channel>');
|
2024-06-04 13:10:56 +00:00
|
|
|
$this->assertTrue(empty($channel->foo));
|
|
|
|
self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]);
|
|
|
|
$this->assertTrue(empty($channel->foo));
|
|
|
|
}
|
|
|
|
}
|