diff --git a/resources/assets/src/js/net.js b/resources/assets/src/js/net.js index 8af5c37d..2a7c609b 100644 --- a/resources/assets/src/js/net.js +++ b/resources/assets/src/js/net.js @@ -3,6 +3,13 @@ import { emit } from './event'; import { queryStringify } from './utils'; import { showAjaxError } from './notify'; +class HTTPError extends Error { + constructor(message, response) { + super(message); + this.response = response; + } +} + const empty = Object.create(null); /** @type Request */ export const init = { @@ -30,9 +37,8 @@ export async function walkFetch(request) { ? response.json() : response.text(); } else { - const text = await response.text(); - emit('fetchError', text); - showAjaxError(text); + const res = response.clone(); + throw new HTTPError(await response.text(), res); } } catch (error) { emit('fetchError', error); diff --git a/resources/assets/src/js/notify.js b/resources/assets/src/js/notify.js index 227556b0..a695f617 100644 --- a/resources/assets/src/js/notify.js +++ b/resources/assets/src/js/notify.js @@ -21,16 +21,11 @@ export function showMsg(msg, type = 'info') { /** * Show modal if error occured when sending an ajax request. * - * @param {TypeError | string} error + * @param {Error} error * @return {void} */ export function showAjaxError(error) { - if (!error) { - return console.warn('Empty Ajax response body.'); - } - - const message = typeof error === 'string' ? error : error.message; - showModal(message.replace(/\n/g, '
'), trans('general.fatalError'), 'danger'); + showModal(error.message.replace(/\n/g, '
'), trans('general.fatalError'), 'danger'); } /** diff --git a/resources/assets/tests/js/net.test.js b/resources/assets/tests/js/net.test.js index 63f9ad6c..67fd03ca 100644 --- a/resources/assets/tests/js/net.test.js +++ b/resources/assets/tests/js/net.test.js @@ -78,10 +78,11 @@ test('the POST method', async () => { test('low level fetch', async () => { const json = jest.fn().mockResolvedValue({}); window.fetch = jest.fn() - .mockRejectedValueOnce(new Error) + .mockRejectedValueOnce(new Error('network')) .mockResolvedValueOnce({ ok: false, - text: () => Promise.resolve('404') + text: () => Promise.resolve('404'), + clone: () => ({}) }) .mockResolvedValueOnce({ ok: true, @@ -101,11 +102,13 @@ test('low level fetch', async () => { await net.walkFetch(request); expect(showAjaxError.mock.calls[0][0]).toBeInstanceOf(Error); + expect(showAjaxError.mock.calls[0][0]).toHaveProperty('message', 'network'); expect(stub).toBeCalledWith(expect.any(Error)); await net.walkFetch(request); - expect(showAjaxError).toBeCalledWith('404'); - expect(stub).toBeCalledWith('404'); + expect(showAjaxError.mock.calls[1][0]).toBeInstanceOf(Error); + expect(stub.mock.calls[1][0]).toHaveProperty('message', '404'); + expect(stub.mock.calls[1][0]).toHaveProperty('response'); await net.walkFetch(request); expect(json).toBeCalled(); diff --git a/resources/assets/tests/js/notify.test.js b/resources/assets/tests/js/notify.test.js index 50d421d0..658d47e7 100644 --- a/resources/assets/tests/js/notify.test.js +++ b/resources/assets/tests/js/notify.test.js @@ -12,13 +12,9 @@ test('show message', () => { }); test('show AJAX error', () => { - notify.showAjaxError(); // Can be no arguments - $.fn.modal = function () { document.body.innerHTML = this.html(); }; - notify.showAjaxError('error\nerror'); - expect(document.body.innerHTML).toContain('error
error'); notify.showAjaxError(new Error('an-error')); expect(document.body.innerHTML).toContain('an-error');