slack_messaging/blocks/elements/
file_input.rs

1use crate::blocks::elements::types::FileType;
2use crate::validators::*;
3
4use serde::Serialize;
5use slack_messaging_derive::Builder;
6
7/// [File input element](https://docs.slack.dev/reference/block-kit/block-elements/file-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/file-input-element).
14///
15/// | Field | Type | Required | Validation |
16/// |-------|------|----------|------------|
17/// | action_id | String | No | Max length 255 characters |
18/// | filetypes | Vec<[FileType]> | No | N/A |
19/// | max_files | i64 | No | Min value 1, Max value 10 |
20///
21/// # Example
22///
23/// ```
24/// use slack_messaging::blocks::elements::{FileInput, types::FileType};
25/// # use std::error::Error;
26///
27/// # fn try_main() -> Result<(), Box<dyn Error>> {
28/// let input = FileInput::builder()
29///     .action_id("file_input_action_id_1")
30///     .filetype(FileType::Jpg)
31///     .build()?;
32///
33/// let expected = serde_json::json!({
34///     "type": "file_input",
35///     "action_id": "file_input_action_id_1",
36///     "filetypes": ["jpg"]
37/// });
38///
39/// let json = serde_json::to_value(input).unwrap();
40///
41/// assert_eq!(json, expected);
42///
43/// // If your object has any validation errors, the build method returns Result::Err
44/// let input = FileInput::builder()
45///     .action_id("file_input_action_id_1")
46///     .filetype(FileType::Jpg)
47///     .max_files(99)
48///     .build();
49///
50/// assert!(input.is_err());
51/// #     Ok(())
52/// # }
53/// # fn main() {
54/// #     try_main().unwrap()
55/// # }
56/// ```
57#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
58#[serde(tag = "type", rename = "file_input")]
59pub struct FileInput {
60    #[serde(skip_serializing_if = "Option::is_none")]
61    #[builder(validate("text::max_255"))]
62    pub(crate) action_id: Option<String>,
63
64    #[serde(skip_serializing_if = "Option::is_none")]
65    #[builder(push_item = "filetype")]
66    pub(crate) filetypes: Option<Vec<FileType>>,
67
68    #[serde(skip_serializing_if = "Option::is_none")]
69    #[builder(validate("integer::min_1", "integer::max_10"))]
70    pub(crate) max_files: Option<i64>,
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use crate::errors::*;
77
78    #[test]
79    fn it_implements_builder() {
80        let expected = FileInput {
81            action_id: Some("file_input_0".into()),
82            filetypes: Some(vec![FileType::Jpg, FileType::Png]),
83            max_files: Some(5),
84        };
85
86        let val = FileInput::builder()
87            .set_action_id(Some("file_input_0"))
88            .set_filetypes(Some(vec![FileType::Jpg, FileType::Png]))
89            .set_max_files(Some(5))
90            .build()
91            .unwrap();
92
93        assert_eq!(val, expected);
94
95        let val = FileInput::builder()
96            .action_id("file_input_0")
97            .filetypes(vec![FileType::Jpg, FileType::Png])
98            .max_files(5)
99            .build()
100            .unwrap();
101
102        assert_eq!(val, expected);
103    }
104
105    #[test]
106    fn it_implements_push_item_method() {
107        let expected = FileInput {
108            action_id: None,
109            filetypes: Some(vec![FileType::Jpg, FileType::Png]),
110            max_files: None,
111        };
112
113        let val = FileInput::builder()
114            .filetype(FileType::Jpg)
115            .filetype(FileType::Png)
116            .build()
117            .unwrap();
118
119        assert_eq!(val, expected);
120    }
121
122    #[test]
123    fn it_requires_action_id_less_than_255_characters_long() {
124        let err = FileInput::builder()
125            .action_id("a".repeat(256))
126            .build()
127            .unwrap_err();
128        assert_eq!(err.object(), "FileInput");
129
130        let errors = err.field("action_id");
131        assert!(errors.includes(ValidationErrorKind::MaxTextLength(255)));
132    }
133
134    #[test]
135    fn it_requires_max_files_greater_than_1() {
136        let err = FileInput::builder().max_files(0).build().unwrap_err();
137        assert_eq!(err.object(), "FileInput");
138
139        let errors = err.field("max_files");
140        assert!(errors.includes(ValidationErrorKind::MinIntegerValue(1)));
141    }
142
143    #[test]
144    fn it_requires_max_files_less_than_10() {
145        let err = FileInput::builder().max_files(11).build().unwrap_err();
146        assert_eq!(err.object(), "FileInput");
147
148        let errors = err.field("max_files");
149        assert!(errors.includes(ValidationErrorKind::MaxIntegerValue(10)));
150    }
151}