-
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: ability to have fallbacks and timeouts with backend plugin (#3385)
- Loading branch information
Showing
11 changed files
with
332 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { createBackendFetch } from './BackendFetch'; | ||
import { createFetchingUtility } from './__test__/fetchingUtillity'; | ||
|
||
describe('backend fetch', () => { | ||
let f: ReturnType<typeof createFetchingUtility>; | ||
|
||
beforeEach(() => { | ||
f = createFetchingUtility(); | ||
}); | ||
|
||
it('calls fetch with correct params', () => { | ||
const plugin = createBackendFetch(); | ||
plugin.getRecord({ fetch: f.fetchMock, language: 'de' }); | ||
expect(f.fetchMock).toHaveBeenCalledWith( | ||
'/i18n/de.json', | ||
expect.objectContaining({ | ||
headers: { Accept: 'application/json' }, | ||
}) | ||
); | ||
}); | ||
|
||
it('calls fetch with custom prefix', () => { | ||
const plugin = createBackendFetch({ prefix: 'http://test.com/test' }); | ||
plugin.getRecord({ fetch: f.fetchMock, language: 'de', namespace: 'ns' }); | ||
expect(f.fetchMock).toHaveBeenCalledWith( | ||
'http://test.com/test/ns/de.json', | ||
expect.objectContaining({ | ||
headers: { Accept: 'application/json' }, | ||
}) | ||
); | ||
}); | ||
|
||
it('handles extra slash', () => { | ||
const plugin = createBackendFetch({ prefix: 'http://test.com/test/' }); | ||
plugin.getRecord({ fetch: f.fetchMock, language: 'de' }); | ||
expect(f.fetchMock).toHaveBeenCalledWith( | ||
'http://test.com/test/de.json', | ||
expect.objectContaining({ | ||
headers: { Accept: 'application/json' }, | ||
}) | ||
); | ||
}); | ||
|
||
it('adds headers', () => { | ||
const plugin = createBackendFetch({ | ||
prefix: 'http://test.com/test/', | ||
headers: { Authorization: 'test' }, | ||
}); | ||
plugin.getRecord({ fetch: f.fetchMock, language: 'de' }); | ||
expect(f.fetchMock).toHaveBeenCalledWith( | ||
'http://test.com/test/de.json', | ||
expect.objectContaining({ | ||
headers: { Accept: 'application/json', Authorization: 'test' }, | ||
}) | ||
); | ||
}); | ||
|
||
it('passes additional properties', () => { | ||
const plugin = createBackendFetch({ | ||
prefix: 'http://test.com/test/', | ||
cache: 'no-cache', | ||
}); | ||
plugin.getRecord({ fetch: f.fetchMock, language: 'de' }); | ||
expect(f.fetchMock).toHaveBeenCalledWith( | ||
'http://test.com/test/de.json', | ||
expect.objectContaining({ | ||
headers: { Accept: 'application/json' }, | ||
cache: 'no-cache', | ||
}) | ||
); | ||
}); | ||
|
||
it('fails with a timeout', async () => { | ||
const plugin = createBackendFetch({ | ||
prefix: 'http://test.com/test/', | ||
timeout: 5, | ||
}); | ||
await expect( | ||
plugin.getRecord({ fetch: f.infiniteFetch, language: 'de' }) | ||
).rejects.toHaveProperty( | ||
'message', | ||
'TIMEOUT: http://test.com/test/de.json' | ||
); | ||
|
||
expect(f.infiniteFetch).toHaveBeenCalledWith( | ||
'http://test.com/test/de.json', | ||
expect.objectContaining({ | ||
headers: { Accept: 'application/json' }, | ||
}) | ||
); | ||
expect(f.signalHandler).toHaveBeenCalledWith('Aborted with signal'); | ||
}); | ||
|
||
it('throws the original error', async () => { | ||
const plugin = createBackendFetch({ | ||
prefix: 'http://test.com/test/', | ||
}); | ||
expect( | ||
plugin.getRecord({ fetch: f.failingFetch, language: 'de' }) | ||
).rejects.toHaveProperty('message', 'Fetch failed'); | ||
}); | ||
|
||
it('returns undefined when `fallbackOnFail`', async () => { | ||
const plugin = createBackendFetch({ | ||
prefix: 'http://test.com/test/', | ||
fallbackOnFail: true, | ||
}); | ||
expect( | ||
await plugin.getRecord({ fetch: f.failingFetch, language: 'de' }) | ||
).toEqual(undefined); | ||
}); | ||
|
||
it('returns undefined when `fallbackOnFail` and timeout', async () => { | ||
const plugin = createBackendFetch({ | ||
prefix: 'http://test.com/test/', | ||
fallbackOnFail: true, | ||
timeout: 5, | ||
}); | ||
expect( | ||
await plugin.getRecord({ fetch: f.infiniteFetch, language: 'de' }) | ||
).toEqual(undefined); | ||
expect(f.signalHandler).toHaveBeenCalledWith('Aborted with signal'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { TolgeeCore } from '@tolgee/core'; | ||
import { createFetchingUtility } from './fetchingUtillity'; | ||
import { BackendFetch } from '../BackendFetch'; | ||
|
||
describe('tolgee with fallback backend fetch', () => { | ||
let f: ReturnType<typeof createFetchingUtility>; | ||
|
||
beforeEach(() => { | ||
f = createFetchingUtility(); | ||
}); | ||
|
||
it('fallback works with backend fetch', async () => { | ||
// eslint-disable-next-line no-console | ||
console.error = jest.fn(); | ||
const tolgee = TolgeeCore() | ||
.use(BackendFetch({ prefix: '1', timeout: 2, fallbackOnFail: true })) | ||
.use(BackendFetch({ prefix: '2', timeout: 2, fallbackOnFail: true })) | ||
.use(BackendFetch({ prefix: '3', timeout: 2, fallbackOnFail: false })) | ||
.init({ | ||
language: 'en', | ||
availableLanguages: ['en'], | ||
fetch: f.infiniteFetch, | ||
}); | ||
await expect(tolgee.loadRecord({ language: 'en' })).rejects.toHaveProperty( | ||
'message', | ||
'Tolgee: Failed to fetch record for "en"' | ||
); | ||
expect(f.infiniteFetch).toHaveBeenCalledTimes(3); | ||
}); | ||
|
||
it('fallback works when all backend fetch plugins fail', async () => { | ||
const tolgee = TolgeeCore() | ||
.use(BackendFetch({ prefix: '1', timeout: 2, fallbackOnFail: true })) | ||
.use(BackendFetch({ prefix: '2', timeout: 2, fallbackOnFail: true })) | ||
.use(BackendFetch({ prefix: '3', timeout: 2, fallbackOnFail: true })) | ||
.init({ | ||
language: 'en', | ||
availableLanguages: ['en'], | ||
fetch: f.infiniteFetch, | ||
}); | ||
await expect(tolgee.loadRecord({ language: 'en' })).resolves.toEqual( | ||
new Map() | ||
); | ||
expect(f.infiniteFetch).toHaveBeenCalledTimes(3); | ||
}); | ||
|
||
it('fallback works with static data', async () => { | ||
const tolgee = TolgeeCore() | ||
.use(BackendFetch({ prefix: '1', timeout: 2, fallbackOnFail: true })) | ||
.use(BackendFetch({ prefix: '2', timeout: 2, fallbackOnFail: true })) | ||
.init({ | ||
language: 'en', | ||
availableLanguages: ['en'], | ||
fetch: f.infiniteFetch, | ||
staticData: { | ||
en: { test: 'test' }, | ||
}, | ||
}); | ||
await expect(tolgee.loadRecord({ language: 'en' })).resolves.toEqual( | ||
new Map([['test', 'test']]) | ||
); | ||
expect(f.infiniteFetch).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
it('fallback works with dynamic static data', async () => { | ||
const tolgee = TolgeeCore() | ||
.use(BackendFetch({ prefix: '1', timeout: 2, fallbackOnFail: true })) | ||
.use(BackendFetch({ prefix: '2', timeout: 2, fallbackOnFail: true })) | ||
.init({ | ||
language: 'en', | ||
availableLanguages: ['en'], | ||
fetch: f.infiniteFetch, | ||
staticData: { | ||
en: () => Promise.resolve({ test: 'test' }), | ||
}, | ||
}); | ||
await expect(tolgee.loadRecord({ language: 'en' })).resolves.toEqual( | ||
new Map([['test', 'test']]) | ||
); | ||
expect(f.infiniteFetch).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
Oops, something went wrong.