Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions packages/svelte-playground/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Test playground for Hawk Error Tracker integration with SvelteKit and Svelte.

- [Getting Started](#getting-started)
- [Hawk Integration](#hawk-integration)
- [Error Handling](#error-handling)
- [Error Test Pages](#error-test-pages)

## Getting Started

Expand Down Expand Up @@ -41,3 +43,52 @@ Hawk automatically registers global error handlers for:

- `window.onerror`
- `window.onunhandledrejection`

## Error Handling

### Global Error Handlers (🔴)

Global browser error handlers that catch unhandled errors:

- **`window.error`**
- **`window.unhandledrejection`**

**Note:** global errors will be caught using Hawk Catcher.

### Error Boundaries (🟡)

Svelte `<svelte:boundary>` catches errors during:

- Component rendering (synchronous errors in component body)
- Component initialization

Example usage:

```svelte
<svelte:boundary onerror={handleBoundaryError} failed={fallback}>
<ErrorProneComponent />
</svelte:boundary>
```

**Note:** error boundaries will be caught using Hawk Catcher.

## Error Test Pages

The playground includes test pages to demonstrate each error catching mechanism:

### Global Error Handlers (🔴)

1. **Runtime Error** (`/errors/runtime-error`)
- Demonstrates synchronous error in event handler
- Caught by `window.error`

2. **Promise Rejection** (`/errors/promise-rejection`)
- Demonstrates unhandled Promise rejection
- Caught by `window.unhandledrejection`

### Error Boundaries (🟡)

3. **Component Render Error** (`/errors/component-render`)
- Demonstrates error during component rendering
- Caught by `<svelte:boundary>`

8 changes: 8 additions & 0 deletions packages/svelte-playground/src/hooks.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ if (import.meta.env.VITE_HAWK_TOKEN) {
token: import.meta.env.VITE_HAWK_TOKEN,
});
}

window.addEventListener('error', (event) => {
console.error('🔴 [window.error]', event.error, `at ${event.filename}:${event.lineno}`);
});

window.addEventListener('unhandledrejection', (event) => {
console.error('🔴 [window.unhandledrejection]', event.reason);
});
69 changes: 69 additions & 0 deletions packages/svelte-playground/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,3 +1,72 @@
<script lang="ts">
interface ErrorTest {
title: string;
description: string;
href: string;
category: string;
}

const errorTests: ErrorTest[] = [
// Window Error Handlers
{
title: 'Synchronous Runtime Error',
description: 'Error thrown in event handler',
href: '/errors/runtime-error',
category: 'Global Error Handlers (🔴)'
},
{
title: 'Unhandled Promise Rejection',
description: 'Promise rejected without catch handler',
href: '/errors/promise-rejection',
category: 'Global Error Handlers (🔴)'
},

// Error Boundaries
{
title: 'Component Rendering Error',
description: 'Error thrown during component render',
href: '/errors/component-render',
category: 'Error Boundaries (🟡)'
},
];

const categories = Array.from(new Set(errorTests.map(t => t.category)));
</script>

<svelte:head>
<title>Hawk Javascript SvelteKit Integration Playground</title>
</svelte:head>

<div class="container">
<header>
<h1>🧪 SvelteKit Error Handling Test Suite</h1>
</header>

<div class="alert alert-warning">
<strong>⚠️ Testing Instructions:</strong>
<ul>
<li>Open your browser's DevTools Console to see error logs</li>
<li>Look for colored emoji markers:
<ul>
<li>🔴 = Caught by global <code>window.error</code> or <code>window.unhandledrejection</code></li>
<li>🟡 = Caught by <code>&lt;svelte:boundary&gt;</code></li>
</ul>
</li>
<li>Each test demonstrates where errors are caught in the SvelteKit error handling hierarchy</li>
</ul>
</div>

{#each categories as category}
<section>
<h2>{category}</h2>
<div class="grid">
{#each errorTests.filter(t => t.category === category) as test}
<a href={test.href} class="test-card" data-sveltekit-preload-data="off">
<h3>{test.title}</h3>
<p>{test.description}</p>
</a>
{/each}
</div>
</section>
{/each}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts">
import ErrorComponent from './ErrorComponent.svelte';

let showError = $state(false);

function triggerError() {
showError = true;
}

function handleBoundaryError(error: Error) {
console.error('🟡 [svelte:boundary] Caught rendering error:', error);
}
</script>

<div class="container">
<h1>Error Boundary - Rendering Test</h1>
<p>Click the button to trigger a component rendering error.</p>
<p><strong>Caught by:</strong> <code>&lt;svelte:boundary&gt;</code> (🟡 yellow dot in console)</p>

<button onclick={triggerError} disabled={showError}>
Trigger Rendering Error
</button>

{#snippet fallback(error)}
<div class="error-fallback">
<h3>Error Boundary Caught Error</h3>
<p>Message: {error.message}</p>
</div>
{/snippet}

<svelte:boundary onerror={handleBoundaryError} failed={fallback}>
{#if showError}
<ErrorComponent shouldError={true} />
{/if}
</svelte:boundary>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts">
let { shouldError }: { shouldError: boolean } = $props();

if (shouldError) {
throw new Error('Rendering error caught by svelte:boundary');
}
</script>

<div>This should not render if error is thrown</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts">
function triggerRejection() {
Promise.reject(new Error('Unhandled promise rejection'));
}
</script>

<div class="container">
<h1>Unhandled Promise Rejection Test</h1>
<p>Click the button to trigger an unhandled promise rejection.</p>
<p><strong>Caught by:</strong> <code>window.unhandledrejection</code> (🔴 red dot in console)</p>

<button onclick={triggerRejection}>
Trigger Promise Rejection
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts">
function triggerError() {
throw new Error('Runtime error caught by window.onerror');
}
</script>

<div class="container">
<h1>Window Error Handler Test</h1>
<p>Click the button to trigger a runtime error.</p>
<p><strong>Caught by:</strong> <code>window.onerror</code> (🔴 red dot in console)</p>

<button onclick={triggerError}>
Trigger Runtime Error
</button>
</div>
Loading