alpaca_data/news/
response.rs1use crate::{Error, transport::pagination::PaginatedResponse};
2
3use super::NewsItem;
4
5#[derive(Clone, Debug, Default, PartialEq, serde::Deserialize)]
6pub struct ListResponse {
7 pub news: Vec<NewsItem>,
8 pub next_page_token: Option<String>,
9}
10
11impl PaginatedResponse for ListResponse {
12 fn next_page_token(&self) -> Option<&str> {
13 self.next_page_token.as_deref()
14 }
15
16 fn merge_page(&mut self, mut next: Self) -> Result<(), Error> {
17 self.news.append(&mut next.news);
18 self.next_page_token = next.next_page_token;
19 Ok(())
20 }
21
22 fn clear_next_page_token(&mut self) {
23 self.next_page_token = None;
24 }
25}
26
27#[cfg(test)]
28mod tests {
29 use super::ListResponse;
30 use crate::transport::pagination::PaginatedResponse;
31
32 #[test]
33 fn list_response_deserializes_official_wrapper_shape() {
34 let response: ListResponse = serde_json::from_str(
35 r#"{"news":[{"id":24843171,"headline":"Apple headline","author":"Charles Gross","created_at":"2021-12-31T11:08:42Z","updated_at":"2021-12-31T11:08:43Z","summary":"Summary","content":"","url":"https://example.com/article","images":[{"size":"thumb","url":"https://example.com/image.jpg"}],"symbols":["AAPL"],"source":"benzinga"}],"next_page_token":"page-2"}"#,
36 )
37 .expect("response should deserialize");
38
39 assert_eq!(response.news.len(), 1);
40 assert_eq!(response.next_page_token.as_deref(), Some("page-2"));
41 }
42
43 #[test]
44 fn list_response_merge_appends_news_and_clears_next_page_token() {
45 let mut first: ListResponse = serde_json::from_str(
46 r#"{"news":[{"id":1,"headline":"First","author":"Author","created_at":"2026-04-01T00:00:00Z","updated_at":"2026-04-01T00:00:01Z","summary":"Summary","content":"","url":"https://example.com/1","images":[],"symbols":["AAPL"],"source":"benzinga"}],"next_page_token":"page-2"}"#,
47 )
48 .expect("first response should deserialize");
49 let second: ListResponse = serde_json::from_str(
50 r#"{"news":[{"id":2,"headline":"Second","author":"Author","created_at":"2026-04-02T00:00:00Z","updated_at":"2026-04-02T00:00:01Z","summary":"Summary","content":"","url":"https://example.com/2","images":[],"symbols":["MSFT"],"source":"benzinga"}],"next_page_token":null}"#,
51 )
52 .expect("second response should deserialize");
53
54 first
55 .merge_page(second)
56 .expect("merge should append later news page");
57 first.clear_next_page_token();
58
59 assert_eq!(first.news.len(), 2);
60 assert_eq!(first.next_page_token, None);
61 }
62}