1import unittest
2
3from slack.errors import SlackObjectFormationError
4from slack.web.classes.actions import (
5    ActionButton,
6    ActionChannelSelector,
7    ActionConversationSelector,
8    ActionExternalSelector,
9    ActionLinkButton,
10    ActionStaticSelector,
11    ActionUserSelector,
12)
13from slack.web.classes.objects import ConfirmObject, Option, OptionGroup
14from tests.web.classes import STRING_3001_CHARS
15
16
17class ButtonTests(unittest.TestCase):
18    def test_json(self):
19        self.assertDictEqual(
20            ActionButton(name="button_1", text="Click me!", value="btn_1").to_dict(),
21            {
22                "name": "button_1",
23                "text": "Click me!",
24                "value": "btn_1",
25                "type": "button",
26            },
27        )
28
29        confirm = ConfirmObject(title="confirm_title", text="confirm_text")
30        self.assertDictEqual(
31            ActionButton(
32                name="button_1",
33                text="Click me!",
34                value="btn_1",
35                confirm=confirm,
36                style="danger",
37            ).to_dict(),
38            {
39                "name": "button_1",
40                "text": "Click me!",
41                "value": "btn_1",
42                "type": "button",
43                "confirm": confirm.to_dict("action"),
44                "style": "danger",
45            },
46        )
47
48    def test_value_length(self):
49        with self.assertRaises(SlackObjectFormationError):
50            ActionButton(
51                name="button_1", text="Click me!", value=STRING_3001_CHARS
52            ).to_dict()
53
54    def test_style_validator(self):
55        b = ActionButton(name="button_1", text="Click me!", value="btn_1")
56        with self.assertRaises(SlackObjectFormationError):
57            b.style = "abcdefg"
58            b.to_dict()
59
60        b.style = "primary"
61        b.to_dict()
62
63
64class LinkButtonTests(unittest.TestCase):
65    def test_json(self):
66        self.assertDictEqual(
67            ActionLinkButton(text="Click me!", url="http://google.com").to_dict(),
68            {"url": "http://google.com", "text": "Click me!", "type": "button"},
69        )
70
71
72class StaticActionSelectorTests(unittest.TestCase):
73    def setUp(self) -> None:
74        self.options = [
75            Option.from_single_value("one"),
76            Option.from_single_value("two"),
77            Option.from_single_value("three"),
78        ]
79
80        self.option_group = [OptionGroup(label="group_1", options=self.options)]
81
82    def test_json(self):
83        self.assertDictEqual(
84            ActionStaticSelector(
85                name="select_1", text="selector_1", options=self.options
86            ).to_dict(),
87            {
88                "name": "select_1",
89                "text": "selector_1",
90                "options": [o.to_dict("action") for o in self.options],
91                "type": "select",
92                "data_source": "static",
93            },
94        )
95
96        self.assertDictEqual(
97            ActionStaticSelector(
98                name="select_1", text="selector_1", options=self.option_group
99            ).to_dict(),
100            {
101                "name": "select_1",
102                "text": "selector_1",
103                "option_groups": [o.to_dict("action") for o in self.option_group],
104                "type": "select",
105                "data_source": "static",
106            },
107        )
108
109    def test_options_length(self):
110        with self.assertRaises(SlackObjectFormationError):
111            ActionStaticSelector(
112                name="select_1", text="selector_1", options=self.options * 34
113            ).to_dict()
114
115
116class DynamicActionSelectorTests(unittest.TestCase):
117    selectors = {ActionUserSelector, ActionChannelSelector, ActionConversationSelector}
118
119    def setUp(self) -> None:
120        self.selected_opt = Option.from_single_value("U12345")
121
122    def test_json(self):
123        for component in self.selectors:
124            with self.subTest(msg=f"{component} json formation test"):
125                self.assertDictEqual(
126                    component(name="select_1", text="selector_1").to_dict(),
127                    {
128                        "name": "select_1",
129                        "text": "selector_1",
130                        "type": "select",
131                        "data_source": component.data_source,
132                    },
133                )
134
135                self.assertDictEqual(
136                    component(
137                        name="select_1",
138                        text="selector_1",
139                        # next line is a little silly, but so is writing the test
140                        # three times
141                        **{f"selected_{component.data_source[:-1]}": self.selected_opt},
142                    ).to_dict(),
143                    {
144                        "name": "select_1",
145                        "text": "selector_1",
146                        "type": "select",
147                        "data_source": component.data_source,
148                        "selected_options": [self.selected_opt.to_dict("action")],
149                    },
150                )
151
152
153class ExternalActionSelectorTests(unittest.TestCase):
154    def test_json(self):
155        option = Option.from_single_value("one")
156
157        self.assertDictEqual(
158            ActionExternalSelector(
159                name="select_1", text="selector_1", min_query_length=3
160            ).to_dict(),
161            {
162                "name": "select_1",
163                "text": "selector_1",
164                "min_query_length": 3,
165                "type": "select",
166                "data_source": "external",
167            },
168        )
169
170        self.assertDictEqual(
171            ActionExternalSelector(
172                name="select_1", text="selector_1", selected_option=option
173            ).to_dict(),
174            {
175                "name": "select_1",
176                "text": "selector_1",
177                "selected_options": [option.to_dict("action")],
178                "type": "select",
179                "data_source": "external",
180            },
181        )
182