use std::{collections::HashMap, fmt::Display};
use derive_builder::Builder;
use serde_derive::{Deserialize, Serialize};
use serde_json::Value;
use crate::OpenlibraryRequest;
#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
#[serde(default)]
pub struct SearchResult {
pub num_found: u32,
pub start: u32,
pub num_found_exact: bool,
pub docs: Vec<HashMap<String, Value>>,
pub q: String,
}
#[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))]
pub(super) query: Option<String>,
pub(super) search_type: SearchType,
#[builder(default = "1")]
pub(super) page: u32,
#[builder(default = "10")]
pub(super) limit: u32,
#[builder(default = "vec![]")]
pub(super) fields: Vec<String>,
}
impl Search {
pub fn execute(&self) -> SearchResult {
let request = OpenlibraryRequest::search_request(self);
let response = request.execute().unwrap();
println!("{:#?}", response);
response.json().unwrap()
}
}
#[cfg(test)]
mod tests {
use mockito::mock;
use serde_json::json;
use crate::OpenlibraryRequest;
use super::SearchBuilder;
#[test]
fn test_search_execute_valid_response() {
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 request = OpenlibraryRequest::search_request(&search);
let endpoint = &request.url[request.url.find("/search").unwrap()..];
let _m = mock("GET", endpoint)
.with_header("content-type", "application/json")
.with_body(json.to_string())
.create();
let search_result = search.execute();
assert_eq!(search_result.num_found, 1);
assert_eq!(search_result.start, 0);
assert_eq!(search_result.num_found_exact, true);
assert_eq!(search_result.docs.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");
}
}