slack_messaging/blocks/
file.rs

1use crate::validators::*;
2
3use serde::Serialize;
4use slack_messaging_derive::Builder;
5
6/// [File block](https://docs.slack.dev/reference/block-kit/blocks/file-block)
7/// representation.
8///
9/// # Fields and Validations
10///
11/// For more details, see the [official
12/// documentation](https://docs.slack.dev/reference/block-kit/blocks/file-block).
13///
14/// | Field | Type | Required | Validation |
15/// |-------|------|----------|------------|
16/// | external_id | String | Yes | N/A |
17/// | source | [FileSource] | Yes | N/A |
18/// | block_id | String | No | Maximum 255 characters |
19///
20/// # Example
21///
22/// ```
23/// # use slack_messaging::blocks::{File, FileSource};
24/// # use std::error::Error;
25///
26/// # fn try_main() -> Result<(), Box<dyn Error>> {
27/// let file = File::builder()
28///     .external_id("ABCD1")
29///     .source(FileSource::Remote)
30///     .build()?;
31///
32/// let expected = serde_json::json!({
33///     "type": "file",
34///     "external_id": "ABCD1",
35///     "source": "remote"
36/// });
37///
38/// let json = serde_json::to_value(file).unwrap();
39///
40/// assert_eq!(json, expected);
41/// #     Ok(())
42/// # }
43/// # fn main() {
44/// #     try_main().unwrap()
45/// # }
46/// ```
47#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
48#[serde(tag = "type", rename = "file")]
49pub struct File {
50    #[builder(validate("required"))]
51    pub(crate) external_id: Option<String>,
52
53    #[builder(validate("required"))]
54    pub(crate) source: Option<FileSource>,
55
56    #[serde(skip_serializing_if = "Option::is_none")]
57    #[builder(validate("text::max_255"))]
58    pub(crate) block_id: Option<String>,
59}
60
61/// Values that can be set to the source field of [File].
62#[derive(Debug, Copy, Clone, Serialize, PartialEq)]
63#[serde(rename_all = "snake_case")]
64pub enum FileSource {
65    Remote,
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::errors::*;
72
73    #[test]
74    fn it_implements_builder() {
75        let expected = File {
76            external_id: Some("ABCD1".into()),
77            source: Some(FileSource::Remote),
78            block_id: Some("file_0".into()),
79        };
80
81        let val = File::builder()
82            .set_external_id(Some("ABCD1"))
83            .set_source(Some(FileSource::Remote))
84            .set_block_id(Some("file_0"))
85            .build()
86            .unwrap();
87
88        assert_eq!(val, expected);
89
90        let val = File::builder()
91            .external_id("ABCD1")
92            .source(FileSource::Remote)
93            .block_id("file_0")
94            .build()
95            .unwrap();
96
97        assert_eq!(val, expected);
98    }
99
100    #[test]
101    fn it_requires_external_id_field() {
102        let err = File::builder()
103            .source(FileSource::Remote)
104            .build()
105            .unwrap_err();
106        assert_eq!(err.object(), "File");
107
108        let errors = err.field("external_id");
109        assert!(errors.includes(ValidationErrorKind::Required));
110    }
111
112    #[test]
113    fn it_requires_source_field() {
114        let err = File::builder().external_id("ABCD1").build().unwrap_err();
115        assert_eq!(err.object(), "File");
116
117        let errors = err.field("source");
118        assert!(errors.includes(ValidationErrorKind::Required));
119    }
120
121    #[test]
122    fn it_requires_block_id_less_than_255_characters_long() {
123        let err = File::builder()
124            .external_id("ABCD1")
125            .source(FileSource::Remote)
126            .block_id("a".repeat(256))
127            .build()
128            .unwrap_err();
129        assert_eq!(err.object(), "File");
130
131        let errors = err.field("block_id");
132        assert!(errors.includes(ValidationErrorKind::MaxTextLength(255)));
133    }
134}