use proptest::prelude::*;
use proptest::strategy::BoxedStrategy;
use crate::tests::property_tests::generators::directives::arb_const_directives;
use crate::tests::property_tests::generators::directives::arb_directives;
use crate::tests::property_tests::generators::names::arb_field_name;
use crate::tests::property_tests::generators::names::arb_fragment_name;
use crate::tests::property_tests::generators::names::arb_name;
use crate::tests::property_tests::generators::names::arb_type_name;
use crate::tests::property_tests::generators::selections::arb_selection_set;
use crate::tests::property_tests::generators::type_annotations::arb_type_annotation;
use crate::tests::property_tests::generators::values::arb_const_value;
use crate::tests::property_tests::generators::whitespace::arb_separator;
use crate::tests::property_tests::generators::whitespace::join_items;
pub fn arb_operation_definition(depth: usize) -> BoxedStrategy<String> {
prop_oneof![
3 => arb_named_operation(depth),
1 => arb_shorthand_query(depth),
]
.boxed()
}
fn arb_named_operation(depth: usize) -> BoxedStrategy<String> {
(
arb_operation_type(),
prop::option::weighted(0.8, arb_name()),
prop::option::weighted(0.4, arb_variable_definitions()),
arb_directives(depth.min(1)),
arb_selection_set(depth),
)
.prop_map(|(op_type, name, vars, dirs, sel_set)| {
let name_str = name.map_or(String::new(), |n| format!(" {n}"));
let vars_str = vars.map_or(String::new(), |v| format!("({v})"));
format!("{op_type}{name_str}{vars_str}{dirs} {sel_set}")
})
.boxed()
}
fn arb_shorthand_query(depth: usize) -> BoxedStrategy<String> {
arb_selection_set(depth)
}
fn arb_operation_type() -> BoxedStrategy<String> {
prop_oneof![
3 => Just("query".to_string()),
1 => Just("mutation".to_string()),
1 => Just("subscription".to_string()),
]
.boxed()
}
fn arb_variable_definitions() -> BoxedStrategy<String> {
prop::collection::vec((arb_variable_definition(), arb_separator()), 1..4)
.prop_map(|pairs| join_items(&pairs))
.boxed()
}
fn arb_variable_definition() -> BoxedStrategy<String> {
(
arb_field_name(),
arb_type_annotation(2),
prop::option::weighted(0.3, arb_const_value(1)),
arb_const_directives(0),
)
.prop_map(|(name, ty, default, dirs)| {
let default_str = default.map_or(String::new(), |d| format!(" = {d}"));
format!("${name}: {ty}{default_str}{dirs}")
})
.boxed()
}
pub fn arb_fragment_definition(depth: usize) -> BoxedStrategy<String> {
(
arb_fragment_name(),
arb_type_name(),
arb_directives(depth.min(1)),
arb_selection_set(depth),
)
.prop_map(|(name, type_cond, dirs, sel_set)| {
format!("fragment {name} on {type_cond}{dirs} {sel_set}")
})
.boxed()
}
pub fn arb_executable_definition(depth: usize) -> BoxedStrategy<String> {
prop_oneof![
3 => arb_operation_definition(depth),
1 => arb_fragment_definition(depth),
]
.boxed()
}
pub fn arb_named_executable_definition(depth: usize) -> BoxedStrategy<String> {
prop_oneof![
3 => arb_named_operation(depth),
1 => arb_fragment_definition(depth),
]
.boxed()
}