slack_messaging/blocks/elements/
number_input.rs1use crate::composition_objects::{DispatchActionConfiguration, Plain, Text};
2use crate::validators::*;
3
4use serde::Serialize;
5use slack_messaging_derive::Builder;
6
7#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
61#[serde(tag = "type", rename = "number_input")]
62pub struct NumberInput {
63 #[builder(validate("required"))]
64 pub(crate) is_decimal_allowed: Option<bool>,
65
66 #[serde(skip_serializing_if = "Option::is_none")]
67 #[builder(validate("text::max_255"))]
68 pub(crate) action_id: Option<String>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub(crate) initial_value: Option<String>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub(crate) min_value: Option<String>,
75
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub(crate) max_value: Option<String>,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub(crate) dispatch_action_config: Option<DispatchActionConfiguration>,
81
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub(crate) focus_on_load: Option<bool>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
86 #[builder(validate("text_object::max_150"))]
87 pub(crate) placeholder: Option<Text<Plain>>,
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::composition_objects::test_helpers::*;
94 use crate::errors::*;
95
96 #[test]
97 fn it_implements_builder() {
98 let expected = NumberInput {
99 is_decimal_allowed: Some(true),
100 action_id: Some("number_input_0".into()),
101 initial_value: Some("5.0".into()),
102 min_value: Some("0.0".into()),
103 max_value: Some("10.0".into()),
104 dispatch_action_config: Some(dispatch_action_config()),
105 focus_on_load: Some(true),
106 placeholder: Some(plain_text("Input Number")),
107 };
108
109 let val = NumberInput::builder()
110 .set_is_decimal_allowed(Some(true))
111 .set_action_id(Some("number_input_0"))
112 .set_initial_value(Some("5.0"))
113 .set_min_value(Some("0.0"))
114 .set_max_value(Some("10.0"))
115 .set_dispatch_action_config(Some(dispatch_action_config()))
116 .set_focus_on_load(Some(true))
117 .set_placeholder(Some(plain_text("Input Number")))
118 .build()
119 .unwrap();
120
121 assert_eq!(val, expected);
122
123 let val = NumberInput::builder()
124 .is_decimal_allowed(true)
125 .action_id("number_input_0")
126 .initial_value("5.0")
127 .min_value("0.0")
128 .max_value("10.0")
129 .dispatch_action_config(dispatch_action_config())
130 .focus_on_load(true)
131 .placeholder(plain_text("Input Number"))
132 .build()
133 .unwrap();
134
135 assert_eq!(val, expected);
136 }
137
138 #[test]
139 fn it_requires_is_decimal_allowed_field() {
140 let err = NumberInput::builder().build().unwrap_err();
141 assert_eq!(err.object(), "NumberInput");
142
143 let errors = err.field("is_decimal_allowed");
144 assert!(errors.includes(ValidationErrorKind::Required));
145 }
146
147 #[test]
148 fn it_requires_action_id_less_than_255_characters_long() {
149 let err = NumberInput::builder()
150 .is_decimal_allowed(true)
151 .action_id("a".repeat(256))
152 .build()
153 .unwrap_err();
154 assert_eq!(err.object(), "NumberInput");
155
156 let errors = err.field("action_id");
157 assert!(errors.includes(ValidationErrorKind::MaxTextLength(255)));
158 }
159
160 #[test]
161 fn it_requires_placeholder_less_than_150_characters_long() {
162 let err = NumberInput::builder()
163 .is_decimal_allowed(true)
164 .placeholder(plain_text("a".repeat(151)))
165 .build()
166 .unwrap_err();
167 assert_eq!(err.object(), "NumberInput");
168
169 let errors = err.field("placeholder");
170 assert!(errors.includes(ValidationErrorKind::MaxTextLength(150)));
171 }
172}