changes
All checks were successful
CI / ci (push) Successful in 19m38s

This commit is contained in:
2026-08-26 20:55:30 +02:00
parent a557c183e9
commit 23d052278a
523 changed files with 24448 additions and 2005 deletions

View File

@@ -0,0 +1,199 @@
use std::sync::Arc;
use domain::provider::ProviderName;
use domain::song::{RecordingId, Song};
use domain::testing::{
FakeCredentialCipher, FakeNowPlaying, FakeRecordingLookup, InMemoryStore, test_user,
};
use application::provider::commands::ConnectProviderCommand;
use application::provider::use_cases::{connect_provider, get_now_playing};
const RECORDING: &str = "f5c7e7a2-0000-4000-8000-000000000001";
async fn connected_store() -> (Arc<InMemoryStore>, domain::user::UserId) {
let store = Arc::new(InMemoryStore::new());
let user = test_user("alice");
connect_provider::execute(
ConnectProviderCommand {
user_id: user.id().clone(),
provider: ProviderName::new("subsonic").unwrap(),
credential: br#"{"url":"https://music.example"}"#.to_vec(),
},
&connect_provider::Deps {
command: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
},
)
.await
.unwrap();
(store, user.id().clone())
}
fn song() -> Song {
Song::new("Paranoid Android", "Radiohead", None, None).unwrap()
}
#[tokio::test]
async fn a_playing_song_is_returned_enriched_with_its_recording_id() {
let (store, user_id) = connected_store().await;
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::playing("subsonic", song())),
recordings: Arc::new(FakeRecordingLookup::finding(Some(
RecordingId::new(RECORDING).unwrap(),
))),
};
let result = get_now_playing::execute(user_id, &deps).await.unwrap();
let found = result.unwrap();
assert_eq!(found.title().value(), "Paranoid Android");
assert_eq!(
found.recording_id().map(|id| id.value().to_string()),
Some(RECORDING.to_string())
);
}
#[tokio::test]
async fn a_song_with_no_musicbrainz_match_is_still_returned() {
let (store, user_id) = connected_store().await;
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::playing("subsonic", song())),
recordings: Arc::new(FakeRecordingLookup::finding_nothing()),
};
let found = get_now_playing::execute(user_id, &deps)
.await
.unwrap()
.unwrap();
assert!(found.recording_id().is_none());
}
#[tokio::test]
async fn nothing_playing_is_not_an_error() {
let (store, user_id) = connected_store().await;
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::silent("subsonic")),
recordings: Arc::new(FakeRecordingLookup::finding_nothing()),
};
assert!(
get_now_playing::execute(user_id, &deps)
.await
.unwrap()
.is_none()
);
}
#[tokio::test]
async fn a_user_with_no_connection_gets_a_clear_error() {
let store = Arc::new(InMemoryStore::new());
let stranger = test_user("bob");
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::playing("subsonic", song())),
recordings: Arc::new(FakeRecordingLookup::finding_nothing()),
};
assert!(
get_now_playing::execute(stranger.id().clone(), &deps)
.await
.is_err()
);
}
#[tokio::test]
async fn a_provider_that_cannot_be_reached_offers_nothing_rather_than_failing() {
let (store, user_id) = connected_store().await;
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::failing("subsonic", "connection refused")),
recordings: Arc::new(FakeRecordingLookup::finding_nothing()),
};
let asked = get_now_playing::execute(user_id, &deps).await;
assert!(
asked.is_ok(),
"the user must still be able to type a song by hand: {asked:?}"
);
assert!(asked.unwrap().is_none(), "nothing found, not an error");
}
#[tokio::test]
async fn a_recording_lookup_that_fails_yields_a_song_with_no_identity() {
let (store, user_id) = connected_store().await;
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::playing("subsonic", song())),
recordings: Arc::new(FakeRecordingLookup::failing("musicbrainz is rate limiting")),
};
let playing = get_now_playing::execute(user_id, &deps)
.await
.expect("a failing enrichment must not fail the lookup")
.expect("the song is still playing");
assert_eq!(playing.title().value(), song().title().value());
assert!(
playing.recording_id().is_none(),
"an identity that could not be found is simply absent"
);
}
#[tokio::test]
async fn a_recording_lookup_that_finds_nothing_yields_a_song_with_no_identity() {
let (store, user_id) = connected_store().await;
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::playing("subsonic", song())),
recordings: Arc::new(FakeRecordingLookup::finding_nothing()),
};
let playing = get_now_playing::execute(user_id, &deps)
.await
.unwrap()
.unwrap();
assert!(playing.recording_id().is_none());
}
#[tokio::test]
async fn an_account_with_no_connection_is_told_so_rather_than_offered_silence() {
let store = Arc::new(InMemoryStore::new());
let user = test_user("nobody");
let deps = get_now_playing::Deps {
query: store.clone(),
cipher: Arc::new(FakeCredentialCipher),
now_playing: Arc::new(FakeNowPlaying::playing("subsonic", song())),
recordings: Arc::new(FakeRecordingLookup::finding_nothing()),
};
let asked = get_now_playing::execute(user.id().clone(), &deps).await;
assert!(
asked.is_err(),
"nothing to connect to is actionable, unlike a provider being down"
);
}