mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
refactor(network): decouple network-reachability layer from features → lib/network
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.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user