Skip to content

Commit d7af0bc

Browse files
authored
Fix #552 Unable to use request body with lazy listener when socket mode is enabled (#555)
1 parent f3f4718 commit d7af0bc

File tree

4 files changed

+167
-2
lines changed

4 files changed

+167
-2
lines changed

slack_bolt/request/async_request.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ def __init__(
7777
self.mode = mode
7878

7979
def to_copyable(self) -> "AsyncBoltRequest":
80+
body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
8081
return AsyncBoltRequest(
81-
body=self.raw_body,
82+
body=body,
8283
query=self.query,
8384
headers=self.headers,
8485
context=self.context.to_copyable(),

slack_bolt/request/request.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ def __init__(
7474
self.mode = mode
7575

7676
def to_copyable(self) -> "BoltRequest":
77+
body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
7778
return BoltRequest(
78-
body=self.raw_body,
79+
body=body,
7980
query=self.query,
8081
headers=self.headers,
8182
context=self.context.to_copyable(),
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import logging
2+
import time
3+
4+
from slack_sdk import WebClient
5+
6+
from slack_bolt import App
7+
from slack_bolt.adapter.socket_mode import SocketModeHandler
8+
from .mock_socket_mode_server import (
9+
start_socket_mode_server,
10+
stop_socket_mode_server,
11+
)
12+
from .mock_web_api_server import (
13+
setup_mock_web_api_server,
14+
cleanup_mock_web_api_server,
15+
)
16+
from ...utils import remove_os_env_temporarily, restore_os_env
17+
18+
19+
class TestSocketModeLazyListeners:
20+
logger = logging.getLogger(__name__)
21+
22+
def setup_method(self):
23+
self.old_os_env = remove_os_env_temporarily()
24+
setup_mock_web_api_server(self)
25+
self.web_client = WebClient(
26+
token="xoxb-api_test",
27+
base_url="http://localhost:8888",
28+
)
29+
start_socket_mode_server(self, 3011)
30+
time.sleep(2) # wait for the server
31+
32+
def teardown_method(self):
33+
cleanup_mock_web_api_server(self)
34+
restore_os_env(self.old_os_env)
35+
stop_socket_mode_server(self)
36+
37+
def test_lazy_listener_calls(self):
38+
39+
app = App(client=self.web_client)
40+
41+
result = {"lazy_called": False}
42+
43+
@app.shortcut("do-something")
44+
def handle_shortcuts(ack):
45+
ack()
46+
47+
@app.event("message")
48+
def handle_message_events(body, logger):
49+
logger.info(body)
50+
51+
def lazy_func(body):
52+
assert body.get("command") == "/hello-socket-mode"
53+
result["lazy_called"] = True
54+
55+
app.command("/hello-socket-mode")(
56+
ack=lambda ack: ack(),
57+
lazy=[lazy_func],
58+
)
59+
60+
handler = SocketModeHandler(
61+
app_token="xapp-A111-222-xyz",
62+
app=app,
63+
trace_enabled=True,
64+
)
65+
try:
66+
handler.client.wss_uri = "ws://127.0.0.1:3011/link"
67+
handler.connect()
68+
assert handler.client.is_connected() is True
69+
time.sleep(2) # wait for the message receiver
70+
handler.client.send_message("foo")
71+
72+
spent_time = 0
73+
while spent_time < 5 and result["lazy_called"] is False:
74+
spent_time += 0.5
75+
time.sleep(0.5)
76+
assert result["lazy_called"] is True
77+
78+
finally:
79+
handler.client.close()
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import asyncio
2+
3+
import pytest
4+
from slack_sdk.web.async_client import AsyncWebClient
5+
6+
from slack_bolt.adapter.socket_mode.aiohttp import AsyncSocketModeHandler
7+
from slack_bolt.app.async_app import AsyncApp
8+
from tests.mock_web_api_server import (
9+
setup_mock_web_api_server,
10+
cleanup_mock_web_api_server,
11+
)
12+
from tests.utils import remove_os_env_temporarily, restore_os_env
13+
from ...adapter_tests.socket_mode.mock_socket_mode_server import (
14+
start_socket_mode_server,
15+
stop_socket_mode_server_async,
16+
)
17+
18+
19+
class TestSocketModeAiohttp:
20+
valid_token = "xoxb-valid"
21+
mock_api_server_base_url = "http://localhost:8888"
22+
web_client = AsyncWebClient(
23+
token=valid_token,
24+
base_url=mock_api_server_base_url,
25+
)
26+
27+
@pytest.fixture
28+
def event_loop(self):
29+
old_os_env = remove_os_env_temporarily()
30+
try:
31+
setup_mock_web_api_server(self)
32+
loop = asyncio.get_event_loop()
33+
yield loop
34+
loop.close()
35+
cleanup_mock_web_api_server(self)
36+
finally:
37+
restore_os_env(old_os_env)
38+
39+
@pytest.mark.asyncio
40+
async def test_lazy_listeners(self):
41+
start_socket_mode_server(self, 3021)
42+
await asyncio.sleep(1) # wait for the server
43+
44+
app = AsyncApp(client=self.web_client)
45+
46+
result = {"lazy_called": False}
47+
48+
@app.shortcut("do-something")
49+
async def shortcut_handler(ack):
50+
await ack()
51+
52+
@app.event("message")
53+
async def handle_message_events(body, logger):
54+
logger.info(body)
55+
56+
async def just_ack(ack):
57+
await ack()
58+
59+
async def lazy_func(body):
60+
assert body.get("command") == "/hello-socket-mode"
61+
result["lazy_called"] = True
62+
63+
app.command("/hello-socket-mode")(ack=just_ack, lazy=[lazy_func])
64+
65+
handler = AsyncSocketModeHandler(
66+
app_token="xapp-A111-222-xyz",
67+
app=app,
68+
)
69+
try:
70+
handler.client.wss_uri = "ws://localhost:3021/link"
71+
72+
await handler.connect_async()
73+
await asyncio.sleep(2) # wait for the message receiver
74+
await handler.client.send_message("foo")
75+
76+
spent_time = 0
77+
while spent_time < 5 and result["lazy_called"] is False:
78+
spent_time += 0.5
79+
await asyncio.sleep(0.5)
80+
assert result["lazy_called"] is True
81+
82+
finally:
83+
await handler.client.close()
84+
await stop_socket_mode_server_async(self)

0 commit comments

Comments
 (0)