fix: guard normalizeRelayUrl against undefined env var
The web UI crashed on load when VITE_NOTIFIER_RELAY was not set because normalizeRelayUrl(undefined) calls url.match(...) on the undefined argument, producing: TypeError: can't access property 'match', A is undefined Fix: guard with a truthy check before calling normalizeRelayUrl, and early-return from loadAlerts when NOTIFIER_RELAY is undefined. Fixes bead mailship-4ic
This commit is contained in:
parent
b3d8d186a5
commit
57f7d94669
2 changed files with 67 additions and 1 deletions
61
test/web-ui.test.js
Normal file
61
test/web-ui.test.js
Normal file
|
|
@ -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);
|
||||||
|
|
@ -15,7 +15,7 @@ import {Nip07Signer, decrypt} from '@welshman/signer'
|
||||||
|
|
||||||
const NOTIFIER_PUBKEY = import.meta.env.VITE_NOTIFIER_PUBKEY
|
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)
|
const INDEXER_RELAYS = import.meta.env.VITE_INDEXER_RELAYS.split(',').map(normalizeRelayUrl)
|
||||||
|
|
||||||
|
|
@ -105,6 +105,11 @@ const login = async () => {
|
||||||
const loadAlerts = async () => {
|
const loadAlerts = async () => {
|
||||||
const {signer, pubkey} = state.get()
|
const {signer, pubkey} = state.get()
|
||||||
|
|
||||||
|
if (!NOTIFIER_RELAY) {
|
||||||
|
state.update(assoc('alertsLoading', false))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
state.update(assoc('alertsLoading', true))
|
state.update(assoc('alertsLoading', true))
|
||||||
|
|
||||||
const events = await load({
|
const events = await load({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue