use std::path::{Path, PathBuf}; use path_macro::path; use rstest::rstest; use time::macros::{date, datetime}; use musixmatch_inofficial::{ models::{AlbumId, ArtistId, TrackId}, ClientType, Error, Musixmatch, }; #[ctor::ctor] fn init() { let _ = dotenvy::dotenv(); env_logger::init(); tokio::runtime::Builder::new_current_thread() .enable_all() .build() .unwrap() .block_on(new_mxm().login()) .unwrap(); } fn new_mxm() -> Musixmatch { let client_type = std::env::var("MUSIXMATCH_CLIENT") .map(|ctype| serde_plain::from_str::(&ctype).expect("valid client type")) .unwrap_or_default(); let mut mxm = Musixmatch::builder().client_type(client_type); if let (Ok(email), Ok(password)) = ( std::env::var("MUSIXMATCH_EMAIL"), std::env::var("MUSIXMATCH_PASSWORD"), ) { mxm = mxm.credentials(email, password); } mxm.build().unwrap() } fn testfile>(name: P) -> PathBuf { path!(env!("CARGO_MANIFEST_DIR") / "testfiles" / name) } mod album { use super::*; use musixmatch_inofficial::models::AlbumType; #[rstest] #[case::id(AlbumId::AlbumId(14248253))] #[case::musicbrainz(AlbumId::Musicbrainz("6c3cf9d8-88a8-43ed-850b-55813f01e451"))] #[tokio::test] async fn by_id(#[case] album_id: AlbumId<'_>) { let album = new_mxm().album(album_id).await.unwrap(); assert_eq!(album.album_id, 14248253); assert_eq!( album.album_mbid.unwrap(), "6c3cf9d8-88a8-43ed-850b-55813f01e451" ); assert_eq!(album.album_name, "Gangnam Style (강남스타일)"); assert!(album.album_rating > 20); assert_eq!(album.album_track_count, 1); assert_eq!(album.album_release_date.unwrap(), date!(2012 - 01 - 01)); assert_eq!(album.album_release_type, AlbumType::Single); assert_eq!(album.artist_id, 410698); assert_eq!(album.artist_name, "PSY"); let first_pri_genre = &album.primary_genres.music_genre_list[0].music_genre; assert_eq!(first_pri_genre.music_genre_id, 14); assert_eq!(first_pri_genre.music_genre_parent_id, 34); assert_eq!(first_pri_genre.music_genre_name, "Pop"); assert_eq!(first_pri_genre.music_genre_name_extended, "Pop"); assert_eq!(first_pri_genre.music_genre_vanity.as_ref().unwrap(), "Pop"); let first_sec_genre = &album.secondary_genres.music_genre_list[0].music_genre; assert_eq!(first_sec_genre.music_genre_id, 17); assert_eq!(first_sec_genre.music_genre_parent_id, 34); assert_eq!(first_sec_genre.music_genre_name, "Dance"); assert_eq!(first_sec_genre.music_genre_name_extended, "Dance"); assert_eq!( first_sec_genre.music_genre_vanity.as_ref().unwrap(), "Dance" ); assert_eq!( album.album_copyright.unwrap(), "© 2012 Schoolboy/Universal Republic Records, a division of UMG Recordings, Inc." ); assert_eq!( album.album_label.unwrap(), "Silent Records/Universal Republic Records" ); assert_eq!(album.album_vanity_id, "410698/Gangnam-Style-Single"); assert!(album.updated_time > datetime!(2022-6-3 0:00 UTC)); assert_eq!( album.album_coverart_100x100.unwrap(), "https://s.mxmcdn.net/images-storage/albums/5/4/0/4/4/5/26544045.jpg" ); assert_eq!( album.album_coverart_350x350.unwrap(), "https://s.mxmcdn.net/images-storage/albums/5/4/0/4/4/5/26544045_350_350.jpg" ); assert_eq!( album.album_coverart_500x500.unwrap(), "https://s.mxmcdn.net/images-storage/albums/5/4/0/4/4/5/26544045_500_500.jpg" ); } #[tokio::test] async fn album_ep() { let album = new_mxm().album(AlbumId::AlbumId(23976123)).await.unwrap(); assert_eq!(album.album_name, "Waldbrand EP"); assert_eq!(album.album_release_type, AlbumType::Ep); assert_eq!(album.album_release_date, Some(date!(2016 - 09 - 30))); } #[tokio::test] async fn by_id_missing() { let err = new_mxm() .album(AlbumId::AlbumId(999999999999)) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn artist_albums() { let albums = new_mxm() .artist_albums(ArtistId::ArtistId(1039), None, 10, 1) .await .unwrap(); assert_eq!(albums.len(), 10); } #[tokio::test] async fn artist_albums_missing() { let err = new_mxm() .artist_albums(ArtistId::ArtistId(999999999999), None, 10, 1) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn charts() { let albums = new_mxm().chart_albums("US", 10, 1).await.unwrap(); assert_eq!(albums.len(), 10); } } mod artist { use super::*; #[rstest] #[case::id(ArtistId::ArtistId(410698))] #[case::musicbrainz(ArtistId::Musicbrainz("f99b7d67-4e63-4678-aa66-4c6ac0f7d24a"))] #[tokio::test] async fn by_id(#[case] artist_id: ArtistId<'_>) { let artist = new_mxm().artist(artist_id).await.unwrap(); // dbg!(&artist); assert_eq!(artist.artist_id, 410698); assert_eq!( artist.artist_mbid.unwrap(), "f99b7d67-4e63-4678-aa66-4c6ac0f7d24a" ); assert_eq!(artist.artist_name, "PSY"); assert!( artist.artist_name_translation_list.iter().any(|tl| { tl.artist_name_translation.language == "KO" && tl.artist_name_translation.translation == "싸이" }), "missing Korean translation in: {:?}", artist.artist_name_translation_list ); assert_eq!(artist.artist_country.unwrap(), "KR"); assert!(artist.artist_rating > 50); let first_genre = &artist.primary_genres.music_genre_list[0].music_genre; assert_eq!(first_genre.music_genre_id, 14); assert_eq!(first_genre.music_genre_parent_id, 34); assert_eq!(first_genre.music_genre_name, "Pop"); assert_eq!(first_genre.music_genre_name_extended, "Pop"); assert_eq!(first_genre.music_genre_vanity.as_ref().unwrap(), "Pop"); assert_eq!( artist.artist_twitter_url.unwrap(), "https://twitter.com/psy_oppa" ); assert_eq!( artist.artist_facebook_url.unwrap(), "https://www.facebook.com/officialpsy" ); assert_eq!(artist.artist_vanity_id, "410698"); assert!(artist.updated_time > datetime!(2016-6-30 0:00 UTC)); assert_eq!(artist.begin_date_year.unwrap(), 1977); assert_eq!(artist.begin_date.unwrap(), date!(1977 - 12 - 31)); assert_eq!(artist.end_date_year, None); assert_eq!(artist.end_date, None); } #[tokio::test] async fn by_id_missing() { let err = new_mxm() .artist(ArtistId::ArtistId(999999999999)) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn related() { let artists = new_mxm() .artist_related(ArtistId::ArtistId(26485840), 10, 1) .await .unwrap(); assert_eq!(artists.len(), 10); } #[tokio::test] async fn related_missing() { let err = new_mxm() .artist_related(ArtistId::ArtistId(999999999999), 10, 1) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn search() { let artists = new_mxm().artist_search("psy", 5, 1).await.unwrap(); assert_eq!(artists.len(), 5); let artist = &artists[0]; assert_eq!(artist.artist_id, 410698); assert_eq!(artist.artist_name, "PSY"); } #[tokio::test] async fn search_empty() { let artists = new_mxm() .artist_search( "Rindfleischettikettierungsüberwachungsaufgabenübertragungsgesetz", 5, 1, ) .await .unwrap(); assert_eq!(artists.len(), 0); } #[tokio::test] async fn charts() { let artists = new_mxm().chart_artists("US", 10, 1).await.unwrap(); assert_eq!(artists.len(), 10); } #[tokio::test] async fn charts_no_country() { let artists = new_mxm().chart_artists("XY", 10, 1).await.unwrap(); assert_eq!(artists.len(), 10); } } mod track { use super::*; use musixmatch_inofficial::models::{ChartName, SortOrder}; #[rstest] #[case::no_translation(false, false)] #[case::translation_2c(true, false)] #[case::translation_3c(true, true)] #[tokio::test] async fn from_match(#[case] translation_status: bool, #[case] lang_3c: bool) { let track = new_mxm() .matcher_track( "Poker Face", "Lady Gaga", "The Fame", translation_status, lang_3c, ) .await .unwrap(); // dbg!(&track); assert_eq!(track.track_id, 15476784); assert_eq!( track.track_mbid.unwrap(), "080975b0-39b1-493c-ae64-5cb3292409bb" ); assert_eq!(track.track_isrc.unwrap(), "USUM70824409"); assert!( track.commontrack_isrcs[0] .iter() .any(|isrc| isrc == "USUM70824409"), "commontrack_isrcs: {:?}", &track.commontrack_isrcs[0], ); assert_eq!(track.track_spotify_id.unwrap(), "5R8dQOPq8haW94K7mgERlO"); assert!( track .commontrack_spotify_ids .iter() .any(|spid| spid == "1QV6tiMFM6fSOKOGLMHYYg"), "commontrack_spotify_ids: {:?}", track.commontrack_spotify_ids, ); assert_eq!(track.track_name, "Poker Face"); assert!(track.track_rating > 50); assert_eq!(track.commontrack_id, 47672612); assert!(!track.instrumental); assert!(track.explicit); assert!(track.has_subtitles); assert!(track.has_richsync); assert!(track.has_track_structure); assert!(track.num_favourite > 50); assert!(track.lyrics_id.is_some()); assert_eq!(track.subtitle_id.unwrap(), 36450705); assert_eq!(track.album_id, 13810402); assert_eq!(track.album_name, "The Fame"); assert_eq!(track.artist_id, 378462); assert_eq!( track.artist_mbid.unwrap(), "650e7db6-b795-4eb5-a702-5ea2fc46c848" ); assert_eq!(track.artist_name, "Lady Gaga"); assert_eq!( track.album_coverart_100x100.unwrap(), "https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636.jpg" ); assert_eq!( track.album_coverart_350x350.unwrap(), "https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_350_350.jpg" ); assert_eq!( track.album_coverart_500x500.unwrap(), "https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_500_500.jpg" ); assert_eq!(track.commontrack_vanity_id, "Lady-Gaga/poker-face-1"); let first_release = track.first_release_date.unwrap(); assert_eq!(first_release.date(), date!(2008 - 1 - 1)); assert!(track.updated_time > datetime!(2023-1-17 0:00 UTC)); let first_pri_genre = &track.primary_genres.music_genre_list[0].music_genre; assert_eq!(first_pri_genre.music_genre_id, 14); assert_eq!(first_pri_genre.music_genre_parent_id, 34); assert_eq!(first_pri_genre.music_genre_name, "Pop"); assert_eq!(first_pri_genre.music_genre_name_extended, "Pop"); assert_eq!(first_pri_genre.music_genre_vanity.as_ref().unwrap(), "Pop"); let first_sec_genre = &track.secondary_genres.music_genre_list[0].music_genre; assert_eq!(first_sec_genre.music_genre_id, 17); assert_eq!(first_sec_genre.music_genre_parent_id, 34); assert_eq!(first_sec_genre.music_genre_name, "Dance"); assert_eq!(first_sec_genre.music_genre_name_extended, "Dance"); assert_eq!( first_sec_genre.music_genre_vanity.as_ref().unwrap(), "Dance" ); if translation_status { assert!( track.track_lyrics_translation_status.iter().all(|tl| { (if lang_3c { tl.from.as_deref() == Some("eng") } else { tl.from.as_deref() == Some("en") }) && tl.perc >= 0.0 && tl.perc <= 1.0 }), "translation: {:?}", track.track_lyrics_translation_status ); } else { assert!(track.track_lyrics_translation_status.is_empty()) } } #[rstest] #[case::trackid(TrackId::TrackId(205688271))] #[case::commontrack(TrackId::Commontrack(118480583))] #[case::vanity(TrackId::CommontrackVanity("aespa/Black-Mamba".into()))] #[case::isrc(TrackId::Isrc("KRA302000590".into()))] #[case::spotify(TrackId::Spotify("1t2qYCAjUAoGfeFeoBlK51".into()))] #[tokio::test] async fn from_id(#[case] track_id: TrackId<'_>) { let track = new_mxm().track(track_id, true, false).await.unwrap(); // dbg!(&track); assert_eq!(track.track_id, 205688271); assert_eq!(track.track_isrc.unwrap(), "KRA302000590"); assert_eq!(track.track_spotify_id.unwrap(), "1t2qYCAjUAoGfeFeoBlK51"); assert_eq!(track.track_name, "Black Mamba"); assert!(track.track_rating > 50); assert_eq!(track.track_length, 175); assert!(!track.explicit); assert!(track.has_lyrics); assert!(track.has_subtitles); assert!(track.has_richsync); assert!(track.num_favourite > 200); assert!(track.lyrics_id.is_some()); assert_eq!(track.subtitle_id.unwrap(), 36476905); assert_eq!(track.album_id, 41035954); assert_eq!(track.album_name, "Black Mamba"); assert_eq!(track.artist_id, 46970441); assert_eq!(track.artist_name, "aespa"); assert_eq!( track.album_coverart_100x100.unwrap(), "https://s.mxmcdn.net/images-storage/albums5/2/7/7/6/5/1/52156772.jpg" ); assert_eq!( track.album_coverart_350x350.unwrap(), "https://s.mxmcdn.net/images-storage/albums5/2/7/7/6/5/1/52156772_350_350.jpg" ); assert_eq!( track.album_coverart_500x500.unwrap(), "https://s.mxmcdn.net/images-storage/albums5/2/7/7/6/5/1/52156772_500_500.jpg" ); assert_eq!(track.commontrack_vanity_id, "aespa/Black-Mamba"); let release_date = track.first_release_date.unwrap(); assert_eq!(release_date.date(), date!(2020 - 11 - 17)); assert!(track.updated_time > datetime!(2022-8-27 0:00 UTC)); let first_tstatus = &track.track_lyrics_translation_status[0]; assert_eq!(first_tstatus.from.as_deref(), Some("ko")); assert!(first_tstatus.perc >= 0.0 && first_tstatus.perc <= 1.0); } #[rstest] #[case::no_translation(false, false)] #[case::translation_2c(true, false)] #[case::translation_3c(true, true)] #[tokio::test] async fn from_id_translations(#[case] translation_status: bool, #[case] lang_3c: bool) { let track = new_mxm() .track(TrackId::TrackId(15476784), translation_status, lang_3c) .await .unwrap(); // dbg!(&track); assert_eq!(track.track_id, 15476784); assert_eq!( track.track_mbid.unwrap(), "080975b0-39b1-493c-ae64-5cb3292409bb" ); assert_eq!(track.track_isrc.unwrap(), "USUM70824409"); assert!( track.commontrack_isrcs[0] .iter() .any(|isrc| isrc == "USUM70824409"), "commontrack_isrcs: {:?}", &track.commontrack_isrcs[0], ); assert_eq!(track.track_spotify_id.unwrap(), "5R8dQOPq8haW94K7mgERlO"); assert!( track .commontrack_spotify_ids .iter() .any(|spid| spid == "1QV6tiMFM6fSOKOGLMHYYg"), "commontrack_spotify_ids: {:?}", track.commontrack_spotify_ids, ); assert_eq!(track.track_name, "Poker Face"); assert!(track.track_rating > 50); assert_eq!(track.commontrack_id, 47672612); assert!(!track.instrumental); assert!(track.explicit); assert!(track.has_subtitles); assert!(track.has_richsync); assert!(track.has_track_structure); assert!(track.num_favourite > 50); assert!(track.lyrics_id.is_some()); assert_eq!(track.subtitle_id.unwrap(), 36450705); assert_eq!(track.album_id, 13810402); assert_eq!(track.album_name, "The Fame"); assert_eq!(track.artist_id, 378462); assert_eq!( track.artist_mbid.unwrap(), "650e7db6-b795-4eb5-a702-5ea2fc46c848" ); assert_eq!(track.artist_name, "Lady Gaga"); assert_eq!( track.album_coverart_100x100.unwrap(), "https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636.jpg" ); assert_eq!( track.album_coverart_350x350.unwrap(), "https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_350_350.jpg" ); assert_eq!( track.album_coverart_500x500.unwrap(), "https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_500_500.jpg" ); assert_eq!(track.commontrack_vanity_id, "Lady-Gaga/poker-face-1"); let first_release = track.first_release_date.unwrap(); assert_eq!(first_release.date(), date!(2008 - 1 - 1)); assert!(track.updated_time > datetime!(2023-1-17 0:00 UTC)); let first_pri_genre = &track.primary_genres.music_genre_list[0].music_genre; assert_eq!(first_pri_genre.music_genre_id, 14); assert_eq!(first_pri_genre.music_genre_parent_id, 34); assert_eq!(first_pri_genre.music_genre_name, "Pop"); assert_eq!(first_pri_genre.music_genre_name_extended, "Pop"); assert_eq!(first_pri_genre.music_genre_vanity.as_ref().unwrap(), "Pop"); let first_sec_genre = &track.secondary_genres.music_genre_list[0].music_genre; assert_eq!(first_sec_genre.music_genre_id, 17); assert_eq!(first_sec_genre.music_genre_parent_id, 34); assert_eq!(first_sec_genre.music_genre_name, "Dance"); assert_eq!(first_sec_genre.music_genre_name_extended, "Dance"); assert_eq!( first_sec_genre.music_genre_vanity.as_ref().unwrap(), "Dance" ); if translation_status { assert!( track.track_lyrics_translation_status.iter().all(|tl| { (if lang_3c { tl.from.as_deref() == Some("eng") } else { tl.from.as_deref() == Some("en") }) && tl.perc >= 0.0 && tl.perc <= 1.0 }), "translation: {:?}", track.track_lyrics_translation_status ); } else { assert!(track.track_lyrics_translation_status.is_empty()) } } #[tokio::test] async fn from_id_missing() { let err = new_mxm() .track(TrackId::TrackId(999999999999), false, false) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn album_tracks() { let tracks = new_mxm() .album_tracks(AlbumId::AlbumId(17118624), true, 20, 1) .await .unwrap(); // dbg!(&tracks); let track_names = tracks .iter() .map(|t| t.track_name.to_owned()) .collect::>(); assert_eq!( track_names, vec![ "Gäa", "Vergiss mein nicht", "Orome", "Falke flieg", "Minne", "Das Lied der Ahnen", "Hörst du den Wind", "Nan Úye", "Faolan", "Hymne der Nacht", "Avalon", "Tolo Nan", "Oonagh", ] ); tracks.iter().for_each(|t| { assert!(t.has_lyrics); assert!(t.has_subtitles); }); } #[tokio::test] async fn album_missing() { let err = new_mxm() .album_tracks(AlbumId::AlbumId(999999999999), false, 20, 1) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[rstest] #[case::top(ChartName::Top)] #[case::hot(ChartName::Hot)] #[tokio::test] async fn charts(#[case] chart_name: ChartName) { let tracks = new_mxm() .chart_tracks("US", chart_name, true, 20, 1) .await .unwrap(); assert_eq!(tracks.len(), 20); } #[tokio::test] async fn search() { let tracks = new_mxm() .track_search() .q_artist("Lena") .q_track("Satellite") .s_track_rating(SortOrder::Desc) .send(1, 0) .await .unwrap(); // dbg!(&tracks); assert_eq!(tracks.len(), 1); let track = &tracks[0]; assert_eq!(track.commontrack_id, 72643758); assert_eq!(track.track_name, "Satellite"); assert_eq!(track.artist_name, "Lena"); } #[tokio::test] async fn search_lyrics() { let tracks = new_mxm() .track_search() .q_lyrics("the whole world stops and stares for a while") .s_track_rating(SortOrder::Desc) .send(10, 1) .await .unwrap(); assert_eq!(tracks.len(), 10); let track = &tracks[0]; assert_eq!(track.track_name, "Just the Way You Are"); assert_eq!(track.artist_name, "Bruno Mars"); } #[tokio::test] async fn search_empty() { let artists = new_mxm() .track_search() .q("Rindfleischettikettierungsüberwachungsaufgabenübertragungsgesetz") .send(10, 1) .await .unwrap(); assert_eq!(artists.len(), 0); } #[tokio::test] async fn genres() { let genres = new_mxm().genres().await.unwrap(); assert!(genres.len() > 360); // dbg!(&genres); } #[tokio::test] async fn snippet() { let snippet = new_mxm() .track_snippet(TrackId::Commontrack(8874280)) .await .unwrap(); assert_eq!(snippet.snippet_id, 23036767); assert_eq!(snippet.snippet_language.unwrap(), "en"); assert!(!snippet.instrumental); assert!(snippet.updated_time > datetime!(2022-8-29 0:00 UTC)); assert_eq!( snippet.snippet_body, "There's not a thing that I would change" ); } } mod lyrics { use futures::stream::{self, StreamExt}; use std::{fs::File, io::BufWriter}; use super::*; #[tokio::test] async fn from_match() { let lyrics = new_mxm().matcher_lyrics("Shine", "Spektrem").await.unwrap(); // dbg!(&lyrics); assert_eq!(lyrics.lyrics_id, 25947036); assert!(!lyrics.instrumental); assert!(!lyrics.explicit); assert!(lyrics .lyrics_body .starts_with("Eyes, in the sky, gazing far into the night\n")); assert_eq!(lyrics.lyrics_language.unwrap(), "en"); assert_eq!(lyrics.lyrics_language_description.unwrap(), "English"); let copyright = lyrics.lyrics_copyright.unwrap(); assert!(copyright.contains("Kim Jeffeson"), "copyright: {copyright}",); assert!(lyrics.updated_time > datetime!(2021-6-3 0:00 UTC)); } #[rstest] #[case::trackid(TrackId::TrackId(205688271))] #[case::commontrack(TrackId::Commontrack(118480583))] #[case::vanity(TrackId::CommontrackVanity("aespa/Black-Mamba".into()))] #[case::isrc(TrackId::Isrc("KRA302000590".into()))] #[case::spotify(TrackId::Spotify("1t2qYCAjUAoGfeFeoBlK51".into()))] #[tokio::test] async fn from_id(#[case] track_id: TrackId<'_>) { let lyrics = new_mxm().track_lyrics(track_id).await.unwrap(); // dbg!(&lyrics); assert_eq!(lyrics.lyrics_id, 30126001); assert_eq!(lyrics.lyrics_language.unwrap(), "ko"); assert_eq!(lyrics.lyrics_language_description.unwrap(), "Korean"); let copyright = lyrics.lyrics_copyright.unwrap(); assert!( copyright.contains("Kenneth Scott Chesak"), "copyright: {copyright}", ); assert!(lyrics.updated_time > datetime!(2022-8-27 0:00 UTC)); } /// This track has no lyrics #[tokio::test] async fn instrumental() { let lyrics = new_mxm() .matcher_lyrics("drivers license", "Bobby G") .await .unwrap(); assert_eq!(lyrics.lyrics_id, 25891609); assert!(lyrics.instrumental); assert!(!lyrics.explicit); assert_eq!(lyrics.lyrics_body, ""); assert_eq!(lyrics.lyrics_language, None); assert_eq!(lyrics.lyrics_language_description, None); assert_eq!(lyrics.lyrics_copyright, None); assert!(lyrics.updated_time > datetime!(2021-6-21 0:00 UTC)); } /// This track does not exist #[tokio::test] async fn missing() { let err = new_mxm() .track_lyrics(TrackId::Spotify("674JwwTP7xCje81T0DRrLn".into())) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn download_testdata() { let json_path = testfile("lyrics.json"); if json_path.exists() { return; } let lyrics = new_mxm() .track_lyrics(TrackId::Commontrack(18576954)) .await .unwrap(); let json_file = File::create(json_path).unwrap(); serde_json::to_writer_pretty(BufWriter::new(json_file), &lyrics).unwrap(); } #[tokio::test] async fn download_testdata_translation() { let json_path = testfile("translation.json"); if json_path.exists() { return; } let translations = new_mxm() .track_lyrics_translation(TrackId::Commontrack(18576954), "de") .await .unwrap(); let json_file = File::create(json_path).unwrap(); serde_json::to_writer_pretty(BufWriter::new(json_file), &translations).unwrap(); } #[tokio::test] async fn concurrency() { let mxm = new_mxm(); let album = mxm .album_tracks( musixmatch_inofficial::models::AlbumId::AlbumId(17118624), true, 20, 1, ) .await .unwrap(); let x = stream::iter(album) .map(|track| { mxm.track_lyrics(musixmatch_inofficial::models::TrackId::TrackId( track.track_id, )) }) .buffered(8) .collect::>() .await .into_iter() .map(Result::unwrap) .collect::>(); dbg!(x); } } mod subtitles { use std::{fs::File, io::BufWriter}; use super::*; use musixmatch_inofficial::models::SubtitleFormat; #[tokio::test] async fn from_match() { let subtitle = new_mxm() .matcher_subtitle( "Shine", "Spektrem", SubtitleFormat::Json, Some(315.0), Some(1.0), ) .await .unwrap(); // dbg!(&subtitle); assert_eq!(subtitle.subtitle_id, 36913312); assert_eq!(subtitle.subtitle_language.unwrap(), "en"); assert_eq!(subtitle.subtitle_language_description.unwrap(), "English"); let copyright = subtitle.lyrics_copyright.unwrap(); assert!(copyright.contains("Kim Jeffeson"), "copyright: {copyright}",); assert_eq!(subtitle.subtitle_length, 315); assert!(subtitle.updated_time > datetime!(2021-6-30 0:00 UTC)); } #[rstest] #[case::trackid(TrackId::TrackId(205688271))] #[case::commontrack(TrackId::Commontrack(118480583))] #[case::vanity(TrackId::CommontrackVanity("aespa/Black-Mamba".into()))] #[case::isrc(TrackId::Isrc("KRA302000590".into()))] #[case::spotify(TrackId::Spotify("1t2qYCAjUAoGfeFeoBlK51".into()))] #[tokio::test] async fn from_id(#[case] track_id: TrackId<'_>) { let subtitle = new_mxm() .track_subtitle(track_id, SubtitleFormat::Json, Some(175.0), Some(1.0)) .await .unwrap(); // dbg!(&subtitle); assert_eq!(subtitle.subtitle_id, 36476905); assert_eq!(subtitle.subtitle_language.unwrap(), "ko"); assert_eq!(subtitle.subtitle_language_description.unwrap(), "Korean"); let copyright = subtitle.lyrics_copyright.unwrap(); assert!( copyright.contains("Kenneth Scott Chesak"), "copyright: {copyright}", ); assert_eq!(subtitle.subtitle_length, 175); assert!(subtitle.updated_time > datetime!(2022-8-27 0:00 UTC)); } /// This track has no lyrics #[tokio::test] async fn instrumental() { let err = new_mxm() .matcher_subtitle( "drivers license", "Bobby G", SubtitleFormat::Json, Some(246.0), Some(1.0), ) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } /// This track has not been synced #[tokio::test] async fn unsynced() { let err = new_mxm() .track_subtitle( TrackId::Spotify("6oaWIABGL7eeiMILEDyGX1".into()), SubtitleFormat::Json, Some(213.0), Some(1.0), ) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } /// Try to get subtitles with wrong length parameter #[tokio::test] async fn wrong_length() { let err = new_mxm() .track_subtitle( TrackId::Commontrack(118480583), SubtitleFormat::Json, Some(200.0), Some(1.0), ) .await .unwrap_err(); assert!(matches!(err, Error::NotFound)); } #[tokio::test] async fn download_testdata() { let json_path = testfile("subtitles.json"); if json_path.exists() { return; } let subtitle = new_mxm() .track_subtitle( TrackId::Commontrack(18576954), SubtitleFormat::Json, Some(259.0), Some(1.0), ) .await .unwrap(); let json_file = File::create(json_path).unwrap(); serde_json::to_writer_pretty(BufWriter::new(json_file), &subtitle).unwrap(); } } mod translation { use std::{fs::File, io::BufReader}; use musixmatch_inofficial::models::{Lyrics, Subtitle, TranslationList, TranslationMap}; use crate::testfile; #[test] fn translation_test() { let lyrics_path = testfile("lyrics.json"); let subtitles_path = testfile("subtitles.json"); let translation_path = testfile("translation.json"); let lyrics: Lyrics = serde_json::from_reader(BufReader::new(File::open(lyrics_path).unwrap())).unwrap(); let subtitle: Subtitle = serde_json::from_reader(BufReader::new(File::open(subtitles_path).unwrap())).unwrap(); let translations: TranslationList = serde_json::from_reader(BufReader::new(File::open(translation_path).unwrap())).unwrap(); let t_map = TranslationMap::from(translations); let lyrics_trans = t_map.translate_lyrics(&lyrics.lyrics_body); let expected_lyrics = std::fs::read_to_string(testfile("translated_lyrics.txt")).unwrap(); assert_eq!(lyrics_trans.trim(), expected_lyrics.trim()); let subtitles_trans = t_map.translate_subtitles(&subtitle.to_lines().unwrap()); let expected_lrc = std::fs::read_to_string(testfile("translated_subtitles.lrc")).unwrap(); let expected_ttml = std::fs::read_to_string(testfile("translated_subtitles.xml")).unwrap(); assert_eq!(subtitles_trans.to_lrc().trim(), expected_lrc.trim()); assert_eq!(subtitles_trans.to_ttml().trim(), expected_ttml.trim()); } } #[tokio::test] async fn no_credentials() { let mxm = Musixmatch::builder() .client_type(ClientType::Android) .no_storage() .build() .unwrap(); let err = mxm .track_lyrics(TrackId::TrackId(205688271)) .await .unwrap_err(); assert!(matches!(err, Error::MissingCredentials), "error: {err}"); }