From d6641a370e875902c4229da95889e5769bcdb4b4 Mon Sep 17 00:00:00 2001 From: yyh Date: Thu, 30 Apr 2026 13:54:06 +0800 Subject: [PATCH] refactor(web): use typed error toast --- .../__tests__/dropdown-callbacks.spec.tsx | 8 +++-- .../app-sidebar/dataset-info/dropdown.tsx | 34 ++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx b/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx index ceb8302ee6..05a06f2f77 100644 --- a/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx +++ b/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx @@ -113,7 +113,9 @@ vi.mock('@/service/datasets', () => ({ })) vi.mock('@langgenius/dify-ui/toast', () => ({ - toast: (...args: unknown[]) => mockToast(...args), + toast: { + error: (...args: unknown[]) => mockToast(...args), + }, })) vi.mock('@/app/components/datasets/rename-modal', () => ({ @@ -220,7 +222,7 @@ describe('Dropdown callback coverage', () => { await user.click(screen.getByText('datasetPipeline.operations.exportPipeline')) await waitFor(() => { - expect(mockToast).toHaveBeenCalledWith('app.exportFailed', { type: 'error' }) + expect(mockToast).toHaveBeenCalledWith('app.exportFailed') }) }) @@ -257,7 +259,7 @@ describe('Dropdown callback coverage', () => { await user.click(screen.getByText('common.operation.delete')) await waitFor(() => { - expect(mockToast).toHaveBeenCalledWith('check failed', { type: 'error' }) + expect(mockToast).toHaveBeenCalledWith('check failed') }) expect(screen.queryByText('dataset.deleteDatasetConfirmTitle')).not.toBeInTheDocument() }) diff --git a/web/app/components/app-sidebar/dataset-info/dropdown.tsx b/web/app/components/app-sidebar/dataset-info/dropdown.tsx index 3676547cdf..fa5a40f8a4 100644 --- a/web/app/components/app-sidebar/dataset-info/dropdown.tsx +++ b/web/app/components/app-sidebar/dataset-info/dropdown.tsx @@ -34,6 +34,25 @@ type DropDownProps = { expand: boolean } +type JsonErrorResponse = { + json: () => Promise<{ message?: string }> +} + +const isJsonErrorResponse = (error: unknown): error is JsonErrorResponse => { + return typeof error === 'object' + && error !== null + && 'json' in error + && typeof error.json === 'function' +} + +const getErrorMessage = async (error: unknown) => { + if (!isJsonErrorResponse(error)) + return 'Unknown error' + + const res = await error.json() + return res?.message || 'Unknown error' +} + const DropDown = ({ expand, }: DropDownProps) => { @@ -78,7 +97,7 @@ const DropDown = ({ downloadBlob({ data: file, fileName: `${name}.pipeline` }) } catch { - toast(t('exportFailed', { ns: 'app' }), { type: 'error' }) + toast.error(t('exportFailed', { ns: 'app' })) } }, [dataset, exportPipelineConfig, t]) @@ -90,18 +109,7 @@ const DropDown = ({ setShowConfirmDelete(true) } catch (e: unknown) { - let message = 'Unknown error' - const errorWithJson = typeof e === 'object' && e !== null ? e as { json?: unknown } : null - if (e instanceof Response) { - const res = await e.json() as { message?: string } - message = res?.message || message - } - else if (typeof errorWithJson?.json === 'function') { - const parseErrorResponse = errorWithJson.json as () => Promise<{ message?: string }> - const res = await parseErrorResponse() - message = res?.message || message - } - toast(message, { type: 'error' }) + toast.error(await getErrorMessage(e)) } }, [dataset.id, t])