use crate::error::FaucetError;
use jsonpath_rust::JsonPath;
use serde_json::Value;
pub fn advance(
body: &Value,
next_link_path: &str,
next_link: &mut Option<String>,
) -> Result<bool, FaucetError> {
let results = body
.query(next_link_path)
.map_err(|e| FaucetError::JsonPath(format!("{e}")))?;
match results.first() {
Some(v) if !v.is_null() => {
let url = v.as_str().unwrap_or(&v.to_string()).to_string();
if url.is_empty() {
*next_link = None;
Ok(false)
} else {
*next_link = Some(url);
Ok(true)
}
}
_ => {
*next_link = None;
Ok(false)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn extracts_next_link_url() {
let body = json!({"results": [], "next_link": "https://api.example.com/workers?page=2"});
let mut next_link = None;
let has_next = advance(&body, "$.next_link", &mut next_link).unwrap();
assert!(has_next);
assert_eq!(
next_link,
Some("https://api.example.com/workers?page=2".into())
);
}
#[test]
fn stops_on_null() {
let body = json!({"results": [], "next_link": null});
let mut next_link = Some("stale".into());
let has_next = advance(&body, "$.next_link", &mut next_link).unwrap();
assert!(!has_next);
assert!(next_link.is_none());
}
#[test]
fn stops_when_field_absent() {
let body = json!({"results": []});
let mut next_link = None;
let has_next = advance(&body, "$.next_link", &mut next_link).unwrap();
assert!(!has_next);
assert!(next_link.is_none());
}
#[test]
fn stops_on_empty_string() {
let body = json!({"results": [], "next_link": ""});
let mut next_link = None;
let has_next = advance(&body, "$.next_link", &mut next_link).unwrap();
assert!(!has_next);
assert!(next_link.is_none());
}
}