-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* remove unused basic endpoint * add implementation for splits endpoint TODO: add unit tests * add unit tests for splits endpoint * add splits types and corresponding unit tests for deserialization * complete splits endpoint implementation
- Loading branch information
1 parent
219ccdc
commit 07db997
Showing
7 changed files
with
401 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
//! Implemented endpoints for `splits` | ||
|
||
use std::collections::BTreeSet; | ||
|
||
use chrono::NaiveDate; | ||
use derive_builder::Builder; | ||
|
||
use crate::api::common::SortOrder; | ||
use crate::api::paged::PaginationError; | ||
use crate::api::{endpoint_prelude::*, ApiError}; | ||
|
||
/// Query for `splits`. | ||
#[derive(Debug, Builder, Clone)] | ||
#[builder(setter(strip_option))] | ||
pub struct Splits<'a> { | ||
/// Search for `splits` for a symbol. | ||
#[builder(setter(name = "_symbols"), default)] | ||
symbols: BTreeSet<Cow<'a, str>>, | ||
/// The sort order for the return results. | ||
#[builder(default)] | ||
sort: Option<SortOrder>, | ||
/// Date to query EOD data from. | ||
#[builder(default)] | ||
date_from: Option<NaiveDate>, | ||
/// Date to query EOD date to. | ||
#[builder(default)] | ||
date_to: Option<NaiveDate>, | ||
/// 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<'a> Splits<'a> { | ||
/// Create a bulder for this endpoint. | ||
pub fn builder() -> SplitsBuilder<'a> { | ||
SplitsBuilder::default() | ||
} | ||
} | ||
|
||
impl<'a> SplitsBuilder<'a> { | ||
/// Search the given symbol. | ||
/// | ||
/// This provides sane defaults for the user to call symbol() | ||
/// on the builder without needing to wrap his symbol in a | ||
/// BTreeSet beforehand. | ||
pub fn symbol(&mut self, symbol: &'a str) -> &mut Self { | ||
self.symbols | ||
.get_or_insert_with(BTreeSet::new) | ||
.insert(symbol.into()); | ||
self | ||
} | ||
|
||
/// Search the given symbols. | ||
pub fn symbols<I, V>(&mut self, iter: I) -> &mut Self | ||
where | ||
I: Iterator<Item = V>, | ||
V: Into<Cow<'a, str>>, | ||
{ | ||
self.symbols | ||
.get_or_insert_with(BTreeSet::new) | ||
.extend(iter.map(|v| v.into())); | ||
self | ||
} | ||
|
||
/// 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 Splits<'a> { | ||
fn method(&self) -> Method { | ||
Method::GET | ||
} | ||
|
||
fn endpoint(&self) -> Cow<'static, str> { | ||
"splits".into() | ||
} | ||
|
||
fn parameters(&self) -> QueryParams { | ||
let mut params = QueryParams::default(); | ||
|
||
params | ||
.extend(self.symbols.iter().map(|value| ("symbols", value))) | ||
.push_opt("sort", self.sort) | ||
.push_opt("date_from", self.date_from) | ||
.push_opt("date_to", self.date_to) | ||
.push_opt("limit", self.limit.clone()) | ||
.push_opt("offset", self.offset); | ||
|
||
params | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
||
use chrono::NaiveDate; | ||
|
||
use crate::api::common::SortOrder; | ||
use crate::api::splits::Splits; | ||
use crate::api::{self, Query}; | ||
use crate::test::client::{ExpectedUrl, SingleTestClient}; | ||
|
||
#[test] | ||
fn splits_defaults_are_sufficient() { | ||
Splits::builder().build().unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_endpoint() { | ||
let endpoint = ExpectedUrl::builder().endpoint("splits").build().unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder().build().unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_symbol() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("symbols", "AAPL")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder().symbol("AAPL").build().unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_symbols() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("symbols", "AAPL"), ("symbols", "GOOG")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder() | ||
.symbol("AAPL") | ||
.symbols(["AAPL", "GOOG"].iter().copied()) | ||
.build() | ||
.unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_sort() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("sort", "ASC")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder() | ||
.sort(SortOrder::Ascending) | ||
.build() | ||
.unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_date_from() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("date_from", "2020-01-01")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder() | ||
.date_from(NaiveDate::from_ymd_opt(2020, 1, 1).unwrap()) | ||
.build() | ||
.unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_date_to() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("date_to", "2020-01-01")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder() | ||
.date_to(NaiveDate::from_ymd_opt(2020, 1, 1).unwrap()) | ||
.build() | ||
.unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_limit() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("limit", "50")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder().limit(50).unwrap().build().unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
|
||
#[test] | ||
fn splits_over_limit() { | ||
assert!(Splits::builder().limit(9999).is_err()); | ||
} | ||
|
||
#[test] | ||
fn splits_offset() { | ||
let endpoint = ExpectedUrl::builder() | ||
.endpoint("splits") | ||
.add_query_params(&[("offset", "2")]) | ||
.build() | ||
.unwrap(); | ||
let client = SingleTestClient::new_raw(endpoint, ""); | ||
|
||
let endpoint = Splits::builder().offset(2).build().unwrap(); | ||
api::ignore(endpoint).query(&client).unwrap(); | ||
} | ||
} |
Oops, something went wrong.