use indoc::indoc;
use liwe::graph::Graph;
use liwe::model::config::MarkdownOptions;
use liwe::query::execute;
use liwe::query::prelude::{and, eq, exists, filter, find, gte, or};
use liwe::query::{
Filter, FindOp, Outcome, Projection, ProjectionField, ProjectionMode, ProjectionSource,
PseudoField, Sort,
};
use liwe::state::from_indoc;
use serde_yaml::{Mapping, Value};
fn run_find(docs: &str, op: FindOp) -> Vec<(String, Mapping)> {
let graph = Graph::import(&from_indoc(docs), MarkdownOptions::default(), None);
match execute(&find(op), &graph) {
Outcome::Find { matches } => matches
.into_iter()
.map(|m| (m.key.to_string(), m.document))
.collect(),
other => panic!("expected Find, got {:?}", other),
}
}
fn assert_keys(docs: &str, op: FindOp, expected: &[&str]) {
let actual: Vec<String> = run_find(docs, op).into_iter().map(|(k, _)| k).collect();
let expected: Vec<String> = expected.iter().map(|s| s.to_string()).collect();
assert_eq!(actual, expected);
}
#[test]
fn find_no_filter_returns_whole_corpus() {
assert_keys(
indoc! {"
# A
_
# B
_
# C
"},
FindOp::new(),
&["1", "2", "3"],
);
}
#[test]
fn find_filter_status_draft() {
assert_keys(
indoc! {"
---
status: draft
---
# A
_
---
status: published
---
# B
_
---
status: draft
---
# C
"},
filter(eq("status", "draft")),
&["1", "3"],
);
}
#[test]
fn find_filter_with_or_and_nested() {
assert_keys(
indoc! {"
---
modified: 2026-04-15
priority: 9
---
# A
_
---
modified: 2026-04-20
tags:
- urgent
---
# B
_
---
modified: 2026-03-15
priority: 9
---
# C
_
---
modified: 2026-04-15
priority: 5
---
# D
"},
filter(and(vec![
gte("modified", "2026-04-01"),
or(vec![gte("priority", 8i64), eq("tags", "urgent")]),
])),
&["1", "2"],
);
}
#[test]
fn find_projection_drops_unprojected_fields() {
let matches = run_find(
indoc! {"
---
title: Foo
author: dmytro
status: draft
---
# A
"},
filter::<FindOp>(Filter::all()).project(Projection::fields(&["title", "status"])),
);
assert_eq!(matches.len(), 1);
let doc = &matches[0].1;
assert!(doc.contains_key(Value::String("title".into())));
assert!(doc.contains_key(Value::String("status".into())));
assert!(!doc.contains_key(Value::String("author".into())));
}
fn projection(fields: &[(&str, ProjectionSource)], mode: ProjectionMode) -> Projection {
Projection {
fields: fields
.iter()
.map(|(name, src)| ProjectionField {
output: (*name).to_string(),
source: src.clone(),
})
.collect(),
mode,
}
}
#[test]
fn find_projection_pseudo_key_and_title() {
let matches = run_find(
indoc! {"
---
status: draft
---
# Doc One
"},
filter::<FindOp>(Filter::all()).project(projection(
&[
("k", ProjectionSource::Pseudo(PseudoField::Key)),
("t", ProjectionSource::Pseudo(PseudoField::Title)),
],
ProjectionMode::Replace,
)),
);
assert_eq!(matches.len(), 1);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("k".into())).and_then(|v| v.as_str()),
Some("1")
);
assert_eq!(
doc.get(Value::String("t".into())).and_then(|v| v.as_str()),
Some("Doc One")
);
assert!(!doc.contains_key(Value::String("status".into())));
}
#[test]
fn find_projection_title_slug() {
let matches = run_find(
indoc! {"
# My Cool Doc!
"},
filter::<FindOp>(Filter::all()).project(projection(
&[("slug", ProjectionSource::Pseudo(PseudoField::TitleSlug))],
ProjectionMode::Replace,
)),
);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("slug".into())).and_then(|v| v.as_str()),
Some("my-cool-doc")
);
}
#[test]
fn find_projection_content_returns_body() {
let matches = run_find(
indoc! {"
---
status: draft
---
# Title
Hello.
"},
filter::<FindOp>(Filter::all()).project(projection(
&[("body", ProjectionSource::Pseudo(PseudoField::Content))],
ProjectionMode::Replace,
)),
);
let doc = &matches[0].1;
let body = doc
.get(Value::String("body".into()))
.and_then(|v| v.as_str())
.unwrap_or("");
assert!(body.contains("# Title"));
assert!(body.contains("Hello."));
assert!(!body.contains("status"));
}
#[test]
fn find_projection_extend_keeps_defaults_and_appends() {
let matches = run_find(
indoc! {"
---
status: draft
---
# A
"},
filter::<FindOp>(Filter::all()).project(projection(
&[("body", ProjectionSource::Pseudo(PseudoField::Content))],
ProjectionMode::Extend,
)),
);
let doc = &matches[0].1;
assert!(doc.contains_key(Value::String("key".into())));
assert!(doc.contains_key(Value::String("title".into())));
assert!(doc.contains_key(Value::String("includedBy".into())));
assert!(doc.contains_key(Value::String("body".into())));
assert!(doc.contains_key(Value::String("status".into())));
}
#[test]
fn find_projection_alias_with_user_chosen_name() {
let matches = run_find(
indoc! {"
# Alpha
"},
filter::<FindOp>(Filter::all()).project(projection(
&[
("heading", ProjectionSource::Pseudo(PseudoField::Title)),
("ident", ProjectionSource::Pseudo(PseudoField::Key)),
],
ProjectionMode::Replace,
)),
);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("heading".into())).and_then(|v| v.as_str()),
Some("Alpha")
);
assert!(!doc.contains_key(Value::String("title".into())));
assert!(!doc.contains_key(Value::String("key".into())));
}
#[test]
fn find_sort_and_limit() {
assert_keys(
indoc! {"
---
modified: 2026-04-10
---
# A
_
---
modified: 2026-04-20
---
# B
_
---
modified: 2026-04-15
---
# C
"},
filter::<FindOp>(Filter::all())
.sort(Sort::desc("modified"))
.limit(2),
&["2", "3"],
);
}
#[test]
fn find_ties_broken_by_key_ascending() {
assert_keys(
indoc! {"
---
priority: 1
---
# First
_
---
priority: 1
---
# Second
_
---
priority: 1
---
# Third
"},
filter::<FindOp>(eq("priority", 1i64)).sort(Sort::asc("priority")),
&["1", "2", "3"],
);
}
#[test]
fn find_no_sort_with_filter_returns_keys_in_ascending_order() {
assert_keys(
indoc! {"
---
status: draft
---
# First
_
---
status: draft
---
# Second
_
---
status: draft
---
# Third
"},
filter(eq("status", "draft")),
&["1", "2", "3"],
);
}
#[test]
fn find_empty_corpus_returns_empty() {
let graph = Graph::import(
&std::collections::HashMap::new(),
MarkdownOptions::default(),
None,
);
match execute(&find(FindOp::new()), &graph) {
Outcome::Find { matches } => assert!(matches.is_empty()),
other => panic!("{:?}", other),
}
}
#[test]
fn find_doc_without_frontmatter_appears_as_empty_mapping() {
assert_keys(
indoc! {"
# A
_
---
status: draft
---
# B
"},
filter(exists("status", false)),
&["1"],
);
}
#[test]
fn find_projection_dotted_path_resolves_nested_fm() {
let matches = run_find(
indoc! {"
---
metadata:
priority: 5
---
# Doc One
"},
filter::<FindOp>(Filter::all()).project(projection(
&[(
"p",
ProjectionSource::Frontmatter(liwe::query::FieldPath::from_dotted("metadata.priority")),
)],
ProjectionMode::Replace,
)),
);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("p".into())).and_then(|v| v.as_i64()),
Some(5),
);
}
#[test]
fn find_projection_dotted_path_missing_intermediate_emits_null() {
let matches = run_find(
indoc! {"
---
other: 1
---
# Doc One
"},
filter::<FindOp>(Filter::all()).project(projection(
&[(
"p",
ProjectionSource::Frontmatter(liwe::query::FieldPath::from_dotted("metadata.priority")),
)],
ProjectionMode::Replace,
)),
);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("p".into())),
Some(&Value::Null),
);
}
#[test]
fn find_projection_pseudo_includes_emits_edge_refs() {
let matches = run_find(
indoc! {"
[B](2)
_
# B
"},
filter::<FindOp>(Filter::all()).project(projection(
&[
("k", ProjectionSource::Pseudo(PseudoField::Key)),
("inc", ProjectionSource::Pseudo(PseudoField::Includes)),
],
ProjectionMode::Replace,
)),
);
let parent = matches
.iter()
.find(|(k, _)| k == "1")
.expect("expected parent doc");
let inc = parent
.1
.get(Value::String("inc".into()))
.and_then(|v| v.as_sequence())
.expect("inc should be a sequence");
assert_eq!(inc.len(), 1);
let edge = inc[0].as_mapping().expect("edge should be a mapping");
assert_eq!(
edge.get(Value::String("key".into())).and_then(|v| v.as_str()),
Some("2"),
);
assert_eq!(
edge.get(Value::String("title".into())).and_then(|v| v.as_str()),
Some("B"),
);
assert!(
edge.get(Value::String("sectionPath".into())).is_some(),
"edge should have sectionPath key",
);
}
#[test]
fn find_projection_pseudo_referenced_by_emits_edge_refs() {
let matches = run_find(
indoc! {"
See [B](2).
_
# B
"},
filter::<FindOp>(Filter::all()).project(projection(
&[
("k", ProjectionSource::Pseudo(PseudoField::Key)),
("rb", ProjectionSource::Pseudo(PseudoField::ReferencedBy)),
],
ProjectionMode::Replace,
)),
);
let target = matches
.iter()
.find(|(k, _)| k == "2")
.expect("expected target doc");
let rb = target
.1
.get(Value::String("rb".into()))
.and_then(|v| v.as_sequence())
.expect("rb should be a sequence");
assert_eq!(rb.len(), 1);
let edge = rb[0].as_mapping().expect("edge should be a mapping");
assert_eq!(
edge.get(Value::String("key".into())).and_then(|v| v.as_str()),
Some("1"),
);
assert!(
edge.get(Value::String("sectionPath".into())).is_some(),
"edge should have sectionPath key",
);
}
#[test]
fn find_projection_pseudo_frontmatter_emits_full_object() {
let matches = run_find(
indoc! {"
---
status: draft
priority: 5
---
# Doc One
"},
filter::<FindOp>(Filter::all()).project(projection(
&[("fm", ProjectionSource::Pseudo(PseudoField::Frontmatter))],
ProjectionMode::Replace,
)),
);
let doc = &matches[0].1;
let fm = doc
.get(Value::String("fm".into()))
.and_then(|v| v.as_mapping())
.expect("fm should be a mapping");
assert_eq!(
fm.get(Value::String("status".into())).and_then(|v| v.as_str()),
Some("draft"),
);
assert_eq!(
fm.get(Value::String("priority".into())).and_then(|v| v.as_i64()),
Some(5),
);
}
#[test]
fn find_extend_user_fm_references_does_not_override_system() {
let matches = run_find(
indoc! {"
---
references:
- bogus-from-user
---
# Doc One
"},
filter::<FindOp>(Filter::all()).project(Projection::extend(vec![ProjectionField {
output: "note".to_string(),
source: ProjectionSource::Pseudo(PseudoField::Key),
}])),
);
let doc = &matches[0].1;
let refs = doc
.get(Value::String("references".into()))
.and_then(|v| v.as_sequence())
.expect("references should be present as a sequence");
assert!(
refs.is_empty(),
"system-synthesized references should win over user FM; got: {:?}",
refs,
);
}
#[test]
fn find_user_frontmatter_title_overrides_pseudo_title() {
let matches = run_find(
indoc! {"
---
title: FM Title
---
# H1 Heading
"},
filter::<FindOp>(Filter::all()).project(Projection::extend(vec![ProjectionField {
output: "note".to_string(),
source: ProjectionSource::Pseudo(PseudoField::Key),
}])),
);
assert_eq!(matches.len(), 1);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("title".into())).and_then(|v| v.as_str()),
Some("FM Title"),
);
}
#[test]
fn find_user_frontmatter_key_overrides_pseudo_key() {
let matches = run_find(
indoc! {"
---
key: user-supplied
---
# Heading
"},
filter::<FindOp>(Filter::all()).project(Projection::extend(vec![ProjectionField {
output: "note".to_string(),
source: ProjectionSource::Pseudo(PseudoField::Title),
}])),
);
assert_eq!(matches.len(), 1);
let doc = &matches[0].1;
assert_eq!(
doc.get(Value::String("key".into())).and_then(|v| v.as_str()),
Some("user-supplied"),
);
}