diff --git a/.travis.yml b/.travis.yml index c7e9603f..91d06a2f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ git: cache: directories: - vendor + - plugins - node_modules env: @@ -19,6 +20,7 @@ before_script: - mysql -e 'CREATE DATABASE IF NOT EXISTS test;' - php artisan key:random - php artisan salt:random +- php -f ./tests/scripts/download-plugins.php script: ./vendor/bin/phpunit diff --git a/app/Http/Controllers/PluginController.php b/app/Http/Controllers/PluginController.php index d54927f8..e3886e63 100644 --- a/app/Http/Controllers/PluginController.php +++ b/app/Http/Controllers/PluginController.php @@ -10,6 +10,9 @@ use App\Services\PluginManager; class PluginController extends Controller { + /** + * @codeCoverageIgnore + */ public function showMarket() { return redirect('/')->setTargetUrl( @@ -29,7 +32,7 @@ class PluginController extends Controller if ($plugin && $plugin->isEnabled() && $plugin->hasConfigView()) { return $plugin->getConfigView(); } else { - abort(404, trans('admin.plugins.operations.no-config-notice')); + return abort(404, trans('admin.plugins.operations.no-config-notice')); } } @@ -58,9 +61,10 @@ class PluginController extends Controller return json(trans('admin.plugins.operations.deleted'), 0); default: - # code... - break; + return json(trans('admin.invalid-action'), 1); } + } else { + return json(trans('admin.plugins.operations.not-found'), 1); } } diff --git a/app/Services/PluginManager.php b/app/Services/PluginManager.php index 712e1835..97665264 100644 --- a/app/Services/PluginManager.php +++ b/app/Services/PluginManager.php @@ -175,7 +175,7 @@ class PluginManager $this->disable($name); - // fire event before deleeting plugin files + // fire event before deleting plugin files $this->dispatcher->fire(new Events\PluginWasDeleted($plugin)); $this->filesystem->deleteDirectory($plugin->getPath()); diff --git a/app/helpers.php b/app/helpers.php index a4895f0f..693ecb72 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -51,6 +51,10 @@ if (! function_exists('assets')) { if (! function_exists('plugin')) { + /** + * @param string $id + * @return \App\Services\Plugin + */ function plugin($id) { return app('plugins')->getPlugin($id); diff --git a/resources/lang/en/admin.yml b/resources/lang/en/admin.yml index 27a81d73..276cb972 100644 --- a/resources/lang/en/admin.yml +++ b/resources/lang/en/admin.yml @@ -108,6 +108,7 @@ plugins: disabled: :plugin has been disabled. deleted: The plugin was deleted successfully. no-config-notice: The plugin is not installed or doesn't provide configuration page. + not-found: No such plugin. empty: No result @@ -155,3 +156,5 @@ update: write-permission: Unable to make cache directory. Please sure permission. unzip: "Failed to unzip update file. Error code: " overwrite: Unable to overwrite files. + +invalid-action: Invalid action diff --git a/resources/lang/zh_CN/admin.yml b/resources/lang/zh_CN/admin.yml index 8b4318dd..b00f2851 100644 --- a/resources/lang/zh_CN/admin.yml +++ b/resources/lang/zh_CN/admin.yml @@ -108,6 +108,7 @@ plugins: disabled: :plugin 已禁用 deleted: 插件已被成功删除 no-config-notice: 插件未安装或未提供配置页面 + not-found: 插件不存在 empty: 无结果 @@ -155,3 +156,5 @@ update: write-permission: 您的服务器不支持自动更新:创建下载缓存文件夹失败,请检查目录权限。 unzip: 更新包解压缩失败。错误代码: overwrite: 您的服务器不支持自动更新:无法覆盖文件。 + +invalid-action: 无效的操作名 diff --git a/tests/PluginControllerTest.php b/tests/PluginControllerTest.php new file mode 100644 index 00000000..7e5307fd --- /dev/null +++ b/tests/PluginControllerTest.php @@ -0,0 +1,114 @@ +actAs('admin'); + } + + public function testShowManage() + { + $this->visit('/admin/plugins/manage') + ->see(trans('general.plugin-manage')); + } + + public function testConfig() + { + // Plugin is disabled + $this->get('/admin/plugins/config/example-plugin') + ->see(trans('admin.plugins.operations.no-config-notice')) + ->assertResponseStatus(404); + + // Plugin is enabled but it doesn't have config view + plugin('avatar-api')->setEnabled(true); + $this->get('/admin/plugins/config/avatar-api') + ->see(trans('admin.plugins.operations.no-config-notice')) + ->assertResponseStatus(404); + + // Plugin has config view + plugin('example-plugin')->setEnabled(true); + $this->get('/admin/plugins/config/example-plugin') + ->assertResponseStatus(200); + } + + public function testManage() + { + // An not-existed plugin + $this->post('/admin/plugins/manage', ['name' => 'nope']) + ->seeJson([ + 'errno' => 1, + 'msg' => trans('admin.plugins.operations.not-found') + ]); + + // Invalid action + $this->post('/admin/plugins/manage', ['name' => 'avatar-api']) + ->seeJson([ + 'errno' => 1, + 'msg' => trans('admin.invalid-action') + ]); + + // Enable a plugin + $this->expectsEvents(App\Events\PluginWasEnabled::class); + $this->post('/admin/plugins/manage', [ + 'name' => 'avatar-api', + 'action' => 'enable' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans( + 'admin.plugins.operations.enabled', + ['plugin' => plugin('avatar-api')->title] + ) + ]); + + // Disable a plugin + $this->post('/admin/plugins/manage', [ + 'name' => 'avatar-api', + 'action' => 'disable' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans( + 'admin.plugins.operations.disabled', + ['plugin' => plugin('avatar-api')->title] + ) + ]); + $this->expectsEvents(App\Events\PluginWasDisabled::class); + + // Delete a plugin + $this->post('/admin/plugins/manage', [ + 'name' => 'avatar-api', + 'action' => 'delete' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('admin.plugins.operations.deleted') + ]); + $this->expectsEvents(App\Events\PluginWasDeleted::class); + $this->assertFalse(file_exists(base_path('plugins/avatar-api/'))); + } + + public function testGetPluginData() + { + $this->get('/admin/plugins/data') + ->seeJsonStructure([ + 'data' => [[ + 'name', + 'version', + 'path', + 'title', + 'description', + 'author' => ['author', 'url'], + 'url', + 'namespace', + 'status', + 'operations' => ['enabled', 'hasConfigView'] + ]] + ]); + } +} diff --git a/tests/scripts/download-plugins.php b/tests/scripts/download-plugins.php new file mode 100644 index 00000000..33ade77d --- /dev/null +++ b/tests/scripts/download-plugins.php @@ -0,0 +1,57 @@ +open('./storage/'.$filename); + $zip->extractTo('./plugins/'); + $zip->close(); + unlink('./storage/'.$filename); + } catch (Exception $e) { + fwrite(STDOUT, error("Failed to unzip!")); + exit(1); + } + $time_diff = round(microtime(true) - $timer, 3); + fwrite(STDOUT, success("Finished: \"$plugin_name\" in {$time_diff}s")); + } else { + fwrite(STDOUT, success("Plugin \"$plugin_name\" is existed. OK.")); + } +} + +$plugins = [ + 'example-plugin' => 'example-plugin_v1.0.zip', + 'avatar-api' => 'avatar-api_v1.1.zip' +]; + +foreach ($plugins as $plugin_name => $filename) { + getPlugin($plugin_name, $filename); +}