mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
c37d5f7389
The connection-reachability + Subsonic network-guard helpers were pinned low by four lib/api consumers (subsonicLibrary/Playlists/Ratings/Scrobble) yet ran two lower-layer→feature inversions. Both removed without a registry: - devOfflineBrowseStore is a self-contained DEV-only toggle with zero offline- feature coupling — it was only colocated there. Relocated features/offline/store → store/ (global). The @/features/offline barrel re-exports it so feature/UI consumers are unchanged; the three lower-layer readers (subsonicNetworkGuard, activeServerReachability, useConnectionStatus) now import it from @/store directly. - subsonicNetworkGuard's only other feature dep was playback's resolvePlaybackUrl, used solely for the psysonic-local:// skip check. Added hasLocalPlaybackUrl to the existing M4 substrate store/localPlaybackResolve — it mirrors resolvePlaybackUrl's local-source branch exactly (same profile resolution; the empty-serverId playback fallback never applies in the guard), so the skip stays bit-identical. network/ (subsonicNetworkGuard + activeServerReachability + tests) → lib/network, now @/features-free. useConnectionStatus is now iron-rule-clean and stays in hooks/ (cross-cutting). Test mocks retargeted to the new seam modules. Behavior-adjacent (covered by suite; default paths identical): the local-bytes skip helper — flag for offline-playback runtime QA alongside the M4 media-resolver seam.
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { useDevOfflineBrowseStore } from '@/store/devOfflineBrowseStore';
|
|
import {
|
|
getActiveServerReachable,
|
|
isActiveServerReachable,
|
|
onActiveServerBecameReachable,
|
|
resetActiveServerConnectionSnapshot,
|
|
setActiveServerReachable,
|
|
} from '@/lib/network/activeServerReachability';
|
|
|
|
describe('activeServerReachability', () => {
|
|
beforeEach(() => {
|
|
useDevOfflineBrowseStore.setState({ forceOffline: false });
|
|
resetActiveServerConnectionSnapshot();
|
|
});
|
|
|
|
it('isActiveServerReachable requires an explicit successful probe', () => {
|
|
expect(isActiveServerReachable()).toBe(false);
|
|
setActiveServerReachable(true);
|
|
expect(isActiveServerReachable()).toBe(true);
|
|
setActiveServerReachable(false);
|
|
expect(isActiveServerReachable()).toBe(false);
|
|
});
|
|
|
|
it('exposes the last probe result', () => {
|
|
setActiveServerReachable(true);
|
|
expect(getActiveServerReachable()).toBe(true);
|
|
});
|
|
|
|
it('isActiveServerReachable is false when DEV force-offline is enabled', () => {
|
|
if (!import.meta.env.DEV) return;
|
|
setActiveServerReachable(true);
|
|
useDevOfflineBrowseStore.setState({ forceOffline: true });
|
|
expect(isActiveServerReachable()).toBe(false);
|
|
});
|
|
|
|
it('onActiveServerBecameReachable fires only on false/null → true', () => {
|
|
const listener = vi.fn();
|
|
onActiveServerBecameReachable(listener);
|
|
setActiveServerReachable(false);
|
|
setActiveServerReachable(true);
|
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
setActiveServerReachable(true);
|
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|