use std::fmt::Display;
use derive_builder::Builder;
use crate::OpenlibraryRequest;
#[derive(Default, Clone, Debug)]
pub enum SearchType {
#[default]
Books,
Authors,
Subjects,
Lists,
}
impl Display for SearchType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Books => "",
Self::Authors => "/authors",
Self::Subjects => "/subjects",
Self::Lists => "/lists",
}
)
}
}
#[derive(Builder, Default, Debug)]
#[builder(setter(into), default)]
pub struct Search {
#[builder(setter(strip_option))]
query: Option<String>,
search_type: SearchType,
#[builder(default = "1")]
page: u32,
#[builder(default = "10")]
limit: u32,
#[builder(default = "vec![]")]
fields: Vec<String>,
}
impl OpenlibraryRequest for Search {
fn path(&self) -> String {
format!("/search{}.json", self.search_type)
}
fn query(&self) -> Vec<(&'static str, String)> {
vec![
("page", self.page.to_string()),
("limit", self.limit.to_string()),
("q", self.query.as_deref().unwrap_or_default().to_string()),
("fields", self.fields.join(",")),
]
}
}
#[cfg(test)]
mod tests {
use mockito::mock;
use serde_json::json;
use crate::OpenlibraryRequest;
use super::SearchBuilder;
#[test]
fn test_search_execute() {
let search = SearchBuilder::default()
.query("test")
.fields(
["key", "title"]
.into_iter()
.map(String::from)
.collect::<Vec<String>>(),
)
.build()
.unwrap();
let json = json!({
"numFound": 1,
"start": 0,
"numFoundExact": true,
"docs": [
{
"key": "/works/43242",
"title": "test",
}
]
});
let _m = mock(
"GET",
format!("{}?{}", search.url().path(), search.url().query().unwrap()).as_str(),
)
.with_header("content-type", "application/json")
.with_body(json.to_string())
.create();
let search_result = search.execute();
assert_eq!(search_result["numFound"], 1);
assert_eq!(search_result["start"], 0);
assert_eq!(search_result["numFoundExact"], true);
assert_eq!(search_result["docs"].as_array().unwrap().len(), 1);
let doc = &search_result["docs"][0];
assert_eq!(doc.get("key").unwrap().as_str().unwrap(), "/works/43242");
assert_eq!(doc.get("title").unwrap().as_str().unwrap(), "test");
}
}