slack_messaging/blocks/elements/
workflow_button.rs

1use crate::composition_objects::{Plain, Text, Workflow};
2use crate::validators::*;
3
4use serde::Serialize;
5use slack_messaging_derive::Builder;
6
7/// [Workflow button element](https://docs.slack.dev/reference/block-kit/block-elements/workflow-button-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/workflow-button-element).
14///
15/// | Field | Type | Required | Validation |
16/// |-------|------|----------|------------|
17/// | text | [Text]<[Plain]> | Yes | Max length 75 characters |
18/// | action_id | String | Yes | Max length 255 characters |
19/// | workflow | [Workflow] | Yes | N/A |
20/// | style | &'static str | No | Must be one of "primary", "danger" |
21/// | accessibility_label | String | No | Max length 75 characters |
22///
23/// # Example
24///
25/// ```
26/// use slack_messaging::plain_text;
27/// use slack_messaging::blocks::elements::WorkflowButton;
28/// use slack_messaging::composition_objects::{types::InputParameter, Trigger, Workflow};
29/// # use std::error::Error;
30///
31/// # fn try_main() -> Result<(), Box<dyn Error>> {
32/// let button = WorkflowButton::builder()
33///     .text(plain_text!("Run Workflow")?)
34///     .action_id("workflowbutton123")
35///     .workflow(
36///         Workflow::builder()
37///             .trigger(
38///                 Trigger::builder()
39///                      .url("https://slack.com/shortcuts/Ft0123ABC456/123...xyz")
40///                      .customizable_input_parameter(
41///                          InputParameter::builder()
42///                              .name("input_parameter_a")
43///                              .value("Value for input param A")
44///                              .build()?
45///                      )
46///                      .customizable_input_parameter(
47///                          InputParameter::builder()
48///                              .name("input_parameter_b")
49///                              .value("Value for input param B")
50///                              .build()?
51///                      )
52///                      .build()?
53///             )
54///             .build()?
55///     )
56///     .build()?;
57///
58/// let expected = serde_json::json!({
59///     "type": "workflow_button",
60///     "text": {
61///         "type": "plain_text",
62///         "text": "Run Workflow"
63///     },
64///     "action_id": "workflowbutton123",
65///     "workflow": {
66///         "trigger": {
67///             "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz",
68///             "customizable_input_parameters": [
69///                 {
70///                     "name": "input_parameter_a",
71///                     "value": "Value for input param A"
72///                 },
73///                 {
74///                     "name": "input_parameter_b",
75///                     "value": "Value for input param B"
76///                 }
77///             ]
78///         }
79///     }
80/// });
81///
82/// let json = serde_json::to_value(button).unwrap();
83///
84/// assert_eq!(json, expected);
85///
86/// // If your object has any validation errors, the build method returns Result::Err
87/// let button = WorkflowButton::builder()
88///     .text(plain_text!("Run Workflow")?)
89///     .action_id("workflowbutton123")
90///     .build();
91///
92/// assert!(button.is_err());
93/// #     Ok(())
94/// # }
95/// # fn main() {
96/// #     try_main().unwrap()
97/// # }
98/// ```
99#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
100#[serde(tag = "type", rename = "workflow_button")]
101pub struct WorkflowButton {
102    #[builder(validate("required", "text_object::max_75"))]
103    pub(crate) text: Option<Text<Plain>>,
104
105    #[builder(validate("required", "text::max_255"))]
106    pub(crate) action_id: Option<String>,
107
108    #[builder(validate("required"))]
109    pub(crate) workflow: Option<Workflow>,
110
111    #[serde(skip_serializing_if = "Option::is_none")]
112    #[builder(private_setter)]
113    pub(crate) style: Option<&'static str>,
114
115    #[serde(skip_serializing_if = "Option::is_none")]
116    #[builder(validate("text::max_75"))]
117    pub(crate) accessibility_label: Option<String>,
118}
119
120impl WorkflowButtonBuilder {
121    /// set "primary" to style field
122    pub fn primary(self) -> Self {
123        self.style("primary")
124    }
125
126    /// set "danger" to style field
127    pub fn danger(self) -> Self {
128        self.style("danger")
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135    use crate::composition_objects::test_helpers::*;
136    use crate::errors::*;
137
138    #[test]
139    fn it_implements_builder() {
140        let expected = WorkflowButton {
141            text: Some(plain_text("Run Workflow")),
142            action_id: Some("workflow_button_0".into()),
143            workflow: Some(workflow()),
144            style: Some("primary"),
145            accessibility_label: Some("Run Workflow!".into()),
146        };
147
148        let val = WorkflowButton::builder()
149            .set_text(Some(plain_text("Run Workflow")))
150            .set_action_id(Some("workflow_button_0"))
151            .set_workflow(Some(workflow()))
152            .primary()
153            .set_accessibility_label(Some("Run Workflow!"))
154            .build()
155            .unwrap();
156
157        assert_eq!(val, expected);
158
159        let expected = WorkflowButton {
160            style: Some("danger"),
161            ..expected
162        };
163
164        let val = WorkflowButton::builder()
165            .text(plain_text("Run Workflow"))
166            .action_id("workflow_button_0")
167            .workflow(workflow())
168            .danger()
169            .accessibility_label("Run Workflow!")
170            .build()
171            .unwrap();
172
173        assert_eq!(val, expected);
174    }
175
176    #[test]
177    fn it_requries_text_field() {
178        let err = WorkflowButton::builder()
179            .action_id("workflow_button_0")
180            .workflow(workflow())
181            .build()
182            .unwrap_err();
183        assert_eq!(err.object(), "WorkflowButton");
184
185        let errors = err.field("text");
186        assert!(errors.includes(ValidationErrorKind::Required));
187    }
188
189    #[test]
190    fn it_requires_text_length_less_than_75_characters_long() {
191        let err = WorkflowButton::builder()
192            .text(plain_text("a".repeat(76)))
193            .action_id("workflow_button_0")
194            .workflow(workflow())
195            .build()
196            .unwrap_err();
197        assert_eq!(err.object(), "WorkflowButton");
198
199        let errors = err.field("text");
200        assert!(errors.includes(ValidationErrorKind::MaxTextLength(75)));
201    }
202
203    #[test]
204    fn it_requries_action_id_field() {
205        let err = WorkflowButton::builder()
206            .text(plain_text("Run Workflow"))
207            .workflow(workflow())
208            .build()
209            .unwrap_err();
210        assert_eq!(err.object(), "WorkflowButton");
211
212        let errors = err.field("action_id");
213        assert!(errors.includes(ValidationErrorKind::Required));
214    }
215
216    #[test]
217    fn it_requries_action_id_less_than_255_characters_long() {
218        let err = WorkflowButton::builder()
219            .text(plain_text("Run Workflow"))
220            .action_id("a".repeat(256))
221            .workflow(workflow())
222            .build()
223            .unwrap_err();
224        assert_eq!(err.object(), "WorkflowButton");
225
226        let errors = err.field("action_id");
227        assert!(errors.includes(ValidationErrorKind::MaxTextLength(255)));
228    }
229
230    #[test]
231    fn it_requries_workflow_field() {
232        let err = WorkflowButton::builder()
233            .text(plain_text("Run Workflow"))
234            .action_id("workflow_button_0")
235            .build()
236            .unwrap_err();
237        assert_eq!(err.object(), "WorkflowButton");
238
239        let errors = err.field("workflow");
240        assert!(errors.includes(ValidationErrorKind::Required));
241    }
242
243    #[test]
244    fn it_requries_accessibility_label_less_than_75_characters_long() {
245        let err = WorkflowButton::builder()
246            .text(plain_text("Run Workflow"))
247            .action_id("workflow_button_0")
248            .workflow(workflow())
249            .accessibility_label("a".repeat(76))
250            .build()
251            .unwrap_err();
252        assert_eq!(err.object(), "WorkflowButton");
253
254        let errors = err.field("accessibility_label");
255        assert!(errors.includes(ValidationErrorKind::MaxTextLength(75)));
256    }
257}