# All files / src/components/error ErrorFallback.tsx

83.16% Statements 84/101
57.14% Branches 4/7
66.66% Functions 2/3
83.16% Lines 84/101

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    1021x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    24x
    24x

    24x
    24x
    24x
    24x
    24x
    24x
    24x

    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x

    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x

    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
     import { useState } from "react";
    import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
    import { AIErrorHelper } from "@/components/error/AIErrorHelper";
    import { Button } from "@/components/ui/button";
    import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
    import { AlertTriangleIcon, RefreshCwIcon, ChevronDownIcon, ChevronUpIcon, CopyIcon, CheckIcon } from "lucide-react";

    interface ErrorFallbackProps {
      error: Error;
    }

    export function ErrorFallback({ error }: ErrorFallbackProps) {
      // Only throw in development environment (not in tests)
      if (typeof process !== 'undefined' && process.env.NODE_ENV === 'development') {
        throw error;
      }

      const [isStackOpen, setIsStackOpen] = useState(false);
      const [copied, setCopied] = useState(false);

      const errorDetails = `Error: ${error.message}\n\nStack Trace:\n${error.stack || 'No stack trace available'}`;

      const handleCopy = () => {
        navigator.clipboard.writeText(errorDetails);
        setCopied(true);
        setTimeout(() => setCopied(false), 2000);
      };

      return (
        <div className="min-h-screen bg-background flex items-center justify-center p-4" data-testid="error-fallback">
          <div className="w-full max-w-3xl">
            <Alert variant="destructive" className="mb-6" data-testid="error-alert">
              <AlertTriangleIcon aria-hidden="true" />
              <AlertTitle>This spark has encountered a runtime error</AlertTitle>
              <AlertDescription className="mt-3 space-y-4">
                <div className="flex items-center justify-between gap-2">
                  <code
                    className="text-sm bg-destructive/20 px-2 py-1 rounded flex-1 break-all"
                    data-testid="error-message"
                  >
                    {error.message}
                  </code>
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={handleCopy}
                    className="shrink-0"
                    data-testid="copy-error-btn"
                    aria-label="Copy error details"
                  >
                    {copied ? (
                      <>
                        <CheckIcon className="h-3.5 w-3.5" />
                        Copied
                      </>
                    ) : (
                      <>
                        <CopyIcon className="h-3.5 w-3.5" />
                        Copy
                      </>
                    )}
                  </Button>
                </div>

                <Collapsible open={isStackOpen} onOpenChange={setIsStackOpen}>
                  <CollapsibleTrigger className="w-full justify-between">
                    {isStackOpen ? (
                      <>
                        Hide Stack Trace <ChevronUpIcon className="h-4 w-4 ml-2" />
                      </>
                    ) : (
                      <>
                        Show Stack Trace <ChevronDownIcon className="h-4 w-4 ml-2" />
                      </>
                    )}
                  </CollapsibleTrigger>
                  <CollapsibleContent>
                    <div className="mt-4">
                      <pre className="text-xs bg-destructive/10 p-3 rounded overflow-auto max-h-60">
                        {error.stack || 'No stack trace available'}
                      </pre>
                    </div>
                  </CollapsibleContent>
                </Collapsible>
              </AlertDescription>
            </Alert>

            <AIErrorHelper error={error} />

            <Button
              onClick={() => window.location.reload()}
              className="w-full mt-6"
              variant="outline"
            >
              <RefreshCwIcon className="h-4 w-4 mr-2" />
              Try Reloading
            </Button>
          </div>
        </div>
      );
    }