use super::config::{
Configuration, Endpoint, EndpointClass, GraphqlType, Relationship, Type, TypeDef,
};
use super::objects::Node;
use crate::engine::context::RequestContext;
use crate::error::Error;
use inflector::Inflector;
use juniper::RootNode;
use maplit::hashmap;
use serde::{Deserialize, Serialize};
use std::collections::hash_map::Values;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::panic::catch_unwind;
use std::slice::Iter;
use std::sync::Arc;
#[derive(Clone, Debug, PartialEq)]
pub struct Info {
pub(crate) name: String,
type_defs: Arc<HashMap<String, NodeType>>,
}
impl Info {
pub(crate) fn new(name: String, type_defs: Arc<HashMap<String, NodeType>>) -> Info {
Info { name, type_defs }
}
pub(crate) fn name(&self) -> &str {
&self.name
}
pub(crate) fn type_def(&self) -> Result<&NodeType, Error> {
self.type_def_by_name(&self.name)
}
pub(crate) fn type_def_by_name(&self, name: &str) -> Result<&NodeType, Error> {
self.type_defs
.get(name)
.ok_or_else(|| Error::SchemaItemNotFound {
name: self.name.to_string(),
})
}
pub(crate) fn type_defs(&self) -> Arc<HashMap<String, NodeType>> {
self.type_defs.clone()
}
}
pub(super) type RootRef<RequestCtx> =
Arc<RootNode<'static, Node<RequestCtx>, Node<RequestCtx>, Node<RequestCtx>>>;
#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub(crate) enum ArgumentKind {
Required,
Optional,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub(crate) enum PropertyKind {
CustomResolver,
DynamicScalar,
DynamicRel { rel_name: String },
Input,
NodeCreateMutation,
NodeUpdateMutation,
NodeDeleteMutation { label: String },
Object,
Rel { rel_name: String },
RelCreateMutation { src_label: String, rel_name: String },
RelUpdateMutation { src_label: String, rel_name: String },
RelDeleteMutation { src_label: String, rel_name: String },
Scalar,
ScalarComp,
Union,
VersionQuery,
}
#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub(crate) enum TypeKind {
Input,
Object,
Rel,
Union,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct NodeType {
props: HashMap<String, Property>,
type_kind: TypeKind,
type_name: String,
union_types: Option<Vec<String>>,
}
impl NodeType {
fn new(type_name: String, type_kind: TypeKind, props: HashMap<String, Property>) -> NodeType {
NodeType {
props,
type_kind,
type_name,
union_types: None,
}
}
pub(crate) fn property(&self, property_name: &str) -> Result<&Property, Error> {
self.props
.get(property_name)
.ok_or_else(|| Error::SchemaItemNotFound {
name: self.type_name.to_string() + "::" + property_name,
})
}
pub(crate) fn props(&self) -> Values<String, Property> {
self.props.values()
}
pub(crate) fn type_kind(&self) -> &TypeKind {
&self.type_kind
}
pub(crate) fn type_name(&self) -> &str {
&self.type_name
}
pub(crate) fn union_types(&self) -> Option<Iter<String>> {
self.union_types.as_ref().map(|uts| uts.iter())
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub(crate) struct Property {
name: String,
kind: PropertyKind,
type_name: String,
hidden: bool,
required: bool,
list: bool,
arguments: HashMap<String, Argument>,
resolver: Option<String>,
validator: Option<String>,
}
impl Property {
fn new(name: String, kind: PropertyKind, type_name: String) -> Property {
Property {
name,
kind,
type_name,
hidden: false,
required: false,
list: false,
arguments: HashMap::new(),
resolver: None,
validator: None,
}
}
pub(crate) fn arguments(&self) -> Values<String, Argument> {
self.arguments.values()
}
pub(crate) fn input_type_definition<'i>(&self, info: &'i Info) -> Result<&'i NodeType, Error> {
self.arguments
.get("input")
.ok_or_else(|| Error::SchemaItemNotFound {
name: "input".to_string(),
})
.and_then(|input_arg| {
info.type_defs
.get(&input_arg.type_name)
.ok_or_else(|| Error::SchemaItemNotFound {
name: input_arg.type_name.to_string(),
})
})
}
pub(crate) fn hidden(&self) -> bool {
self.hidden
}
pub(crate) fn kind(&self) -> &PropertyKind {
&self.kind
}
pub(crate) fn list(&self) -> bool {
self.list
}
pub(crate) fn name(&self) -> &str {
&self.name
}
pub(crate) fn resolver(&self) -> Option<&String> {
self.resolver.as_ref()
}
pub(crate) fn required(&self) -> bool {
self.required
}
pub(crate) fn type_name(&self) -> &str {
&self.type_name
}
pub(crate) fn validator(&self) -> Option<&String> {
self.validator.as_ref()
}
fn with_arguments(mut self, arguments: HashMap<String, Argument>) -> Self {
self.arguments = arguments;
self
}
fn with_hidden(mut self, hidden: bool) -> Self {
self.hidden = hidden;
self
}
fn with_list(mut self, list: bool) -> Self {
self.list = list;
self
}
fn with_required(mut self, required: bool) -> Self {
self.required = required;
self
}
fn with_resolver(mut self, resolver: &str) -> Self {
self.resolver = Some(resolver.to_string());
self
}
fn with_validator(mut self, validator: Option<String>) -> Self {
self.validator = validator;
self
}
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub(crate) struct Argument {
name: String,
kind: ArgumentKind,
type_name: String,
}
impl Argument {
fn new(name: String, kind: ArgumentKind, type_name: String) -> Argument {
Argument {
name,
kind,
type_name,
}
}
pub(crate) fn kind(&self) -> &ArgumentKind {
&self.kind
}
pub(crate) fn name(&self) -> &str {
&self.name
}
pub(crate) fn type_name(&self) -> &str {
&self.type_name
}
}
fn generate_create_props(props: &[crate::engine::config::Property]) -> HashMap<String, Property> {
let mut hm = HashMap::new();
hm.insert(
"id".to_string(),
Property::new("id".to_string(), PropertyKind::Scalar, "ID".to_string())
.with_required(false),
);
props.iter().for_each(|p| {
match &p.resolver() {
None => {
hm.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
PropertyKind::Scalar,
p.type_name().to_string(),
)
.with_required(p.required())
.with_hidden(!p.uses().create())
.with_list(p.list())
.with_validator(p.validator().cloned()),
);
}
Some(r) => {
hm.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
PropertyKind::DynamicScalar,
p.type_name().to_string(),
)
.with_required(p.required())
.with_hidden(!p.uses().create())
.with_list(p.list())
.with_resolver(r)
.with_validator(p.validator().cloned()),
);
}
};
});
hm
}
fn generate_update_props(props: &[crate::engine::config::Property]) -> HashMap<String, Property> {
let mut hm = HashMap::new();
props.iter().for_each(|p| {
match &p.resolver() {
None => {
hm.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
PropertyKind::Scalar,
p.type_name().to_string(),
)
.with_required(false)
.with_hidden(!p.uses().update())
.with_list(p.list())
.with_validator(p.validator().cloned()),
);
}
Some(r) => {
hm.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
PropertyKind::DynamicScalar,
p.type_name().to_string(),
)
.with_required(false)
.with_hidden(!p.uses().update())
.with_list(p.list())
.with_resolver(r)
.with_validator(p.validator().cloned()),
);
}
};
});
hm
}
fn generate_output_props(props: &[crate::engine::config::Property]) -> HashMap<String, Property> {
let mut hm = HashMap::new();
hm.insert(
"id".to_string(),
Property::new("id".to_string(), PropertyKind::Scalar, "ID".to_string()).with_required(true),
);
props.iter().for_each(|p| {
match &p.resolver() {
None => {
hm.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
PropertyKind::Scalar,
p.type_name().to_string(),
)
.with_required(p.required())
.with_hidden(!p.uses().output())
.with_list(p.list())
.with_validator(p.validator().cloned()),
);
}
Some(r) => {
hm.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
PropertyKind::DynamicScalar,
p.type_name().to_string(),
)
.with_required(p.required())
.with_hidden(!p.uses().output())
.with_list(p.list())
.with_resolver(r)
.with_validator(p.validator().cloned()),
);
}
};
});
hm
}
fn generate_query_props(
props: &[crate::engine::config::Property],
) -> Result<HashMap<String, Property>, Error> {
let mut query_props = HashMap::new();
query_props.insert(
"id".to_string(),
Property::new(
"id".to_string(),
PropertyKind::ScalarComp,
fmt_string_query_input_name(),
),
);
for p in props.iter() {
query_props.insert(
p.name().to_string(),
Property::new(
p.name().to_string(),
match p.type_name() {
"Boolean" => PropertyKind::Scalar,
"ID" => PropertyKind::ScalarComp,
"String" => PropertyKind::ScalarComp,
"Int" => PropertyKind::ScalarComp,
"Float" => PropertyKind::ScalarComp,
_ => {
return Err(Error::SchemaItemNotFound {
name: p.type_name().to_string(),
})
}
},
match p.type_name() {
"Boolean" => "Boolean".to_string(),
"ID" => fmt_string_query_input_name(),
"String" => fmt_string_query_input_name(),
"Int" => fmt_int_query_input_name(),
"Float" => fmt_float_query_input_name(),
_ => {
return Err(Error::SchemaItemNotFound {
name: p.type_name().to_string(),
})
}
},
)
.with_hidden(!p.uses().query()),
);
}
Ok(query_props)
}
fn fmt_node_object_name(t: &Type) -> String {
t.name().to_string()
}
fn generate_node_object(t: &Type) -> NodeType {
let mut props = generate_output_props(t.props_as_slice());
t.rels().for_each(|r| {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Optional,
fmt_rel_query_input_name(t, r),
),
);
let mut p = Property::new(
r.name().to_string(),
match r.resolver() {
None => PropertyKind::Rel {
rel_name: r.name().to_string(),
},
Some(_) => PropertyKind::DynamicRel {
rel_name: r.name().to_string(),
},
},
fmt_rel_object_name(t, r),
)
.with_list(r.list())
.with_arguments(arguments);
if let Some(resolver) = r.resolver() {
p = p.with_resolver(resolver);
}
props.insert(r.name().to_string(), p);
});
NodeType::new(t.name().to_string(), TypeKind::Object, props)
}
fn fmt_node_query_input_name(t: &Type) -> String {
t.name().to_string() + "QueryInput"
}
fn generate_node_query_input(t: &Type) -> Result<NodeType, Error> {
let mut props = generate_query_props(t.props_as_slice())?;
t.rels().for_each(|r| {
props.insert(
r.name().to_string(),
Property::new(
r.name().to_string(),
PropertyKind::Input,
fmt_rel_query_input_name(t, r),
), );
});
Ok(NodeType::new(
fmt_node_query_input_name(t),
TypeKind::Input,
props,
))
}
fn fmt_node_create_mutation_input_name(t: &Type) -> String {
t.name().to_string() + "CreateMutationInput"
}
fn generate_node_create_mutation_input(t: &Type) -> NodeType {
let mut props = generate_create_props(t.props_as_slice());
t.rels().for_each(|r| {
props.insert(
r.name().to_string(),
Property::new(
r.name().to_string(),
PropertyKind::Input,
fmt_rel_create_mutation_input_name(t, r),
)
.with_list(r.list()),
);
});
NodeType::new(
fmt_node_create_mutation_input_name(t),
TypeKind::Input,
props,
)
}
fn fmt_node_update_mutation_input_name(t: &Type) -> String {
t.name().to_string() + "UpdateMutationInput"
}
fn generate_node_update_mutation_input(t: &Type) -> NodeType {
let mut props = generate_update_props(t.props_as_slice());
t.rels().for_each(|r| {
props.insert(
r.name().to_string(),
Property::new(
r.name().to_string(),
PropertyKind::Input,
fmt_rel_change_input_name(t, r),
)
.with_list(r.list()),
);
});
NodeType::new(
fmt_node_update_mutation_input_name(t),
TypeKind::Input,
props,
)
}
fn fmt_node_input_name(t: &Type) -> String {
t.name().to_string() + "Input"
}
fn generate_node_input(t: &Type) -> NodeType {
let mut props = HashMap::new();
props.insert(
"EXISTING".to_string(),
Property::new(
"EXISTING".to_string(),
PropertyKind::Input,
fmt_node_query_input_name(t),
),
);
props.insert(
"NEW".to_string(),
Property::new(
"NEW".to_string(),
PropertyKind::Input,
fmt_node_create_mutation_input_name(t),
),
);
NodeType::new(fmt_node_input_name(t), TypeKind::Input, props)
}
fn fmt_node_update_input_name(t: &Type) -> String {
t.name().to_string() + "UpdateInput"
}
fn generate_node_update_input(t: &Type) -> NodeType {
let mut props = HashMap::new();
props.insert(
"MATCH".to_string(),
Property::new(
"MATCH".to_string(),
PropertyKind::Input,
fmt_node_query_input_name(t),
),
);
props.insert(
"SET".to_string(),
Property::new(
"SET".to_string(),
PropertyKind::Input,
fmt_node_update_mutation_input_name(t),
),
);
NodeType::new(fmt_node_update_input_name(t), TypeKind::Input, props)
}
fn fmt_node_delete_input_name(t: &Type) -> String {
t.name().to_string() + "DeleteInput"
}
fn generate_node_delete_input(t: &Type) -> NodeType {
let mut props = HashMap::new();
props.insert(
"MATCH".to_string(),
Property::new(
"MATCH".to_string(),
PropertyKind::Input,
fmt_node_query_input_name(t),
),
);
props.insert(
"DELETE".to_string(),
Property::new(
"DELETE".to_string(),
PropertyKind::Input,
fmt_node_delete_mutation_input_name(t),
),
);
NodeType::new(fmt_node_delete_input_name(t), TypeKind::Input, props)
}
fn fmt_node_delete_mutation_input_name(t: &Type) -> String {
t.name().to_string() + "DeleteMutationInput"
}
fn generate_node_delete_mutation_input(t: &Type) -> NodeType {
let mut props = HashMap::new();
t.rels().for_each(|r| {
props.insert(
r.name().to_string(),
Property::new(
r.name().to_string(),
PropertyKind::Input,
fmt_rel_delete_input_name(t, r),
)
.with_list(r.list()),
);
});
NodeType::new(
fmt_node_delete_mutation_input_name(t),
TypeKind::Input,
props,
)
}
fn fmt_node_read_endpoint_name(t: &Type) -> String {
t.name().to_string()
}
fn generate_node_read_endpoint(t: &Type) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Optional,
fmt_node_query_input_name(t),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_node_read_endpoint_name(t),
PropertyKind::Object,
t.name().to_string(),
)
.with_list(true)
.with_arguments(arguments)
}
fn fmt_node_create_endpoint_name(t: &Type) -> String {
t.name().to_string() + "Create"
}
fn generate_node_create_endpoint(t: &Type) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Required,
fmt_node_create_mutation_input_name(t),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_node_create_endpoint_name(t),
PropertyKind::NodeCreateMutation,
t.name().to_string(),
)
.with_arguments(arguments)
}
fn fmt_node_update_endpoint_name(t: &Type) -> String {
t.name().to_string() + "Update"
}
fn generate_node_update_endpoint(t: &Type) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Required,
fmt_node_update_input_name(t),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_node_update_endpoint_name(t),
PropertyKind::NodeUpdateMutation,
t.name().to_string(),
)
.with_list(true)
.with_arguments(arguments)
}
fn fmt_node_delete_endpoint_name(t: &Type) -> String {
t.name().to_string() + "Delete"
}
fn generate_node_delete_endpoint(t: &Type) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Required,
fmt_node_delete_input_name(t),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_node_delete_endpoint_name(t),
PropertyKind::NodeDeleteMutation {
label: fmt_node_object_name(t),
},
"Int".to_string(),
)
.with_arguments(arguments)
}
fn fmt_rel_object_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "Rel"
}
fn fmt_rel_name(r: &Relationship) -> String {
r.name().to_string()
}
fn generate_rel_object(t: &Type, r: &Relationship) -> NodeType {
let mut props = generate_output_props(r.props_as_slice());
props.insert(
"src".to_string(),
Property::new(
"src".to_string(),
PropertyKind::Object,
t.name().to_string(),
)
.with_required(true),
);
props.insert(
"dst".to_string(),
Property::new(
"dst".to_string(),
PropertyKind::Union,
fmt_rel_nodes_union_name(t, r),
)
.with_required(true),
);
NodeType::new(fmt_rel_object_name(t, r), TypeKind::Rel, props)
}
fn fmt_rel_nodes_union_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "NodesUnion"
}
fn generate_rel_nodes_union(t: &Type, r: &Relationship) -> NodeType {
let mut nt = NodeType::new(
fmt_rel_nodes_union_name(t, r),
TypeKind::Union,
HashMap::new(),
);
nt.union_types = Some(r.nodes().cloned().collect());
nt
}
fn fmt_rel_query_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "QueryInput"
}
fn generate_rel_query_input(t: &Type, r: &Relationship) -> Result<NodeType, Error> {
let mut props = generate_query_props(r.props_as_slice())?;
props.insert(
"src".to_string(),
Property::new(
"src".to_string(),
PropertyKind::Input,
fmt_rel_src_query_input_name(t, r),
),
);
props.insert(
"dst".to_string(),
Property::new(
"dst".to_string(),
PropertyKind::Input,
fmt_rel_dst_query_input_name(t, r),
),
);
Ok(NodeType::new(
fmt_rel_query_input_name(t, r),
TypeKind::Input,
props,
))
}
fn fmt_rel_create_mutation_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "CreateMutationInput"
}
fn generate_rel_create_mutation_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = generate_create_props(r.props_as_slice());
props.insert(
"dst".to_string(),
Property::new(
"dst".to_string(),
PropertyKind::Input,
fmt_rel_nodes_mutation_input_union_name(t, r),
)
.with_required(true),
);
NodeType::new(
fmt_rel_create_mutation_input_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_change_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "ChangeInput"
}
fn generate_rel_change_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
"ADD".to_string(),
Property::new(
"ADD".to_string(),
PropertyKind::Input,
fmt_rel_create_mutation_input_name(t, r),
),
);
props.insert(
"UPDATE".to_string(),
Property::new(
"UPDATE".to_string(),
PropertyKind::Input,
fmt_rel_update_input_name(t, r),
),
);
props.insert(
"DELETE".to_string(),
Property::new(
"DELETE".to_string(),
PropertyKind::Input,
fmt_rel_delete_input_name(t, r),
),
);
NodeType::new(fmt_rel_change_input_name(t, r), TypeKind::Input, props)
}
fn fmt_rel_update_mutation_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "UpdateMutationInput"
}
fn generate_rel_update_mutation_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = generate_update_props(r.props_as_slice());
props.insert(
"src".to_string(),
Property::new(
"src".to_string(),
PropertyKind::Input,
fmt_rel_src_update_mutation_input_name(t, r),
),
);
props.insert(
"dst".to_string(),
Property::new(
"dst".to_string(),
PropertyKind::Input,
fmt_rel_dst_update_mutation_input_name(t, r),
),
);
NodeType::new(
fmt_rel_update_mutation_input_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_src_update_mutation_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "SrcUpdateMutationInput"
}
fn generate_rel_src_update_mutation_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
t.name().to_string(),
Property::new(
t.name().to_string(),
PropertyKind::Input,
fmt_node_update_mutation_input_name(t),
),
);
NodeType::new(
fmt_rel_src_update_mutation_input_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_dst_update_mutation_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "DstUpdateMutationInput"
}
fn generate_rel_dst_update_mutation_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
r.nodes().for_each(|node| {
props.insert(
node.to_string(),
Property::new(
node.to_string(),
PropertyKind::Input,
node.to_string() + "UpdateMutationInput",
),
);
});
NodeType::new(
fmt_rel_dst_update_mutation_input_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_src_query_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "SrcQueryInput"
}
fn generate_rel_src_query_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
t.name().to_string(),
Property::new(
t.name().to_string(),
PropertyKind::Input,
t.name().to_string() + "QueryInput",
),
);
NodeType::new(fmt_rel_src_query_input_name(t, r), TypeKind::Input, props)
}
fn fmt_rel_dst_query_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "DstQueryInput"
}
fn generate_rel_dst_query_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
r.nodes().for_each(|node| {
props.insert(
node.to_string(),
Property::new(
node.to_string(),
PropertyKind::Input,
node.to_string() + "QueryInput",
),
);
});
NodeType::new(fmt_rel_dst_query_input_name(t, r), TypeKind::Input, props)
}
fn fmt_rel_nodes_mutation_input_union_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "NodesMutationInputUnion"
}
fn generate_rel_nodes_mutation_input_union(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
r.nodes().for_each(|node| {
props.insert(
node.to_string(),
Property::new(
node.to_string(),
PropertyKind::Input,
node.to_string() + "Input",
),
);
});
NodeType::new(
fmt_rel_nodes_mutation_input_union_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_create_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "CreateInput"
}
fn generate_rel_create_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
"MATCH".to_string(),
Property::new(
"MATCH".to_string(),
PropertyKind::Input,
fmt_node_query_input_name(t),
),
);
props.insert(
"CREATE".to_string(),
Property::new(
"CREATE".to_string(),
PropertyKind::Input,
fmt_rel_create_mutation_input_name(t, r),
)
.with_list(r.list()),
);
NodeType::new(fmt_rel_create_input_name(t, r), TypeKind::Input, props)
}
fn fmt_rel_update_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "UpdateInput"
}
fn generate_rel_update_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
"MATCH".to_string(),
Property::new(
"MATCH".to_string(),
PropertyKind::Input,
fmt_rel_query_input_name(t, r),
),
);
props.insert(
"SET".to_string(),
Property::new(
"SET".to_string(),
PropertyKind::Input,
fmt_rel_update_mutation_input_name(t, r),
)
.with_required(true),
);
NodeType::new(fmt_rel_update_input_name(t, r), TypeKind::Input, props)
}
fn fmt_rel_delete_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "DeleteInput"
}
fn generate_rel_delete_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
"MATCH".to_string(),
Property::new(
"MATCH".to_string(),
PropertyKind::Input,
fmt_rel_query_input_name(t, r),
),
);
props.insert(
"src".to_string(),
Property::new(
"src".to_string(),
PropertyKind::Input,
fmt_rel_src_delete_mutation_input_name(t, r),
),
);
props.insert(
"dst".to_string(),
Property::new(
"dst".to_string(),
PropertyKind::Input,
fmt_rel_dst_delete_mutation_input_name(t, r),
),
);
NodeType::new(fmt_rel_delete_input_name(t, r), TypeKind::Input, props)
}
fn fmt_rel_src_delete_mutation_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "SrcDeleteMutationInput"
}
fn generate_rel_src_delete_mutation_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
props.insert(
t.name().to_string(),
Property::new(
t.name().to_string(),
PropertyKind::Input,
fmt_node_delete_mutation_input_name(t),
),
);
NodeType::new(
fmt_rel_src_delete_mutation_input_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_dst_delete_mutation_input_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "DstDeleteMutationInput"
}
fn generate_rel_dst_delete_mutation_input(t: &Type, r: &Relationship) -> NodeType {
let mut props = HashMap::new();
r.nodes().for_each(|node| {
props.insert(
node.to_string(),
Property::new(
node.to_string(),
PropertyKind::Input,
node.to_string() + "DeleteMutationInput",
),
);
});
NodeType::new(
fmt_rel_dst_delete_mutation_input_name(t, r),
TypeKind::Input,
props,
)
}
fn fmt_rel_read_endpoint_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
}
fn generate_rel_read_endpoint(t: &Type, r: &Relationship) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Optional,
fmt_rel_query_input_name(t, r),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_rel_read_endpoint_name(t, r),
PropertyKind::Rel {
rel_name: r.name().to_string(),
},
fmt_rel_object_name(t, r),
)
.with_list(true)
.with_arguments(arguments)
}
fn fmt_rel_create_endpoint_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "Create"
}
fn generate_rel_create_endpoint(t: &Type, r: &Relationship) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Required,
fmt_rel_create_input_name(t, r),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_rel_create_endpoint_name(t, r),
PropertyKind::RelCreateMutation {
src_label: fmt_node_object_name(t),
rel_name: fmt_rel_name(r),
},
fmt_rel_object_name(t, r),
)
.with_list(true)
.with_arguments(arguments)
}
fn fmt_rel_update_endpoint_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "Update"
}
fn generate_rel_update_endpoint(t: &Type, r: &Relationship) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Required,
fmt_rel_update_input_name(t, r),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_rel_update_endpoint_name(t, r),
PropertyKind::RelUpdateMutation {
src_label: fmt_node_object_name(t),
rel_name: fmt_rel_name(r),
},
fmt_rel_object_name(t, r),
)
.with_list(true)
.with_arguments(arguments)
}
fn fmt_rel_delete_endpoint_name(t: &Type, r: &Relationship) -> String {
t.name().to_string()
+ &*((&r.name().to_string().to_title_case())
.split_whitespace()
.collect::<String>())
+ "Delete"
}
fn generate_rel_delete_endpoint(t: &Type, r: &Relationship) -> Property {
let mut arguments = HashMap::new();
arguments.insert(
"input".to_string(),
Argument::new(
"input".to_string(),
ArgumentKind::Required,
fmt_rel_delete_input_name(t, r),
),
);
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
Property::new(
fmt_rel_delete_endpoint_name(t, r),
PropertyKind::RelDeleteMutation {
src_label: fmt_node_object_name(t),
rel_name: fmt_rel_name(r),
},
"Int".to_string(),
)
.with_arguments(arguments)
}
fn generate_custom_endpoint(e: &Endpoint) -> Property {
let mut arguments = HashMap::new();
if let Some(input) = e.input() {
let is_required = if input.required() {
ArgumentKind::Required
} else {
ArgumentKind::Optional
};
arguments.insert(
"partitionKey".to_string(),
Argument::new(
"partitionKey".to_string(),
ArgumentKind::Optional,
"String".to_string(),
),
);
match input.type_def() {
TypeDef::Scalar(s) => match s {
GraphqlType::Boolean => arguments.insert(
"input".to_string(),
Argument::new("input".to_string(), is_required, "Boolean".to_string()),
),
GraphqlType::Float => arguments.insert(
"input".to_string(),
Argument::new("input".to_string(), is_required, "Float".to_string()),
),
GraphqlType::Int => arguments.insert(
"input".to_string(),
Argument::new("input".to_string(), is_required, "Int".to_string()),
),
GraphqlType::String => arguments.insert(
"input".to_string(),
Argument::new("input".to_string(), is_required, "String".to_string()),
),
},
TypeDef::Existing(e) => arguments.insert(
"input".to_string(),
Argument::new("input".to_string(), is_required, e.clone()),
),
TypeDef::Custom(c) => arguments.insert(
"input".to_string(),
Argument::new("input".to_string(), is_required, c.name().to_string()),
),
};
}
Property::new(
e.name().to_string(),
PropertyKind::CustomResolver,
match &e.output().type_def() {
TypeDef::Scalar(t) => match &t {
GraphqlType::Int => "Int".to_string(),
GraphqlType::Float => "Float".to_string(),
GraphqlType::String => "String".to_string(),
GraphqlType::Boolean => "Boolean".to_string(),
},
TypeDef::Existing(s) => s.clone(),
TypeDef::Custom(t) => t.name().to_string(),
},
)
.with_required(e.output().required())
.with_list(e.output().list())
.with_arguments(arguments)
}
fn generate_custom_endpoint_input(t: &Type) -> NodeType {
let mut props = generate_update_props(t.props_as_slice());
t.rels().for_each(|r| {
props.insert(
r.name().to_string(),
Property::new(
r.name().to_string(),
PropertyKind::Input,
fmt_rel_query_input_name(t, r),
)
.with_list(r.list()),
);
});
NodeType::new(t.name().to_string(), TypeKind::Input, props)
}
fn generate_static_version_query() -> Property {
Property::new(
"_version".to_string(),
PropertyKind::VersionQuery,
"String".to_string(),
)
}
fn fmt_string_query_input_name() -> String {
"StringQueryInput".to_string()
}
fn string_query_input() -> NodeType {
NodeType::new(
fmt_string_query_input_name(),
TypeKind::Input,
hashmap! {
"EQ".to_string() => string_input("EQ"),
"NOTEQ".to_string() => string_input("NOTEQ"),
"CONTAINS".to_string() => string_input("CONTAINS"),
"NOTCONTAINS".to_string() => string_input("NOTCONTAINS"),
"IN".to_string() => string_array_input("IN"),
"NOTIN".to_string() => string_array_input("NOTIN"),
"GT".to_string() => string_input("GT"),
"GTE".to_string() => string_input("GTE"),
"LT".to_string() => string_input("LT"),
"LTE".to_string() => string_input("LTE"),
},
)
}
fn string_input(name: &str) -> Property {
Property::new(name.to_string(), PropertyKind::Scalar, "String".to_string())
}
fn string_array_input(name: &str) -> Property {
Property {
name: name.to_string(),
kind: PropertyKind::Scalar,
type_name: "String".to_string(),
hidden: false,
required: false,
list: true,
arguments: HashMap::new(),
resolver: None,
validator: None,
}
}
fn fmt_int_query_input_name() -> String {
"IntQueryInput".to_string()
}
fn int_query_input() -> NodeType {
NodeType::new(
fmt_int_query_input_name(),
TypeKind::Input,
hashmap! {
"EQ".to_string() => int_input("EQ"),
"NOTEQ".to_string() => int_input("NOTEQ"),
"IN".to_string() => int_input("IN"),
"NOTIN".to_string() => int_input("NOTIN"),
"GT".to_string() => int_input("GT"),
"GTE".to_string() => int_input("GTE"),
"LT".to_string() => int_input("LT"),
"LTE".to_string() => int_input("LTE"),
},
)
}
fn int_input(name: &str) -> Property {
Property::new(name.to_string(), PropertyKind::Scalar, "Int".to_string())
}
fn fmt_float_query_input_name() -> String {
"FloatQueryInput".to_string()
}
fn float_query_input() -> NodeType {
NodeType::new(
fmt_int_query_input_name(),
TypeKind::Input,
hashmap! {
"EQ".to_string() => float_input("EQ"),
"NOTEQ".to_string() => float_input("NOTEQ"),
"IN".to_string() => float_input("IN"),
"NOTIN".to_string() => float_input("NOTIN"),
"GT".to_string() => float_input("GT"),
"GTE".to_string() => float_input("GTE"),
"LT".to_string() => float_input("LT"),
"LTE".to_string() => float_input("LTE"),
},
)
}
fn float_input(name: &str) -> Property {
Property::new(name.to_string(), PropertyKind::Scalar, "Float".to_string())
}
pub(crate) fn generate_schema(c: &Configuration) -> Result<HashMap<String, NodeType>, Error> {
let mut nthm = HashMap::new();
let mut mutation_props = HashMap::new();
let mut query_props = HashMap::new();
nthm.insert(fmt_string_query_input_name(), string_query_input());
nthm.insert(fmt_int_query_input_name(), int_query_input());
nthm.insert(fmt_float_query_input_name(), float_query_input());
for t in c.types() {
let node_type = generate_node_object(t);
nthm.insert(node_type.type_name.to_string(), node_type);
let node_query_input = generate_node_query_input(t)?;
nthm.insert(node_query_input.type_name.to_string(), node_query_input);
let node_create_mutation_input = generate_node_create_mutation_input(t);
nthm.insert(
node_create_mutation_input.type_name.to_string(),
node_create_mutation_input,
);
let node_update_mutation_input = generate_node_update_mutation_input(t);
nthm.insert(
node_update_mutation_input.type_name.to_string(),
node_update_mutation_input,
);
let node_input = generate_node_input(t);
nthm.insert(node_input.type_name.to_string(), node_input);
let node_update_input = generate_node_update_input(t);
nthm.insert(node_update_input.type_name.to_string(), node_update_input);
let node_delete_input = generate_node_delete_input(t);
nthm.insert(node_delete_input.type_name.to_string(), node_delete_input);
let node_delete_mutation_input = generate_node_delete_mutation_input(t);
nthm.insert(
node_delete_mutation_input.type_name.to_string(),
node_delete_mutation_input,
);
if t.endpoints().read() {
let read_endpoint = generate_node_read_endpoint(t);
query_props.insert(read_endpoint.name().to_string(), read_endpoint);
}
if t.endpoints().create() {
let create_endpoint = generate_node_create_endpoint(t);
mutation_props.insert(create_endpoint.name().to_string(), create_endpoint);
}
if t.endpoints().update() {
let update_endpoint = generate_node_update_endpoint(t);
mutation_props.insert(update_endpoint.name().to_string(), update_endpoint);
}
if t.endpoints().delete() {
let delete_endpoint = generate_node_delete_endpoint(t);
mutation_props.insert(delete_endpoint.name().to_string(), delete_endpoint);
}
for r in t.rels() {
let rel_object = generate_rel_object(t, r);
nthm.insert(rel_object.type_name.to_string(), rel_object);
let rel_nodes_union = generate_rel_nodes_union(t, r);
nthm.insert(rel_nodes_union.type_name.to_string(), rel_nodes_union);
let rel_query_input = generate_rel_query_input(t, r)?;
nthm.insert(rel_query_input.type_name.to_string(), rel_query_input);
let rel_create_mutation_input = generate_rel_create_mutation_input(t, r);
nthm.insert(
rel_create_mutation_input.type_name.to_string(),
rel_create_mutation_input,
);
let rel_change_input = generate_rel_change_input(t, r);
nthm.insert(rel_change_input.type_name.to_string(), rel_change_input);
let rel_update_mutation_input = generate_rel_update_mutation_input(t, r);
nthm.insert(
rel_update_mutation_input.type_name.to_string(),
rel_update_mutation_input,
);
let rel_src_update_mutation_input = generate_rel_src_update_mutation_input(t, r);
nthm.insert(
rel_src_update_mutation_input.type_name.to_string(),
rel_src_update_mutation_input,
);
let rel_dst_update_mutation_input = generate_rel_dst_update_mutation_input(t, r);
nthm.insert(
rel_dst_update_mutation_input.type_name.to_string(),
rel_dst_update_mutation_input,
);
let rel_src_query_input = generate_rel_src_query_input(t, r);
nthm.insert(
rel_src_query_input.type_name.to_string(),
rel_src_query_input,
);
let rel_dst_query_input = generate_rel_dst_query_input(t, r);
nthm.insert(
rel_dst_query_input.type_name.to_string(),
rel_dst_query_input,
);
let rel_nodes_mutation_input_union = generate_rel_nodes_mutation_input_union(t, r);
nthm.insert(
rel_nodes_mutation_input_union.type_name.to_string(),
rel_nodes_mutation_input_union,
);
let rel_create_input = generate_rel_create_input(t, r);
nthm.insert(rel_create_input.type_name.to_string(), rel_create_input);
let rel_update_input = generate_rel_update_input(t, r);
nthm.insert(rel_update_input.type_name.to_string(), rel_update_input);
let rel_delete_input = generate_rel_delete_input(t, r);
nthm.insert(rel_delete_input.type_name.to_string(), rel_delete_input);
let rel_src_delete_mutation_input = generate_rel_src_delete_mutation_input(t, r);
nthm.insert(
rel_src_delete_mutation_input.type_name.to_string(),
rel_src_delete_mutation_input,
);
let rel_dst_delete_mutation_input = generate_rel_dst_delete_mutation_input(t, r);
nthm.insert(
rel_dst_delete_mutation_input.type_name.to_string(),
rel_dst_delete_mutation_input,
);
if r.endpoints().read() {
let rel_read_endpoint = generate_rel_read_endpoint(t, r);
query_props.insert(rel_read_endpoint.name().to_string(), rel_read_endpoint);
}
if r.endpoints().create() {
let rel_create_endpoint = generate_rel_create_endpoint(t, r);
mutation_props.insert(rel_create_endpoint.name().to_string(), rel_create_endpoint);
}
if r.endpoints().update() {
let rel_update_endpoint = generate_rel_update_endpoint(t, r);
mutation_props.insert(rel_update_endpoint.name().to_string(), rel_update_endpoint);
}
if r.endpoints().delete() {
let rel_delete_endpoint = generate_rel_delete_endpoint(t, r);
mutation_props.insert(rel_delete_endpoint.name().to_string(), rel_delete_endpoint);
}
}
}
c.endpoints().for_each(|e| {
let endpoint = generate_custom_endpoint(e);
match e.class() {
EndpointClass::Mutation => {
mutation_props.insert(e.name().to_string(), endpoint);
}
EndpointClass::Query => {
query_props.insert(e.name().to_string(), endpoint);
}
}
if let Some(input) = e.input() {
if let TypeDef::Custom(t) = input.type_def() {
let input = generate_custom_endpoint_input(t);
nthm.insert(t.name().to_string(), input);
}
}
if let TypeDef::Custom(t) = &e.output().type_def() {
let node_type = generate_node_object(t);
nthm.insert(node_type.type_name.to_string(), node_type);
}
});
query_props.insert("_version".to_string(), generate_static_version_query());
nthm.insert(
"Mutation".to_string(),
NodeType::new("Mutation".to_string(), TypeKind::Object, mutation_props),
);
nthm.insert(
"Query".to_string(),
NodeType::new("Query".to_string(), TypeKind::Object, query_props),
);
nthm.insert(
"Subscription".to_string(),
NodeType::new("Subscription".to_string(), TypeKind::Object, HashMap::new()),
);
Ok(nthm)
}
pub(super) fn create_root_node<RequestCtx>(c: &Configuration) -> Result<RootRef<RequestCtx>, Error>
where
RequestCtx: RequestContext,
{
let nthm = generate_schema(c)?;
let nts = Arc::new(nthm);
let root_mutation_info = Info::new("Mutation".to_string(), nts.clone());
let root_query_info = Info::new("Query".to_string(), nts.clone());
let root_subscription_info = Info::new("Subscription".to_string(), nts);
catch_unwind(|| {
Arc::new(RootNode::new_with_info(
Node::new("Query".to_string(), HashMap::new()),
Node::new("Mutation".to_string(), HashMap::new()),
Node::new("Subscription".to_string(), HashMap::new()),
root_query_info,
root_mutation_info,
root_subscription_info,
))
})
.map_err(|e| {
e.downcast::<Error>()
.map(|e| *e)
.unwrap_or_else(|e| Error::SchemaItemNotFound {
name: format!("{:#?}", e),
})
})
}
pub(crate) fn type_name_variants(t: &Type) -> HashSet<String> {
let mut hs = HashSet::new();
hs.insert(fmt_node_query_input_name(t));
hs.insert(fmt_node_create_mutation_input_name(t));
hs.insert(fmt_node_update_mutation_input_name(t));
hs.insert(fmt_node_input_name(t));
hs.insert(fmt_node_update_input_name(t));
hs.insert(fmt_node_delete_input_name(t));
hs.insert(fmt_node_delete_mutation_input_name(t));
hs.insert(fmt_node_create_endpoint_name(t));
hs.insert(fmt_node_update_endpoint_name(t));
hs.insert(fmt_node_delete_endpoint_name(t));
hs
}
pub(crate) fn rel_name_variants(t: &Type, r: &Relationship) -> HashSet<String> {
let mut hs = HashSet::new();
hs.insert(fmt_rel_object_name(t, r));
hs.insert(fmt_rel_name(r));
hs.insert(fmt_rel_nodes_union_name(t, r));
hs.insert(fmt_rel_query_input_name(t, r));
hs.insert(fmt_rel_create_mutation_input_name(t, r));
hs.insert(fmt_rel_change_input_name(t, r));
hs.insert(fmt_rel_update_mutation_input_name(t, r));
hs.insert(fmt_rel_src_update_mutation_input_name(t, r));
hs.insert(fmt_rel_dst_update_mutation_input_name(t, r));
hs.insert(fmt_rel_src_query_input_name(t, r));
hs.insert(fmt_rel_dst_query_input_name(t, r));
hs.insert(fmt_rel_nodes_mutation_input_union_name(t, r));
hs.insert(fmt_rel_create_input_name(t, r));
hs.insert(fmt_rel_update_input_name(t, r));
hs.insert(fmt_rel_delete_input_name(t, r));
hs.insert(fmt_rel_src_delete_mutation_input_name(t, r));
hs.insert(fmt_rel_dst_delete_mutation_input_name(t, r));
hs.insert(fmt_rel_read_endpoint_name(t, r));
hs.insert(fmt_rel_create_endpoint_name(t, r));
hs.insert(fmt_rel_update_endpoint_name(t, r));
hs.insert(fmt_rel_delete_endpoint_name(t, r));
hs
}
#[cfg(test)]
mod tests {
use super::{
create_root_node, fmt_node_create_endpoint_name, fmt_node_create_mutation_input_name,
fmt_node_delete_endpoint_name, fmt_node_delete_input_name,
fmt_node_delete_mutation_input_name, fmt_node_input_name, fmt_node_object_name,
fmt_node_query_input_name, fmt_node_read_endpoint_name, fmt_node_update_endpoint_name,
fmt_node_update_input_name, fmt_node_update_mutation_input_name, fmt_rel_change_input_name,
fmt_rel_create_endpoint_name, fmt_rel_create_input_name,
fmt_rel_create_mutation_input_name, fmt_rel_delete_endpoint_name,
fmt_rel_delete_input_name, fmt_rel_dst_delete_mutation_input_name,
fmt_rel_dst_query_input_name, fmt_rel_dst_update_mutation_input_name,
fmt_rel_nodes_mutation_input_union_name, fmt_rel_nodes_union_name, fmt_rel_object_name,
fmt_rel_query_input_name, fmt_rel_read_endpoint_name,
fmt_rel_src_delete_mutation_input_name, fmt_rel_src_query_input_name,
fmt_rel_src_update_mutation_input_name, fmt_rel_update_endpoint_name,
fmt_rel_update_input_name, fmt_rel_update_mutation_input_name, generate_custom_endpoint,
generate_node_create_endpoint, generate_node_create_mutation_input,
generate_node_delete_endpoint, generate_node_delete_input,
generate_node_delete_mutation_input, generate_node_input, generate_node_object,
generate_node_query_input, generate_node_read_endpoint, generate_node_update_endpoint,
generate_node_update_input, generate_node_update_mutation_input, generate_rel_change_input,
generate_rel_create_endpoint, generate_rel_create_input,
generate_rel_create_mutation_input, generate_rel_delete_endpoint,
generate_rel_delete_input, generate_rel_dst_delete_mutation_input,
generate_rel_dst_query_input, generate_rel_dst_update_mutation_input,
generate_rel_nodes_mutation_input_union, generate_rel_nodes_union, generate_rel_object,
generate_rel_query_input, generate_rel_read_endpoint,
generate_rel_src_delete_mutation_input, generate_rel_src_update_mutation_input,
generate_rel_update_endpoint, generate_rel_update_input,
generate_rel_update_mutation_input, generate_schema, ArgumentKind, Info, NodeType,
Property, PropertyKind, TypeKind,
};
use crate::engine::config::{
mock_config, mock_endpoint_one, mock_endpoint_three, mock_endpoint_two,
mock_endpoints_filter, mock_project_config, mock_project_type,
};
use std::collections::HashMap;
use std::sync::Arc;
#[test]
fn info_new() {
let i = Info::new("typename".to_string(), Arc::new(HashMap::new()));
assert!(i.name == "typename");
}
#[test]
fn node_type_new() {
let nt = NodeType::new("typename".to_string(), TypeKind::Object, HashMap::new());
assert!(nt.type_name == "typename");
assert!(nt.type_kind == TypeKind::Object);
}
#[test]
fn property_new() {
let p = Property::new(
"propname".to_string(),
PropertyKind::Scalar,
"String".to_string(),
)
.with_required(true);
assert!(p.name == "propname");
assert!(p.kind == PropertyKind::Scalar);
assert!(p.type_name == "String");
assert!(p.required);
assert!(!p.list());
assert!(p.arguments.is_empty());
}
#[test]
fn test_fmt_node_object_name() {
let project_type = mock_project_type();
assert!(fmt_node_object_name(&project_type) == "Project");
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_node_object() {
let project_type = mock_project_type();
let project_node_object = generate_node_object(&project_type);
assert!(project_node_object.type_name == "Project");
assert!(project_node_object.props.len() == 8);
assert!(project_node_object.type_kind == TypeKind::Object);
let project_id = project_node_object.props.get("id").unwrap();
assert!(project_id.name == "id");
assert!(project_id.kind == PropertyKind::Scalar);
assert!(project_id.type_name == "ID");
assert!(project_id.required);
assert!(!project_id.list);
assert!(project_id.arguments.is_empty());
let project_name = project_node_object.props.get("name").unwrap();
assert!(project_name.name == "name");
assert!(project_name.kind == PropertyKind::Scalar);
assert!(project_name.type_name == "String");
assert!(project_name.required);
assert!(!project_name.list);
assert!(project_name.arguments.is_empty());
let project_tags = project_node_object.props.get("tags").unwrap();
assert!(project_tags.name == "tags");
assert!(project_tags.kind == PropertyKind::Scalar);
assert!(project_tags.type_name == "String");
assert!(!project_tags.required);
assert!(project_tags.list);
assert!(project_tags.arguments.is_empty());
let project_public = project_node_object.props.get("public").unwrap();
assert!(project_public.name == "public");
assert!(project_public.kind == PropertyKind::Scalar);
assert!(project_public.type_name == "Boolean");
assert!(project_public.required);
assert!(!project_public.list);
assert!(project_public.arguments.is_empty());
let project_owner = project_node_object.props.get("owner").unwrap();
assert!(project_owner.name() == "owner");
assert!(match &project_owner.kind {
PropertyKind::Rel { rel_name } => rel_name == "owner",
_ => false,
});
assert!(project_owner.type_name == "ProjectOwnerRel");
assert!(!project_owner.required);
assert!(!project_owner.list());
assert!(project_owner.arguments.contains_key("input"));
if let Some(input) = project_owner.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "ProjectOwnerQueryInput");
}
let project_board = project_node_object.props.get("board").unwrap();
assert!(project_board.name == "board");
assert!(match &project_board.kind {
PropertyKind::Rel { rel_name } => rel_name == "board",
_ => false,
});
assert!(project_board.type_name == "ProjectBoardRel");
assert!(!project_board.required);
assert!(!project_board.list);
assert!(project_board.arguments.contains_key("input"));
if let Some(input) = project_board.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "ProjectBoardQueryInput");
}
let project_commits = project_node_object.props.get("commits").unwrap();
assert!(project_commits.name == "commits");
assert!(match &project_commits.kind {
PropertyKind::Rel { rel_name } => rel_name == "commits",
_ => false,
});
assert!(project_commits.type_name == "ProjectCommitsRel");
assert!(!project_commits.required);
assert!(project_commits.list);
assert!(project_commits.arguments.contains_key("input"));
if let Some(input) = project_commits.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "ProjectCommitsQueryInput");
}
let project_issues = project_node_object.props.get("issues").unwrap();
assert!(project_issues.name == "issues");
assert!(match &project_issues.kind {
PropertyKind::Rel { rel_name } => rel_name == "issues",
_ => false,
});
assert!(project_issues.type_name == "ProjectIssuesRel");
assert!(!project_issues.required);
assert!(project_issues.list);
assert!(project_issues.arguments.contains_key("input"));
if let Some(input) = project_issues.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "ProjectIssuesQueryInput");
}
}
#[test]
fn test_fmt_node_query_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_query_input_name(&project_type) == "ProjectQueryInput");
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_node_query_input() {
let project_type = mock_project_type();
let project_query_input = generate_node_query_input(&project_type).unwrap();
assert!(project_query_input.type_name == "ProjectQueryInput");
assert!(project_query_input.type_kind == TypeKind::Input);
assert!(project_query_input.props.len() == 8);
let project_id = project_query_input.props.get("id").unwrap();
assert!(project_id.name == "id");
assert!(project_id.kind == PropertyKind::ScalarComp);
assert!(project_id.type_name == "StringQueryInput");
assert!(!project_id.required);
assert!(!project_id.list);
assert!(project_id.arguments.is_empty());
let project_name = project_query_input.props.get("name").unwrap();
assert!(project_name.name == "name");
assert!(project_name.kind == PropertyKind::ScalarComp);
assert!(project_name.type_name == "StringQueryInput");
assert!(!project_name.required);
assert!(!project_name.list);
assert!(project_name.arguments.is_empty());
let project_tags = project_query_input.props.get("tags").unwrap();
assert!(project_tags.name == "tags");
assert!(project_tags.kind == PropertyKind::ScalarComp);
assert!(project_tags.type_name == "StringQueryInput");
assert!(!project_tags.required);
assert!(project_tags.arguments.is_empty());
let project_public = project_query_input.props.get("public").unwrap();
assert!(project_public.name == "public");
assert!(project_public.kind == PropertyKind::Scalar);
assert!(project_public.type_name == "Boolean");
assert!(!project_public.required);
assert!(!project_public.list);
assert!(project_public.arguments.is_empty());
let project_owner = project_query_input.props.get("owner").unwrap();
assert!(project_owner.name() == "owner");
assert!(project_owner.kind == PropertyKind::Input);
assert!(project_owner.type_name == "ProjectOwnerQueryInput");
assert!(!project_owner.required);
assert!(!project_owner.list());
assert!(project_owner.arguments.is_empty());
let project_board = project_query_input.props.get("board").unwrap();
assert!(project_board.name == "board");
assert!(project_board.kind == PropertyKind::Input);
assert!(project_board.type_name == "ProjectBoardQueryInput");
assert!(!project_board.required);
assert!(!project_board.list);
assert!(project_board.arguments.is_empty());
let project_commits = project_query_input.props.get("commits").unwrap();
assert!(project_commits.name == "commits");
assert!(project_commits.kind == PropertyKind::Input);
assert!(project_commits.type_name == "ProjectCommitsQueryInput");
assert!(!project_commits.required);
assert!(!project_commits.list);
assert!(project_commits.arguments.is_empty());
let project_issues = project_query_input.props.get("issues").unwrap();
assert!(project_issues.name == "issues");
assert!(project_issues.kind == PropertyKind::Input);
assert!(project_issues.type_name == "ProjectIssuesQueryInput");
assert!(!project_issues.required);
assert!(!project_issues.list);
assert!(project_issues.arguments.is_empty());
}
#[test]
fn test_fmt_node_create_mutation_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_create_mutation_input_name(&project_type) == "ProjectCreateMutationInput");
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_node_create_mutation_input() {
let project_type = mock_project_type();
let project_mutation_input = generate_node_create_mutation_input(&project_type);
assert!(project_mutation_input.type_name == "ProjectCreateMutationInput");
assert!(project_mutation_input.type_kind == TypeKind::Input);
assert!(project_mutation_input.props.len() == 8);
let project_name = project_mutation_input.props.get("name").unwrap();
assert!(project_name.name == "name");
assert!(project_name.kind == PropertyKind::Scalar);
assert!(project_name.type_name == "String");
assert!(project_name.required);
assert!(!project_name.list);
assert!(project_name.arguments.is_empty());
let project_tags = project_mutation_input.props.get("tags").unwrap();
assert!(project_tags.name == "tags");
assert!(project_tags.kind == PropertyKind::Scalar);
assert!(project_tags.type_name == "String");
assert!(!project_tags.required);
assert!(project_tags.list);
assert!(project_tags.arguments.is_empty());
let project_public = project_mutation_input.props.get("public").unwrap();
assert!(project_public.name == "public");
assert!(project_public.kind == PropertyKind::Scalar);
assert!(project_public.type_name == "Boolean");
assert!(project_public.required);
assert!(!project_public.list);
assert!(project_public.arguments.is_empty());
let project_owner = project_mutation_input.props.get("owner").unwrap();
assert!(project_owner.name() == "owner");
assert!(project_owner.kind == PropertyKind::Input);
assert!(project_owner.type_name == "ProjectOwnerCreateMutationInput");
assert!(!project_owner.required);
assert!(!project_owner.list());
assert!(project_owner.arguments.is_empty());
let project_board = project_mutation_input.props.get("board").unwrap();
assert!(project_board.name == "board");
assert!(project_board.kind == PropertyKind::Input);
assert!(project_board.type_name == "ProjectBoardCreateMutationInput");
assert!(!project_board.required);
assert!(!project_board.list);
assert!(project_board.arguments.is_empty());
let project_commits = project_mutation_input.props.get("commits").unwrap();
assert!(project_commits.name == "commits");
assert!(project_commits.kind == PropertyKind::Input);
assert!(project_commits.type_name == "ProjectCommitsCreateMutationInput");
assert!(!project_commits.required);
assert!(project_commits.list);
assert!(project_commits.arguments.is_empty());
let project_issues = project_mutation_input.props.get("issues").unwrap();
assert!(project_issues.name == "issues");
assert!(project_issues.kind == PropertyKind::Input);
assert!(project_issues.type_name == "ProjectIssuesCreateMutationInput");
assert!(!project_issues.required);
assert!(project_issues.list);
assert!(project_issues.arguments.is_empty());
}
#[test]
fn test_fmt_node_update_mutation_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_update_mutation_input_name(&project_type) == "ProjectUpdateMutationInput");
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_node_update_mutation_input() {
let project_type = mock_project_type();
let project_update_mutation_input = generate_node_update_mutation_input(&project_type);
assert!(project_update_mutation_input.type_name == "ProjectUpdateMutationInput");
assert!(project_update_mutation_input.type_kind == TypeKind::Input);
assert!(project_update_mutation_input.props.len() == 7);
let name = project_update_mutation_input.props.get("name").unwrap();
assert!(name.name == "name");
assert!(name.kind == PropertyKind::Scalar);
assert!(name.type_name == "String");
assert!(!name.required);
assert!(!name.list);
assert!(name.arguments.is_empty());
let tags = project_update_mutation_input.props.get("tags").unwrap();
assert!(tags.name == "tags");
assert!(tags.kind == PropertyKind::Scalar);
assert!(tags.type_name == "String");
assert!(!tags.required);
assert!(tags.list);
assert!(tags.arguments.is_empty());
let public = project_update_mutation_input.props.get("public").unwrap();
assert!(public.name == "public");
assert!(public.kind == PropertyKind::Scalar);
assert!(public.type_name == "Boolean");
assert!(!public.required);
assert!(!public.list);
assert!(public.arguments.is_empty());
let owner = project_update_mutation_input.props.get("owner").unwrap();
assert!(owner.name() == "owner");
assert!(owner.kind == PropertyKind::Input);
assert!(owner.type_name == "ProjectOwnerChangeInput");
assert!(!owner.required);
assert!(!owner.list());
assert!(owner.arguments.is_empty());
let board = project_update_mutation_input.props.get("board").unwrap();
assert!(board.name == "board");
assert!(board.kind == PropertyKind::Input);
assert!(board.type_name == "ProjectBoardChangeInput");
assert!(!board.required);
assert!(!board.list);
assert!(board.arguments.is_empty());
let commits = project_update_mutation_input.props.get("commits").unwrap();
assert!(commits.name == "commits");
assert!(commits.kind == PropertyKind::Input);
assert!(commits.type_name == "ProjectCommitsChangeInput");
assert!(!commits.required);
assert!(commits.list);
assert!(commits.arguments.is_empty());
let issues = project_update_mutation_input.props.get("issues").unwrap();
assert!(issues.name == "issues");
assert!(issues.kind == PropertyKind::Input);
assert!(issues.type_name == "ProjectIssuesChangeInput");
assert!(!issues.required);
assert!(issues.list);
assert!(issues.arguments.is_empty());
}
#[test]
fn test_fmt_node_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_input_name(&project_type) == "ProjectInput");
}
#[test]
fn test_generate_node_input() {
let project_type = mock_project_type();
let project_input = generate_node_input(&project_type);
let project_match = project_input.props.get("EXISTING").unwrap();
assert!(project_match.name == "EXISTING");
assert!(project_match.kind == PropertyKind::Input);
assert!(project_match.type_name == "ProjectQueryInput");
assert!(!project_match.required);
assert!(!project_match.list);
assert!(project_match.arguments.is_empty());
let project_create = project_input.props.get("NEW").unwrap();
assert!(project_create.name == "NEW");
assert!(project_create.kind == PropertyKind::Input);
assert!(project_create.type_name == "ProjectCreateMutationInput");
assert!(!project_create.required);
assert!(!project_create.list);
assert!(project_create.arguments.is_empty());
}
#[test]
fn test_fmt_node_update_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_update_input_name(&project_type) == "ProjectUpdateInput");
}
#[test]
fn test_generate_node_update_input() {
let project_type = mock_project_type();
let project_update_input = generate_node_update_input(&project_type);
let project_match = project_update_input.props.get("MATCH").unwrap();
assert!(project_match.name == "MATCH");
assert!(project_match.kind == PropertyKind::Input);
assert!(project_match.type_name == "ProjectQueryInput");
assert!(!project_match.required);
assert!(!project_match.list);
assert!(project_match.arguments.is_empty());
let project_update = project_update_input.props.get("SET").unwrap();
assert!(project_update.name == "SET");
assert!(project_update.kind == PropertyKind::Input);
assert!(project_update.type_name == "ProjectUpdateMutationInput");
assert!(!project_update.required);
assert!(!project_update.list);
assert!(project_update.arguments.is_empty());
}
#[test]
fn test_fmt_node_delete_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_delete_input_name(&project_type) == "ProjectDeleteInput");
}
#[test]
fn test_generate_node_delete_input() {
let project_type = mock_project_type();
let project_delete_input = generate_node_delete_input(&project_type);
assert!(project_delete_input.type_name == "ProjectDeleteInput");
assert!(project_delete_input.props.len() == 2);
let project_match = project_delete_input.props.get("MATCH").unwrap();
assert!(project_match.name == "MATCH");
assert!(project_match.kind == PropertyKind::Input);
assert!(project_match.type_name == "ProjectQueryInput");
assert!(!project_match.required);
assert!(!project_match.list);
assert!(project_match.arguments.is_empty());
let project_delete = project_delete_input.props.get("DELETE").unwrap();
assert!(project_delete.name == "DELETE");
assert!(project_delete.kind == PropertyKind::Input);
assert!(project_delete.type_name == "ProjectDeleteMutationInput");
assert!(!project_delete.required);
assert!(!project_delete.list);
assert!(project_delete.arguments.is_empty());
}
#[test]
fn test_fmt_node_delete_mutation_input_name() {
let project_type = mock_project_type();
assert!(fmt_node_delete_mutation_input_name(&project_type) == "ProjectDeleteMutationInput");
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_node_delete_mutation_input() {
let project_type = mock_project_type();
let project_delete_mutation_input = generate_node_delete_mutation_input(&project_type);
assert!(project_delete_mutation_input.type_name == "ProjectDeleteMutationInput");
assert!(project_delete_mutation_input.props.len() == 4);
let owner = project_delete_mutation_input.props.get("owner").unwrap();
assert!(owner.name() == "owner");
assert!(owner.kind == PropertyKind::Input);
assert!(owner.type_name == "ProjectOwnerDeleteInput");
assert!(!owner.required);
assert!(!owner.list());
assert!(owner.arguments.is_empty());
let board = project_delete_mutation_input.props.get("board").unwrap();
assert!(board.name == "board");
assert!(board.kind == PropertyKind::Input);
assert!(board.type_name == "ProjectBoardDeleteInput");
assert!(!board.required);
assert!(!board.list);
assert!(board.arguments.is_empty());
let commits = project_delete_mutation_input.props.get("commits").unwrap();
assert!(commits.name == "commits");
assert!(commits.kind == PropertyKind::Input);
assert!(commits.type_name == "ProjectCommitsDeleteInput");
assert!(!commits.required);
assert!(commits.list);
assert!(commits.arguments.is_empty());
let issues = project_delete_mutation_input.props.get("issues").unwrap();
assert!(issues.name == "issues");
assert!(issues.kind == PropertyKind::Input);
assert!(issues.type_name == "ProjectIssuesDeleteInput");
assert!(!issues.required);
assert!(issues.list);
assert!(issues.arguments.is_empty());
}
#[test]
fn test_fmt_node_read_endpoint_name() {
let project_type = mock_project_type();
assert!(fmt_node_read_endpoint_name(&project_type) == "Project");
}
#[test]
fn test_generate_node_read_endpoint() {
let project_type = mock_project_type();
let project_read_endpoint = generate_node_read_endpoint(&project_type);
assert!(project_read_endpoint.name == "Project");
assert!(project_read_endpoint.kind == PropertyKind::Object);
assert!(project_read_endpoint.type_name == "Project");
assert!(!project_read_endpoint.required);
assert!(project_read_endpoint.list);
assert!(project_read_endpoint.arguments.contains_key("input"));
if let Some(input) = project_read_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "ProjectQueryInput");
}
}
#[test]
fn test_fmt_node_create_endpoint_name() {
let project_type = mock_project_type();
assert!(fmt_node_create_endpoint_name(&project_type) == "ProjectCreate");
}
#[test]
fn test_generate_node_create_endpoint() {
let project_type = mock_project_type();
let project_create_endpoint = generate_node_create_endpoint(&project_type);
assert!(project_create_endpoint.name == "ProjectCreate");
assert!(project_create_endpoint.kind == PropertyKind::NodeCreateMutation);
assert!(project_create_endpoint.type_name == "Project");
assert!(!project_create_endpoint.required);
assert!(!project_create_endpoint.list);
assert!(project_create_endpoint.arguments.contains_key("input"));
if let Some(input) = project_create_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "ProjectCreateMutationInput");
}
}
#[test]
fn test_fmt_node_update_endpoint_name() {
let project_type = mock_project_type();
assert!(fmt_node_update_endpoint_name(&project_type) == "ProjectUpdate");
}
#[test]
fn test_generate_node_update_endpoint() {
let project_type = mock_project_type();
let project_update_endpoint = generate_node_update_endpoint(&project_type);
assert!(project_update_endpoint.name == "ProjectUpdate");
assert!(project_update_endpoint.kind == PropertyKind::NodeUpdateMutation);
assert!(project_update_endpoint.type_name == "Project");
assert!(!project_update_endpoint.required);
assert!(project_update_endpoint.list);
assert!(project_update_endpoint.arguments.contains_key("input"));
if let Some(input) = project_update_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "ProjectUpdateInput");
}
}
#[test]
fn test_fmt_node_delete_endpoint_name() {
let project_type = mock_project_type();
assert!(fmt_node_delete_endpoint_name(&project_type) == "ProjectDelete");
}
#[test]
fn test_generate_node_delete_endpoint() {
let project_type = mock_project_type();
let project_delete_endpoint = generate_node_delete_endpoint(&project_type);
assert!(project_delete_endpoint.name == "ProjectDelete");
assert!(match &project_delete_endpoint.kind {
PropertyKind::NodeDeleteMutation { label } => label == "Project",
_ => false,
});
assert!(project_delete_endpoint.type_name == "Int");
assert!(!project_delete_endpoint.required);
assert!(!project_delete_endpoint.list);
assert!(project_delete_endpoint.arguments.contains_key("input"));
if let Some(input) = project_delete_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "ProjectDeleteInput");
}
}
#[test]
fn test_fmt_rel_object_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(fmt_rel_object_name(&project_type, project_owner_rel) == "ProjectOwnerRel");
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_rel_object() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_object = generate_rel_object(&project_type, project_owner_rel);
let project_owner_id = project_owner_object.props.get("id").unwrap();
assert!(project_owner_id.name == "id");
assert!(project_owner_id.kind == PropertyKind::Scalar);
assert!(project_owner_id.type_name == "ID");
assert!(project_owner_id.required);
assert!(!project_owner_id.list);
assert!(project_owner_id.arguments.is_empty());
let project_owner_since = project_owner_object.props.get("since").unwrap();
assert!(project_owner_since.name == "since");
assert!(project_owner_since.kind == PropertyKind::Scalar);
assert!(project_owner_since.type_name == "String");
assert!(!project_owner_since.required);
assert!(!project_owner_since.list);
assert!(project_owner_since.arguments.is_empty());
let project_owner_dst = project_owner_object.props.get("dst").unwrap();
assert!(project_owner_dst.name == "dst");
assert!(project_owner_dst.kind == PropertyKind::Union);
assert!(project_owner_dst.type_name == "ProjectOwnerNodesUnion");
assert!(project_owner_dst.required);
assert!(!project_owner_dst.list);
assert!(project_owner_dst.arguments.is_empty());
let project_owner_src = project_owner_object.props.get("src").unwrap();
assert!(project_owner_src.name == "src");
assert!(project_owner_src.kind == PropertyKind::Object);
assert!(project_owner_src.type_name == "Project");
assert!(project_owner_src.required);
assert!(!project_owner_src.list);
assert!(project_owner_src.arguments.is_empty());
let project_type = mock_project_type();
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_object = generate_rel_object(&project_type, project_board_rel);
let project_board_id = project_board_object.props.get("id").unwrap();
assert!(project_board_id.name == "id");
assert!(project_board_id.kind == PropertyKind::Scalar);
assert!(project_board_id.type_name == "ID");
assert!(project_board_id.required);
assert!(!project_board_id.list);
assert!(project_board_id.arguments.is_empty());
let project_board_dst = project_board_object.props.get("dst").unwrap();
assert!(project_board_dst.name == "dst");
assert!(project_board_dst.kind == PropertyKind::Union);
assert!(project_board_dst.type_name == "ProjectBoardNodesUnion");
assert!(project_board_dst.required);
assert!(!project_board_dst.list);
assert!(project_board_dst.arguments.is_empty());
let project_board_src = project_board_object.props.get("src").unwrap();
assert!(project_board_src.name == "src");
assert!(project_board_src.kind == PropertyKind::Object);
assert!(project_board_src.type_name == "Project");
assert!(project_board_src.required);
assert!(!project_board_src.list);
assert!(project_board_src.arguments.is_empty());
}
#[test]
fn test_fmt_rel_nodes_union_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_nodes_union_name(&project_type, project_owner_rel) == "ProjectOwnerNodesUnion"
);
}
#[test]
fn test_generate_rel_nodes_union() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_nodes_union = generate_rel_nodes_union(&project_type, project_owner_rel);
assert!(project_owner_nodes_union.type_name == "ProjectOwnerNodesUnion");
assert!(project_owner_nodes_union.type_kind == TypeKind::Union);
assert!(project_owner_nodes_union.props.is_empty());
let project_owner_nodes = project_owner_nodes_union.union_types.unwrap();
assert!(project_owner_nodes.len() == 1);
assert!(project_owner_nodes[0] == "User");
let project_type = mock_project_type();
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_nodes_union = generate_rel_nodes_union(&project_type, project_board_rel);
assert!(project_board_nodes_union.type_name == "ProjectBoardNodesUnion");
assert!(project_board_nodes_union.type_kind == TypeKind::Union);
assert!(project_board_nodes_union.props.is_empty());
let project_board_nodes = project_board_nodes_union.union_types.unwrap();
assert!(project_board_nodes.len() == 2);
assert!(project_board_nodes[0] == "ScrumBoard");
assert!(project_board_nodes[1] == "KanbanBoard");
}
#[test]
fn test_fmt_rel_query_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_query_input_name(&project_type, project_owner_rel) == "ProjectOwnerQueryInput"
);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_rel_query_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_query_input =
generate_rel_query_input(&project_type, project_owner_rel).unwrap();
let project_owner_id = project_owner_query_input.props.get("id").unwrap();
assert!(project_owner_id.name == "id");
assert!(project_owner_id.kind == PropertyKind::ScalarComp);
assert!(project_owner_id.type_name == "StringQueryInput");
assert!(!project_owner_id.required);
assert!(!project_owner_id.list);
assert!(project_owner_id.arguments.is_empty());
let project_owner_since = project_owner_query_input.props.get("since").unwrap();
assert!(project_owner_since.name == "since");
assert!(project_owner_since.kind == PropertyKind::ScalarComp);
assert!(project_owner_since.type_name == "StringQueryInput");
assert!(!project_owner_since.required);
assert!(!project_owner_since.list);
assert!(project_owner_since.arguments.is_empty());
let project_owner_src = project_owner_query_input.props.get("src").unwrap();
assert!(project_owner_src.name == "src");
assert!(project_owner_src.kind == PropertyKind::Input);
assert!(project_owner_src.type_name == "ProjectOwnerSrcQueryInput");
assert!(!project_owner_src.required);
assert!(!project_owner_src.list);
assert!(project_owner_src.arguments.is_empty());
let project_owner_dst = project_owner_query_input.props.get("dst").unwrap();
assert!(project_owner_dst.name == "dst");
assert!(project_owner_dst.kind == PropertyKind::Input);
assert!(project_owner_dst.type_name == "ProjectOwnerDstQueryInput");
assert!(!project_owner_dst.required);
assert!(!project_owner_dst.list);
assert!(project_owner_dst.arguments.is_empty());
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_query_input =
generate_rel_query_input(&project_type, project_board_rel).unwrap();
let project_board_id = project_board_query_input.props.get("id").unwrap();
assert!(project_board_id.name == "id");
assert!(project_board_id.kind == PropertyKind::ScalarComp);
assert!(project_board_id.type_name == "StringQueryInput");
assert!(!project_board_id.required);
assert!(!project_board_id.list);
assert!(project_board_id.arguments.is_empty());
let project_board_src = project_board_query_input.props.get("src").unwrap();
assert!(project_board_src.name == "src");
assert!(project_board_src.kind == PropertyKind::Input);
assert!(project_board_src.type_name == "ProjectBoardSrcQueryInput");
assert!(!project_board_src.required);
assert!(!project_board_src.list);
assert!(project_board_src.arguments.is_empty());
let project_board_dst = project_board_query_input.props.get("dst").unwrap();
assert!(project_board_dst.name == "dst");
assert!(project_board_dst.kind == PropertyKind::Input);
assert!(project_board_dst.type_name == "ProjectBoardDstQueryInput");
assert!(!project_board_dst.required);
assert!(!project_board_dst.list);
assert!(project_board_dst.arguments.is_empty());
}
#[test]
fn test_fmt_rel_create_mutation_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_create_mutation_input_name(&project_type, project_owner_rel)
== "ProjectOwnerCreateMutationInput"
);
}
#[test]
fn test_generate_rel_create_mutation_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_mutation_input =
generate_rel_create_mutation_input(&project_type, project_owner_rel);
assert!(project_owner_mutation_input.type_name == "ProjectOwnerCreateMutationInput");
let project_owner_since = project_owner_mutation_input.props.get("since").unwrap();
assert!(project_owner_since.name == "since");
assert!(project_owner_since.kind == PropertyKind::Scalar);
assert!(project_owner_since.type_name == "String");
assert!(!project_owner_since.required);
assert!(!project_owner_since.list);
assert!(project_owner_since.arguments.is_empty());
let project_owner_dst = project_owner_mutation_input.props.get("dst").unwrap();
assert!(project_owner_dst.name == "dst");
assert!(project_owner_dst.kind == PropertyKind::Input);
assert!(project_owner_dst.type_name == "ProjectOwnerNodesMutationInputUnion");
assert!(project_owner_dst.required);
assert!(!project_owner_dst.list);
assert!(project_owner_dst.arguments.is_empty());
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_mutation_input =
generate_rel_create_mutation_input(&project_type, project_board_rel);
assert!(project_board_mutation_input.type_name == "ProjectBoardCreateMutationInput");
let project_board_props = project_board_mutation_input.props.get("props");
assert!(project_board_props.is_none());
let project_board_dst = project_board_mutation_input.props.get("dst").unwrap();
assert!(project_board_dst.name == "dst");
assert!(project_board_dst.kind == PropertyKind::Input);
assert!(project_board_dst.type_name == "ProjectBoardNodesMutationInputUnion");
assert!(project_board_dst.required);
assert!(!project_board_dst.list);
assert!(project_board_dst.arguments.is_empty());
}
#[test]
fn test_fmt_rel_change_input_name() {
let project_type = mock_project_type();
let project_issues_rel = project_type.rels().find(|&r| r.name() == "issues").unwrap();
assert!(
fmt_rel_change_input_name(&project_type, project_issues_rel)
== "ProjectIssuesChangeInput"
);
}
#[test]
fn test_generate_rel_change_input() {
let project_type = mock_project_type();
let project_issues_rel = project_type.rels().find(|&r| r.name() == "issues").unwrap();
let project_issues_change_input =
generate_rel_change_input(&project_type, project_issues_rel);
assert!(project_issues_change_input.type_name == "ProjectIssuesChangeInput");
let project_issues_add = project_issues_change_input.props.get("ADD").unwrap();
assert!(project_issues_add.name == "ADD");
assert!(project_issues_add.kind == PropertyKind::Input);
assert!(project_issues_add.type_name == "ProjectIssuesCreateMutationInput");
assert!(!project_issues_add.required);
assert!(!project_issues_add.list);
assert!(project_issues_add.arguments.is_empty());
let project_issues_update = project_issues_change_input.props.get("UPDATE").unwrap();
assert!(project_issues_update.name == "UPDATE");
assert!(project_issues_update.kind == PropertyKind::Input);
assert!(project_issues_update.type_name == "ProjectIssuesUpdateInput");
assert!(!project_issues_update.required);
assert!(!project_issues_update.list);
assert!(project_issues_update.arguments.is_empty());
let project_issues_delete = project_issues_change_input.props.get("DELETE").unwrap();
assert!(project_issues_delete.name == "DELETE");
assert!(project_issues_delete.kind == PropertyKind::Input);
assert!(project_issues_delete.type_name == "ProjectIssuesDeleteInput");
assert!(!project_issues_delete.required);
assert!(!project_issues_delete.list);
assert!(project_issues_delete.arguments.is_empty());
}
#[test]
fn test_fmt_rel_update_mutation_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_update_mutation_input_name(&project_type, project_owner_rel)
== "ProjectOwnerUpdateMutationInput"
);
}
#[test]
fn test_generate_rel_update_mutation_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_update_mutation_input =
generate_rel_update_mutation_input(&project_type, project_owner_rel);
assert!(project_owner_update_mutation_input.type_name == "ProjectOwnerUpdateMutationInput");
let since = project_owner_update_mutation_input
.props
.get("since")
.unwrap();
assert!(since.name == "since");
assert!(since.kind == PropertyKind::Scalar);
assert!(since.type_name == "String");
assert!(!since.required);
assert!(!since.list);
assert!(since.arguments.is_empty());
let src = project_owner_update_mutation_input
.props
.get("src")
.unwrap();
assert!(src.name == "src");
assert!(src.kind == PropertyKind::Input);
assert!(src.type_name == "ProjectOwnerSrcUpdateMutationInput");
assert!(!src.required);
assert!(!src.list);
assert!(src.arguments.is_empty());
let dst = project_owner_update_mutation_input
.props
.get("dst")
.unwrap();
assert!(dst.name == "dst");
assert!(dst.kind == PropertyKind::Input);
assert!(dst.type_name == "ProjectOwnerDstUpdateMutationInput");
assert!(!dst.required);
assert!(!dst.list);
assert!(dst.arguments.is_empty());
}
#[test]
fn test_fmt_rel_src_update_mutation_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_src_update_mutation_input_name(&project_type, project_owner_rel)
== "ProjectOwnerSrcUpdateMutationInput"
);
}
#[test]
fn test_generate_rel_src_update_mutation_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_src_update_mutation_input =
generate_rel_src_update_mutation_input(&project_type, project_owner_rel);
assert!(
project_owner_src_update_mutation_input.type_name
== "ProjectOwnerSrcUpdateMutationInput"
);
let project = project_owner_src_update_mutation_input
.props
.get("Project")
.unwrap();
assert!(project.name == "Project");
assert!(project.kind == PropertyKind::Input);
assert!(project.type_name == "ProjectUpdateMutationInput");
assert!(!project.required);
assert!(!project.list);
assert!(project.arguments.is_empty());
let project_issues_rel = project_type.rels().find(|&r| r.name() == "issues").unwrap();
let project_issues_src_update_mutation_input =
generate_rel_src_update_mutation_input(&project_type, project_issues_rel);
assert!(
project_issues_src_update_mutation_input.type_name
== "ProjectIssuesSrcUpdateMutationInput"
);
let project2 = project_issues_src_update_mutation_input
.props
.get("Project")
.unwrap();
assert!(project2.name == "Project");
assert!(project2.kind == PropertyKind::Input);
assert!(project2.type_name == "ProjectUpdateMutationInput");
assert!(!project2.required);
assert!(!project2.list);
assert!(project2.arguments.is_empty());
}
#[test]
fn test_fmt_rel_dst_update_mutation_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_dst_update_mutation_input_name(&project_type, project_owner_rel)
== "ProjectOwnerDstUpdateMutationInput"
);
}
#[test]
fn test_generate_rel_dst_update_mutation_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_dst_update_mutation_input =
generate_rel_dst_update_mutation_input(&project_type, project_owner_rel);
assert!(
project_owner_dst_update_mutation_input.type_name
== "ProjectOwnerDstUpdateMutationInput"
);
let user = project_owner_dst_update_mutation_input
.props
.get("User")
.unwrap();
assert!(user.name() == "User");
assert!(user.kind == PropertyKind::Input);
assert!(user.type_name == "UserUpdateMutationInput");
assert!(!user.required);
assert!(!user.list());
assert!(user.arguments.is_empty());
let project_issues_rel = project_type.rels().find(|&r| r.name() == "issues").unwrap();
let project_issues_dst_update_mutation_input =
generate_rel_dst_update_mutation_input(&project_type, project_issues_rel);
assert!(
project_issues_dst_update_mutation_input.type_name
== "ProjectIssuesDstUpdateMutationInput"
);
let bug = project_issues_dst_update_mutation_input
.props
.get("Bug")
.unwrap();
assert!(bug.name == "Bug");
assert!(bug.kind == PropertyKind::Input);
assert!(bug.type_name == "BugUpdateMutationInput");
assert!(!bug.required);
assert!(!bug.list);
assert!(bug.arguments.is_empty());
let feature = project_issues_dst_update_mutation_input
.props
.get("Feature")
.unwrap();
assert!(feature.name == "Feature");
assert!(feature.kind == PropertyKind::Input);
assert!(feature.type_name == "FeatureUpdateMutationInput");
assert!(!feature.required);
assert!(!feature.list);
assert!(feature.arguments.is_empty());
}
#[test]
fn test_fmt_rel_src_query_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_src_query_input_name(&project_type, project_owner_rel)
== "ProjectOwnerSrcQueryInput"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_src_query_input_name(&project_type, project_board_rel)
== "ProjectBoardSrcQueryInput"
);
}
#[test]
fn test_fmt_rel_dst_query_input_name_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_dst_query_input_name(&project_type, project_owner_rel)
== "ProjectOwnerDstQueryInput"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_dst_query_input_name(&project_type, project_board_rel)
== "ProjectBoardDstQueryInput"
);
}
#[test]
fn test_generate_rel_dst_query_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_nodes_query_input_union =
generate_rel_dst_query_input(&project_type, project_owner_rel);
assert!(project_owner_nodes_query_input_union.type_name == "ProjectOwnerDstQueryInput");
assert!(project_owner_nodes_query_input_union.type_kind == TypeKind::Input);
assert!(project_owner_nodes_query_input_union.props.len() == 1);
let user_input = project_owner_nodes_query_input_union
.props
.get("User")
.unwrap();
assert!(user_input.name == "User");
assert!(user_input.kind == PropertyKind::Input);
assert!(user_input.type_name == "UserQueryInput");
assert!(!user_input.required());
assert!(!user_input.list);
assert!(user_input.arguments.is_empty());
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_nodes_query_input_union =
generate_rel_dst_query_input(&project_type, project_board_rel);
assert!(project_board_nodes_query_input_union.type_name == "ProjectBoardDstQueryInput");
assert!(project_board_nodes_query_input_union.type_kind == TypeKind::Input);
assert!(project_board_nodes_query_input_union.props.len() == 2);
let kanbanboard_input = project_board_nodes_query_input_union
.props
.get("KanbanBoard")
.unwrap();
assert!(kanbanboard_input.name == "KanbanBoard");
assert!(kanbanboard_input.kind == PropertyKind::Input);
assert!(kanbanboard_input.type_name == "KanbanBoardQueryInput");
assert!(!kanbanboard_input.required());
assert!(!kanbanboard_input.list);
assert!(kanbanboard_input.arguments.is_empty());
let scrumboard_input = project_board_nodes_query_input_union
.props
.get("ScrumBoard")
.unwrap();
assert!(scrumboard_input.name == "ScrumBoard");
assert!(scrumboard_input.kind == PropertyKind::Input);
assert!(scrumboard_input.type_name == "ScrumBoardQueryInput");
assert!(!scrumboard_input.required());
assert!(!scrumboard_input.list);
assert!(scrumboard_input.arguments.is_empty());
}
#[test]
fn test_fmt_rel_nodes_mutation_input_union_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_nodes_mutation_input_union_name(&project_type, project_owner_rel)
== "ProjectOwnerNodesMutationInputUnion"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_nodes_mutation_input_union_name(&project_type, project_board_rel)
== "ProjectBoardNodesMutationInputUnion"
);
}
#[test]
fn test_generate_rel_nodes_mutation_input_union() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_nodes_mutation_input_union =
generate_rel_nodes_mutation_input_union(&project_type, project_owner_rel);
assert!(
project_owner_nodes_mutation_input_union.type_name
== "ProjectOwnerNodesMutationInputUnion"
);
assert!(project_owner_nodes_mutation_input_union.type_kind == TypeKind::Input);
assert!(project_owner_nodes_mutation_input_union.props.len() == 1);
let user_input = project_owner_nodes_mutation_input_union
.props
.get("User")
.unwrap();
assert!(user_input.name == "User");
assert!(user_input.kind == PropertyKind::Input);
assert!(user_input.type_name == "UserInput");
assert!(!user_input.required());
assert!(!user_input.list);
assert!(user_input.arguments.is_empty());
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_nodes_mutation_input_union =
generate_rel_nodes_mutation_input_union(&project_type, project_board_rel);
assert!(
project_board_nodes_mutation_input_union.type_name
== "ProjectBoardNodesMutationInputUnion"
);
assert!(project_board_nodes_mutation_input_union.type_kind == TypeKind::Input);
assert!(project_board_nodes_mutation_input_union.props.len() == 2);
let kanbanboard_input = project_board_nodes_mutation_input_union
.props
.get("KanbanBoard")
.unwrap();
assert!(kanbanboard_input.name == "KanbanBoard");
assert!(kanbanboard_input.kind == PropertyKind::Input);
assert!(kanbanboard_input.type_name == "KanbanBoardInput");
assert!(!kanbanboard_input.required());
assert!(!kanbanboard_input.list);
assert!(kanbanboard_input.arguments.is_empty());
let scrumboard_input = project_board_nodes_mutation_input_union
.props
.get("ScrumBoard")
.unwrap();
assert!(scrumboard_input.name == "ScrumBoard");
assert!(scrumboard_input.kind == PropertyKind::Input);
assert!(scrumboard_input.type_name == "ScrumBoardInput");
assert!(!scrumboard_input.required());
assert!(!scrumboard_input.list);
assert!(scrumboard_input.arguments.is_empty());
}
#[test]
fn test_fmt_rel_create_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_create_input_name(&project_type, project_owner_rel)
== "ProjectOwnerCreateInput"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_create_input_name(&project_type, project_board_rel)
== "ProjectBoardCreateInput"
);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_rel_create_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_create_input =
generate_rel_create_input(&project_type, project_owner_rel);
assert!(project_owner_create_input.type_name == "ProjectOwnerCreateInput");
assert!(project_owner_create_input.type_kind == TypeKind::Input);
assert!(project_owner_create_input.props.len() == 2);
let project_owner_match = project_owner_create_input.props.get("MATCH").unwrap();
assert!(project_owner_match.name == "MATCH");
assert!(project_owner_match.kind == PropertyKind::Input);
assert!(project_owner_match.type_name == "ProjectQueryInput");
assert!(!project_owner_match.required);
assert!(!project_owner_match.list);
assert!(project_owner_match.arguments.is_empty());
let project_owner_create = project_owner_create_input.props.get("CREATE").unwrap();
assert!(project_owner_create.name == "CREATE");
assert!(project_owner_create.kind == PropertyKind::Input);
assert!(project_owner_create.type_name == "ProjectOwnerCreateMutationInput");
assert!(!project_owner_create.required);
assert!(!project_owner_create.list);
assert!(project_owner_create.arguments.is_empty());
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_create_input =
generate_rel_create_input(&project_type, project_board_rel);
assert!(project_board_create_input.type_name == "ProjectBoardCreateInput");
assert!(project_board_create_input.type_kind == TypeKind::Input);
assert!(project_board_create_input.props.len() == 2);
let project_board_match = project_board_create_input.props.get("MATCH").unwrap();
assert!(project_board_match.name == "MATCH");
assert!(project_board_match.kind == PropertyKind::Input);
assert!(project_board_match.type_name == "ProjectQueryInput");
assert!(!project_board_match.required);
assert!(!project_board_match.list);
assert!(project_board_match.arguments.is_empty());
let project_board_create = project_board_create_input.props.get("CREATE").unwrap();
assert!(project_board_create.name == "CREATE");
assert!(project_board_create.kind == PropertyKind::Input);
assert!(project_board_create.type_name == "ProjectBoardCreateMutationInput");
assert!(!project_board_create.required);
assert!(!project_board_create.list);
assert!(project_board_create.arguments.is_empty());
}
#[test]
fn test_fmt_rel_update_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_update_input_name(&project_type, project_owner_rel)
== "ProjectOwnerUpdateInput"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_update_input_name(&project_type, project_board_rel)
== "ProjectBoardUpdateInput"
);
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_rel_update_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_update_input =
generate_rel_update_input(&project_type, project_owner_rel);
assert!(project_owner_update_input.type_name == "ProjectOwnerUpdateInput");
assert!(project_owner_update_input.type_kind == TypeKind::Input);
assert!(project_owner_update_input.props.len() == 2);
let project_owner_match = project_owner_update_input.props.get("MATCH").unwrap();
assert!(project_owner_match.name == "MATCH");
assert!(project_owner_match.kind == PropertyKind::Input);
assert!(project_owner_match.type_name == "ProjectOwnerQueryInput");
assert!(!project_owner_match.required);
assert!(!project_owner_match.list);
assert!(project_owner_match.arguments.is_empty());
let project_owner_update = project_owner_update_input.props.get("SET").unwrap();
assert!(project_owner_update.name == "SET");
assert!(project_owner_update.kind == PropertyKind::Input);
assert!(project_owner_update.type_name == "ProjectOwnerUpdateMutationInput");
assert!(project_owner_update.required);
assert!(!project_owner_update.list);
assert!(project_owner_update.arguments.is_empty());
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
let project_board_update_input =
generate_rel_update_input(&project_type, project_board_rel);
assert!(project_board_update_input.type_name == "ProjectBoardUpdateInput");
assert!(project_board_update_input.type_kind == TypeKind::Input);
assert!(project_board_update_input.props.len() == 2);
let project_board_match = project_board_update_input.props.get("MATCH").unwrap();
assert!(project_board_match.name == "MATCH");
assert!(project_board_match.kind == PropertyKind::Input);
assert!(project_board_match.type_name == "ProjectBoardQueryInput");
assert!(!project_board_match.required);
assert!(!project_board_match.list);
assert!(project_board_match.arguments.is_empty());
let project_board_update = project_board_update_input.props.get("SET").unwrap();
assert!(project_board_update.name == "SET");
assert!(project_board_update.kind == PropertyKind::Input);
assert!(project_board_update.type_name == "ProjectBoardUpdateMutationInput");
assert!(project_board_update.required);
assert!(!project_board_update.list);
assert!(project_board_update.arguments.is_empty());
}
#[test]
fn test_fmt_rel_delete_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_delete_input_name(&project_type, project_owner_rel)
== "ProjectOwnerDeleteInput"
);
}
#[test]
fn test_generate_rel_delete_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_delete_input =
generate_rel_delete_input(&project_type, project_owner_rel);
assert!(project_owner_delete_input.type_name == "ProjectOwnerDeleteInput");
let pmatch = project_owner_delete_input.props.get("MATCH").unwrap();
assert!(pmatch.name == "MATCH");
assert!(pmatch.kind == PropertyKind::Input);
assert!(pmatch.type_name == "ProjectOwnerQueryInput");
assert!(!pmatch.required);
assert!(!pmatch.list);
assert!(pmatch.arguments.is_empty());
let src = project_owner_delete_input.props.get("src").unwrap();
assert!(src.name == "src");
assert!(src.kind == PropertyKind::Input);
assert!(src.type_name == "ProjectOwnerSrcDeleteMutationInput");
assert!(!src.required);
assert!(!src.list);
assert!(src.arguments.is_empty());
let dst = project_owner_delete_input.props.get("dst").unwrap();
assert!(dst.name == "dst");
assert!(dst.kind == PropertyKind::Input);
assert!(dst.type_name == "ProjectOwnerDstDeleteMutationInput");
assert!(!dst.required);
assert!(!dst.list);
assert!(dst.arguments.is_empty());
}
#[test]
fn test_fmt_rel_src_delete_mutation_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_src_delete_mutation_input_name(&project_type, project_owner_rel)
== "ProjectOwnerSrcDeleteMutationInput"
);
}
#[test]
fn test_generate_rel_src_delete_mutation_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_src_delete_mutation_input =
generate_rel_src_delete_mutation_input(&project_type, project_owner_rel);
assert!(
project_owner_src_delete_mutation_input.type_name
== "ProjectOwnerSrcDeleteMutationInput"
);
assert!(project_owner_src_delete_mutation_input.props.len() == 1);
let project = project_owner_src_delete_mutation_input
.props
.get("Project")
.unwrap();
assert!(project.name == "Project");
assert!(project.kind == PropertyKind::Input);
assert!(project.type_name == "ProjectDeleteMutationInput");
assert!(!project.required);
assert!(!project.list);
assert!(project.arguments.is_empty());
}
#[test]
fn test_fmt_rel_dst_delete_mutation_input_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_dst_delete_mutation_input_name(&project_type, project_owner_rel)
== "ProjectOwnerDstDeleteMutationInput"
);
}
#[test]
fn test_generate_rel_dst_delete_mutation_input() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_dst_delete_mutation_input =
generate_rel_dst_delete_mutation_input(&project_type, project_owner_rel);
assert!(
project_owner_dst_delete_mutation_input.type_name
== "ProjectOwnerDstDeleteMutationInput"
);
assert!(project_owner_dst_delete_mutation_input.props.len() == 1);
let user = project_owner_dst_delete_mutation_input
.props
.get("User")
.unwrap();
assert!(user.name() == "User");
assert!(user.kind == PropertyKind::Input);
assert!(user.type_name == "UserDeleteMutationInput");
assert!(!user.required);
assert!(!user.list());
assert!(user.arguments.is_empty());
let project_issues_rel = project_type.rels().find(|&r| r.name() == "issues").unwrap();
let project_issues_dst_delete_mutation_input =
generate_rel_dst_delete_mutation_input(&project_type, project_issues_rel);
assert!(
project_issues_dst_delete_mutation_input.type_name
== "ProjectIssuesDstDeleteMutationInput"
);
assert!(project_issues_dst_delete_mutation_input.props.len() == 2);
let bug = project_issues_dst_delete_mutation_input
.props
.get("Bug")
.unwrap();
assert!(bug.name == "Bug");
assert!(bug.kind == PropertyKind::Input);
assert!(bug.type_name == "BugDeleteMutationInput");
assert!(!bug.required);
assert!(!bug.list);
assert!(bug.arguments.is_empty());
let feature = project_issues_dst_delete_mutation_input
.props
.get("Feature")
.unwrap();
assert!(feature.name == "Feature");
assert!(feature.kind == PropertyKind::Input);
assert!(feature.type_name == "FeatureDeleteMutationInput");
assert!(!feature.required);
assert!(!feature.list);
assert!(feature.arguments.is_empty());
}
#[test]
fn test_fmt_rel_read_endpoint_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(fmt_rel_read_endpoint_name(&project_type, project_owner_rel) == "ProjectOwner");
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(fmt_rel_read_endpoint_name(&project_type, project_board_rel) == "ProjectBoard");
}
#[test]
fn test_generate_rel_read_endpoint() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_read_endpoint =
generate_rel_read_endpoint(&project_type, project_owner_rel);
assert!(project_owner_read_endpoint.name == "ProjectOwner");
assert!(match &project_owner_read_endpoint.kind {
PropertyKind::Rel { rel_name } => rel_name == "owner",
_ => false,
});
assert!(project_owner_read_endpoint.type_name == "ProjectOwnerRel");
assert!(!project_owner_read_endpoint.required);
assert!(project_owner_read_endpoint.list);
assert!(project_owner_read_endpoint.arguments.contains_key("input"));
if let Some(input) = project_owner_read_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "ProjectOwnerQueryInput");
}
}
#[test]
fn test_fmt_rel_create_endpoint_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_create_endpoint_name(&project_type, project_owner_rel) == "ProjectOwnerCreate"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_create_endpoint_name(&project_type, project_board_rel) == "ProjectBoardCreate"
);
}
#[test]
fn test_generate_rel_create_endpoint() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_create_endpoint =
generate_rel_create_endpoint(&project_type, project_owner_rel);
assert!(project_owner_create_endpoint.name == "ProjectOwnerCreate");
assert!(match &project_owner_create_endpoint.kind {
PropertyKind::RelCreateMutation {
src_label,
rel_name,
} => src_label == "Project" && rel_name == "owner",
_ => false,
});
assert!(project_owner_create_endpoint.type_name == "ProjectOwnerRel");
assert!(!project_owner_create_endpoint.required);
assert!(project_owner_create_endpoint.list);
assert!(project_owner_create_endpoint
.arguments
.contains_key("input"));
if let Some(input) = project_owner_create_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "ProjectOwnerCreateInput");
}
}
#[test]
fn test_fmt_rel_update_endpoint_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_update_endpoint_name(&project_type, project_owner_rel) == "ProjectOwnerUpdate"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_update_endpoint_name(&project_type, project_board_rel) == "ProjectBoardUpdate"
);
}
#[test]
fn test_generate_rel_update_endpoint() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_update_endpoint =
generate_rel_update_endpoint(&project_type, project_owner_rel);
assert!(project_owner_update_endpoint.name == "ProjectOwnerUpdate");
assert!(match &project_owner_update_endpoint.kind {
PropertyKind::RelUpdateMutation {
src_label,
rel_name,
} => src_label == "Project" && rel_name == "owner",
_ => false,
});
assert!(project_owner_update_endpoint.type_name == "ProjectOwnerRel");
assert!(!project_owner_update_endpoint.required);
assert!(project_owner_update_endpoint.list);
assert!(project_owner_update_endpoint
.arguments
.contains_key("input"));
if let Some(input) = project_owner_update_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "ProjectOwnerUpdateInput");
}
}
#[test]
fn test_fmt_rel_delete_endpoint_name() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
assert!(
fmt_rel_delete_endpoint_name(&project_type, project_owner_rel) == "ProjectOwnerDelete"
);
let project_board_rel = project_type.rels().find(|&r| r.name() == "board").unwrap();
assert!(
fmt_rel_delete_endpoint_name(&project_type, project_board_rel) == "ProjectBoardDelete"
);
}
#[test]
fn test_generate_rel_delete_endpoint() {
let project_type = mock_project_type();
let project_owner_rel = project_type.rels().find(|&r| r.name() == "owner").unwrap();
let project_owner_delete_endpoint =
generate_rel_delete_endpoint(&project_type, project_owner_rel);
assert!(project_owner_delete_endpoint.name == "ProjectOwnerDelete");
assert!(match &project_owner_delete_endpoint.kind {
PropertyKind::RelDeleteMutation {
src_label,
rel_name,
} => src_label == "Project" && rel_name == "owner",
_ => false,
});
assert!(project_owner_delete_endpoint.type_name == "Int");
assert!(!project_owner_delete_endpoint.required);
assert!(!project_owner_delete_endpoint.list);
assert!(project_owner_delete_endpoint
.arguments
.contains_key("input"));
if let Some(input) = project_owner_delete_endpoint.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "ProjectOwnerDeleteInput");
}
}
#[allow(clippy::cognitive_complexity)]
#[test]
fn test_generate_custom_endpoint() {
let e1 = mock_endpoint_one();
let e1_object = generate_custom_endpoint(&e1);
assert!(e1_object.name == "RegisterUsers");
assert!(e1_object.kind == PropertyKind::CustomResolver);
assert!(e1_object.type_name == "User");
assert!(e1_object.required);
assert!(e1_object.list);
assert!(e1_object.arguments.contains_key("input"));
if let Some(input) = e1_object.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "UserCreateMutationInput");
}
let e2 = mock_endpoint_two();
let e2_object = generate_custom_endpoint(&e2);
assert!(e2_object.name == "DisableUser");
assert!(e2_object.kind == PropertyKind::CustomResolver);
assert!(e2_object.type_name == "User");
assert!(e2_object.required);
assert!(!e2_object.list);
assert!(e2_object.arguments.contains_key("input"));
if let Some(input) = e2_object.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Required);
assert!(input.type_name == "UserQueryInput");
}
let e3 = mock_endpoint_three();
let e3_object = generate_custom_endpoint(&e3);
assert!(e3_object.name == "ComputeBurndown");
assert!(e3_object.kind == PropertyKind::CustomResolver);
assert!(e3_object.type_name == "BurndownMetrics");
assert!(e3_object.required);
assert!(!e3_object.list);
assert!(e3_object.arguments.contains_key("input"));
if let Some(input) = e3_object.arguments.get("input") {
assert!(input.name == "input");
assert!(input.kind == ArgumentKind::Optional);
assert!(input.type_name == "BurndownFilter");
}
}
#[test]
fn test_generate_schema() {
let config = mock_config();
let schema = generate_schema(&config).unwrap();
assert!(schema.contains_key("Project"));
assert!(schema.contains_key("ProjectQueryInput"));
assert!(schema.contains_key("ProjectCreateMutationInput"));
assert!(schema.contains_key("ProjectUpdateMutationInput"));
assert!(schema.contains_key("ProjectInput"));
assert!(schema.contains_key("ProjectUpdateInput"));
assert!(schema.contains_key("ProjectOwnerRel"));
assert!(schema.contains_key("Query"));
assert!(schema.contains_key("Mutation"));
}
#[test]
fn test_wg_type_endpoints_filter() {
let config = mock_endpoints_filter();
let schema = generate_schema(&config).unwrap();
let query = schema.get("Query").unwrap();
let mutation = schema.get("Mutation").unwrap();
assert!(query.props.len() == 1);
assert!(mutation.props.len() == 1);
}
#[test]
fn test_wg_rels_endpoints_filter() {}
#[test]
fn test_create_root_node() {
let config = mock_config();
let root_node = create_root_node::<()>(&config);
assert!(root_node.is_ok());
}
#[test]
fn type_lookup_error() {
let config = mock_project_config();
let root_node = create_root_node::<()>(&config);
assert!(root_node.is_err());
}
#[test]
fn test_info_send() {
fn assert_send<T: Send>() {}
assert_send::<Info>();
}
#[test]
fn test_info_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<Info>();
}
}