From 102aa6134b196578c201c1ad18f69f7b148aa643 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Thu, 12 Sep 2024 15:49:14 -0400 Subject: [PATCH 1/4] Quick and simple solution --- slack_bolt/app/app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slack_bolt/app/app.py b/slack_bolt/app/app.py index c72394821..f7761773e 100644 --- a/slack_bolt/app/app.py +++ b/slack_bolt/app/app.py @@ -877,6 +877,7 @@ def function( callback_id: Union[str, Pattern], matchers: Optional[Sequence[Callable[..., bool]]] = None, middleware: Optional[Sequence[Union[Callable, Middleware]]] = None, + auto_acknowledge: bool = True, ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]: """Registers a new Function listener. This method can be used as either a decorator or a method. @@ -911,7 +912,7 @@ def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail): def __call__(*args, **kwargs): functions = self._to_listener_functions(kwargs) if kwargs else list(args) primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger) - return self._register_listener(functions, primary_matcher, matchers, middleware, True) + return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge) return __call__ From 1be96be2e3a912bcabdc7783c85808038676669b Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Thu, 12 Sep 2024 17:03:29 -0400 Subject: [PATCH 2/4] Update async_app.py --- slack_bolt/app/async_app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slack_bolt/app/async_app.py b/slack_bolt/app/async_app.py index 92bad71b7..febf2464c 100644 --- a/slack_bolt/app/async_app.py +++ b/slack_bolt/app/async_app.py @@ -911,6 +911,7 @@ def function( callback_id: Union[str, Pattern], matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None, + auto_acknowledge: bool = True, ) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]]: """Registers a new Function listener. This method can be used as either a decorator or a method. @@ -947,7 +948,7 @@ def __call__(*args, **kwargs): primary_matcher = builtin_matchers.function_executed( callback_id=callback_id, base_logger=self._base_logger, asyncio=True ) - return self._register_listener(functions, primary_matcher, matchers, middleware, True) + return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge) return __call__ From 0ea95790cdc7e8de72c6042df35628eb59798c63 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Wed, 2 Oct 2024 14:08:38 -0400 Subject: [PATCH 3/4] Add some unit tests --- tests/scenario_tests/test_function.py | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/scenario_tests/test_function.py b/tests/scenario_tests/test_function.py index d00898082..a39c68315 100644 --- a/tests/scenario_tests/test_function.py +++ b/tests/scenario_tests/test_function.py @@ -112,6 +112,31 @@ def test_invalid_declaration(self): with pytest.raises(TypeError): func("hello world") + def test_auto_acknowledge_false_without_acknowledging(self): + app = App( + client=self.web_client, + signing_secret=self.signing_secret, + ) + app.function("reverse", auto_acknowledge=False)(just_no_ack) + + request = self.build_request_from_body(function_body) + response = app.dispatch(request) + + assert response.status == 404 + assert_auth_test_count(self, 1) + + def test_auto_acknowledge_false_with_acknowledging(self): + app = App( + client=self.web_client, + signing_secret=self.signing_secret, + ) + app.function("reverse", auto_acknowledge=False)(just_ack) + + request = self.build_request_from_body(function_body) + response = app.dispatch(request) + assert response.status == 200 + assert_auth_test_count(self, 1) + function_body = { "token": "verification_token", @@ -230,3 +255,14 @@ def complete_it(body, event, complete): assert body == function_body assert event == function_body["event"] complete(outputs={}) + + +def just_ack(ack, body, event): + assert body == function_body + assert event == function_body["event"] + ack() + + +def just_no_ack(ack, body, event): + assert body == function_body + assert event == function_body["event"] From 2377b5617787d8a96c3951b0ffe9892791d5ea3d Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Wed, 2 Oct 2024 15:22:01 -0400 Subject: [PATCH 4/4] Add async tests --- tests/scenario_tests/test_function.py | 17 ++++----- tests/scenario_tests_async/test_function.py | 38 +++++++++++++++++++++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/tests/scenario_tests/test_function.py b/tests/scenario_tests/test_function.py index a39c68315..00f0efba8 100644 --- a/tests/scenario_tests/test_function.py +++ b/tests/scenario_tests/test_function.py @@ -112,30 +112,31 @@ def test_invalid_declaration(self): with pytest.raises(TypeError): func("hello world") - def test_auto_acknowledge_false_without_acknowledging(self): + def test_auto_acknowledge_false_with_acknowledging(self): app = App( client=self.web_client, signing_secret=self.signing_secret, ) - app.function("reverse", auto_acknowledge=False)(just_no_ack) + app.function("reverse", auto_acknowledge=False)(just_ack) request = self.build_request_from_body(function_body) response = app.dispatch(request) - - assert response.status == 404 + assert response.status == 200 assert_auth_test_count(self, 1) - def test_auto_acknowledge_false_with_acknowledging(self): + def test_auto_acknowledge_false_without_acknowledging(self, caplog): app = App( client=self.web_client, signing_secret=self.signing_secret, ) - app.function("reverse", auto_acknowledge=False)(just_ack) + app.function("reverse", auto_acknowledge=False)(just_no_ack) request = self.build_request_from_body(function_body) response = app.dispatch(request) - assert response.status == 200 + + assert response.status == 404 assert_auth_test_count(self, 1) + assert f"WARNING {just_no_ack.__name__} didn't call ack()" in caplog.text function_body = { @@ -263,6 +264,6 @@ def just_ack(ack, body, event): ack() -def just_no_ack(ack, body, event): +def just_no_ack(body, event): assert body == function_body assert event == function_body["event"] diff --git a/tests/scenario_tests_async/test_function.py b/tests/scenario_tests_async/test_function.py index 0aefd7774..a2c10950c 100644 --- a/tests/scenario_tests_async/test_function.py +++ b/tests/scenario_tests_async/test_function.py @@ -116,6 +116,33 @@ async def test_invalid_callback_id(self): assert response.status == 404 await assert_auth_test_count_async(self, 1) + @pytest.mark.asyncio + async def test_auto_acknowledge_false_with_acknowledging(self): + app = AsyncApp( + client=self.web_client, + signing_secret=self.signing_secret, + ) + app.function("reverse", auto_acknowledge=False)(just_ack) + + request = self.build_request_from_body(function_body) + response = await app.async_dispatch(request) + assert response.status == 200 + await assert_auth_test_count_async(self, 1) + + @pytest.mark.asyncio + async def test_auto_acknowledge_false_without_acknowledging(self, caplog): + app = AsyncApp( + client=self.web_client, + signing_secret=self.signing_secret, + ) + app.function("reverse", auto_acknowledge=False)(just_no_ack) + + request = self.build_request_from_body(function_body) + response = await app.async_dispatch(request) + assert response.status == 404 + await assert_auth_test_count_async(self, 1) + assert f"WARNING {just_no_ack.__name__} didn't call ack()" in caplog.text + function_body = { "token": "verification_token", @@ -238,3 +265,14 @@ async def complete_it(body, event, complete): await complete( outputs={}, ) + + +async def just_ack(ack, body, event): + assert body == function_body + assert event == function_body["event"] + await ack() + + +async def just_no_ack(body, event): + assert body == function_body + assert event == function_body["event"]