use crate::{Error, transport::pagination::PaginatedResponse};
use super::CorporateActions;
#[derive(Clone, Debug, Default, PartialEq, serde::Deserialize)]
pub struct ListResponse {
pub corporate_actions: CorporateActions,
pub next_page_token: Option<String>,
}
impl PaginatedResponse for ListResponse {
fn next_page_token(&self) -> Option<&str> {
self.next_page_token.as_deref()
}
fn merge_page(&mut self, next: Self) -> Result<(), Error> {
self.corporate_actions.merge(next.corporate_actions);
self.next_page_token = next.next_page_token;
Ok(())
}
fn clear_next_page_token(&mut self) {
self.next_page_token = None;
}
}
#[cfg(test)]
mod tests {
use super::ListResponse;
use crate::transport::pagination::PaginatedResponse;
#[test]
fn list_response_deserializes_official_bucketed_wrapper_shape() {
let response: ListResponse = serde_json::from_str(
r#"{"corporate_actions":{"cash_dividends":[{"id":"e2b597ca-c2cb-47af-9315-cafb8708766d","symbol":"640CVR031","cusip":"640CVR031","rate":0.055284,"special":false,"foreign":false,"process_date":"2024-08-14","ex_date":"2024-08-07","record_date":"2024-08-07","payable_date":"2024-08-15"}],"name_changes":[{"id":"564620f3-dac4-4558-a227-5c8dd6f4d82e","old_symbol":"007975113","old_cusip":"007975113","new_symbol":"22112H119","new_cusip":"22112H119","process_date":"2024-08-13"}],"contract_adjustments":[{"id":"ca-undocumented","memo":"undocumented family"}],"mystery_bucket":[{"id":"mystery-1","field":"value"}]},"next_page_token":"page-2"}"#,
)
.expect("response should deserialize");
assert_eq!(response.corporate_actions.cash_dividends.len(), 1);
assert_eq!(response.corporate_actions.name_changes.len(), 1);
assert_eq!(response.corporate_actions.contract_adjustments.len(), 1);
assert_eq!(
response
.corporate_actions
.other
.get("mystery_bucket")
.map(Vec::len),
Some(1)
);
assert_eq!(response.next_page_token.as_deref(), Some("page-2"));
}
#[test]
fn list_response_merge_appends_bucketed_pages_and_clears_next_page_token() {
let mut first: ListResponse = serde_json::from_str(
r#"{"corporate_actions":{"cash_dividends":[{"id":"ca-1","symbol":"AAA","cusip":"111111111","rate":0.1,"special":false,"foreign":false,"process_date":"2024-08-01","ex_date":"2024-08-01"}],"contract_adjustments":[{"id":"undoc-1"}],"mystery_bucket":[{"id":"mystery-1"}]},"next_page_token":"page-2"}"#,
)
.expect("first response should deserialize");
let second: ListResponse = serde_json::from_str(
r#"{"corporate_actions":{"cash_dividends":[{"id":"ca-2","symbol":"BBB","cusip":"222222222","rate":0.2,"special":false,"foreign":false,"process_date":"2024-08-02","ex_date":"2024-08-02"}],"name_changes":[{"id":"name-1","old_symbol":"OLD","old_cusip":"333333333","new_symbol":"NEW","new_cusip":"444444444","process_date":"2024-08-02"}],"contract_adjustments":[{"id":"undoc-2"}],"mystery_bucket":[{"id":"mystery-2"}]},"next_page_token":null}"#,
)
.expect("second response should deserialize");
first
.merge_page(second)
.expect("merge should append bucketed corporate action pages");
first.clear_next_page_token();
assert_eq!(first.corporate_actions.cash_dividends.len(), 2);
assert_eq!(first.corporate_actions.name_changes.len(), 1);
assert_eq!(first.corporate_actions.contract_adjustments.len(), 2);
assert_eq!(
first
.corporate_actions
.other
.get("mystery_bucket")
.map(Vec::len),
Some(2)
);
assert_eq!(first.next_page_token, None);
}
}