Add unit tests and url checking
This commit is contained in:
parent
c8c259ab7a
commit
97c9080d50
123
src/lib.rs
123
src/lib.rs
@ -44,6 +44,20 @@ pub trait IUuid {
|
|||||||
fn uuid(&self) -> &str;
|
fn uuid(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
enum UrlType {
|
||||||
|
MusicBrainz,
|
||||||
|
MusicButler,
|
||||||
|
Bandcamp,
|
||||||
|
Qobuz,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
struct InvalidUrlError {
|
||||||
|
url_type: UrlType,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// MusicBrainz reference.
|
/// MusicBrainz reference.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
pub struct MusicBrainz {
|
pub struct MusicBrainz {
|
||||||
@ -54,18 +68,25 @@ pub struct MusicBrainz {
|
|||||||
impl MusicBrainz {
|
impl MusicBrainz {
|
||||||
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
||||||
let url = Url::parse(url.as_ref())?;
|
let url = Url::parse(url.as_ref())?;
|
||||||
let mbid: Mbid = match url.path_segments().and_then(|mut ps| ps.nth(2)) {
|
|
||||||
|
if !url.domain().map(|u| u.ends_with("musicbrainz.org")).unwrap_or(false) {
|
||||||
|
return Err(Self::invalid_url_error(url).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
let mbid: Mbid = match url.path_segments().and_then(|mut ps| ps.nth(1)) {
|
||||||
Some(segment) => Mbid::new(segment)?,
|
Some(segment) => Mbid::new(segment)?,
|
||||||
None => {
|
None => return Err(Self::invalid_url_error(url).into()),
|
||||||
return Err(Error::UrlParseError(format!(
|
|
||||||
"invalid MusicBrainz URL: {}",
|
|
||||||
url.as_str()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(MusicBrainz { url, mbid })
|
Ok(MusicBrainz { url, mbid })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invalid_url_error<S: Into<String>>(url: S) -> InvalidUrlError {
|
||||||
|
InvalidUrlError {
|
||||||
|
url_type: UrlType::MusicBrainz,
|
||||||
|
url: url.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for MusicBrainz {
|
impl IUrl for MusicBrainz {
|
||||||
@ -89,8 +110,20 @@ pub struct MusicButler {
|
|||||||
impl MusicButler {
|
impl MusicButler {
|
||||||
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
||||||
let url = Url::parse(url.as_ref())?;
|
let url = Url::parse(url.as_ref())?;
|
||||||
|
|
||||||
|
if !url.domain().map(|u| u.ends_with("musicbutler.io")).unwrap_or(false) {
|
||||||
|
return Err(Self::invalid_url_error(url).into())
|
||||||
|
}
|
||||||
|
|
||||||
Ok(MusicButler { url })
|
Ok(MusicButler { url })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invalid_url_error<S: Into<String>>(url: S) -> InvalidUrlError {
|
||||||
|
InvalidUrlError {
|
||||||
|
url_type: UrlType::MusicButler,
|
||||||
|
url: url.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for MusicButler {
|
impl IUrl for MusicButler {
|
||||||
@ -108,8 +141,20 @@ pub struct Bandcamp {
|
|||||||
impl Bandcamp {
|
impl Bandcamp {
|
||||||
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
||||||
let url = Url::parse(url.as_ref())?;
|
let url = Url::parse(url.as_ref())?;
|
||||||
|
|
||||||
|
if !url.domain().map(|u| u.ends_with("bandcamp.com")).unwrap_or(false) {
|
||||||
|
return Err(Self::invalid_url_error(url).into())
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Bandcamp { url })
|
Ok(Bandcamp { url })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invalid_url_error<S: Into<String>>(url: S) -> InvalidUrlError {
|
||||||
|
InvalidUrlError {
|
||||||
|
url_type: UrlType::Bandcamp,
|
||||||
|
url: url.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for Bandcamp {
|
impl IUrl for Bandcamp {
|
||||||
@ -127,8 +172,20 @@ pub struct Qobuz {
|
|||||||
impl Qobuz {
|
impl Qobuz {
|
||||||
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> {
|
||||||
let url = Url::parse(url.as_ref())?;
|
let url = Url::parse(url.as_ref())?;
|
||||||
|
|
||||||
|
if !url.domain().map(|u| u.ends_with("qobuz.com")).unwrap_or(false) {
|
||||||
|
return Err(Self::invalid_url_error(url).into())
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Qobuz { url })
|
Ok(Qobuz { url })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invalid_url_error<S: Into<String>>(url: S) -> InvalidUrlError {
|
||||||
|
InvalidUrlError {
|
||||||
|
url_type: UrlType::Qobuz,
|
||||||
|
url: url.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for Qobuz {
|
impl IUrl for Qobuz {
|
||||||
@ -323,6 +380,8 @@ pub enum Error {
|
|||||||
DatabaseError(String),
|
DatabaseError(String),
|
||||||
/// The [`MusicHoard`] failed to parse a user-provided URL.
|
/// The [`MusicHoard`] failed to parse a user-provided URL.
|
||||||
UrlParseError(String),
|
UrlParseError(String),
|
||||||
|
/// The user-provided URL is not valid.
|
||||||
|
InvalidUrlError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -333,6 +392,7 @@ impl fmt::Display for Error {
|
|||||||
write!(f, "failed to read/write from/to the database: {s}")
|
write!(f, "failed to read/write from/to the database: {s}")
|
||||||
}
|
}
|
||||||
Self::UrlParseError(ref s) => write!(f, "failed to parse a user-provided URL: {s}"),
|
Self::UrlParseError(ref s) => write!(f, "failed to parse a user-provided URL: {s}"),
|
||||||
|
Self::InvalidUrlError(ref s) => write!(f, "user-provided URL is invalid: {s}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,6 +427,12 @@ impl From<uuid::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<InvalidUrlError> for Error {
|
||||||
|
fn from(err: InvalidUrlError) -> Error {
|
||||||
|
Error::InvalidUrlError(format!("{:?} - {}", err.url_type, err.url))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The Music Hoard. It is responsible for pulling information from both the library and the
|
/// The Music Hoard. It is responsible for pulling information from both the library and the
|
||||||
/// database, ensuring its consistent and writing back any changes.
|
/// database, ensuring its consistent and writing back any changes.
|
||||||
pub struct MusicHoard<LIB, DB> {
|
pub struct MusicHoard<LIB, DB> {
|
||||||
@ -545,6 +611,49 @@ mod tests {
|
|||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn musicbrainz() {
|
||||||
|
let uuid = "d368baa8-21ca-4759-9731-0b2753071ad8";
|
||||||
|
let url = format!("https://musicbrainz.org/artist/{uuid}");
|
||||||
|
let mb = MusicBrainz::new(&url).unwrap();
|
||||||
|
assert_eq!(url, mb.url());
|
||||||
|
assert_eq!(uuid, mb.uuid());
|
||||||
|
|
||||||
|
let url = format!("https://musicbrainz.org/artist/i-am-not-a-uuid");
|
||||||
|
assert!(MusicBrainz::new(&url).is_err());
|
||||||
|
|
||||||
|
let url = format!("https://musicbrainz.org/artist");
|
||||||
|
assert!(MusicBrainz::new(&url).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn urls() {
|
||||||
|
let musicbrainz = "https://musicbrainz.org/artist/d368baa8-21ca-4759-9731-0b2753071ad8";
|
||||||
|
let musicbutler = "https://www.musicbutler.io/artist-page/483340948";
|
||||||
|
let bandcamp = "https://thelasthangmen.bandcamp.com/";
|
||||||
|
let qobuz = "https://www.qobuz.com/nl-nl/interpreter/the-last-hangmen/1244413";
|
||||||
|
|
||||||
|
assert!(MusicBrainz::new(&musicbrainz).is_ok());
|
||||||
|
assert!(MusicBrainz::new(&musicbutler).is_err());
|
||||||
|
assert!(MusicBrainz::new(&bandcamp).is_err());
|
||||||
|
assert!(MusicBrainz::new(&qobuz).is_err());
|
||||||
|
|
||||||
|
assert!(MusicButler::new(&musicbrainz).is_err());
|
||||||
|
assert!(MusicButler::new(&musicbutler).is_ok());
|
||||||
|
assert!(MusicButler::new(&bandcamp).is_err());
|
||||||
|
assert!(MusicButler::new(&qobuz).is_err());
|
||||||
|
|
||||||
|
assert!(Bandcamp::new(&musicbrainz).is_err());
|
||||||
|
assert!(Bandcamp::new(&musicbutler).is_err());
|
||||||
|
assert!(Bandcamp::new(&bandcamp).is_ok());
|
||||||
|
assert!(Bandcamp::new(&qobuz).is_err());
|
||||||
|
|
||||||
|
assert!(Qobuz::new(&musicbrainz).is_err());
|
||||||
|
assert!(Qobuz::new(&musicbutler).is_err());
|
||||||
|
assert!(Qobuz::new(&bandcamp).is_err());
|
||||||
|
assert!(Qobuz::new(&qobuz).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn merge_track() {
|
fn merge_track() {
|
||||||
let left = Track {
|
let left = Track {
|
||||||
|
Loading…
Reference in New Issue
Block a user