#[cfg(feature = "mock")]
mod mock_tests {
use lastfm_edit::{
Album, AlbumPage, EditResponse, ExactScrobbleEdit, LastFmEditClient, MockLastFmEditClient,
Result, ScrobbleEdit, Track, TrackPage,
};
use mockall::predicate::*;
#[test_log::test(tokio::test)]
async fn test_mock_basic_functionality() -> Result<()> {
let mut mock_client = MockLastFmEditClient::new();
mock_client
.expect_username()
.times(1)
.returning(|| "testuser".to_string());
let client: &dyn LastFmEditClient = &mock_client;
assert_eq!(client.username(), "testuser");
Ok(())
}
#[test_log::test(tokio::test)]
async fn test_mock_edit_scrobble() -> Result<()> {
let mut mock_client = MockLastFmEditClient::new();
let edit = ScrobbleEdit::new(
Some("Old Track".to_string()),
Some("Old Album".to_string()),
"Old Artist".to_string(),
Some("Old Artist".to_string()),
Some("New Track".to_string()),
Some("New Album".to_string()),
"New Artist".to_string(),
Some("New Artist".to_string()),
Some(1640995200),
false,
);
let expected_exact_edit = ExactScrobbleEdit::new(
"Old Track".to_string(),
"Old Album".to_string(),
"Old Artist".to_string(),
"Old Artist".to_string(),
"New Track".to_string(),
"New Album".to_string(),
"New Artist".to_string(),
"New Artist".to_string(),
1640995200,
false,
);
let expected_response = EditResponse::single(
true,
Some("Edit completed successfully".to_string()),
None,
expected_exact_edit,
);
mock_client
.expect_edit_scrobble()
.with(eq(edit.clone()))
.times(1)
.returning(move |_| Ok(expected_response.clone()));
let client: &dyn LastFmEditClient = &mock_client;
let response = client.edit_scrobble(&edit).await?;
assert!(response.success());
assert_eq!(
response.message(),
Some("Edit completed successfully".to_string())
);
Ok(())
}
#[test_log::test(tokio::test)]
async fn test_mock_get_recent_scrobbles() -> Result<()> {
let mut mock_client = MockLastFmEditClient::new();
let expected_tracks = vec![
Track {
name: "Test Track 1".to_string(),
artist: "Test Artist 1".to_string(),
album: Some("Test Album 1".to_string()),
album_artist: Some("Test Artist 1".to_string()),
playcount: 5,
timestamp: Some(1640995200),
},
Track {
name: "Test Track 2".to_string(),
artist: "Test Artist 2".to_string(),
album: Some("Test Album 2".to_string()),
album_artist: Some("Test Artist 2".to_string()),
playcount: 3,
timestamp: Some(1640995100),
},
];
mock_client
.expect_get_recent_tracks_page()
.with(eq(1))
.times(1)
.returning(move |page| {
Ok(TrackPage {
tracks: expected_tracks.clone(),
page_number: page,
has_next_page: false,
total_pages: Some(1),
})
});
let client: &dyn LastFmEditClient = &mock_client;
let page = client.get_recent_tracks_page(1).await?;
assert_eq!(page.tracks.len(), 2);
assert_eq!(page.tracks[0].name, "Test Track 1");
assert_eq!(page.tracks[1].name, "Test Track 2");
assert_eq!(page.page_number, 1);
Ok(())
}
#[test_log::test(tokio::test)]
async fn test_mock_iterator_concept() -> Result<()> {
let mut mock_client = MockLastFmEditClient::new();
mock_client
.expect_get_artist_tracks_page()
.with(eq("test_artist"), eq(1))
.returning(|_, _| {
Ok(TrackPage {
tracks: vec![Track {
name: "Mocked Track".to_string(),
artist: "Mocked Artist".to_string(),
album: Some("Mocked Album".to_string()),
album_artist: Some("Mocked Artist".to_string()),
playcount: 10,
timestamp: Some(1640995200),
}],
page_number: 1,
has_next_page: false,
total_pages: Some(1),
})
});
let client: &dyn LastFmEditClient = &mock_client;
let page = client.get_artist_tracks_page("test_artist", 1).await?;
assert_eq!(page.tracks.len(), 1);
assert_eq!(page.tracks[0].name, "Mocked Track");
Ok(())
}
#[test_log::test(tokio::test)]
async fn test_mock_iterator_trait_objects() -> Result<()> {
let mut mock_client = MockLastFmEditClient::new();
mock_client
.expect_get_artist_tracks_page()
.with(eq("test_artist"), eq(1))
.returning(|_, _| {
Ok(TrackPage {
tracks: vec![Track {
name: "Iterator Track 1".to_string(),
artist: "test_artist".to_string(),
album: Some("Test Album".to_string()),
album_artist: Some("test_artist".to_string()),
playcount: 5,
timestamp: Some(1640995200),
}],
page_number: 1,
has_next_page: false,
total_pages: Some(1),
})
});
mock_client
.expect_get_recent_tracks_page()
.with(eq(1))
.returning(|page| {
Ok(TrackPage {
tracks: vec![Track {
name: "Recent Track 1".to_string(),
artist: "Recent Artist".to_string(),
album: Some("Recent Album".to_string()),
album_artist: Some("Recent Artist".to_string()),
playcount: 1,
timestamp: Some(1640995300),
}],
page_number: page,
has_next_page: false,
total_pages: Some(1),
})
});
mock_client
.expect_get_artist_albums_page()
.with(eq("test_artist"), eq(1))
.returning(|_, _| {
Ok(AlbumPage {
albums: vec![Album {
name: "Test Album".to_string(),
artist: "test_artist".to_string(),
playcount: 10,
timestamp: Some(1640995200),
}],
page_number: 1,
has_next_page: false,
total_pages: Some(1),
})
});
let client: &dyn LastFmEditClient = &mock_client;
let tracks_page = client.get_artist_tracks_page("test_artist", 1).await?;
assert_eq!(tracks_page.tracks.len(), 1);
assert_eq!(tracks_page.tracks[0].name, "Iterator Track 1");
let recent_page = client.get_recent_tracks_page(1).await?;
assert_eq!(recent_page.tracks.len(), 1);
assert_eq!(recent_page.tracks[0].name, "Recent Track 1");
let albums_page = client.get_artist_albums_page("test_artist", 1).await?;
assert_eq!(albums_page.albums.len(), 1);
assert_eq!(albums_page.albums[0].name, "Test Album");
Ok(())
}
}
#[cfg(not(feature = "mock"))]
mod no_mock_tests {
#[test]
fn test_mock_feature_disabled() {
log::debug!("Mock feature is disabled - MockLastFmEditClient is not available");
}
}