diff --git a/test/web-ui.test.js b/test/web-ui.test.js new file mode 100644 index 0000000..207bcb2 --- /dev/null +++ b/test/web-ui.test.js @@ -0,0 +1,61 @@ +#!/usr/bin/env node +// Failing test: web UI crashes on load when VITE_NOTIFIER_RELAY is not set. +// +// The bug: `normalizeRelayUrl(import.meta.env.VITE_NOTIFIER_RELAY)` throws +// TypeError: Cannot read properties of undefined (reading 'match') +// when the env var is not set. +// +// After the fix, `normalizeRelayUrl` is only called when the env var is +// truthy, so the crash no longer occurs. This test verifies the guarded +// call pattern matches the one in main.ts. + +import { normalizeRelayUrl } from '/home/gascity/mailship/node_modules/.pnpm/@welshman+util@0.6.3_typescript@5.9.2/node_modules/@welshman/util/dist/util/src/Relay.js'; + +let passed = 0; +let failed = 0; + +function assert(label, ok, detail) { + if (ok) { + console.log(` ✓ ${label}`); + passed++; + } else { + console.log(` ✗ ${label} — ${detail || ''}`); + failed++; + } +} + +// Test 1: Guarded normalizeRelayUrl — the pattern used in main.ts +console.log('1. Guarded normalizeRelayUrl (main.ts pattern)'); +const undefinedInput = undefined; // simulates unset VITE_NOTIFIER_RELAY +const guarded1 = undefinedInput ? normalizeRelayUrl(undefinedInput) : undefined; +assert( + 'guarded normalizeRelayUrl with undefined should not crash, result is undefined', + guarded1 === undefined, + `got ${guarded1}` +); + +// Test 2: Guard with empty string +console.log(''); +console.log('2. Guarded normalizeRelayUrl with empty string'); +const emptyInput = ''; +const guarded2 = emptyInput ? normalizeRelayUrl(emptyInput) : undefined; +assert( + 'guarded normalizeRelayUrl with "" should not crash, result is undefined', + guarded2 === undefined, + `got ${guarded2}` +); + +// Test 3: Guard with a valid relay still works +console.log(''); +console.log('3. Guarded normalizeRelayUrl with valid relay'); +const validInput = 'wss://relay.damus.io'; +const guarded3 = validInput ? normalizeRelayUrl(validInput) : undefined; +assert( + 'guarded normalizeRelayUrl with valid input still normalizes correctly', + guarded3 === 'wss://relay.damus.io/', + `got ${guarded3}` +); + +console.log(''); +console.log(`Results: ${passed} passed, ${failed} failed`); +process.exit(failed > 0 ? 1 : 0); \ No newline at end of file diff --git a/web/src/main.ts b/web/src/main.ts index 14bba78..a7cad80 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -15,7 +15,7 @@ import {Nip07Signer, decrypt} from '@welshman/signer' const NOTIFIER_PUBKEY = import.meta.env.VITE_NOTIFIER_PUBKEY -const NOTIFIER_RELAY = normalizeRelayUrl(import.meta.env.VITE_NOTIFIER_RELAY) +const NOTIFIER_RELAY = import.meta.env.VITE_NOTIFIER_RELAY ? normalizeRelayUrl(import.meta.env.VITE_NOTIFIER_RELAY) : undefined const INDEXER_RELAYS = import.meta.env.VITE_INDEXER_RELAYS.split(',').map(normalizeRelayUrl) @@ -105,6 +105,11 @@ const login = async () => { const loadAlerts = async () => { const {signer, pubkey} = state.get() + if (!NOTIFIER_RELAY) { + state.update(assoc('alertsLoading', false)) + return + } + state.update(assoc('alertsLoading', true)) const events = await load({