slack_messaging/blocks/elements/
plain_text_input.rs

1use crate::composition_objects::{DispatchActionConfiguration, Plain, Text};
2use crate::validators::*;
3
4use serde::Serialize;
5use slack_messaging_derive::Builder;
6
7/// [Plain-text input element](https://docs.slack.dev/reference/block-kit/block-elements/plain-text-input-element)
8/// representation.
9///
10/// # Fields and Validations
11///
12/// For more details, see the [official
13/// documentation](https://docs.slack.dev/reference/block-kit/block-elements/plain-text-input-element).
14///
15/// | Field | Type | Required | Validation |
16/// |-------|------|----------|------------|
17/// | action_id | String | No | Max length 255 characters |
18/// | initial_value | String | No | N/A |
19/// | multiline | bool | No | N/A |
20/// | min_length | i64 | No | Min value 0, Max value 3000 |
21/// | max_length | i64 | No | Min value 1, Max value 3000 |
22/// | dispatch_action_config | [DispatchActionConfiguration] | No | N/A |
23/// | focus_on_load | bool | No | N/A |
24/// | placeholder | [Text]<[Plain]> | No | Max length 150 characters |
25///
26/// # Example
27///
28/// ```
29/// use slack_messaging::plain_text;
30/// use slack_messaging::blocks::elements::PlainTextInput;
31/// # use std::error::Error;
32///
33/// # fn try_main() -> Result<(), Box<dyn Error>> {
34/// let input = PlainTextInput::builder()
35///     .action_id("plain_input")
36///     .multiline(true)
37///     .placeholder(plain_text!("Enter some plain text")?)
38///     .build()?;
39///
40/// let expected = serde_json::json!({
41///     "type": "plain_text_input",
42///     "action_id": "plain_input",
43///     "multiline": true,
44///     "placeholder": {
45///         "type": "plain_text",
46///         "text": "Enter some plain text"
47///     }
48/// });
49///
50/// let json = serde_json::to_value(input).unwrap();
51///
52/// assert_eq!(json, expected);
53///
54/// // If your object has any validation errors, the build method returns Result::Err
55/// let input = PlainTextInput::builder()
56///     .action_id("plain_input")
57///     .multiline(true)
58///     .placeholder(plain_text!("{}", "verrrrrrry long text".repeat(100))?)
59///     .build();
60///
61/// assert!(input.is_err());
62/// #     Ok(())
63/// # }
64/// # fn main() {
65/// #     try_main().unwrap()
66/// # }
67/// ```
68#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
69#[serde(tag = "type", rename = "plain_text_input")]
70pub struct PlainTextInput {
71    #[serde(skip_serializing_if = "Option::is_none")]
72    #[builder(validate("text::max_255"))]
73    pub(crate) action_id: Option<String>,
74
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub(crate) initial_value: Option<String>,
77
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub(crate) multiline: Option<bool>,
80
81    #[serde(skip_serializing_if = "Option::is_none")]
82    #[builder(validate("integer::min_0", "integer::max_3000"))]
83    pub(crate) min_length: Option<i64>,
84
85    #[serde(skip_serializing_if = "Option::is_none")]
86    #[builder(validate("integer::min_1", "integer::max_3000"))]
87    pub(crate) max_length: Option<i64>,
88
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub(crate) dispatch_action_config: Option<DispatchActionConfiguration>,
91
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub(crate) focus_on_load: Option<bool>,
94
95    #[serde(skip_serializing_if = "Option::is_none")]
96    #[builder(validate("text_object::max_150"))]
97    pub(crate) placeholder: Option<Text<Plain>>,
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103    use crate::composition_objects::test_helpers::*;
104    use crate::errors::*;
105
106    #[test]
107    fn it_implements_builder() {
108        let expected = PlainTextInput {
109            action_id: Some("plain_text_input_0".into()),
110            initial_value: Some("foobar".into()),
111            multiline: Some(true),
112            min_length: Some(0),
113            max_length: Some(3000),
114            dispatch_action_config: Some(dispatch_action_config()),
115            focus_on_load: Some(true),
116            placeholder: Some(plain_text("Input Text")),
117        };
118
119        let val = PlainTextInput::builder()
120            .set_action_id(Some("plain_text_input_0"))
121            .set_initial_value(Some("foobar"))
122            .set_multiline(Some(true))
123            .set_min_length(Some(0))
124            .set_max_length(Some(3000))
125            .set_dispatch_action_config(Some(dispatch_action_config()))
126            .set_focus_on_load(Some(true))
127            .set_placeholder(Some(plain_text("Input Text")))
128            .build()
129            .unwrap();
130
131        assert_eq!(val, expected);
132
133        let val = PlainTextInput::builder()
134            .action_id("plain_text_input_0")
135            .initial_value("foobar")
136            .multiline(true)
137            .min_length(0)
138            .max_length(3000)
139            .dispatch_action_config(dispatch_action_config())
140            .focus_on_load(true)
141            .placeholder(plain_text("Input Text"))
142            .build()
143            .unwrap();
144
145        assert_eq!(val, expected);
146    }
147
148    #[test]
149    fn it_requires_action_id_less_than_255_characters_long() {
150        let err = PlainTextInput::builder()
151            .action_id("a".repeat(256))
152            .build()
153            .unwrap_err();
154        assert_eq!(err.object(), "PlainTextInput");
155
156        let errors = err.field("action_id");
157        assert!(errors.includes(ValidationErrorKind::MaxTextLength(255)));
158    }
159
160    #[test]
161    fn it_requires_min_length_greater_than_0() {
162        let err = PlainTextInput::builder()
163            .min_length(-1)
164            .build()
165            .unwrap_err();
166        assert_eq!(err.object(), "PlainTextInput");
167
168        let errors = err.field("min_length");
169        assert!(errors.includes(ValidationErrorKind::MinIntegerValue(0)));
170    }
171
172    #[test]
173    fn it_requires_min_length_less_than_3000() {
174        let err = PlainTextInput::builder()
175            .min_length(3001)
176            .build()
177            .unwrap_err();
178        assert_eq!(err.object(), "PlainTextInput");
179
180        let errors = err.field("min_length");
181        assert!(errors.includes(ValidationErrorKind::MaxIntegerValue(3000)));
182    }
183
184    #[test]
185    fn it_requires_max_length_greater_than_1() {
186        let err = PlainTextInput::builder().max_length(0).build().unwrap_err();
187        assert_eq!(err.object(), "PlainTextInput");
188
189        let errors = err.field("max_length");
190        assert!(errors.includes(ValidationErrorKind::MinIntegerValue(1)));
191    }
192
193    #[test]
194    fn it_requires_max_length_less_than_3000() {
195        let err = PlainTextInput::builder()
196            .max_length(3001)
197            .build()
198            .unwrap_err();
199        assert_eq!(err.object(), "PlainTextInput");
200
201        let errors = err.field("max_length");
202        assert!(errors.includes(ValidationErrorKind::MaxIntegerValue(3000)));
203    }
204
205    #[test]
206    fn it_requires_placeholder_less_than_150_characters_long() {
207        let err = PlainTextInput::builder()
208            .placeholder(plain_text("a".repeat(151)))
209            .build()
210            .unwrap_err();
211        assert_eq!(err.object(), "PlainTextInput");
212
213        let errors = err.field("placeholder");
214        assert!(errors.includes(ValidationErrorKind::MaxTextLength(150)));
215    }
216}