use std::num::NonZeroU64;
use serde_json::{Value, json};
use super::support::{Fixture, TestResult, patients, request, values};
const FOUR: NonZeroU64 = NonZeroU64::MIN.saturating_add(3);
#[test]
fn group_by_service_returns_three_wards_in_key_order_with_captured_origins() -> TestResult {
let documents = vec![
json!({"ward":"4B","name":"Ada"}),
json!({"ward":"3A","name":"Bea"}),
json!({"ward":"4B","name":"Cy"}),
json!({"ward":"5C","name":"Dee"}),
];
let fixture = Fixture::new(None, &documents)?;
let answer = fixture.run(&request("patients | group_by(.ward)", FOUR), &[])?;
assert_eq!(
values(&answer)?,
vec![
json!({"key":"3A","count":1,"values":[documents[1]]}),
json!({"key":"4B","count":2,"values":[documents[0], documents[2]]}),
json!({"key":"5C","count":1,"values":[documents[3]]}),
]
);
for row in answer
.get("rows")
.and_then(Value::as_array)
.ok_or("missing rows")?
{
let origin = row.get("origin").ok_or("missing origin")?;
assert_eq!(
origin.get("collection").ok_or("missing collection")?,
"patients"
);
assert_eq!(origin.get("id").ok_or("missing id")?, "");
assert_eq!(
origin.get("version").ok_or("missing version")?,
answer
.get("selection")
.and_then(|selection| selection.get("version"))
.ok_or("missing captured version")?
);
}
assert_eq!(
answer.get("stages").ok_or("missing stages")?,
&json!(["group_by"])
);
assert_eq!(answer.get("records_read").ok_or("missing scan count")?, 4);
assert!(answer.get("next").ok_or("missing next")?.is_null());
Ok(())
}
#[test]
fn group_by_service_missing_field_is_null_and_denied_members_are_excluded() -> TestResult {
let documents = vec![
json!({"name":"Ada"}),
json!({"ward":null}),
json!({"ward":"4B","name":"Cy"}),
];
let fixture = Fixture::new(None, &documents)?;
let answer = fixture.run(
&request("patients | group_by(.ward)", FOUR),
&[("patients", "p1")],
)?;
assert_eq!(
values(&answer)?,
vec![
json!({"key":null,"count":1,"values":[documents[0]]}),
json!({"key":"4B","count":1,"values":[documents[2]]}),
]
);
assert!(answer.get("next").ok_or("missing next")?.is_null());
Ok(())
}
#[test]
fn group_by_service_scan_limit_refusal_names_two() -> TestResult {
let mut fixture = Fixture::new(None, &patients())?;
fixture.scan(NonZeroU64::MIN.saturating_add(1));
let error = fixture
.run(&request("patients | group_by(.ward)", FOUR), &[])
.err()
.ok_or("incomplete group returned")?;
assert_eq!(error.code, "query_scan_limit");
assert_eq!(error.message, "records read exceed scan limit 2");
Ok(())
}
#[test]
fn group_by_service_small_page_refuses_instead_of_returning_next() -> TestResult {
let fixture = Fixture::new(None, &patients())?;
let error = fixture
.run(&request("patients | group_by(.ward)", NonZeroU64::MIN), &[])
.err()
.ok_or("partial grouped page accepted")?;
assert_eq!(error.code, "query_output_limit");
assert!(error.message.contains("larger page"), "{}", error.message);
Ok(())
}
#[test]
fn group_by_service_upstream_filters_and_downstream_count_keep_their_order() -> TestResult {
let fixture = Fixture::new(None, &patients())?;
let answer = fixture.run(
&request("patients(ward: \"4B\") | group_by(.ward) | count", FOUR),
&[],
)?;
assert_eq!(values(&answer)?, vec![json!(1)]);
assert_eq!(
answer.get("stages").ok_or("missing stages")?,
&json!(["filter", "group_by", "count"])
);
assert_eq!(answer.get("records_read").ok_or("missing scan count")?, 4);
assert!(answer.get("next").ok_or("missing next")?.is_null());
Ok(())
}