Skip to content

Commit 7004e7a

Browse files
committed
Fix slackapi#81 by supporting input validations in dialogs
1 parent 844d1ae commit 7004e7a

4 files changed

Lines changed: 57 additions & 4 deletions

File tree

samples/dialogs_app.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
logging.basicConfig(level=logging.DEBUG)
1111

12-
from slack_bolt import App
12+
from slack_bolt import App, Ack
1313

1414
app = App()
1515

@@ -52,8 +52,21 @@ def test_command(body, client, ack, logger):
5252

5353

5454
@app.action({"type": "dialog_submission", "callback_id": "dialog-callback-id"})
55-
def dialog_submission(ack):
56-
ack()
55+
def dialog_submission(ack: Ack, body: dict):
56+
errors = []
57+
submission = body["submission"]
58+
if len(submission["loc_origin"]) <= 3:
59+
errors = [
60+
{
61+
"name": "loc_origin",
62+
"error": "Pickup Location must be longer than 3 characters"
63+
}
64+
]
65+
if len(errors) > 0:
66+
# or ack({"errors": errors})
67+
ack(errors=errors)
68+
else:
69+
ack()
5770

5871

5972
@app.options({"type": "dialog_suggestion", "callback_id": "dialog-callback-id"})

slack_bolt/context/ack/internals.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ def _set_response(
6262
if view:
6363
body["view"] = convert_to_dict(view)
6464
self.response = BoltResponse(status=200, body=body)
65+
elif errors:
66+
# dialogs: errors without response_action
67+
body = {"errors": convert_to_dict_list(errors)}
68+
self.response = BoltResponse(status=200, body=body)
6569
else:
6670
if len(body) == 1 and "text" in body:
6771
self.response = BoltResponse(status=200, body=body["text"])
@@ -79,7 +83,12 @@ def _set_response(
7983
if "option_groups" in body:
8084
body["option_groups"] = convert_to_dict_list(body["option_groups"])
8185
if "errors" in body:
82-
body["errors"] = convert_to_dict(body["errors"])
86+
if body.get("response_action", "") == "errors":
87+
# modal
88+
body["errors"] = convert_to_dict(body["errors"])
89+
else:
90+
# dialog
91+
body["errors"] = convert_to_dict_list(body["errors"])
8392
if "view" in body:
8493
body["view"] = convert_to_dict(body["view"])
8594
# no modification for response_type, response_action here

tests/slack_bolt/context/test_ack.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,21 @@ def test_response_type(self):
9797
'{"text": "foo", "response_type": "in_channel"}',
9898
)
9999

100+
def test_dialog_errors(self):
101+
expected_body = '{"errors": [{"name": "loc_origin", "error": "Pickup Location must be longer than 3 characters"}]}'
102+
errors = [
103+
{
104+
"name": "loc_origin",
105+
"error": "Pickup Location must be longer than 3 characters",
106+
}
107+
]
108+
109+
ack = Ack()
110+
response: BoltResponse = ack(errors=errors)
111+
assert (response.status, response.body) == (200, expected_body)
112+
response: BoltResponse = ack({"errors": errors})
113+
assert (response.status, response.body) == (200, expected_body)
114+
100115
def test_view_errors(self):
101116
ack = Ack()
102117
response: BoltResponse = ack(

tests/slack_bolt_async/context/test_async_ack.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ async def test_response_type(self):
101101
'{"text": "foo", "response_type": "in_channel"}',
102102
)
103103

104+
@pytest.mark.asyncio
105+
async def test_dialog_errors(self):
106+
expected_body = '{"errors": [{"name": "loc_origin", "error": "Pickup Location must be longer than 3 characters"}]}'
107+
errors = [
108+
{
109+
"name": "loc_origin",
110+
"error": "Pickup Location must be longer than 3 characters",
111+
}
112+
]
113+
114+
ack = AsyncAck()
115+
response: BoltResponse = await ack(errors=errors)
116+
assert (response.status, response.body) == (200, expected_body)
117+
response: BoltResponse = await ack({"errors": errors})
118+
assert (response.status, response.body) == (200, expected_body)
119+
104120
@pytest.mark.asyncio
105121
async def test_view_errors(self):
106122
ack = AsyncAck()

0 commit comments

Comments
 (0)