diff --git a/resources/assets/src/js/__tests__/admin.test.js b/resources/assets/src/js/__tests__/admin.test.js index 84f6a5eb..7a5cb7c1 100644 --- a/resources/assets/src/js/__tests__/admin.test.js +++ b/resources/assets/src/js/__tests__/admin.test.js @@ -566,6 +566,124 @@ describe('tests for "plugins" module', () => { }); }); +describe('tests for "market" module', () => { + const modulePath = '../admin/market'; + + // TODO: test initializing market table + + it('install a plugin', async () => { + const fetch = jest.fn() + .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' })) + .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'failed' })) + .mockReturnValueOnce(Promise.reject()); + const url = jest.fn(path => path); + const swal = jest.fn(); + const toastr = { + success: jest.fn(), + warning: jest.fn() + }; + const trans = jest.fn(key => key); + const reloadTable = jest.fn(); + const showAjaxError = jest.fn(); + window.trans = trans; + window.fetch = fetch; + window.url = url; + window.swal = swal; + window.toastr = toastr; + window.showAjaxError = showAjaxError; + $.marketTable = { + ajax: { + reload: reloadTable + } + }; + document.body.innerHTML = ` + + `; + + const installPlugin = require(modulePath).installPlugin; + + await installPlugin('foo-bar'); + expect(fetch).toBeCalledWith({ + type: 'POST', + url: 'admin/plugins/market/download', + dataType: 'json', + data: { name: 'foo-bar' }, + beforeSend: expect.any(Function) + }); + expect(swal).not.toBeCalledWith({ type: 'warning' }); + expect(toastr.success).toBeCalledWith('success'); + expect(reloadTable).toBeCalledWith(null, false); + + await installPlugin('foo-bar'); + expect(swal).toBeCalledWith({ type: 'warning', html: 'failed' }); + + await installPlugin('foo-bar'); + expect(showAjaxError).toBeCalled(); + }); + + it('update a plugin', async () => { + const fetch = jest.fn() + .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' })); + const getPluginRowData = jest.fn() + .mockReturnValueOnce({ installed: false }) + .mockReturnValue({ + title: 'Foo Bar', + version: '5.1.4', + installed: '1.1.4' + }); + const url = jest.fn(path => path); + const swal = jest.fn() + .mockReturnValueOnce(Promise.resolve()) + .mockReturnValueOnce(Promise.reject()) + .mockReturnValueOnce(Promise.resolve()); + const toastr = { + success: jest.fn(), + warning: jest.fn() + }; + const trans = jest.fn(key => key); + const reloadTable = jest.fn(); + const showAjaxError = jest.fn(); + window.trans = trans; + window.fetch = fetch; + window.url = url; + window.swal = swal; + window.toastr = toastr; + window.showAjaxError = showAjaxError; + $.marketTable = { + ajax: { + reload: reloadTable + }, + row: () => ({ + data: getPluginRowData + }) + }; + document.body.innerHTML = ` + + `; + + const updatePlugin = require(modulePath).updatePlugin; + + await updatePlugin('foo-bar'); + expect(swal).toBeCalledWith({ type: 'warning', html: 'not installed' }); + expect(fetch).not.toBeCalled(); + + await updatePlugin('foo-bar'); + expect(swal).toBeCalledWith({ type: 'warning', text: 'admin.confirmUpdate', showCancelButton: true }); + expect(fetch).not.toBeCalled(); + + await updatePlugin('foo-bar'); + expect(fetch).toBeCalledWith({ + type: 'POST', + url: 'admin/plugins/market/download', + dataType: 'json', + data: { name: 'foo-bar' }, + beforeSend: expect.any(Function) + }); + expect(toastr.success).toBeCalledWith('success'); + expect(reloadTable).toBeCalledWith(null, false); + }); +}); + describe('tests for "update" module', () => { const modulePath = '../admin/update'; diff --git a/resources/assets/src/js/admin/market.js b/resources/assets/src/js/admin/market.js index 1b1c6f49..ed157f91 100644 --- a/resources/assets/src/js/admin/market.js +++ b/resources/assets/src/js/admin/market.js @@ -130,14 +130,18 @@ async function updatePlugin(name) { const data = $.marketTable.row(`#plugin-${name}`).data(); if (data.installed === false) { - swal({ type: 'warning', html: 'not installed' }); + return swal({ type: 'warning', html: 'not installed' }); } - await swal({ - text: trans('admin.confirmUpdate', { plugin: data.title, old: data.installed, new: data.version }), - type: 'warning', - showCancelButton: true - }); + try { + await swal({ + text: trans('admin.confirmUpdate', { plugin: data.title, old: data.installed, new: data.version }), + type: 'warning', + showCancelButton: true + }); + } catch (error) { + return; + } installPlugin(name, { beforeSend: () => { diff --git a/tests/MarketControllerTest.php b/tests/MarketControllerTest.php new file mode 100644 index 00000000..471f9d5f --- /dev/null +++ b/tests/MarketControllerTest.php @@ -0,0 +1,59 @@ +actAs('admin'); + } + + public function testShowMarket() + { + $this->visit('/admin/plugins/market') + ->see(trans('general.plugin-market')); + } + + public function testDownload() + { + // Try to download a non-existent plugin + $this->post('/admin/plugins/market/download', [ + 'name' => 'non-existent-plugin' + ])->seeJson([ + 'errno' => 1, + 'msg' => trans('admin.plugins.market.non-existent', ['plugin' => 'non-existent-plugin']) + ]); + + // Download and extract plugin + $this->post('/admin/plugins/market/download', [ + 'name' => 'hello-dolly' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('admin.plugins.market.install-success') + ]); + $this->assertTrue(is_dir(base_path('plugins/hello-dolly'))); + $this->assertFileNotExists(base_path('plugins/hello-dolly_v1.0.0.zip')); + } + + public function testGetMarketData() + { + $this->post('/admin/plugins/market-data') + ->seeJsonStructure([ + 'data' => [[ + 'name', + 'title', + 'version', + 'installed', + 'description', + 'author', + 'dist', + 'enabled', + 'dependencies' + ]] + ]); + + // Get plugins info without an valid certificate + config(['secure.certificates' => '']); + $this->setExpectedException('Error')->post('/admin/plugins/market-data'); + } +}