async-graphql/src/validation/rules/unique_argument_names.rs

206 lines
4.0 KiB
Rust
Raw Normal View History

2020-10-15 06:38:10 +00:00
use std::collections::HashSet;
use crate::parser::types::{Directive, Field};
2020-03-24 10:54:22 +00:00
use crate::validation::visitor::{Visitor, VisitorContext};
use crate::{Name, Positioned};
use async_graphql_value::Value;
2020-03-09 12:39:46 +00:00
#[derive(Default)]
pub struct UniqueArgumentNames<'a> {
names: HashSet<&'a str>,
}
impl<'a> Visitor<'a> for UniqueArgumentNames<'a> {
fn enter_directive(
&mut self,
_ctx: &mut VisitorContext<'a>,
2020-05-10 02:59:51 +00:00
_directive: &'a Positioned<Directive>,
) {
2020-03-09 12:39:46 +00:00
self.names.clear();
}
fn enter_argument(
&mut self,
2020-03-22 08:45:59 +00:00
ctx: &mut VisitorContext<'a>,
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 !self.names.insert(name.node.as_str()) {
2020-03-09 12:39:46 +00:00
ctx.report_error(
2020-09-06 05:38:31 +00:00
vec![name.pos],
2020-03-09 12:39:46 +00:00
format!("There can only be one argument named \"{}\"", name),
)
}
}
2020-05-10 02:59:51 +00:00
fn enter_field(&mut self, _ctx: &mut VisitorContext<'a>, _field: &'a Positioned<Field>) {
2020-03-09 12:39:46 +00:00
self.names.clear();
}
}
2020-04-05 08:00:26 +00:00
#[cfg(test)]
mod tests {
use super::*;
pub fn factory<'a>() -> UniqueArgumentNames<'a> {
UniqueArgumentNames::default()
}
#[test]
fn no_arguments_on_field() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field
}
"#,
);
}
#[test]
fn no_arguments_on_directive() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
dog @directive
}
"#,
);
}
#[test]
fn argument_on_field() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field(arg: "value")
}
"#,
);
}
#[test]
fn argument_on_directive() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
dog @directive(arg: "value")
}
"#,
);
}
#[test]
fn same_argument_on_two_fields() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
one: field(arg: "value")
two: field(arg: "value")
}
"#,
);
}
#[test]
fn same_argument_on_field_and_directive() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field(arg: "value") @directive(arg: "value")
}
"#,
);
}
#[test]
fn same_argument_on_two_directives() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field @directive1(arg: "value") @directive2(arg: "value")
}
"#,
);
}
#[test]
fn multiple_field_arguments() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field(arg1: "value", arg2: "value", arg3: "value")
}
"#,
);
}
#[test]
fn multiple_directive_arguments() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field @directive(arg1: "value", arg2: "value", arg3: "value")
}
"#,
);
}
#[test]
fn duplicate_field_arguments() {
2020-05-29 09:29:15 +00:00
expect_fails_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field(arg1: "value", arg1: "value")
}
"#,
);
}
#[test]
fn many_duplicate_field_arguments() {
2020-05-29 09:29:15 +00:00
expect_fails_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field(arg1: "value", arg1: "value", arg1: "value")
}
"#,
);
}
#[test]
fn duplicate_directive_arguments() {
2020-05-29 09:29:15 +00:00
expect_fails_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field @directive(arg1: "value", arg1: "value")
}
"#,
);
}
#[test]
fn many_duplicate_directive_arguments() {
2020-05-29 09:29:15 +00:00
expect_fails_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
{
field @directive(arg1: "value", arg1: "value", arg1: "value")
}
"#,
);
}
}