Skip to content

Commit

Permalink
fix(useFetch): chain callbacks from createFetch and useFetch
Browse files Browse the repository at this point in the history
  • Loading branch information
tobyzerner committed May 1, 2022
1 parent e24db79 commit 2ed10f6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
66 changes: 66 additions & 0 deletions packages/core/useFetch/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,72 @@ describe('useFetch', () => {
})
})

test('should chain beforeFetch function when using a factory instance', async() => {
const useMyFetch = createFetch({
baseUrl: 'https://example.com',
options: {
beforeFetch({ options }) {
options.headers = { ...options.headers, Global: 'foo' }
return { options }
},
},
})
useMyFetch('test', {
beforeFetch({ options }) {
options.headers = { ...options.headers, Local: 'foo' }
return { options }
},
})

await retry(() => {
expect(fetchSpyHeaders()).toMatchObject({ Global: 'foo', Local: 'foo' })
})
})

test('should chain afterFetch function when using a factory instance', async() => {
const useMyFetch = createFetch({
baseUrl: 'https://example.com',
options: {
afterFetch(ctx) {
ctx.data.title = 'Global'
return ctx
},
},
})
const { data } = useMyFetch('test?json', {
afterFetch(ctx) {
ctx.data.title += ' Local'
return ctx
},
}).json()

await retry(() => {
expect(data.value).toEqual(expect.objectContaining({ title: 'Global Local' }))
})
})

test('should chain onFetchError function when using a factory instance', async() => {
const useMyFetch = createFetch({
baseUrl: 'https://example.com',
options: {
onFetchError(ctx) {
ctx.data.title = 'Global'
return ctx
},
},
})
const { data } = useMyFetch('test?status=400&json', {
onFetchError(ctx) {
ctx.data.title += ' Local'
return ctx
},
}).json()

await retry(() => {
expect(data.value).toEqual(expect.objectContaining({ title: 'Global Local' }))
})
})

test('should run the beforeFetch function and add headers to the request', async() => {
useFetch('https://example.com', { headers: { 'Accept-Language': 'en-US' } }, {
beforeFetch({ options }) {
Expand Down
18 changes: 17 additions & 1 deletion packages/core/useFetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ function headersToObject(headers: HeadersInit | undefined) {
return headers
}

function chainCallbacks<T = any>(...callbacks: (((ctx: T) => void | Partial<T> | Promise<void | Partial<T>>) | undefined)[]) {
return (ctx: T) => {
callbacks.forEach(async(callback) => {
if (callback)
ctx = { ...ctx, ...(await callback(ctx)) }
})
return ctx
}
}

export function createFetch(config: CreateFetchOptions = {}) {
const _options = config.options || {}
const _fetchOptions = config.fetchOptions || {}
Expand All @@ -231,7 +241,13 @@ export function createFetch(config: CreateFetchOptions = {}) {
// Merge properties into a single object
if (args.length > 0) {
if (isFetchOptions(args[0])) {
options = { ...options, ...args[0] }
options = {
...options,
...args[0],
beforeFetch: chainCallbacks(_options.beforeFetch, args[0].beforeFetch),
afterFetch: chainCallbacks(_options.afterFetch, args[0].afterFetch),
onFetchError: chainCallbacks(_options.onFetchError, args[0].onFetchError),
}
}
else {
fetchOptions = {
Expand Down

0 comments on commit 2ed10f6

Please sign in to comment.