diff --git a/src/app/configure-tasks-app/ui/Subtemplates.tsx b/src/app/configure-tasks-app/ui/Subtemplates.tsx index f1742287a..22b50d1e9 100644 --- a/src/app/configure-tasks-app/ui/Subtemplates.tsx +++ b/src/app/configure-tasks-app/ui/Subtemplates.tsx @@ -90,7 +90,7 @@ export const Subtemplates = ({ template_id, token }: { template_id: string; toke const optimisticData = sortTaskByDescendingOrder([...currentSubtemplates, tempSubtemplate]) try { - mutate( + await mutate( cacheKey, async () => { const subTask = await createSubTemplate(token, template_id, payload) diff --git a/src/app/detail/ui/ActivityWrapper.tsx b/src/app/detail/ui/ActivityWrapper.tsx index 8bd1b1ff9..4aa5fd240 100644 --- a/src/app/detail/ui/ActivityWrapper.tsx +++ b/src/app/detail/ui/ActivityWrapper.tsx @@ -102,7 +102,7 @@ export const ActivityWrapper = ({ const optimisticData = getOptimisticData(postCommentPayload, activities.data, tempLog) try { - mutate( + await mutate( cacheKey, async () => { shouldRefetchRef.current = false diff --git a/src/app/detail/ui/Subtasks.tsx b/src/app/detail/ui/Subtasks.tsx index 51c45cf86..87f077855 100644 --- a/src/app/detail/ui/Subtasks.tsx +++ b/src/app/detail/ui/Subtasks.tsx @@ -104,7 +104,7 @@ export const Subtasks = ({ ) const optimisticData = subTasks?.tasks ? sortSubtasksByPriority([...subTasks.tasks, tempSubtask]) : [tempSubtask] try { - mutate( + await mutate( cacheKey, async () => { const subTask = await handleCreate(token, payload, { disableSubtaskTemplates: true }) diff --git a/src/utils/fetcher.test.ts b/src/utils/fetcher.test.ts new file mode 100644 index 000000000..9f2427efc --- /dev/null +++ b/src/utils/fetcher.test.ts @@ -0,0 +1,35 @@ +import { fetcher } from '@/utils/fetcher' + +describe('fetcher', () => { + const originalFetch = global.fetch + + afterEach(() => { + global.fetch = originalFetch + jest.restoreAllMocks() + }) + + it('returns parsed JSON for successful responses', async () => { + global.fetch = jest.fn().mockResolvedValue({ + ok: true, + json: async () => ({ tasks: [] }), + }) + + await expect(fetcher('/api/tasks/?token=test')).resolves.toEqual({ tasks: [] }) + }) + + it('throws an error with status, url, and response body for failed responses', async () => { + global.fetch = jest.fn().mockResolvedValue({ + ok: false, + status: 500, + text: async () => 'Internal server error', + }) + + await expect(fetcher('/api/tasks/?token=test')).rejects.toThrow( + 'An error occurred while fetching the data. [500] /api/tasks/?token=test: Internal server error', + ) + }) + + it('returns undefined when url is null', async () => { + await expect(fetcher(null)).resolves.toBeUndefined() + }) +}) diff --git a/src/utils/fetcher.ts b/src/utils/fetcher.ts index 99f9dfe43..46e1b2c34 100644 --- a/src/utils/fetcher.ts +++ b/src/utils/fetcher.ts @@ -4,8 +4,9 @@ export const fetcher = async (url: string | null) => { const res = await fetch(url) if (!res.ok) { - const error = new Error('An error occurred while fetching the data.') - throw error + const responseText = await res.text().catch(() => '') + const detail = responseText ? `: ${responseText.slice(0, 200)}` : '' + throw new Error(`An error occurred while fetching the data. [${res.status}] ${url}${detail}`) } return res.json()