extern crate rand;
use crate::CacheRequestResponse;
use crate::CacheResult;
use crate::CreateSubscriptionResult;
use crate::FeedbinApi;
use rand::distr::Alphanumeric;
use rand::{rng, RngExt};
use reqwest::Client;
use std::env;
use url::Url;
fn test_setup_env() -> FeedbinApi {
dotenv::dotenv().ok(); let url = env::var("FEEDBIN_URL").expect("Failed to read FEEDBIN_URL");
let user = env::var("FEEDBIN_USERNAME").expect("Failed to read FEEDBIN_USERNAME");
let password = env::var("FEEDBIN_PASSWORD").expect("Failed to read FEEDBIN_PASSWORD");
let url = Url::parse(&url).unwrap();
FeedbinApi::new(&url, user, password)
}
#[tokio::test(flavor = "current_thread")]
async fn authenticated_valid_password() {
let api = test_setup_env();
assert!(api.is_authenticated(&Client::new()).await.unwrap());
}
#[tokio::test(flavor = "current_thread")]
async fn authenticated_invalid_password() {
let api = test_setup_env().with_password("invalid password");
assert!(!api.is_authenticated(&Client::new()).await.unwrap());
}
#[tokio::test(flavor = "current_thread")]
async fn is_reachable_valid_password() {
let api = test_setup_env();
assert!(api.is_reachable(&Client::new()).await.unwrap());
}
#[tokio::test(flavor = "current_thread")]
async fn is_not_reachable_valid_password() {
let api = test_setup_env()
.with_base_url(&Url::parse("http://notarealsubdomain.example.com").unwrap());
assert!(!api.is_reachable(&Client::new()).await.unwrap());
}
#[tokio::test(flavor = "current_thread")]
async fn is_reachable_invalid_password() {
let api = test_setup_env().with_password("invalid password");
assert!(api.is_reachable(&Client::new()).await.unwrap());
}
#[tokio::test(flavor = "current_thread")]
async fn create_and_delete_subscription() {
let api = test_setup_env();
let token: Vec<u8> = rng().sample_iter(&Alphanumeric).take(16).collect();
let token = std::str::from_utf8(&token).unwrap();
let mut url = Url::parse("https://www.brendanlong.com/feeds/all.atom.xml").unwrap();
url.set_query(Some(&format!("token={}", token)));
match api
.create_subscription(&Client::new(), url.as_str())
.await
.unwrap()
{
CreateSubscriptionResult::Created(subscription) => {
assert_eq!(
subscription.feed_url,
url.as_str(),
"Returned Subscription URL should match the URL we used to create the subscription"
);
let response = match api
.get_subscriptions(&Client::new(), None, None, None)
.await
.unwrap()
{
CacheRequestResponse::Modified(CacheResult {
value: response,
cache: _,
}) => response,
CacheRequestResponse::NotModified => panic!(),
};
assert_eq!(
response
.iter()
.filter(|sub| sub.id == subscription.id)
.count(),
1,
"Newly created subscription should exist in the full list of subscriptions"
);
assert_eq!(
api.get_subscription(&Client::new(), subscription.id)
.await
.unwrap()
.id,
subscription.id,
"Newly created subscription can be looked up by ID"
);
api.delete_subscription(&Client::new(), subscription.id)
.await
.unwrap();
let response = match api
.get_subscriptions(&Client::new(), None, None, None)
.await
.unwrap()
{
CacheRequestResponse::Modified(CacheResult {
value: response,
cache: _,
}) => response,
CacheRequestResponse::NotModified => panic!(),
};
assert_eq!(
response
.iter()
.filter(|sub| sub.id == subscription.id)
.count(),
0,
"Deleted subscription does not exist in the subscription list"
);
assert!(
api.get_subscription(&Client::new(), subscription.id + 1000)
.await
.is_err(),
"Deleted subscription cannot be looked up by ID"
);
}
_ => panic!(),
}
}
#[tokio::test(flavor = "current_thread")]
async fn get_entries() {
let api = test_setup_env();
let entries = api
.get_entries(&Client::new(), None, None, None, None, Some(true), true)
.await
.unwrap();
assert!(!entries.is_empty());
}
#[tokio::test(flavor = "current_thread")]
async fn http_cache() {
let api = test_setup_env();
let cache = match api
.get_subscriptions(&Client::new(), None, None, None)
.await
.unwrap()
{
CacheRequestResponse::Modified(CacheResult {
value: _subscriptions,
cache,
}) => cache,
CacheRequestResponse::NotModified => None,
};
if let CacheRequestResponse::Modified(_) = api
.get_subscriptions(&Client::new(), None, None, cache)
.await
.unwrap()
{
unreachable!()
}
}