1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::fmt;

use crate::{Directive, StringValue, Type_};

#[derive(Debug, PartialEq, Clone)]
/// Input Field in a given Input Object.
/// A GraphQL Input Object defines a set of input fields; the input fields are
/// either scalars, enums, or other input objects. Input fields are similar to
/// Fields, but can have a default value.
///
/// ### Example
/// ```rust
/// use apollo_encoder::{Type_, InputField};
///
/// let ty_1 = Type_::NamedType {
///     name: "CatBreed".to_string(),
/// };
///
/// let mut field = InputField::new("cat".to_string(), ty_1);
/// field.default(Some("\"Norwegian Forest\"".to_string()));
///
/// assert_eq!(field.to_string(), r#"  cat: CatBreed = "Norwegian Forest""#);
/// ```
pub struct InputField {
    // Name must return a String.
    name: String,
    // Description may return a String.
    description: StringValue,
    // Type must return a __Type that represents the type of value returned by this field.
    type_: Type_,
    // Default value for this input field.
    default_value: Option<String>,
    /// Contains all directives for this input value definition
    directives: Vec<Directive>,
}

impl InputField {
    /// Create a new instance of InputField.
    pub fn new(name: String, type_: Type_) -> Self {
        Self {
            description: StringValue::Field { source: None },
            name,
            type_,
            default_value: None,
            directives: Vec::new(),
        }
    }

    /// Set the InputField's description.
    pub fn description(&mut self, description: Option<String>) {
        self.description = StringValue::Field {
            source: description,
        };
    }

    /// Set the InputField's default value.
    pub fn default(&mut self, default: Option<String>) {
        self.default_value = default;
    }

    /// Add a directive.
    pub fn directive(&mut self, directive: Directive) {
        self.directives.push(directive)
    }
}

impl fmt::Display for InputField {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.description)?;

        write!(f, "  {}: {}", self.name, self.type_)?;
        if let Some(default) = &self.default_value {
            write!(f, " = {}", default)?;
        }

        for directive in &self.directives {
            write!(f, " {}", directive)?;
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use crate::{Argument, Value};

    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn it_encodes_fields_with_defaults() {
        let ty_1 = Type_::NamedType {
            name: "CatBreed".to_string(),
        };

        let mut field = InputField::new("cat".to_string(), ty_1);
        field.default(Some("\"Norwegian Forest\"".to_string()));

        assert_eq!(field.to_string(), r#"  cat: CatBreed = "Norwegian Forest""#);
    }
    #[test]
    fn it_encodes_fields_with_directives() {
        let ty_1 = Type_::NamedType {
            name: "CatBreed".to_string(),
        };
        let mut directive = Directive::new(String::from("testDirective"));
        directive.arg(Argument::new(String::from("first"), Value::Int(1)));

        let mut field = InputField::new("cat".to_string(), ty_1);
        field.default(Some("\"Norwegian Forest\"".to_string()));
        field.directive(directive);

        assert_eq!(
            field.to_string(),
            r#"  cat: CatBreed = "Norwegian Forest" @testDirective(first: 1)"#
        );
    }
}