2020-03-30 02:45:41 +00:00
|
|
|
use crate::context::QueryPathNode;
|
2020-09-08 08:21:27 +00:00
|
|
|
use crate::parser::types::{Directive, Field, Value, Name};
|
2020-05-15 02:08:37 +00:00
|
|
|
use crate::registry::MetaInputValue;
|
2020-03-08 12:35:36 +00:00
|
|
|
use crate::validation::utils::is_valid_input_value;
|
2020-03-24 10:54:22 +00:00
|
|
|
use crate::validation::visitor::{Visitor, VisitorContext};
|
2020-09-08 08:21:27 +00:00
|
|
|
use crate::{Positioned, QueryPathSegment};
|
2020-05-16 02:05:48 +00:00
|
|
|
use indexmap::map::IndexMap;
|
2020-03-08 12:35:36 +00:00
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct ArgumentsOfCorrectType<'a> {
|
2020-05-16 02:05:48 +00:00
|
|
|
current_args: Option<&'a IndexMap<&'static str, MetaInputValue>>,
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
|
2020-05-10 02:59:51 +00:00
|
|
|
fn enter_directive(
|
|
|
|
&mut self,
|
|
|
|
ctx: &mut VisitorContext<'a>,
|
|
|
|
directive: &'a Positioned<Directive>,
|
|
|
|
) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = ctx
|
|
|
|
.registry
|
|
|
|
.directives
|
2020-09-08 08:21:27 +00:00
|
|
|
.get(directive.node.name.node.as_str())
|
2020-03-09 12:39:46 +00:00
|
|
|
.map(|d| &d.args);
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
|
2020-05-09 09:55:04 +00:00
|
|
|
fn exit_directive(
|
|
|
|
&mut self,
|
|
|
|
_ctx: &mut VisitorContext<'a>,
|
2020-05-10 02:59:51 +00:00
|
|
|
_directive: &'a Positioned<Directive>,
|
2020-05-09 09:55:04 +00:00
|
|
|
) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = None;
|
|
|
|
}
|
|
|
|
|
2020-03-09 12:39:46 +00:00
|
|
|
fn enter_argument(
|
|
|
|
&mut self,
|
2020-03-22 08:45:59 +00:00
|
|
|
ctx: &mut VisitorContext<'a>,
|
2020-09-08 08:21:27 +00:00
|
|
|
name: &'a Positioned<Name>,
|
2020-05-10 02:59:51 +00:00
|
|
|
value: &'a Positioned<Value>,
|
2020-03-09 12:39:46 +00:00
|
|
|
) {
|
|
|
|
if let Some(arg) = self
|
2020-03-08 12:35:36 +00:00
|
|
|
.current_args
|
2020-09-08 08:21:27 +00:00
|
|
|
.and_then(|args| args.get(name.node.as_str()).map(|input| input))
|
2020-03-08 12:35:36 +00:00
|
|
|
{
|
2020-09-08 08:21:27 +00:00
|
|
|
let value = value.node.clone().into_const_with(|var_name| ctx.variables.and_then(|variables| variables.0.get(&var_name)).map(Clone::clone).ok_or(())).ok();
|
2020-07-11 02:05:30 +00:00
|
|
|
|
2020-09-08 08:21:27 +00:00
|
|
|
if let Some(validator) = &arg.validator {
|
|
|
|
if let Some(value) = &value {
|
2020-07-30 01:43:51 +00:00
|
|
|
if let Err(reason) = validator.is_valid(value) {
|
2020-07-11 02:05:30 +00:00
|
|
|
ctx.report_error(
|
2020-09-06 05:38:31 +00:00
|
|
|
vec![name.pos],
|
2020-07-11 02:05:30 +00:00
|
|
|
format!("Invalid value for argument \"{}\", {}", arg.name, reason),
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2020-03-21 01:32:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-08 08:21:27 +00:00
|
|
|
if let Some(reason) = value.and_then(|value| is_valid_input_value(
|
2020-03-30 02:45:41 +00:00
|
|
|
ctx.registry,
|
2020-07-11 02:05:30 +00:00
|
|
|
ctx.variables,
|
2020-03-30 02:45:41 +00:00
|
|
|
&arg.ty,
|
2020-09-08 08:21:27 +00:00
|
|
|
&value,
|
2020-03-30 02:45:41 +00:00
|
|
|
QueryPathNode {
|
|
|
|
parent: None,
|
|
|
|
segment: QueryPathSegment::Name(arg.name),
|
|
|
|
},
|
2020-09-08 08:21:27 +00:00
|
|
|
)) {
|
2020-05-09 09:55:04 +00:00
|
|
|
ctx.report_error(
|
2020-09-06 05:38:31 +00:00
|
|
|
vec![name.pos],
|
2020-05-09 09:55:04 +00:00
|
|
|
format!("Invalid value for argument {}", reason),
|
|
|
|
);
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-10 02:59:51 +00:00
|
|
|
fn enter_field(&mut self, ctx: &mut VisitorContext<'a>, field: &'a Positioned<Field>) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = ctx
|
|
|
|
.parent_type()
|
2020-09-06 05:38:31 +00:00
|
|
|
.and_then(|p| p.field_by_name(&field.node.name.node))
|
2020-03-09 12:39:46 +00:00
|
|
|
.map(|f| &f.args);
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:59:51 +00:00
|
|
|
fn exit_field(&mut self, _ctx: &mut VisitorContext<'a>, _field: &'a Positioned<Field>) {
|
2020-03-08 12:35:36 +00:00
|
|
|
self.current_args = None;
|
|
|
|
}
|
|
|
|
}
|
2020-04-05 08:00:26 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
pub fn factory<'a>() -> ArgumentsOfCorrectType<'a> {
|
|
|
|
ArgumentsOfCorrectType::default()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_null_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
intArgField(intArg: null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn null_into_int() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
nonNullIntArgField(nonNullIntArg: null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_int_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
intArgField(intArg: 2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_boolean_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
booleanArgField(booleanArg: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_string_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringArgField(stringArg: "foo")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_float_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
floatArgField(floatArg: 1.1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn int_into_float() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
floatArgField(floatArg: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn int_into_id() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
idArgField(idArg: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_into_id() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
idArgField(idArg: "someIdString")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_enum_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: SIT)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn int_into_string() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringArgField(stringArg: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn float_into_string() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringArgField(stringArg: 1.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn boolean_into_string() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringArgField(stringArg: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unquoted_string_into_string() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringArgField(stringArg: BAR)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_into_int() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
intArgField(intArg: "3")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unquoted_string_into_int() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
intArgField(intArg: FOO)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn simple_float_into_int() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
intArgField(intArg: 3.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn float_into_int() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
intArgField(intArg: 3.333)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_into_float() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
floatArgField(floatArg: "3.333")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn boolean_into_float() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
floatArgField(floatArg: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unquoted_into_float() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
floatArgField(floatArg: FOO)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn int_into_boolean() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
booleanArgField(booleanArg: 2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn float_into_boolean() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
booleanArgField(booleanArg: 1.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_into_boolean() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
booleanArgField(booleanArg: "true")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unquoted_into_boolean() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
booleanArgField(booleanArg: TRUE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn float_into_id() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
idArgField(idArg: 1.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn boolean_into_id() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
idArgField(idArg: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unquoted_into_id() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
idArgField(idArg: SOMETHING)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn int_into_enum() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: 2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn float_into_enum() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: 1.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_into_enum() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: "SIT")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn boolean_into_enum() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unknown_enum_value_into_enum() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: JUGGLE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn different_case_enum_value_into_enum() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
doesKnowCommand(dogCommand: sit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn good_list_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringListArgField(stringListArg: ["one", "two"])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn empty_list_value() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringListArgField(stringListArg: [])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn single_value_into_list() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringListArgField(stringListArg: "one")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn incorrect_item_type() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringListArgField(stringListArg: ["one", 2])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn single_value_of_incorrect_type() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
stringListArgField(stringListArg: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn arg_on_optional_arg() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
isHousetrained(atOtherHomes: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_arg_on_optional_arg() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog {
|
|
|
|
isHousetrained
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multiple_args() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleReqs(req1: 1, req2: 2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multiple_args_reverse_order() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleReqs(req2: 2, req1: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_args_on_multiple_optional() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleOpts
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn one_arg_on_multiple_optional() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleOpts(opt1: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn second_arg_on_multiple_optional() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleOpts(opt2: 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multiple_reqs_on_mixed_list() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleOptAndReq(req1: 3, req2: 4)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multiple_reqs_and_one_opt_on_mixed_list() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleOptAndReq(req1: 3, req2: 4, opt1: 5)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn all_reqs_and_opts_on_mixed_list() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn incorrect_value_type() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleReqs(req2: "two", req1: "one")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn incorrect_value_and_missing_argument() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
multipleReqs(req1: "one")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn optional_arg_despite_required_field_in_type() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn partial_object_only_required() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: { requiredField: true })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn partial_object_required_field_can_be_falsy() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: { requiredField: false })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn partial_object_including_required() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: { requiredField: true, intField: 4 })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn full_object() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: {
|
|
|
|
requiredField: true,
|
|
|
|
intField: 4,
|
|
|
|
stringField: "foo",
|
|
|
|
booleanField: false,
|
|
|
|
stringListField: ["one", "two"]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn full_object_with_fields_in_different_order() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: {
|
|
|
|
stringListField: ["one", "two"],
|
|
|
|
booleanField: false,
|
|
|
|
requiredField: true,
|
|
|
|
stringField: "foo",
|
|
|
|
intField: 4,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn partial_object_missing_required() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: { intField: 4 })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn partial_object_invalid_field_type() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: {
|
|
|
|
stringListField: ["one", 2],
|
|
|
|
requiredField: true,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn partial_object_unknown_field_arg() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
complicatedArgs {
|
|
|
|
complexArgField(complexArg: {
|
|
|
|
requiredField: true,
|
|
|
|
unknownField: "value"
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn directive_with_valid_types() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_passes_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog @include(if: true) {
|
|
|
|
name
|
|
|
|
}
|
|
|
|
human @skip(if: false) {
|
|
|
|
name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn directive_with_incorrect_types() {
|
2020-05-29 09:29:15 +00:00
|
|
|
expect_fails_rule!(
|
2020-04-05 08:00:26 +00:00
|
|
|
factory,
|
|
|
|
r#"
|
|
|
|
{
|
|
|
|
dog @include(if: "yes") {
|
|
|
|
name @skip(if: ENUM)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|