Skip to content

Commit

Permalink
add tests for lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
reubenwong97 committed Oct 3, 2023
1 parent 822b9d5 commit b853e3c
Show file tree
Hide file tree
Showing 9 changed files with 589 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ chrono = { version = "0.4.31", default-features = false, features = [
futures-util = "0.3.28"
itertools = "0.11.0"
reqwest = { version = "~0.11.20", features = ["blocking", "json"] }
log = "~0.4.20"

[dev-dependencies]
dotenvy = "0.15.7"
Expand Down
1 change: 1 addition & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// This file may not be copied, modified, or distributed
// except according to those terms.

mod auth;
mod client;
mod endpoint;
mod error;
Expand Down
14 changes: 14 additions & 0 deletions src/api/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed under the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

use crate::api::endpoint_prelude::*;
use crate::auth::Auth;

/// A `auth` modifier that can be applied to any endpoint.
#[derive(Clone)]
pub struct AuthContext {
/// The auth token to use for the endpoint.
token: Auth,
}
3 changes: 1 addition & 2 deletions src/api/eod/eod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,12 @@ impl<'a> Pageable for Eod<'a> {

#[cfg(test)]
mod tests {
use std::borrow::BorrowMut;

use chrono::NaiveDate;

use crate::api::common::SortOrder;
use crate::api::eod::Eod;
use crate::api::{self, endpoint_prelude, Query};
use crate::api::{self, Query};
use crate::test::client::{ExpectedUrl, SingleTestClient};

#[test]
Expand Down
206 changes: 205 additions & 1 deletion src/api/paged/all_at_once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ where
url
};

let mut page_num = 1;
let mut page_num = 0;
let per_page = self.pagination.page_limit();
let per_page_str = per_page.to_string();

Expand Down Expand Up @@ -142,3 +142,207 @@ where
Ok(std::mem::take(&mut locked_results))
}
}

#[cfg(test)]
mod tests {
use http::StatusCode;
use serde::{Deserialize, Serialize};
use serde_json::json;

use crate::api::endpoint_prelude::*;
use crate::api::{self, ApiError, AsyncQuery, Pagination, Query};
use crate::test::client::{ExpectedUrl, PagedTestClient, SingleTestClient};

#[derive(Debug, Default)]
struct Dummy {
with_keyset: bool,
}

impl Endpoint for Dummy {
fn method(&self) -> Method {
Method::GET
}

fn endpoint(&self) -> Cow<'static, str> {
"paged_dummy".into()
}
}

impl Pageable for Dummy {
fn use_keyset_pagination(&self) -> bool {
self.with_keyset
}
}

#[derive(Debug, Deserialize, Serialize)]
struct DummyResult {
value: u8,
}

#[test]
fn test_marketstack_non_json_response() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.add_query_params(&[("limit", "1000"), ("offset", "0")])
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "not json");
let endpoint = Dummy::default();

let res: Result<Vec<DummyResult>, _> = api::paged(endpoint, Pagination::All).query(&client);
let err = res.unwrap_err();
if let ApiError::MarketstackService { status, .. } = err {
assert_eq!(status, http::StatusCode::OK);
} else {
panic!("unexpected error: {}", err);
}
}

#[test]
fn test_marketstack_error_bad_json() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.add_query_params(&[("offset", "0"), ("limit", "1000")])
.status(StatusCode::NOT_FOUND)
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Dummy::default();

let res: Result<Vec<DummyResult>, _> = api::paged(endpoint, Pagination::All).query(&client);
let err = res.unwrap_err();
if let ApiError::MarketstackService { status, .. } = err {
assert_eq!(status, http::StatusCode::NOT_FOUND);
} else {
panic!("unexpected error: {}", err);
}
}

#[test]
fn test_marketstack_error_detection() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.add_query_params(&[("offset", "0"), ("limit", "1000")])
.status(StatusCode::NOT_FOUND)
.build()
.unwrap();
let client = SingleTestClient::new_json(
endpoint,
&json!({
"message": "dummy error message"
}),
);
let endpoint = Dummy::default();

let res: Result<Vec<DummyResult>, _> = api::paged(endpoint, Pagination::All).query(&client);
let err = res.unwrap_err();
if let ApiError::Marketstack { msg } = err {
assert_eq!(msg, "dummy error message");
} else {
panic!("unexpected error: {}", err);
}
}

#[test]
fn test_marketstack_error_detection_unknown() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.add_query_params(&[("limit", "1000"), ("offset", "0")])
.status(StatusCode::NOT_FOUND)
.build()
.unwrap();
let err_obj = json!({
"bogus": "dummy error message"
});
let client = SingleTestClient::new_json(endpoint, &err_obj);
let endpoint = Dummy::default();

let res: Result<Vec<DummyResult>, _> = api::paged(endpoint, Pagination::All).query(&client);
let err = res.unwrap_err();
if let ApiError::MarketstackUnrecognized { obj } = err {
assert_eq!(obj, err_obj);
} else {
panic!("unexpected error: {}", err);
}
}

#[test]
fn test_pagination_limit() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.paginated(true)
.build()
.unwrap();
let client =
PagedTestClient::new_raw(endpoint, (0..=255).map(|value| DummyResult { value }));
let query = Dummy { with_keyset: false };

let res: Vec<DummyResult> = api::paged(query, Pagination::Limit(25))
.query(&client)
.unwrap();
assert_eq!(res.len(), 25);
for (i, value) in res.iter().enumerate() {
assert_eq!(value.value, i as u8);
}
}

#[tokio::test]
async fn test_pagination_limit_async() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.paginated(true)
.build()
.unwrap();
let client =
PagedTestClient::new_raw(endpoint, (0..=255).map(|value| DummyResult { value }));
let query = Dummy { with_keyset: false };

let res: Vec<DummyResult> = api::paged(query, Pagination::Limit(25))
.query_async(&client)
.await
.unwrap();
assert_eq!(res.len(), 25);
for (i, value) in res.iter().enumerate() {
assert_eq!(value.value, i as u8);
}
}

#[test]
fn test_pagination_all() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.paginated(true)
.build()
.unwrap();
let client =
PagedTestClient::new_raw(endpoint, (0..=255).map(|value| DummyResult { value }));
let query = Dummy::default();

let res: Vec<DummyResult> = api::paged(query, Pagination::All).query(&client).unwrap();
assert_eq!(res.len(), 256);
for (i, value) in res.iter().enumerate() {
assert_eq!(value.value, i as u8);
}
}

#[tokio::test]
async fn test_pagination_all_async() {
let endpoint = ExpectedUrl::builder()
.endpoint("paged_dummy")
.paginated(true)
.build()
.unwrap();
let client =
PagedTestClient::new_raw(endpoint, (0..=255).map(|value| DummyResult { value }));
let query = Dummy::default();

let res: Vec<DummyResult> = api::paged(query, Pagination::All)
.query_async(&client)
.await
.unwrap();
assert_eq!(res.len(), 256);
for (i, value) in res.iter().enumerate() {
assert_eq!(value.value, i as u8);
}
}
}
Loading

0 comments on commit b853e3c

Please sign in to comment.