aboutsummaryrefslogtreecommitdiff
path: root/src/models/search.rs
diff options
context:
space:
mode:
authorGravatar Mark Cola <mark@doomsdaytuna.com> 2023-01-24 02:47:36 +1100
committerGravatar GitHub <noreply@github.com> 2023-01-23 07:47:36 -0800
commit97764fb864ae1ab6046749fe5cabe00f508b0c61 (patch)
tree918d00dae06f27bcce7f78f40c13f35cf64e10e3 /src/models/search.rs
parent75a1b4154636de1f3d563cebe4be0627e4b28774 (diff)
downloadnotion-97764fb864ae1ab6046749fe5cabe00f508b0c61.tar.gz
notion-97764fb864ae1ab6046749fe5cabe00f508b0c61.tar.zst
notion-97764fb864ae1ab6046749fe5cabe00f508b0c61.zip
move And and Or variants to FilterCondition to support recursive nesting (#52)
Diffstat (limited to '')
-rw-r--r--src/models/search.rs98
1 files changed, 84 insertions, 14 deletions
diff --git a/src/models/search.rs b/src/models/search.rs
index 5b2b928..c9e7e91 100644
--- a/src/models/search.rs
+++ b/src/models/search.rs
@@ -257,17 +257,20 @@ pub enum PropertyCondition {
Files(FilesCondition),
Relation(RelationCondition),
Formula(FormulaCondition),
- /// Returns pages when **any** of the filters inside the provided vector match.
- Or(Vec<PropertyCondition>),
- /// Returns pages when **all** of the filters inside the provided vector match.
- And(Vec<PropertyCondition>),
}
#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
-pub struct FilterCondition {
- pub property: String,
- #[serde(flatten)]
- pub condition: PropertyCondition,
+#[serde(untagged)]
+pub enum FilterCondition {
+ Property {
+ property: String,
+ #[serde(flatten)]
+ condition: PropertyCondition,
+ },
+ /// Returns pages when **all** of the filters inside the provided vector match.
+ And { and: Vec<FilterCondition> },
+ /// Returns pages when **any** of the filters inside the provided vector match.
+ Or { or: Vec<FilterCondition> },
}
#[derive(Serialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
@@ -376,13 +379,15 @@ impl From<NotionSearch> for SearchRequest {
#[cfg(test)]
mod tests {
mod text_filters {
- use crate::models::search::PropertyCondition::RichText;
- use crate::models::search::{FilterCondition, TextCondition};
+ use crate::models::search::PropertyCondition::{Checkbox, Number, RichText, Select};
+ use crate::models::search::{
+ CheckboxCondition, FilterCondition, NumberCondition, SelectCondition, TextCondition,
+ };
use serde_json::json;
#[test]
fn text_property_equals() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_value(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition::Property {
property: "Name".to_string(),
condition: RichText(TextCondition::Equals("Test".to_string())),
})?;
@@ -396,7 +401,7 @@ mod tests {
#[test]
fn text_property_contains() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_value(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition::Property {
property: "Name".to_string(),
condition: RichText(TextCondition::Contains("Test".to_string())),
})?;
@@ -410,7 +415,7 @@ mod tests {
#[test]
fn text_property_is_empty() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_value(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition::Property {
property: "Name".to_string(),
condition: RichText(TextCondition::IsEmpty),
})?;
@@ -424,7 +429,7 @@ mod tests {
#[test]
fn text_property_is_not_empty() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_value(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition::Property {
property: "Name".to_string(),
condition: RichText(TextCondition::IsNotEmpty),
})?;
@@ -435,5 +440,70 @@ mod tests {
Ok(())
}
+
+ #[test]
+ fn compound_query_and() -> Result<(), Box<dyn std::error::Error>> {
+ let json = serde_json::to_value(&FilterCondition::And {
+ and: vec![
+ FilterCondition::Property {
+ property: "Seen".to_string(),
+ condition: Checkbox(CheckboxCondition::Equals(false)),
+ },
+ FilterCondition::Property {
+ property: "Yearly visitor count".to_string(),
+ condition: Number(NumberCondition::GreaterThan(serde_json::Number::from(
+ 1000000,
+ ))),
+ },
+ ],
+ })?;
+ assert_eq!(
+ dbg!(json),
+ json!({"and":[
+ {"property":"Seen","checkbox":{"equals":false}},
+ {"property":"Yearly visitor count","number":{"greater_than":1000000}}
+ ]})
+ );
+
+ Ok(())
+ }
+
+ #[test]
+ fn compound_query_or() -> Result<(), Box<dyn std::error::Error>> {
+ let json = serde_json::to_value(&FilterCondition::Or {
+ or: vec![
+ FilterCondition::Property {
+ property: "Description".to_string(),
+ condition: RichText(TextCondition::Contains("fish".to_string())),
+ },
+ FilterCondition::And {
+ and: vec![
+ FilterCondition::Property {
+ property: "Food group".to_string(),
+ condition: Select(SelectCondition::Equals(
+ "🥦Vegetable".to_string(),
+ )),
+ },
+ FilterCondition::Property {
+ property: "Is protein rich?".to_string(),
+ condition: Checkbox(CheckboxCondition::Equals(true)),
+ },
+ ],
+ },
+ ],
+ })?;
+ assert_eq!(
+ dbg!(json),
+ json!({"or":[
+ {"property":"Description","rich_text":{"contains":"fish"}},
+ {"and":[
+ {"property":"Food group","select":{"equals":"🥦Vegetable"}},
+ {"property":"Is protein rich?","checkbox":{"equals":true}}
+ ]}
+ ]})
+ );
+
+ Ok(())
+ }
}
}