slack_messaging/blocks/table/
row.rs

1use super::TableCell;
2
3use crate::validators::*;
4
5use serde::Serialize;
6use slack_messaging_derive::Builder;
7
8/// Single table row representation being set to the rows field in [`Table`](crate::blocks::Table) object.
9///
10/// Table rows contain an array of table cells, each represented by
11/// [`TableCell`] enum.
12///
13/// # Fields and Validations
14///
15/// | Field | Type | Required | Validation |
16/// |-------|------|----------|------------|
17/// | cells | Vec<[TableCell]> | Yes | Maximum of 20 items |
18///
19/// # Example
20///
21/// ```
22/// use slack_messaging::blocks::RichText;
23/// use slack_messaging::blocks::rich_text::{types::RichTextElementLink, RichTextSection};
24/// use slack_messaging::blocks::table::TableRow;
25/// # use std::error::Error;
26///
27/// # fn try_main() -> Result<(), Box<dyn Error>> {
28/// let row = TableRow::builder()
29///     .cell("Data 1A")
30///     .cell(
31///         RichText::builder()
32///             .element(
33///                 RichTextSection::builder()
34///                     .element(
35///                         RichTextElementLink::builder()
36///                             .url("https://slack.com")
37///                             .text("Data 1B")
38///                             .build()?
39///                     )
40///                     .build()?
41///             )
42///             .build()?
43///     )
44///     .build()?;
45///
46/// let expected = serde_json::json!([
47///     {
48///         "type": "raw_text",
49///         "text": "Data 1A"
50///     },
51///     {
52///         "type": "rich_text",
53///         "elements": [
54///             {
55///                 "type": "rich_text_section",
56///                 "elements": [
57///                     {
58///                         "text": "Data 1B",
59///                         "type": "link",
60///                         "url": "https://slack.com"
61///                     }
62///                 ]
63///             }
64///         ]
65///     }
66/// ]);
67///
68/// let json = serde_json::to_value(row).unwrap();
69///
70/// assert_eq!(json, expected);
71/// #     Ok(())
72/// # }
73/// # fn main() {
74/// #     try_main().unwrap()
75/// # }
76/// ```
77#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
78#[serde(transparent)]
79pub struct TableRow {
80    #[builder(push_item = "cell", validate("required", "list::max_item_20"))]
81    pub(crate) cells: Option<Vec<TableCell>>,
82}
83
84impl<Cell: Into<TableCell>> FromIterator<Cell> for TableRow {
85    fn from_iter<T: IntoIterator<Item = Cell>>(iter: T) -> Self {
86        Self {
87            cells: Some(iter.into_iter().map(|c| c.into()).collect()),
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use crate::blocks::test_helpers::*;
96    use crate::errors::*;
97
98    #[test]
99    fn it_implements_builder() {
100        let expected = TableRow {
101            cells: Some(vec![
102                TableCell::RawText("foo".into()),
103                TableCell::RichText(rich_text()),
104            ]),
105        };
106
107        let val = TableRow::builder()
108            .set_cells(Some(vec![
109                TableCell::RawText("foo".into()),
110                TableCell::RichText(rich_text()),
111            ]))
112            .build()
113            .unwrap();
114
115        assert_eq!(val, expected);
116
117        let val = TableRow::builder()
118            .cells(vec![
119                TableCell::RawText("foo".into()),
120                TableCell::RichText(rich_text()),
121            ])
122            .build()
123            .unwrap();
124
125        assert_eq!(val, expected);
126    }
127
128    #[test]
129    fn it_implements_push_item_method() {
130        let expected = TableRow {
131            cells: Some(vec![
132                TableCell::RawText("foo".into()),
133                TableCell::RichText(rich_text()),
134            ]),
135        };
136
137        let val = TableRow::builder()
138            .cell("foo")
139            .cell(rich_text())
140            .build()
141            .unwrap();
142
143        assert_eq!(val, expected);
144    }
145
146    #[test]
147    fn it_requires_cells_field() {
148        let err = TableRow::builder().build().unwrap_err();
149        assert_eq!(err.object(), "TableRow");
150
151        let errors = err.field("cells");
152        assert!(errors.includes(ValidationErrorKind::Required));
153    }
154
155    #[test]
156    fn it_requires_cells_size_less_than_20() {
157        let cells: Vec<TableCell> = (0..21).map(|_| "foo".into()).collect();
158        let err = TableRow::builder().cells(cells).build().unwrap_err();
159        assert_eq!(err.object(), "TableRow");
160
161        let errors = err.field("cells");
162        assert!(errors.includes(ValidationErrorKind::MaxArraySize(20)));
163    }
164}