From a605fd260db904de5c45e96991d813d8ae43cac0 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sun, 25 Jun 2023 15:25:51 +0200 Subject: [PATCH] fix(loadTranslations): Handle edge cases where server might return invalid data Signed-off-by: Ferdinand Thiessen --- lib/translation.ts | 10 ++++++--- tests/loadTranslations.test.ts | 39 +++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/translation.ts b/lib/translation.ts index a31b05f3..700f2e64 100644 --- a/lib/translation.ts +++ b/lib/translation.ts @@ -144,9 +144,13 @@ export function loadTranslations(appName: string, callback: (...args: []) => unk } request.onload = () => { if (request.status >= 200 && request.status < 300) { - const bundle = JSON.parse(request.responseText) - if (bundle?.translations) resolve(bundle) - else reject(new Error('Invalid content of translation bundle')) + try { + const bundle = JSON.parse(request.responseText) + if (typeof bundle.translations === 'object') resolve(bundle) + } catch (error) { + // error is probably a SyntaxError due to invalid response text, this is handled by next line + } + reject(new Error('Invalid content of translation bundle')) } else { reject(new Error(request.statusText)) } diff --git a/tests/loadTranslations.test.ts b/tests/loadTranslations.test.ts index ebd61210..7273e491 100644 --- a/tests/loadTranslations.test.ts +++ b/tests/loadTranslations.test.ts @@ -19,19 +19,25 @@ describe('loadTranslations', () => { }, }), }) - .addHandler('GET', '/invalid/l10n/de.json', { + // Response with empty body + .addHandler('GET', '/empty/l10n/de.json', { status: 200, headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - strings: { - 'Hello world!': 'Hallo Welt!', - }, - }), + body: '', }) - .addHandler('GET', '/empty/l10n/de.json', { + // Response contains JSON but no translations + .addHandler('GET', '/missing-bundle/l10n/de.json', { status: 200, headers: { 'Content-Type': 'application/json' }, - body: '', + body: JSON.stringify({}), + }) + // Response contains JSON but the translations are invalid + .addHandler('GET', '/invalid/l10n/de.json', { + status: 200, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + translations: 'invalid', + }), }) .addHandler('GET', '/404/l10n/de.json', { status: 404, @@ -104,8 +110,6 @@ describe('loadTranslations', () => { expect(translate('myapp', 'Hello world!')).toBe('Hallo Welt!') } catch (e) { expect(e).toBe('Unexpected error') - } finally { - console.warn(server.getRequestLog()[0]) } }) @@ -153,10 +157,21 @@ describe('loadTranslations', () => { } }) - it('does reject on empty bundle', async () => { + it('does reject on missing bundle', async () => { const callback = jest.fn() try { - await loadTranslations('invalid', callback) + await loadTranslations('missing-bundle', callback) + expect('').toBe('Unexpected pass') + } catch (e) { + expect(e instanceof Error).toBe(true) + expect((e).message).toBe('Invalid content of translation bundle') + } + }) + + it('does reject on empty response', async () => { + const callback = jest.fn() + try { + await loadTranslations('empty', callback) expect('').toBe('Unexpected pass') } catch (e) { expect(e instanceof Error).toBe(true)