slack_messaging/blocks/elements/select_menus/
static_options.rs1use crate::composition_objects::{ConfirmationDialog, Opt, OptGroup, Plain, Text};
2use crate::errors::ValidationErrorKind;
3use crate::validators::*;
4
5use serde::Serialize;
6use slack_messaging_derive::Builder;
7
8#[derive(Debug, Default, Clone, Serialize, PartialEq, Builder)]
99#[serde(tag = "type", rename = "static_select")]
100#[builder(validate = "validate")]
101pub struct SelectMenuStaticOptions {
102 #[serde(skip_serializing_if = "Option::is_none")]
103 #[builder(validate("text::max_255"))]
104 pub(crate) action_id: Option<String>,
105
106 #[serde(skip_serializing_if = "Option::is_none")]
107 #[builder(push_item = "option", validate("list::max_item_100"))]
108 pub(crate) options: Option<Vec<Opt>>,
109
110 #[serde(skip_serializing_if = "Option::is_none")]
111 #[builder(push_item = "option_group", validate("list::max_item_100"))]
112 pub(crate) option_groups: Option<Vec<OptGroup>>,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
115 pub(crate) initial_option: Option<Opt>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
118 pub(crate) confirm: Option<ConfirmationDialog>,
119
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub(crate) focus_on_load: Option<bool>,
122
123 #[serde(skip_serializing_if = "Option::is_none")]
124 #[builder(validate("text_object::max_150"))]
125 pub(crate) placeholder: Option<Text<Plain>>,
126}
127
128fn validate(val: &SelectMenuStaticOptions) -> Vec<ValidationErrorKind> {
129 match (val.options.as_ref(), val.option_groups.as_ref()) {
130 (Some(_), Some(_)) => {
131 vec![ValidationErrorKind::ExclusiveField(
132 "options",
133 "option_groups",
134 )]
135 }
136 (None, None) => {
137 vec![ValidationErrorKind::EitherRequired(
138 "options",
139 "option_groups",
140 )]
141 }
142 _ => vec![],
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149 use crate::composition_objects::test_helpers::*;
150
151 #[test]
152 fn it_implements_builder() {
153 let expected = SelectMenuStaticOptions {
155 action_id: Some("select_0".into()),
156 options: Some(vec![option("opt0", "val0"), option("opt1", "val1")]),
157 option_groups: None,
158 initial_option: Some(option("opt0", "val0")),
159 confirm: Some(confirm()),
160 focus_on_load: Some(true),
161 placeholder: Some(plain_text("Select item")),
162 };
163
164 let val = SelectMenuStaticOptions::builder()
165 .set_action_id(Some("select_0"))
166 .set_options(Some(vec![option("opt0", "val0"), option("opt1", "val1")]))
167 .set_initial_option(Some(option("opt0", "val0")))
168 .set_confirm(Some(confirm()))
169 .set_focus_on_load(Some(true))
170 .set_placeholder(Some(plain_text("Select item")))
171 .build()
172 .unwrap();
173
174 assert_eq!(val, expected);
175
176 let val = SelectMenuStaticOptions::builder()
177 .action_id("select_0")
178 .options(vec![option("opt0", "val0"), option("opt1", "val1")])
179 .initial_option(option("opt0", "val0"))
180 .confirm(confirm())
181 .focus_on_load(true)
182 .placeholder(plain_text("Select item"))
183 .build()
184 .unwrap();
185
186 assert_eq!(val, expected);
187
188 let expected = SelectMenuStaticOptions {
190 action_id: Some("select_0".into()),
191 options: None,
192 option_groups: Some(vec![
193 option_group(
194 "group0",
195 vec![option("opt00", "val00"), option("opt01", "val01")],
196 ),
197 option_group(
198 "group1",
199 vec![option("opt10", "val10"), option("opt11", "val11")],
200 ),
201 ]),
202 initial_option: Some(option("opt00", "val00")),
203 confirm: Some(confirm()),
204 focus_on_load: Some(true),
205 placeholder: Some(plain_text("Select item")),
206 };
207
208 let val = SelectMenuStaticOptions::builder()
209 .set_action_id(Some("select_0"))
210 .set_option_groups(Some(vec![
211 option_group(
212 "group0",
213 vec![option("opt00", "val00"), option("opt01", "val01")],
214 ),
215 option_group(
216 "group1",
217 vec![option("opt10", "val10"), option("opt11", "val11")],
218 ),
219 ]))
220 .set_initial_option(Some(option("opt00", "val00")))
221 .set_confirm(Some(confirm()))
222 .set_focus_on_load(Some(true))
223 .set_placeholder(Some(plain_text("Select item")))
224 .build()
225 .unwrap();
226
227 assert_eq!(val, expected);
228
229 let val = SelectMenuStaticOptions::builder()
230 .action_id("select_0")
231 .option_groups(vec![
232 option_group(
233 "group0",
234 vec![option("opt00", "val00"), option("opt01", "val01")],
235 ),
236 option_group(
237 "group1",
238 vec![option("opt10", "val10"), option("opt11", "val11")],
239 ),
240 ])
241 .initial_option(option("opt00", "val00"))
242 .confirm(confirm())
243 .focus_on_load(true)
244 .placeholder(plain_text("Select item"))
245 .build()
246 .unwrap();
247
248 assert_eq!(val, expected);
249 }
250
251 #[test]
252 fn it_implements_push_item_method() {
253 let expected = SelectMenuStaticOptions {
254 action_id: None,
255 options: Some(vec![option("opt0", "val0"), option("opt1", "val1")]),
256 option_groups: None,
257 initial_option: None,
258 confirm: None,
259 focus_on_load: None,
260 placeholder: None,
261 };
262
263 let val = SelectMenuStaticOptions::builder()
264 .option(option("opt0", "val0"))
265 .option(option("opt1", "val1"))
266 .build()
267 .unwrap();
268
269 assert_eq!(val, expected);
270
271 let expected = SelectMenuStaticOptions {
272 action_id: None,
273 options: None,
274 option_groups: Some(vec![
275 option_group(
276 "group0",
277 vec![option("opt00", "val00"), option("opt01", "val01")],
278 ),
279 option_group(
280 "group1",
281 vec![option("opt10", "val10"), option("opt11", "val11")],
282 ),
283 ]),
284 initial_option: None,
285 confirm: None,
286 focus_on_load: None,
287 placeholder: None,
288 };
289
290 let val = SelectMenuStaticOptions::builder()
291 .option_group(option_group(
292 "group0",
293 vec![option("opt00", "val00"), option("opt01", "val01")],
294 ))
295 .option_group(option_group(
296 "group1",
297 vec![option("opt10", "val10"), option("opt11", "val11")],
298 ))
299 .build()
300 .unwrap();
301
302 assert_eq!(val, expected);
303 }
304
305 #[test]
306 fn it_requires_action_id_less_than_255_characters_long() {
307 let err = SelectMenuStaticOptions::builder()
308 .option(option("opt", "val"))
309 .action_id("a".repeat(256))
310 .build()
311 .unwrap_err();
312 assert_eq!(err.object(), "SelectMenuStaticOptions");
313
314 let errors = err.field("action_id");
315 assert!(errors.includes(ValidationErrorKind::MaxTextLength(255)));
316 }
317
318 #[test]
319 fn it_requires_options_list_size_less_than_100() {
320 let options: Vec<Opt> = (0..101).map(|_| option("opt", "val")).collect();
321
322 let err = SelectMenuStaticOptions::builder()
323 .options(options)
324 .build()
325 .unwrap_err();
326 assert_eq!(err.object(), "SelectMenuStaticOptions");
327
328 let errors = err.field("options");
329 assert!(errors.includes(ValidationErrorKind::MaxArraySize(100)));
330 }
331
332 #[test]
333 fn it_requires_option_groups_list_size_less_than_100() {
334 let option_groups: Vec<OptGroup> = (0..101)
335 .map(|_| option_group("group", vec![option("opt", "val")]))
336 .collect();
337
338 let err = SelectMenuStaticOptions::builder()
339 .option_groups(option_groups)
340 .build()
341 .unwrap_err();
342 assert_eq!(err.object(), "SelectMenuStaticOptions");
343
344 let errors = err.field("option_groups");
345 assert!(errors.includes(ValidationErrorKind::MaxArraySize(100)));
346 }
347
348 #[test]
349 fn it_requires_placeholder_text_less_than_150_characters_long() {
350 let err = SelectMenuStaticOptions::builder()
351 .option(option("opt", "val"))
352 .placeholder(plain_text("a".repeat(151)))
353 .build()
354 .unwrap_err();
355 assert_eq!(err.object(), "SelectMenuStaticOptions");
356
357 let errors = err.field("placeholder");
358 assert!(errors.includes(ValidationErrorKind::MaxTextLength(150)));
359 }
360
361 #[test]
362 fn it_requires_either_options_or_option_groups_is_set() {
363 let err = SelectMenuStaticOptions::builder().build().unwrap_err();
364 assert_eq!(err.object(), "SelectMenuStaticOptions");
365
366 let errors = err.across_fields();
367 assert!(errors.includes(ValidationErrorKind::EitherRequired(
368 "options",
369 "option_groups"
370 )));
371 }
372
373 #[test]
374 fn it_prevents_from_both_options_or_option_groups_are_set() {
375 let err = SelectMenuStaticOptions::builder()
376 .option(option("opt", "val"))
377 .option_group(option_group("group", vec![option("opt", "val")]))
378 .build()
379 .unwrap_err();
380 assert_eq!(err.object(), "SelectMenuStaticOptions");
381
382 let errors = err.across_fields();
383 assert!(errors.includes(ValidationErrorKind::ExclusiveField(
384 "options",
385 "option_groups"
386 )));
387 }
388}