From 8cb13b912fe60cec0ef53bf9755b5d8d6eb370a1 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Oct 2025 18:27:51 +0700 Subject: [PATCH] Handle errors on test page --- web/src/lib/components/ErrorDisplay.svelte | 158 +++++++++++++++++++++ web/src/lib/components/index.ts | 1 + web/src/routes/+error.svelte | 126 +--------------- web/src/routes/test/[test]/+page.svelte | 57 ++++++-- 4 files changed, 209 insertions(+), 133 deletions(-) create mode 100644 web/src/lib/components/ErrorDisplay.svelte diff --git a/web/src/lib/components/ErrorDisplay.svelte b/web/src/lib/components/ErrorDisplay.svelte new file mode 100644 index 0000000..96cfae2 --- /dev/null +++ b/web/src/lib/components/ErrorDisplay.svelte @@ -0,0 +1,158 @@ + + +
+
+ +
+ +
+ + +

{status}

+ + +

{getErrorTitle(status)}

+ + +

{getErrorDescription(status)}

+ + + {#if message && message !== defaultDescription} + + {/if} + + + {#if showActions} +
+ + + Go Home + + +
+ {/if} + + + {#if status === 404 && showActions} +
+

Looking for something specific?

+ +
+ {/if} +
+
+ + diff --git a/web/src/lib/components/index.ts b/web/src/lib/components/index.ts index e600c11..dadab9e 100644 --- a/web/src/lib/components/index.ts +++ b/web/src/lib/components/index.ts @@ -14,3 +14,4 @@ export { default as HeaderAnalysisCard } from "./HeaderAnalysisCard.svelte"; export { default as PtrRecordsDisplay } from "./PtrRecordsDisplay.svelte"; export { default as PtrForwardRecordsDisplay } from "./PtrForwardRecordsDisplay.svelte"; export { default as TinySurvey } from "./TinySurvey.svelte"; +export { default as ErrorDisplay } from "./ErrorDisplay.svelte"; diff --git a/web/src/routes/+error.svelte b/web/src/routes/+error.svelte index 5d0514c..a429ea5 100644 --- a/web/src/routes/+error.svelte +++ b/web/src/routes/+error.svelte @@ -1,5 +1,6 @@ @@ -55,96 +28,5 @@
-
-
- -
- -
- - -

{status}

- - -

{getErrorTitle(status)}

- - -

{getErrorDescription(status)}

- - - {#if message !== getErrorDescription(status)} - - {/if} - - -
- - - Go Home - - -
- - - {#if status === 404} -
-

Looking for something specific?

- -
- {/if} -
-
+
- - diff --git a/web/src/routes/test/[test]/+page.svelte b/web/src/routes/test/[test]/+page.svelte index 7f50923..c8b5cc0 100644 --- a/web/src/routes/test/[test]/+page.svelte +++ b/web/src/routes/test/[test]/+page.svelte @@ -14,6 +14,7 @@ ContentAnalysisCard, HeaderAnalysisCard, TinySurvey, + ErrorDisplay, } from "$lib/components"; let testId = $derived(page.params.test); @@ -21,6 +22,7 @@ let report = $state(null); let loading = $state(true); let error = $state(null); + let errorStatus = $state(500); let reanalyzing = $state(false); let pollInterval: ReturnType | null = null; let nextfetch = $state(23); @@ -28,6 +30,36 @@ let menuOpen = $state(false); let fetching = $state(false); + // Helper function to handle API errors + function handleApiError(apiError: unknown, defaultMessage: string) { + if (apiError && typeof apiError === "object") { + if ("message" in apiError) { + error = String(apiError.message); + } else { + error = defaultMessage; + } + + // Determine status code based on error type + if ("error" in apiError) { + if (apiError.error === "rate_limit_exceeded") { + errorStatus = 429; + } else if (apiError.error === "not_found") { + errorStatus = 404; + } else { + errorStatus = 500; + } + } else { + errorStatus = 500; + } + } else if (apiError instanceof Error) { + error = apiError.message; + errorStatus = 500; + } else { + error = defaultMessage; + errorStatus = 500; + } + } + async function fetchTest() { if (!testId) return; @@ -36,6 +68,9 @@ } nbfetch += 1; + // Clear any previous errors + error = null; + // Set fetching state and ensure minimum 500ms display time fetching = true; const startTime = Date.now(); @@ -52,10 +87,15 @@ } stopPolling(); } + } else if (testResponse.error) { + handleApiError(testResponse.error, "Failed to fetch test"); + loading = false; + stopPolling(); + return; } loading = false; } catch (err) { - error = err instanceof Error ? err.message : "Failed to fetch test"; + handleApiError(err, "Failed to fetch test"); loading = false; stopPolling(); } finally { @@ -107,7 +147,7 @@ if (newTestId) { testChange(newTestId); } - }) + }); onDestroy(() => { stopPolling(); @@ -124,9 +164,11 @@ const response = await reanalyzeReport({ path: { id: testId } }); if (response.data) { report = response.data; + } else if (response.error) { + handleApiError(response.error, "Failed to reanalyze report"); } } catch (err) { - error = err instanceof Error ? err.message : "Failed to reanalyze report"; + handleApiError(err, "Failed to reanalyze report"); } finally { reanalyzing = false; } @@ -162,14 +204,7 @@

Loading test...

{:else if error} -
-
- -
-
+ {:else if test && test.status !== "analyzed"}