738 lines
26 KiB
PHP
738 lines
26 KiB
PHP
<?php
|
|
|
|
namespace Tests;
|
|
|
|
use App\Events;
|
|
use App\Services\Option;
|
|
use App\Services\Plugin;
|
|
use App\Services\PluginManager;
|
|
use Event;
|
|
use Illuminate\Filesystem\Filesystem;
|
|
use ReflectionClass;
|
|
|
|
class PluginManagerTest extends TestCase
|
|
{
|
|
public function testPreventBootingAgain()
|
|
{
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')->times(0);
|
|
});
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testNotLoadDisabled()
|
|
{
|
|
$dir = config('plugins.directory');
|
|
config(['plugins.directory' => base_path('tests/__mocks__')]);
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
$this->assertFalse(class_exists('Fake\Faker'));
|
|
|
|
config(['plugins.directory' => $dir]);
|
|
}
|
|
|
|
public function testNotLoadUnsatisfied()
|
|
{
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')->with('plugins_enabled', '[]')->andReturn('[]');
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/nano']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/nano'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/nano'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'fake',
|
|
'version' => '0.0.0',
|
|
'require' => ['blessing-skin-server' => '0.0.0'],
|
|
]));
|
|
|
|
$mock->shouldNotReceive('getRequire');
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testReportDuplicatedPlugins()
|
|
{
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')->with('plugins_enabled', '[]')->andReturn('[]');
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/nano', '/yuko']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/nano'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/nano'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'fake',
|
|
'version' => '0.0.0',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/yuko'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/yuko'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'fake',
|
|
'version' => '0.0.0',
|
|
]));
|
|
});
|
|
|
|
$this->expectExceptionMessage(trans('errors.plugins.duplicate', [
|
|
'dir1' => '/nano',
|
|
'dir2' => '/yuko',
|
|
]));
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testDetectVersionChanged()
|
|
{
|
|
Event::fake();
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'mayaka', 'version' => '0.0.0']]));
|
|
$mock->shouldReceive('set')
|
|
->with(
|
|
'plugins_enabled',
|
|
json_encode([['name' => 'mayaka', 'version' => '0.1.0']])
|
|
)
|
|
->once();
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/mayaka']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'mayaka',
|
|
'version' => '0.1.0',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/vendor/autoload.php')
|
|
->once()
|
|
->andReturn(false);
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/bootstrap.php')
|
|
->once()
|
|
->andReturn(false);
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
Event::assertDispatched('plugin.versionChanged', function ($eventName, $payload) {
|
|
$this->assertEquals('0.1.0', $payload[0]->version);
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
public function testLoadComposer()
|
|
{
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'mayaka', 'version' => '0.0.0']]));
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/mayaka']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'mayaka',
|
|
'version' => '0.0.0',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/vendor/autoload.php')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('getRequire')
|
|
->with('/mayaka/vendor/autoload.php')
|
|
->once();
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/bootstrap.php')
|
|
->once()
|
|
->andReturn(false);
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testLoadViews()
|
|
{
|
|
$dir = config('plugins.directory');
|
|
config(['plugins.directory' => base_path('tests/__mocks__')]);
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([
|
|
['name' => 'fake-with-views', 'version' => '0.0.0'],
|
|
]));
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
$this->assertTrue(view()->exists('FakeWithViews::example'));
|
|
|
|
config(['plugins.directory' => $dir]);
|
|
}
|
|
|
|
public function testLoadTranslations()
|
|
{
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'mayaka', 'version' => '0.0.0']]));
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/mayaka', '/chitanda']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'mayaka',
|
|
'version' => '0.0.0',
|
|
'namespace' => 'Mayaka',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/vendor/autoload.php')
|
|
->once()
|
|
->andReturn(false);
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/bootstrap.php')
|
|
->once()
|
|
->andReturn(false);
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/chitanda'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/chitanda'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'chitanda',
|
|
'version' => '0.0.0',
|
|
'namespace' => 'Chitanda',
|
|
]));
|
|
});
|
|
$this->instance('translation.loader', \Mockery::mock(\App\Services\Translations\Loader::class, function ($mock) {
|
|
$mock->shouldReceive('addNamespace')
|
|
->withArgs(['Mayaka', '/mayaka/lang'])
|
|
->once();
|
|
|
|
$mock->shouldReceive('addNamespace')
|
|
->withArgs(['Chitanda', '/chitanda/lang'])
|
|
->once();
|
|
}));
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testLoadBootstrapper()
|
|
{
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'mayaka', 'version' => '0.0.0']]));
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/mayaka']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'mayaka',
|
|
'version' => '0.0.0',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/vendor/autoload.php')
|
|
->once()
|
|
->andReturn(false);
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/bootstrap.php')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('getRequire')
|
|
->with('/mayaka/bootstrap.php')
|
|
->once()
|
|
->andReturn(function (\Illuminate\Contracts\Events\Dispatcher $events, Plugin $plugin) {
|
|
$this->assertTrue(method_exists($events, 'listen'));
|
|
$this->assertEquals('mayaka', $plugin->name);
|
|
});
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testHandleBootstrapperExceptions()
|
|
{
|
|
Event::fake();
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'mayaka', 'version' => '0.0.0']]));
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->andReturn(collect(['/mayaka']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->andReturn(json_encode([
|
|
'name' => 'mayaka',
|
|
'version' => '0.0.0',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/vendor/autoload.php')
|
|
->andReturn(false);
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/bootstrap.php')
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('getRequire')
|
|
->with('/mayaka/bootstrap.php')
|
|
->andReturn(function () {
|
|
throw new \Exception();
|
|
}, fn () => abort(500));
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
Event::assertDispatched(Events\PluginBootFailed::class, function ($event) {
|
|
$this->assertEquals('mayaka', $event->plugin->name);
|
|
|
|
return true;
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
$this->expectException(\Symfony\Component\HttpKernel\Exception\HttpException::class);
|
|
resolve(PluginManager::class)->boot();
|
|
}
|
|
|
|
public function testLifecycleHooks()
|
|
{
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')->with('plugins_enabled', '[]')->andReturn('[]');
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with(base_path('plugins'))
|
|
->once()
|
|
->andReturn(collect(['/mayaka']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('get')
|
|
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(json_encode([
|
|
'name' => 'mayaka',
|
|
'version' => '0.0.0',
|
|
'namespace' => 'Mayaka',
|
|
]));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/mayaka/callbacks.php')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$mock->shouldReceive('getRequire')
|
|
->with('/mayaka/callbacks.php')
|
|
->once()
|
|
->andReturn([
|
|
\App\Events\PluginWasDeleted::class => function ($plugin) {
|
|
$this->assertInstanceOf(Plugin::class, $plugin);
|
|
$this->assertEquals('mayaka', $plugin->name);
|
|
},
|
|
]);
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
event(new \App\Events\PluginWasDeleted(new Plugin('/mayaka', ['name' => 'mayaka'])));
|
|
}
|
|
|
|
public function testRegisterAutoload()
|
|
{
|
|
$dir = config('plugins.directory');
|
|
config(['plugins.directory' => base_path('tests/__mocks__')]);
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'fake', 'version' => '0.0.0']]));
|
|
});
|
|
|
|
$this->assertFalse(class_exists('Fake\Faker'));
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
$this->assertTrue(class_exists('Fake\FakeServiceProvider'));
|
|
|
|
config(['plugins.directory' => $dir]);
|
|
}
|
|
|
|
public function testRegisterServiceProviders()
|
|
{
|
|
Event::fake();
|
|
|
|
$dir = config('plugins.directory');
|
|
config(['plugins.directory' => base_path('tests/__mocks__')]);
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'fake', 'version' => '0.0.0']]));
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->boot();
|
|
Event::assertDispatched('provider.loaded');
|
|
|
|
config(['plugins.directory' => $dir]);
|
|
}
|
|
|
|
public function testGetUnsatisfied()
|
|
{
|
|
$manager = resolve(PluginManager::class);
|
|
|
|
$plugin = new Plugin('', ['require' => ['blessing-skin-server' => '^0.0.0']]);
|
|
$info = $manager->getUnsatisfied($plugin)->get('blessing-skin-server');
|
|
$this->assertEquals(config('app.version'), $info['version']);
|
|
$this->assertEquals('^0.0.0', $info['constraint']);
|
|
|
|
preg_match('/(\d+\.\d+\.\d+)/', PHP_VERSION, $matches);
|
|
$version = $matches[1];
|
|
$plugin = new Plugin('', ['require' => ['php' => '^0.0.0']]);
|
|
$info = $manager->getUnsatisfied($plugin)->get('php');
|
|
$this->assertEquals($version, $info['version']);
|
|
$this->assertEquals('^0.0.0', $info['constraint']);
|
|
|
|
$plugin = new Plugin('', ['require' => ['another-plugin' => '0.0.*']]);
|
|
$info = $manager->getUnsatisfied($plugin)->get('another-plugin');
|
|
$this->assertNull($info['version']);
|
|
$this->assertEquals('0.0.*', $info['constraint']);
|
|
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('enabled');
|
|
$property->setAccessible(true);
|
|
$property->setValue($manager, collect(['another-plugin' => ['version' => '1.2.3']]));
|
|
$info = $manager->getUnsatisfied($plugin)->get('another-plugin');
|
|
$this->assertEquals('1.2.3', $info['version']);
|
|
$this->assertEquals('0.0.*', $info['constraint']);
|
|
|
|
$plugin = new Plugin('', ['require' => ['another-plugin' => '^1.0.0']]);
|
|
$this->assertFalse($manager->getUnsatisfied($plugin)->has('another-plugin'));
|
|
}
|
|
|
|
public function testGetConflicts()
|
|
{
|
|
$manager = resolve(PluginManager::class);
|
|
|
|
$plugin = new Plugin('/', ['enchants' => ['conflicts' => ['a' => '*', 'b' => '^1.2.0']]]);
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('enabled');
|
|
$property->setAccessible(true);
|
|
$property->setValue($manager, collect(['b' => ['version' => '1.2.3']]));
|
|
|
|
$conflicts = $manager->getConflicts($plugin);
|
|
$this->assertNull($conflicts->get('a'));
|
|
$info = $conflicts->get('b');
|
|
$this->assertEquals('1.2.3', $info['version']);
|
|
$this->assertEquals('^1.2.0', $info['constraint']);
|
|
|
|
$plugin = new Plugin('/', ['enchants' => ['conflicts' => ['b' => '^0.0.0']]]);
|
|
$this->assertNull($manager->getConflicts($plugin)->get('b'));
|
|
}
|
|
|
|
public function testFormatUnresolved()
|
|
{
|
|
app()->forgetInstance(PluginManager::class);
|
|
$manager = resolve(PluginManager::class);
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('plugins');
|
|
$property->setAccessible(true);
|
|
$property->setValue($manager, collect([
|
|
'dep' => new Plugin('', ['title' => 'dep', 'version' => '0.0.0']),
|
|
'conf' => new Plugin('', ['title' => 'conf', 'version' => '1.2.3']),
|
|
]));
|
|
|
|
$unsatisfied = collect([
|
|
'blessing-skin-server' => ['version' => '4.0.0', 'constraint' => '^5.0.0'],
|
|
'php' => ['version' => '7.2.0', 'constraint' => '^7.3.0'],
|
|
'dep' => ['version' => '0.0.0', 'constraint' => '^6.6.6'],
|
|
'whatever' => ['version' => null, 'constraint' => '^1.2.3'],
|
|
]);
|
|
$conflicts = collect([
|
|
'conf' => ['version' => '1.2.3', 'constraint' => '^1.0.0'],
|
|
]);
|
|
|
|
$received = $manager->formatUnresolved($unsatisfied, $conflicts);
|
|
$expected = [
|
|
trans('admin.plugins.operations.unsatisfied.version', [
|
|
'title' => 'Blessing Skin Server',
|
|
'constraint' => '^5.0.0',
|
|
]),
|
|
trans('admin.plugins.operations.unsatisfied.version', [
|
|
'title' => 'PHP',
|
|
'constraint' => '^7.3.0',
|
|
]),
|
|
trans('admin.plugins.operations.unsatisfied.version', [
|
|
'title' => 'dep',
|
|
'constraint' => '^6.6.6',
|
|
]),
|
|
trans('admin.plugins.operations.unsatisfied.disabled', ['name' => 'whatever']),
|
|
trans('admin.plugins.operations.unsatisfied.conflict', ['title' => 'conf']),
|
|
];
|
|
$this->assertEquals($expected, $received);
|
|
}
|
|
|
|
public function testEnable()
|
|
{
|
|
Event::fake();
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
$manager = resolve(PluginManager::class);
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('plugins');
|
|
$property->setAccessible(true);
|
|
$property->setValue($manager, collect([
|
|
'fake' => new Plugin('', ['name' => 'fake']),
|
|
'dep' => new Plugin('', ['name' => 'dep', 'require' => ['a' => '*']]),
|
|
]));
|
|
|
|
$this->assertFalse($manager->enable('nope'));
|
|
|
|
$this->assertTrue($manager->enable('fake'));
|
|
|
|
// re-enable should be allowed
|
|
$this->assertTrue($manager->enable('fake'));
|
|
|
|
Event::assertDispatched(Events\PluginWasEnabled::class, function ($event) {
|
|
$this->assertEquals('fake', $event->plugin->name);
|
|
|
|
return true;
|
|
});
|
|
$this->assertTrue($manager->getEnabledPlugins()->has('fake'));
|
|
$this->assertEquals(
|
|
'fake',
|
|
json_decode(resolve(\App\Services\Option::class)->get('plugins_enabled'), true)[0]['name']
|
|
);
|
|
|
|
$this->assertTrue($manager->enable('dep')['unsatisfied']->isNotEmpty());
|
|
}
|
|
|
|
public function testDisable()
|
|
{
|
|
Event::fake();
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
$manager = resolve(PluginManager::class);
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('plugins');
|
|
$property->setAccessible(true);
|
|
$plugin = new Plugin('', ['name' => 'fake']);
|
|
$plugin->setEnabled(true);
|
|
$property->setValue($manager, collect(['fake' => $plugin]));
|
|
|
|
$manager->disable('fake');
|
|
Event::assertDispatched(Events\PluginWasDisabled::class, function ($event) {
|
|
$this->assertEquals('fake', $event->plugin->name);
|
|
|
|
return true;
|
|
});
|
|
$this->assertFalse($manager->getEnabledPlugins()->has('fake'));
|
|
$this->assertCount(0, json_decode(resolve(\App\Services\Option::class)->get('plugins_enabled'), true));
|
|
}
|
|
|
|
public function testDelete()
|
|
{
|
|
Event::fake();
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')
|
|
->with('plugins_enabled', '[]')
|
|
->andReturn(json_encode([['name' => 'fake', 'version' => '0.0.0']]));
|
|
$mock->shouldReceive('set')
|
|
->with('plugins_enabled', '[]');
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')->andReturn(collect([]));
|
|
$mock->shouldReceive('deleteDirectory')->with('/fake')->once();
|
|
});
|
|
|
|
app()->forgetInstance(PluginManager::class);
|
|
$manager = resolve(PluginManager::class);
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('plugins');
|
|
$property->setAccessible(true);
|
|
$plugin = new Plugin('/fake', ['name' => 'fake']);
|
|
$plugin->setEnabled(true);
|
|
$property->setValue($manager, collect(['fake' => $plugin]));
|
|
|
|
$manager->delete('fake');
|
|
Event::assertDispatched(Events\PluginWasDisabled::class, function ($event) {
|
|
$this->assertEquals('fake', $event->plugin->name);
|
|
|
|
return true;
|
|
});
|
|
Event::assertDispatched(Events\PluginWasDeleted::class, function ($event) {
|
|
$this->assertEquals('fake', $event->plugin->name);
|
|
|
|
return true;
|
|
});
|
|
$this->assertFalse($manager->getEnabledPlugins()->has('fake'));
|
|
$this->assertTrue($manager->all()->isEmpty());
|
|
}
|
|
|
|
public function testHelpers()
|
|
{
|
|
$manager = app('plugins');
|
|
$reflection = new ReflectionClass($manager);
|
|
$property = $reflection->getProperty('plugins');
|
|
$property->setAccessible(true);
|
|
$property->setValue($manager, collect(['fake' => new Plugin('', ['name' => 'fake', 'version' => '1'])]));
|
|
|
|
$this->assertNull(plugin('nope'));
|
|
$this->assertInstanceOf(Plugin::class, plugin('fake'));
|
|
|
|
$this->assertEquals(
|
|
url('plugins').'/fake/assets/relative?v=1',
|
|
plugin_assets('fake', 'relative')
|
|
);
|
|
|
|
$this->expectExceptionMessage('No such plugin.');
|
|
plugin_assets('nope', 'relative');
|
|
}
|
|
|
|
public function testDefaultPluginsDirectory()
|
|
{
|
|
$old = config('plugins.directory');
|
|
config(['plugins.directory' => null]);
|
|
|
|
$directories = app('plugins')->getPluginsDirs();
|
|
$this->assertEquals(1, $directories->count());
|
|
$this->assertEquals(base_path('plugins'), $directories->first());
|
|
|
|
config(['plugins.directory' => $old]);
|
|
}
|
|
|
|
public function testReadMultipleDirectories()
|
|
{
|
|
$old = config('plugins.directory');
|
|
config(['plugins.directory' => '/kumiko,/reina']);
|
|
|
|
$this->mock(Option::class, function ($mock) {
|
|
$mock->shouldReceive('get')->with('plugins_enabled', '[]')->andReturn('[]');
|
|
});
|
|
$this->mock(Filesystem::class, function ($mock) {
|
|
$mock->shouldReceive('directories')
|
|
->with('/kumiko')
|
|
->once()
|
|
->andReturn(collect(['/a', '/b']));
|
|
$mock->shouldReceive('directories')
|
|
->with('/reina')
|
|
->once()
|
|
->andReturn(collect(['/b', '/c']));
|
|
|
|
$mock->shouldReceive('exists')
|
|
->with('/a'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(false);
|
|
$mock->shouldReceive('exists')
|
|
->with('/b'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(false);
|
|
$mock->shouldReceive('exists')
|
|
->with('/c'.DIRECTORY_SEPARATOR.'package.json')
|
|
->once()
|
|
->andReturn(false);
|
|
});
|
|
app()->forgetInstance(PluginManager::class);
|
|
resolve(PluginManager::class)->all();
|
|
|
|
config(['plugins.directory' => $old]);
|
|
}
|
|
}
|