Skip to content

Commit

Permalink
Merge pull request #189 from ramsayleung/ramsay_add_unit_tests
Browse files Browse the repository at this point in the history
Add unit tests for pure methods
  • Loading branch information
marioortizmanero authored Mar 9, 2021
2 parents 8594a8f + fffd831 commit ce9ee2c
Show file tree
Hide file tree
Showing 17 changed files with 413 additions and 197 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Cargo.lock
.DS_Store
.spotify_cache/
**/target/
/.test_read_token_cache.json
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ If we missed any change or there's something you'd like to discuss about this ve
+ `ExplicitContent`
+ Fix broken model links refering to Spotify documentation
- ([#188](https://github.com/ramsayleung/rspotify/pull/188)) Replace html links with intra-documentation links
- ([#189](https://github.com/ramsayleung/rspotify/pull/189)) Add `scopes!` macro to generate scope for `Token` from string literal

**Breaking changes:**
- `SpotifyClientCredentials` has been renamed to `Credentials` ([#129](https://github.com/ramsayleung/rspotify/pull/129)), and its members `client_id` and `client_secret` to `id` and `secret`, respectively.
Expand Down
10 changes: 5 additions & 5 deletions examples/current_user_recently_played.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use rspotify::client::SpotifyBuilder;
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};

use std::collections::HashSet;
use rspotify::scopes;

#[tokio::main]
async fn main() {
Expand Down Expand Up @@ -31,9 +30,10 @@ async fn main() {
// .redirect_uri("http://localhost:8888/callback")
// .build()
// .unwrap();
let mut scopes = HashSet::new();
scopes.insert("user-read-recently-played".to_owned());
let oauth = OAuthBuilder::from_env().scope(scopes).build().unwrap();
let oauth = OAuthBuilder::from_env()
.scope(scopes!("user-read-recently-played"))
.build()
.unwrap();

let mut spotify = SpotifyBuilder::default()
.credentials(creds)
Expand Down
32 changes: 21 additions & 11 deletions examples/oauth_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use rspotify::client::SpotifyBuilder;
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};
use rspotify::scopes;

#[tokio::main]
async fn main() {
Expand All @@ -18,17 +19,26 @@ async fn main() {
let creds = CredentialsBuilder::from_env().build().unwrap();

// Using every possible scope
let scope = "user-read-email user-read-private user-top-read \
user-read-recently-played user-follow-read user-library-read \
user-read-currently-playing user-read-playback-state \
user-read-playback-position playlist-read-collaborative \
playlist-read-private user-follow-modify user-library-modify \
user-modify-playback-state playlist-modify-public \
playlist-modify-private ugc-image-upload";
let oauth = OAuthBuilder::from_env()
.scope(scope.split_whitespace().map(|x| x.to_owned()).collect())
.build()
.unwrap();
let scope = scopes!(
"user-read-email",
"user-read-private",
"user-top-read",
"user-read-recently-played",
"user-follow-read",
"user-library-read",
"user-read-currently-playing",
"user-read-playback-state",
"user-read-playback-position",
"playlist-read-collaborative",
"playlist-read-private",
"user-follow-modify",
"user-library-modify",
"user-modify-playback-state",
"playlist-modify-public",
"playlist-modify-private",
"ugc-image-upload"
);
let oauth = OAuthBuilder::from_env().scope(scope).build().unwrap();

let mut spotify = SpotifyBuilder::default()
.credentials(creds)
Expand Down
8 changes: 5 additions & 3 deletions examples/ureq/device.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rspotify::client::SpotifyBuilder;
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};
use rspotify::scope;

use std::collections::HashSet;

Expand Down Expand Up @@ -30,9 +31,10 @@ fn main() {
// .redirect_uri("http://localhost:8888/callback")
// .build()
// .unwrap();
let mut scope = HashSet::new();
scope.insert("user-read-playback-state".to_owned());
let oauth = OAuthBuilder::from_env().scope(scope).build().unwrap();
let oauth = OAuthBuilder::from_env()
.scope(scopes!("user-read-playback-state"))
.build()
.unwrap();

let mut spotify = SpotifyBuilder::default()
.credentials(creds)
Expand Down
8 changes: 5 additions & 3 deletions examples/ureq/me.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rspotify::client::SpotifyBuilder;
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};
use rspotify::scope;

use std::collections::HashSet;

Expand Down Expand Up @@ -30,9 +31,10 @@ fn main() {
// .redirect_uri("http://localhost:8888/callback")
// .build()
// .unwrap();
let mut scope = HashSet::new();
scope.insert("user-read-playback-state".to_owned());
let oauth = OAuthBuilder::from_env().scope(scope).build().unwrap();
let oauth = OAuthBuilder::from_env()
.scope(scopes!("user-read-playback-state"))
.build()
.unwrap();

let mut spotify = SpotifyBuilder::default()
.credentials(creds)
Expand Down
8 changes: 5 additions & 3 deletions examples/ureq/search.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rspotify::client::SpotifyBuilder;
use rspotify::model::{Country, Market, SearchType};
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};
use rspotify::scope;

use std::collections::HashSet;

Expand Down Expand Up @@ -31,9 +32,10 @@ fn main() {
// .redirect_uri("http://localhost:8888/callback")
// .build()
// .unwrap();
let mut scope = HashSet::new();
scope.insert("user-read-playback-state".to_owned());
let oauth = OAuthBuilder::from_env().scope(scope).build().unwrap();
let oauth = OAuthBuilder::from_env()
.scope(scopes!("user-read-playback-state"))
.build()
.unwrap();

let mut spotify = SpotifyBuilder::default()
.credentials(creds)
Expand Down
8 changes: 5 additions & 3 deletions examples/ureq/seek_track.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rspotify::client::SpotifyBuilder;
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};
use rspotify::scope;

use std::collections::HashSet;

Expand Down Expand Up @@ -30,9 +31,10 @@ fn main() {
// .redirect_uri("http://localhost:8888/callback")
// .build()
// .unwrap();
let mut scope = HashSet::new();
scope.insert("user-read-playback-state".to_owned());
let oauth = OAuthBuilder::from_env().scope(scope).build().unwrap();
let oauth = OAuthBuilder::from_env()
.scope(scopes!("user-read-playback-state"))
.build()
.unwrap();

let mut spotify = SpotifyBuilder::default()
.credentials(creds)
Expand Down
5 changes: 3 additions & 2 deletions examples/webapp/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rocket_contrib::json::JsonValue;
use rocket_contrib::templates::Template;
use rspotify::client::{ClientError, SpotifyBuilder};
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder, TokenBuilder};
use rspotify::scope;

use std::fs;
use std::{
Expand Down Expand Up @@ -75,10 +76,10 @@ fn check_cache_path_exists(cookies: &Cookies) -> (bool, PathBuf) {
fn init_spotify() -> SpotifyBuilder {
// Please notice that protocol of redirect_uri, make sure it's http
// (or https). It will fail if you mix them up.
let scope = "user-read-currently-playing playlist-modify-private";
let scope = scopes!("user-read-currently-playing", "playlist-modify-private");
let oauth = OAuthBuilder::default()
.redirect_uri("http://localhost:8000/callback")
.scope(scope.split_whitespace().map(|x| x.to_owned()).collect())
.scope(scope)
.build()
.unwrap();

Expand Down
8 changes: 3 additions & 5 deletions examples/with_refresh_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use rspotify::client::{Spotify, SpotifyBuilder};
use rspotify::model::Id;
use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder};
use rspotify::scopes;

// Sample request that will follow some artists, print the user's
// followed artists, and then unfollow the artists.
Expand Down Expand Up @@ -57,11 +58,8 @@ async fn main() {

// The default credentials from the `.env` file will be used by default.
let creds = CredentialsBuilder::from_env().build().unwrap();
let scope = "user-follow-read user-follow-modify";
let oauth = OAuthBuilder::from_env()
.scope(scope.split_whitespace().map(|x| x.to_owned()).collect())
.build()
.unwrap();
let scope = scopes!("user-follow-read user-follow-modify");
let oauth = OAuthBuilder::from_env().scope(scope).build().unwrap();
let mut spotify = SpotifyBuilder::default()
.credentials(creds.clone())
.oauth(oauth.clone())
Expand Down
23 changes: 22 additions & 1 deletion src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2044,7 +2044,7 @@ fn join_ids<'a, T: 'a + IdType>(ids: impl IntoIterator<Item = &'a Id<T>>) -> Str
}

#[cfg(test)]
mod tests {
mod test {
use super::*;

#[test]
Expand All @@ -2054,4 +2054,25 @@ mod tests {
let code = spotify.parse_response_code(url).unwrap();
assert_eq!(code, "AQD0yXvFEOvw");
}

#[test]
fn test_append_device_id_without_question_mark() {
let path = "me/player/play";
let device_id = Some("fdafdsadfa".to_owned());
let spotify = SpotifyBuilder::default().build().unwrap();
let new_path = spotify.append_device_id(path, device_id);
assert_eq!(new_path, "me/player/play?device_id=fdafdsadfa");
}

#[test]
fn test_append_device_id_with_question_mark() {
let path = "me/player/shuffle?state=true";
let device_id = Some("fdafdsadfa".to_owned());
let spotify = SpotifyBuilder::default().build().unwrap();
let new_path = spotify.append_device_id(path, device_id);
assert_eq!(
new_path,
"me/player/shuffle?state=true&device_id=fdafdsadfa"
);
}
}
66 changes: 66 additions & 0 deletions src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,69 @@ impl Spotify {
self.delete(url, Some(&headers), payload).await
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::client::SpotifyBuilder;
use crate::oauth2::TokenBuilder;
use crate::scopes;
use chrono::prelude::*;
use chrono::Duration;

#[test]
fn test_bearer_auth() {
let access_token = "access_token";
let tok = TokenBuilder::default()
.access_token(access_token)
.build()
.unwrap();
let (auth, value) = headers::bearer_auth(&tok);
assert_eq!(auth, "authorization");
assert_eq!(value, "Bearer access_token");
}

#[test]
fn test_basic_auth() {
let (auth, value) = headers::basic_auth("ramsay", "123456");
assert_eq!(auth, "authorization");
assert_eq!(value, "Basic cmFtc2F5OjEyMzQ1Ng==");
}

#[test]
fn test_endpoint_url() {
let spotify = SpotifyBuilder::default().build().unwrap();
assert_eq!(
spotify.endpoint_url("me/player/play"),
"https://api.spotify.com/v1/me/player/play"
);
assert_eq!(
spotify.endpoint_url("http://api.spotify.com/v1/me/player/play"),
"http://api.spotify.com/v1/me/player/play"
);
assert_eq!(
spotify.endpoint_url("https://api.spotify.com/v1/me/player/play"),
"https://api.spotify.com/v1/me/player/play"
);
}

#[test]
fn test_auth_headers() {
let tok = TokenBuilder::default()
.access_token("test-access_token")
.expires_in(Duration::seconds(1))
.expires_at(Utc::now())
.scope(scopes!("playlist-read-private"))
.refresh_token("...")
.build()
.unwrap();

let spotify = SpotifyBuilder::default().token(tok).build().unwrap();

let headers = spotify.auth_headers().unwrap();
assert_eq!(
headers.get("authorization"),
Some(&"Bearer test-access_token".to_owned())
);
}
}
51 changes: 37 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,26 +165,15 @@ pub mod model;
#[cfg(not(all(feature = "client-reqwest", feature = "client-ureq")))]
pub mod oauth2;

#[macro_use]
mod macros;

#[cfg(all(feature = "client-reqwest", feature = "client-ureq"))]
compile_error!(
"`client-reqwest` and `client-ureq` features cannot both be enabled at the same time, \
if you want to use `client-ureq` you need to set `default-features = false`"
);

#[doc(hidden)]
mod macros {
/// Reduce boilerplate when inserting new elements in a JSON object.
#[macro_export]
macro_rules! json_insert {
($json:expr, $p1:expr, $p2:expr) => {
$json
.as_object_mut()
.unwrap()
.insert($p1.to_string(), json!($p2))
};
}
}

/// Generate `length` random chars
pub(in crate) fn generate_random_string(length: usize) -> String {
let alphanum: &[u8] =
Expand All @@ -197,3 +186,37 @@ pub(in crate) fn generate_random_string(length: usize) -> String {
.map(|byte| alphanum[*byte as usize % range] as char)
.collect()
}

#[cfg(test)]
mod test {
use super::{generate_random_string, json_insert, scopes};
use serde_json::json;
use std::collections::HashSet;

#[test]
fn test_hashset() {
let scope = scopes!("hello", "world", "foo", "bar");
assert_eq!(scope.len(), 4);
assert!(scope.contains(&"hello".to_owned()));
assert!(scope.contains(&"world".to_owned()));
assert!(scope.contains(&"foo".to_owned()));
assert!(scope.contains(&"bar".to_owned()));
}

#[test]
fn test_generate_random_string() {
let mut containers = HashSet::new();
for _ in 1..101 {
containers.insert(generate_random_string(10));
}
assert_eq!(containers.len(), 100);
}

#[test]
fn test_json_insert() {
let mut params = json!({});
let name = "ramsay";
json_insert!(params, "name", name);
assert_eq!(params["name"], name);
}
}
Loading

0 comments on commit ce9ee2c

Please sign in to comment.