Skip to content

Commit

Permalink
Currencies Endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
reubenwong97 committed Oct 20, 2023
1 parent 401a7d9 commit b640bb6
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ mod raw;
pub mod endpoint_prelude;

pub mod common;
pub mod currencies;
pub mod dividends;
pub mod eod;
pub mod paged;
Expand Down
112 changes: 112 additions & 0 deletions src/api/currencies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//! Implementation of the `currencies` API endpoint.
//!
//! This endpoint is used to lookup the currencies supported by Marketstack.

use derive_builder::Builder;

use crate::api::paged::PaginationError;
use crate::api::{endpoint_prelude::*, ApiError};

/// Query for `currencies`.
#[derive(Debug, Clone, Builder)]
#[builder(setter(strip_option))]
pub struct Currencies {
/// Pagination limit for API request.
#[builder(setter(name = "_limit"), default)]
limit: Option<PageLimit>,
/// Pagination offset value for API request.
#[builder(default)]
offset: Option<u64>,
}

impl Currencies {
/// Create a builder for this endpoint.
pub fn builder() -> CurrenciesBuilder {
CurrenciesBuilder::default()
}
}

impl CurrenciesBuilder {
/// Limit the number of results returned.
pub fn limit(&mut self, limit: u16) -> Result<&mut Self, ApiError<PaginationError>> {
let new = self;
new.limit = Some(Some(PageLimit::new(limit)?));
Ok(new)
}
}

impl<'a> Endpoint for Currencies {
fn method(&self) -> Method {
Method::GET
}

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

fn parameters(&self) -> QueryParams {
let mut params = QueryParams::default();

params
.push_opt("limit", self.limit.clone())
.push_opt("offset", self.offset);

params
}
}

#[cfg(test)]
mod tests {

use crate::api::currencies::Currencies;
use crate::api::{self, Query};
use crate::test::client::{ExpectedUrl, SingleTestClient};

#[test]
fn currencies_defaults_are_sufficient() {
Currencies::builder().build().unwrap();
}

#[test]
fn currencies_endpoint() {
let endpoint = ExpectedUrl::builder()
.endpoint("currencies")
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");

let endpoint = Currencies::builder().build().unwrap();
api::ignore(endpoint).query(&client).unwrap();
}

#[test]
fn currencies_limit() {
let endpoint = ExpectedUrl::builder()
.endpoint("currencies")
.add_query_params(&[("limit", "50")])
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");

let endpoint = Currencies::builder().limit(50).unwrap().build().unwrap();
api::ignore(endpoint).query(&client).unwrap();
}

#[test]
fn currencies_over_limit() {
assert!(Currencies::builder().limit(9999).is_err());
}

#[test]
fn currencies_offset() {
let endpoint = ExpectedUrl::builder()
.endpoint("currencies")
.add_query_params(&[("offset", "2")])
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");

let endpoint = Currencies::builder().offset(2).build().unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
}
57 changes: 56 additions & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,31 @@ pub struct DividendsData {
pub data: Vec<DividendsDataItem>,
}

/// Rust representation of single data item from Marketstack `currencies` response.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CurrenciesDataItem {
/// 3-letter code of the given currency.
pub code: String,
/// Name of the given currency.
pub name: String,
/// Text symbol of the given currency.
pub symbol: String,
}

/// Rust representation of the JSON response from `currencies` marketstack endpoint.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CurrenciesData {
/// Corresponds to pagination entry from JSON response from marketstack.
pub pagination: PaginationInfo,
/// Corresponds to data entry from JSON response from marketstack.
pub data: Vec<CurrenciesDataItem>,
}

#[cfg(test)]
mod tests {
use chrono::NaiveDate;

use crate::{DividendsData, EodData, SplitsData};
use crate::{CurrenciesData, DividendsData, EodData, SplitsData};

#[test]
fn test_deserialize_eod() {
Expand Down Expand Up @@ -243,4 +263,39 @@ mod tests {
NaiveDate::from_ymd_opt(2023, 8, 11).unwrap()
);
}

#[test]
fn test_deserialize_currencies() {
let json_data = r#"{
"pagination": {
"limit": 3,
"offset": 0,
"count": 3,
"total": 42
},
"data": [
{
"code": "USD",
"symbol": "$",
"name": "US Dollar"
},
{
"code": "ARS",
"symbol": "AR$",
"name": "Argentine Peso"
},
{
"code": "EUR",
"symbol": "€",
"name": "Euro"
}
]
}"#;

let currencies_data: CurrenciesData = serde_json::from_str(json_data).unwrap();
assert_eq!(currencies_data.pagination.limit, 3);
assert_eq!(currencies_data.data[0].code, "USD");
assert_eq!(currencies_data.data[0].symbol, "$");
assert_eq!(currencies_data.data[0].name, "US Dollar");
}
}
44 changes: 44 additions & 0 deletions tests/currencies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use marketstack::api::{currencies, AsyncQuery, Query};
use marketstack::{AsyncMarketstack, CurrenciesData, Marketstack};

mod setup;

#[test]
#[ignore]
fn test_currencies() {
let api_key = setup::setup_key();
let client = Marketstack::new_insecure("api.marketstack.com", api_key).unwrap();

let endpoint = currencies::Currencies::builder()
.limit(3)
.unwrap()
.build()
.unwrap();
let currencies_result: CurrenciesData = endpoint.query(&client).unwrap();

assert_eq!(currencies_result.pagination.limit, 3);
assert_eq!(currencies_result.pagination.offset, 0);

assert_eq!(currencies_result.data.len(), 3);
}

#[tokio::test]
#[ignore]
async fn test_async_currencies() {
let api_key = setup::setup_key();
let client = AsyncMarketstack::new_insecure("api.marketstack.com", api_key)
.await
.unwrap();

let endpoint = currencies::Currencies::builder()
.limit(3)
.unwrap()
.build()
.unwrap();
let currencies_result: CurrenciesData = endpoint.query_async(&client).await.unwrap();

assert_eq!(currencies_result.pagination.limit, 3);
assert_eq!(currencies_result.pagination.offset, 0);

assert_eq!(currencies_result.data.len(), 3);
}

0 comments on commit b640bb6

Please sign in to comment.