use std::collections::HashMap;
use castle_query_parser::parse_message;
use castle_types::{Field, FieldKind, Input, Primitive, Projection};
#[test]
fn can_parse_empty_message() {
let query = "";
let expected: Projection = HashMap::new();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
type Root = HashMap<Box<str>, Field>;
#[test]
fn can_parse_single_field() {
let query = "message { first_name }";
let expected = [(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
)]
.into_iter()
.collect::<Root>();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_ident_with_underscore_prefix() {
let query = "message { _first_name }";
let expected = [(
"_first_name".into(),
Field {
ident: "_first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
)]
.into_iter()
.collect::<Root>();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_two_fields_with_empty_args() {
let query = "message {
first_name()
last_name
email()
}";
let expected = [
(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"last_name".into(),
Field {
ident: "last_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"email".into(),
Field {
ident: "email".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
]
.into_iter()
.collect::<Root>();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_object_projection() {
let query = "message {
me {
first_name
}
}";
let expected: Root = [(
"me".into(),
Field {
ident: "me".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(
[(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
)]
.into(),
),
},
)]
.into();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_object_projection_with_two_fields() {
let query = "message {
me() {
first_name,
last_name
}
}";
let expected = [(
"me".into(),
Field {
ident: "me".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(
[
(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"last_name".into(),
Field {
ident: "last_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
]
.into_iter()
.collect::<Root>(),
),
},
)]
.into_iter()
.collect::<Root>();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn query_with_two_separators_fails() {
let query = "message {
me() {
first_name,,
last_name
}
}";
parse_message(query).unwrap_err();
}
#[test]
fn query_with_trailing_comma_succeeds() {
let query = "message {
me() {
first_name,
last_name,
}
}";
let expected: Root = [(
"me".into(),
Field {
ident: "me".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(
[
(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"last_name".into(),
Field {
ident: "last_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
]
.into(),
),
},
)]
.into();
let actual = &parse_message(query).expect("Expected success").projection;
assert_eq!(&expected, actual);
}
#[test]
fn query_without_trailing_comma_succeeds() {
let query = "message {
me() {
first_name
last_name
}
}";
let expected: Root = [(
"me".into(),
Field {
ident: "me".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(
[
(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"last_name".into(),
Field {
ident: "last_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
]
.into(),
),
},
)]
.into();
let actual = &parse_message(query).expect("Expected success").projection;
assert_eq!(&expected, actual);
}
#[test]
fn query_with_missing_closing_bracket_fails() {
let query = "message {
me() {
first_name
}";
parse_message(query).unwrap_err();
}
#[test]
fn can_parse_object_and_single_field() {
let query = "message {
foo {
bar as sdsd
baz
}
xyz
}";
let expected: Root = [
(
"foo".into(),
Field {
ident: "foo".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(
[
(
"bar".into(),
Field {
ident: "bar".into(),
inputs: HashMap::new(),
rename: Some("sdsd".into()),
kind: FieldKind::Field,
},
),
(
"baz".into(),
Field {
ident: "baz".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
]
.into(),
),
},
),
(
"xyz".into(),
Field {
ident: "xyz".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
]
.into();
let actual = &parse_message(query)
.expect("Failed to parse query")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_numeric_argument() {
let query = "message {
profile_picture(size: 48)
}";
let expected: Root = [(
"profile_picture".into(),
Field {
ident: "profile_picture".into(),
inputs: [(
"size".into(),
Input::Primitive(Primitive::Number(48.into())),
)]
.into(),
rename: None,
kind: FieldKind::Field,
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_multiple_numeric_arguments() {
let query = "message {
profile_picture(size: 48, width: 100)
}";
let expected: Root = [(
"profile_picture".into(),
Field {
ident: "profile_picture".into(),
inputs: [
(
"size".into(),
Input::Primitive(Primitive::Number(48.into())),
),
(
"width".into(),
Input::Primitive(Primitive::Number(100.into())),
),
]
.into(),
rename: None,
kind: FieldKind::Field,
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_string_arguments() {
let query = "message {
profile_picture(size: \"48\")
}";
let expected: Root = [(
"profile_picture".into(),
Field {
ident: "profile_picture".into(),
inputs: [(
"size".into(),
Input::Primitive(Primitive::String("48".into())),
)]
.into(),
rename: None,
kind: FieldKind::Field,
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_boolean_arguments() {
let query = "message {
foo(a: true, b: false)
}";
let expected: Root = [(
"foo".into(),
Field {
ident: "foo".into(),
inputs: [
("a".into(), Input::Primitive(Primitive::Boolean(true))),
("b".into(), Input::Primitive(Primitive::Boolean(false))),
]
.into(),
rename: None,
kind: FieldKind::Field,
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_deeply_nested_message() {
let query = "message {
me() {
first_name
last_name
profile_picture(size: 48) {
url
}
}
}";
let expected: Root = [(
"me".into(),
Field {
ident: "me".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(
[
(
"first_name".into(),
Field {
ident: "first_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"last_name".into(),
Field {
ident: "last_name".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
),
(
"profile_picture".into(),
Field {
ident: "profile_picture".into(),
inputs: [(
"size".into(),
Input::Primitive(Primitive::Number(48.into())),
)]
.into(),
rename: None,
kind: FieldKind::Object(
[(
"url".into(),
Field {
ident: "url".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Field,
},
)]
.into(),
),
},
),
]
.into(),
),
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_object_argument() {
let query = "message {
create_user(user: {
first_name: \"John\"
last_name: \"Doe\"
})
}
";
let expected: Root = [(
"create_user".into(),
Field {
ident: "create_user".into(),
inputs: [(
"user".into(),
Input::Map(
[
(
"first_name".into(),
Input::Primitive(Primitive::String("John".into())),
),
(
"last_name".into(),
Input::Primitive(Primitive::String("Doe".into())),
),
]
.into(),
),
)]
.into(),
rename: None,
kind: FieldKind::Field,
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn can_parse_array_arguments() {
let query = "message {
create_user(user: [
{
first_name: \"John\"
last_name: \"Doe\"
},
{
first_name: \"Jane\"
last_name: \"Doe\"
}
])
}
";
let expected: Root = [(
"create_user".into(),
Field {
ident: "create_user".into(),
inputs: [(
"user".into(),
Input::List(
[
Input::Map(
[
(
"first_name".into(),
Input::Primitive(Primitive::String("John".into())),
),
(
"last_name".into(),
Input::Primitive(Primitive::String("Doe".into())),
),
]
.into(),
),
Input::Map(
[
(
"first_name".into(),
Input::Primitive(Primitive::String("Jane".into())),
),
(
"last_name".into(),
Input::Primitive(Primitive::String("Doe".into())),
),
]
.into(),
),
]
.into(),
),
)]
.into(),
rename: None,
kind: FieldKind::Field,
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}
#[test]
fn arg_with_no_ident_fails() {
let query = "message {
()
}
";
parse_message(query).unwrap_err();
}
#[test]
fn can_parse_resolver_with_no_fields() {
let query = "message {
me {
}
}";
let expected: Root = [(
"me".into(),
Field {
ident: "me".into(),
inputs: HashMap::new(),
rename: None,
kind: FieldKind::Object(HashMap::new()),
},
)]
.into();
let actual = &parse_message(query)
.expect("Expected query to parse")
.projection;
assert_eq!(&expected, actual);
}