mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { useBackendReachable } from '../useBackendReachable';
|
||||
|
||||
vi.mock('../../services/backendUrl', () => ({
|
||||
getBackendUrl: vi.fn().mockResolvedValue('http://localhost:5005'),
|
||||
}));
|
||||
|
||||
describe('useBackendReachable', () => {
|
||||
beforeEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('reports reachable when fetch resolves with any HTTP response', async () => {
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response(null, { status: 200 }));
|
||||
|
||||
const { result } = renderHook(() => useBackendReachable());
|
||||
expect(result.current).toBe('probing');
|
||||
await waitFor(() => expect(result.current).toBe('reachable'));
|
||||
});
|
||||
|
||||
it('reports reachable on 4xx (host answered)', async () => {
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response(null, { status: 404 }));
|
||||
|
||||
const { result } = renderHook(() => useBackendReachable());
|
||||
await waitFor(() => expect(result.current).toBe('reachable'));
|
||||
});
|
||||
|
||||
it('reports unreachable when fetch rejects (network error)', async () => {
|
||||
vi.spyOn(globalThis, 'fetch').mockRejectedValue(new TypeError('Failed to fetch'));
|
||||
|
||||
const { result } = renderHook(() => useBackendReachable());
|
||||
await waitFor(() => expect(result.current).toBe('unreachable'));
|
||||
});
|
||||
});
|
||||
@@ -1,59 +0,0 @@
|
||||
import createDebug from 'debug';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { getBackendUrl } from '../services/backendUrl';
|
||||
|
||||
const log = createDebug('app:backend-probe');
|
||||
|
||||
export type BackendProbeStatus = 'probing' | 'reachable' | 'unreachable';
|
||||
|
||||
const PROBE_TIMEOUT_MS = 2500;
|
||||
|
||||
/**
|
||||
* Probes the configured backend URL once on mount and reports whether it is
|
||||
* reachable. The "Continue locally" CTA on the Welcome screen is gated on
|
||||
* `unreachable` so users only see it when the backend OAuth flow can't be
|
||||
* completed (per issue #2037 AC).
|
||||
*
|
||||
* We treat any successful HTTP response (incl. 4xx) as reachable — the goal is
|
||||
* to confirm the host is online, not that a specific route exists.
|
||||
*/
|
||||
export function useBackendReachable(): BackendProbeStatus {
|
||||
const [status, setStatus] = useState<BackendProbeStatus>('probing');
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const controller = new AbortController();
|
||||
const timeoutId = window.setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
const base = await getBackendUrl();
|
||||
log('[probe] fetching %s/health', base);
|
||||
const response = await fetch(`${base}/health`, {
|
||||
method: 'GET',
|
||||
signal: controller.signal,
|
||||
cache: 'no-store',
|
||||
});
|
||||
if (cancelled) return;
|
||||
// Any HTTP response (even 404) means the host answered — it's online.
|
||||
log('[probe] response status=%d → reachable', response.status);
|
||||
setStatus('reachable');
|
||||
} catch (err) {
|
||||
if (cancelled) return;
|
||||
log('[probe] failed → unreachable: %o', err);
|
||||
setStatus('unreachable');
|
||||
} finally {
|
||||
window.clearTimeout(timeoutId);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
controller.abort();
|
||||
window.clearTimeout(timeoutId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return status;
|
||||
}
|
||||
Reference in New Issue
Block a user