refactor(qconnect): tighten cast-predicate test, dedupe test fixture, document shared-gate intent

Cross-check test now pins admission to is_castable_to_qconnect (incl. OfflineCache)
instead of the streamable predicate. Dedupe the queuePlaybackService test builder.
Document is_castable_to_qconnect/from_source_str_strict/TrackOriginTag as the shared
QConnect-admission gate consumed by the Slint port.

cc
This commit is contained in:
vicrodh committed 2026-06-01 02:00:12 -06:00
1 parent a16d6d0c81
commit c657b80271
3 files changed
+14 -9

No files matched your search

+9
View File
@@ -64,6 +64,9 @@ impl PlaybackSource {
/// The admission-side cast predicate. Offline-cache maps to castable (the /// The admission-side cast predicate. Offline-cache maps to castable (the
/// offline copy carries a valid Qobuz track id). This is the method the /// offline copy carries a valid Qobuz track id). This is the method the
/// QConnect gate consults; is_qobuz_streamable stays "streams live from Qobuz". /// QConnect gate consults; is_qobuz_streamable stays "streams live from Qobuz".
///
/// Shared QConnect-admission gate primitive: this is the single predicate
/// both the Tauri and the upcoming Slint frontends call to gate casting.
pub fn is_castable_to_qconnect(self) -> bool { pub fn is_castable_to_qconnect(self) -> bool {
matches!(self, Self::Qobuz | Self::OfflineCache) matches!(self, Self::Qobuz | Self::OfflineCache)
} }
@@ -71,6 +74,9 @@ impl PlaybackSource {
/// Admission-only origin tag. Unlike PlaybackSource, this has ExternalUnknown /// Admission-only origin tag. Unlike PlaybackSource, this has ExternalUnknown
/// so the Qobuz Connect gate can default unknown/absent to *blocked* not *Qobuz*. /// so the Qobuz Connect gate can default unknown/absent to *blocked* not *Qobuz*.
///
/// Shared QConnect-admission gate primitive consumed by the Slint port (its
/// strict-parse companion for the cast gate); kept intentionally for that use.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TrackOriginTag { pub enum TrackOriginTag {
Qobuz, Qobuz,
@@ -82,6 +88,9 @@ pub enum TrackOriginTag {
impl PlaybackSource { impl PlaybackSource {
/// Strict parse for the admission path: unknown/absent → ExternalUnknown (blocked). /// Strict parse for the admission path: unknown/absent → ExternalUnknown (blocked).
///
/// Shared QConnect-admission gate primitive consumed by the Slint port (it
/// feeds the cast gate, where unknown origins must block, not default to Qobuz).
pub fn from_source_str_strict(s: Option<&str>) -> TrackOriginTag { pub fn from_source_str_strict(s: Option<&str>) -> TrackOriginTag {
match s { match s {
Some("qobuz") => TrackOriginTag::Qobuz, Some("qobuz") => TrackOriginTag::Qobuz,
+3 -2
View File
@@ -68,16 +68,17 @@ mod tests {
use qbz_models::PlaybackSource; use qbz_models::PlaybackSource;
#[test] #[test]
fn admission_matches_playback_source_predicate() { fn admission_matches_cast_predicate() {
let pairs = [ let pairs = [
(TrackOrigin::QobuzOnline, PlaybackSource::Qobuz), (TrackOrigin::QobuzOnline, PlaybackSource::Qobuz),
(TrackOrigin::QobuzOfflineCache, PlaybackSource::OfflineCache),
(TrackOrigin::LocalLibrary, PlaybackSource::Local), (TrackOrigin::LocalLibrary, PlaybackSource::Local),
(TrackOrigin::Plex, PlaybackSource::Plex), (TrackOrigin::Plex, PlaybackSource::Plex),
]; ];
for (origin, source) in pairs { for (origin, source) in pairs {
assert_eq!( assert_eq!(
evaluate_remote_queue_admission(origin).accepted, evaluate_remote_queue_admission(origin).accepted,
source.is_qobuz_streamable(), source.is_castable_to_qconnect(),
"admission/predicate disagree for {origin:?}", "admission/predicate disagree for {origin:?}",
); );
} }
@@ -67,21 +67,16 @@ describe('assessQconnectQueueSync', () => {
}); });
}); });
const track = (over: Partial<BackendQueueTrack>): BackendQueueTrack =>
({ id: 1, title: 't', artist: 'a', album: 'al', duration_secs: 0, artwork_url: null,
hires: false, bit_depth: null, sample_rate: null, is_local: false, album_id: null,
artist_id: null, streamable: true, source: 'qobuz', parental_warning: false, ...over }) as BackendQueueTrack;
describe('assessQconnectQueueSync — offline-cache', () => { describe('assessQconnectQueueSync — offline-cache', () => {
it('treats qobuz_download as syncable (offline copy carries a Qobuz id)', () => { it('treats qobuz_download as syncable (offline copy carries a Qobuz id)', () => {
const r = assessQconnectQueueSync([track({ id: 5, source: 'qobuz_download' })]); const r = assessQconnectQueueSync([buildTrack(5, { source: 'qobuz_download' })]);
expect(r.syncable).toBe(true); expect(r.syncable).toBe(true);
expect(r.trackIds).toEqual([5]); expect(r.trackIds).toEqual([5]);
expect(r.blockedTrackIds).toEqual([]); expect(r.blockedTrackIds).toEqual([]);
}); });
it('still blocks local and plex', () => { it('still blocks local and plex', () => {
const r = assessQconnectQueueSync([ const r = assessQconnectQueueSync([
track({ id: 1, source: 'qobuz' }), track({ id: 2, source: 'local' }), buildTrack(1, { source: 'qobuz' }), buildTrack(2, { source: 'local' }),
]); ]);
expect(r.syncable).toBe(false); expect(r.syncable).toBe(false);
expect(r.blockedTrackIds).toContain(2); expect(r.blockedTrackIds).toContain(2);