async def test_self_events(self): app = AsyncApp(client=self.web_client) app.event("reaction_added")(whats_up) self_event = { "token": "verification_token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "reaction_added", "user": "******", # bot_user_id "item": { "type": "message", "channel": "C111", "ts": "1599529504.000400", }, "reaction": "heart_eyes", "item_user": "******", "event_ts": "1599616881.000800", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, "authed_users": ["W111"], } request = AsyncBoltRequest(body=self_event, mode="socket_mode") response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1 await asyncio.sleep(1) # wait a bit after auto ack() # The listener should not be executed assert self.mock_received_requests.get("/chat.postMessage") is None
async def test_uninstallation_and_revokes(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret) app._client = AsyncWebClient(token="uninstalled-revoked", base_url=self.mock_api_server_base_url) @app.event("app_uninstalled") async def handler1(say: AsyncSay): await say(channel="C111", text="What's up?") @app.event("tokens_revoked") async def handler2(say: AsyncSay): await say(channel="C111", text="What's up?") app_uninstalled_body = { "token": "verification_token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "app_uninstalled" }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, } timestamp, body = str(int(time())), json.dumps(app_uninstalled_body) request: AsyncBoltRequest = AsyncBoltRequest( body=body, headers=self.build_headers(timestamp, body)) response = await app.async_dispatch(request) assert response.status == 200 tokens_revoked_body = { "token": "verification_token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "tokens_revoked", "tokens": { "oauth": ["UXXXXXXXX"], "bot": ["UXXXXXXXX"] }, }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, } timestamp, body = str(int(time())), json.dumps(tokens_revoked_body) request: AsyncBoltRequest = AsyncBoltRequest( body=body, headers=self.build_headers(timestamp, body)) response = await app.async_dispatch(request) assert response.status == 200 # AsyncApp doesn't call auth.test when booting assert self.mock_received_requests.get("/auth.test") is None await asyncio.sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 2
async def test_string_keyword(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) result = {"call_count": 0} @app.message("Hi there!") async def handle_messages(event, logger): logger.info(event) result["call_count"] = result["call_count"] + 1 request = self.build_request(user_message_event_payload) response = await app.async_dispatch(request) assert response.status == 200 request = self.build_request(bot_message_event_payload) response = await app.async_dispatch(request) assert response.status == 200 request = self.build_request(classic_bot_message_event_payload) response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1 await asyncio.sleep(1) # wait a bit after auto ack() assert result["call_count"] == 3
async def test_app_uninstalled(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, installation_store=MyInstallationStore(), ) event_payload = { "token": "verification-token", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "app_uninstalled" }, "type": "event_callback", "event_id": "Ev111", "event_time": 1606805974, } timestamp, body = str(int(time())), json.dumps(event_payload) request: AsyncBoltRequest = AsyncBoltRequest( body=body, headers=self.build_headers(timestamp, body)) response = await app.async_dispatch(request) assert response.status == 404 # Enable the built-in event listeners app.enable_token_revocation_listeners() response = await app.async_dispatch(request) assert response.status == 200 # auth.test API call must be skipped await assert_auth_test_count_async(self, 0) await asyncio.sleep(1) # wait a bit after auto ack() assert app.installation_store.delete_bot_called is True assert app.installation_store.delete_installation_called is True assert app.installation_store.delete_all_called is True
async def test_instance_methods_uncommon_name(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret) awesome = AwesomeClass("Slackbot") app.use(awesome.instance_middleware) app.shortcut("test-shortcut")(awesome.instance_method2) await self.run_app_and_verify(app)
async def test_success_2(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.dialog_suggestion("dialog-callback-id")(handle_suggestion) app.dialog_submission("dialog-callback-id")(handle_submission) app.dialog_cancellation("dialog-callback-id")(handle_cancellation) request = self.build_valid_request(suggestion_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body != "" assert response.headers["content-type"][ 0] == "application/json;charset=utf-8" assert self.mock_received_requests["/auth.test"] == 1 request = self.build_valid_request(submission_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == "" assert self.mock_received_requests["/auth.test"] == 2 request = self.build_valid_request(cancellation_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == "" assert self.mock_received_requests["/auth.test"] == 3
def test_oauth(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, oauth_settings=AsyncOAuthSettings( client_id="111.111", client_secret="xxx", scopes=["chat:write", "commands"], ), ) app_handler = AsyncSlackRequestHandler(app) async def endpoint(req: Request): return await app_handler.handle(req) api = Starlette( debug=True, routes=[ Route("/slack/install", endpoint=endpoint, methods=["GET"]) ], ) client = TestClient(api) response = client.get("/slack/install", allow_redirects=False) assert response.status_code == 200 assert response.headers.get( "content-type") == "text/html; charset=utf-8" assert response.headers.get("content-length") == "565" assert "https://slack.com/oauth/v2/authorize?state=" in response.text
async def test_process_before_response_2(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, process_before_response=True, ) app.dialog_suggestion("dialog-callback-id")(handle_suggestion) app.dialog_submission("dialog-callback-id")(handle_submission) app.dialog_cancellation("dialog-callback-id")(handle_cancellation) request = self.build_valid_request(suggestion_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == json.dumps(options_response) assert response.headers["content-type"][ 0] == "application/json;charset=utf-8" await assert_auth_test_count_async(self, 1) request = self.build_valid_request(submission_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == "" await assert_auth_test_count_async(self, 1) request = self.build_valid_request(cancellation_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == "" await assert_auth_test_count_async(self, 1)
async def test_success_without_type(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.options("dialog-callback-id")(handle_suggestion) app.action("dialog-callback-id")(handle_submission_or_cancellation) request = self.build_valid_request(suggestion_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body != "" assert response.headers["content-type"][ 0] == "application/json;charset=utf-8" await assert_auth_test_count_async(self, 1) request = self.build_valid_request(submission_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == "" await assert_auth_test_count_async(self, 1) request = self.build_valid_request(cancellation_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert response.body == "" await assert_auth_test_count_async(self, 1)
async def test_invalid_message_events(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) async def handle(): pass # valid app.event("message")(handle) with pytest.raises(ValueError): app.event("message.channels")(handle) with pytest.raises(ValueError): app.event("message.groups")(handle) with pytest.raises(ValueError): app.event("message.im")(handle) with pytest.raises(ValueError): app.event("message.mpim")(handle) with pytest.raises(ValueError): app.event(re.compile("message\\..*"))(handle) with pytest.raises(ValueError): app.event({"type": "message.channels"})(handle) with pytest.raises(ValueError): app.event({"type": re.compile("message\\..*")})(handle)
async def test_handle_callback(self): oauth_flow = AsyncOAuthFlow( client=AsyncWebClient(base_url=self.mock_api_server_base_url), settings=AsyncOAuthSettings( client_id="111.222", client_secret="xxx", scopes=["chat:write", "commands"], installation_store=FileInstallationStore(), state_store=FileOAuthStateStore(expiration_seconds=120), success_url="https://www.example.com/completion", failure_url="https://www.example.com/failure", ), ) state = await oauth_flow.issue_new_state(None) req = AsyncBoltRequest( body="", query=f"code=foo&state={state}", headers={ "cookie": [f"{oauth_flow.settings.state_cookie_name}={state}"] }, ) resp = await oauth_flow.handle_callback(req) assert resp.status == 200 assert "https://www.example.com/completion" in resp.body app = AsyncApp(signing_secret="signing_secret", oauth_flow=oauth_flow) global_shortcut_body = { "type": "shortcut", "token": "verification_token", "action_ts": "111.111", "team": { "id": "T111", "domain": "workspace-domain", "enterprise_id": "E111", "enterprise_name": "Org Name", }, "user": { "id": "W111", "username": "******", "team_id": "T111" }, "callback_id": "test-shortcut", "trigger_id": "111.111.xxxxxx", } body = f"payload={quote(json.dumps(global_shortcut_body))}" timestamp = str(int(time())) signature_verifier = SignatureVerifier("signing_secret") headers = { "content-type": ["application/x-www-form-urlencoded"], "x-slack-signature": [ signature_verifier.generate_signature(body=body, timestamp=timestamp) ], "x-slack-request-timestamp": [timestamp], } request = AsyncBoltRequest(body=body, headers=headers) response = await app.async_dispatch(request) assert response.status == 200 await assert_auth_test_count_async(self, 1)
async def test_success_global(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,) app.shortcut("test-shortcut")(simple_listener) request = self.build_valid_request(global_shortcut_raw_body) response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1
def build_app(self, callback_id: str): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret) app.step(callback_id=callback_id, edit=edit, save=save, execute=execute) return app
async def test_middleware_skip(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret) app.event("app_mention", middleware=[skip_middleware])(whats_up) request = self.build_valid_app_mention_request() response = await app.async_dispatch(request) assert response.status == 404 assert self.mock_received_requests["/auth.test"] == 1
async def test_stable_auto_ack(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,) app.event("reaction_added")(always_failing) for _ in range(10): request = self.build_valid_reaction_added_request() response = await app.async_dispatch(request) assert response.status == 200
async def test_middleware_skip(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret) app.event("app_mention", middleware=[skip_middleware])(whats_up) request = self.build_valid_app_mention_request() response = await app.async_dispatch(request) assert response.status == 404 await assert_auth_test_count_async(self, 1)
async def test_app_home_opened(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, installation_store=OrgAppInstallationStore(), ) event_payload = { "token": "verification-token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "app_home_opened", "user": "******", "channel": "D111", "tab": "messages", "event_ts": "1606810927.510671", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1606810927, "authorizations": [{ "enterprise_id": "E111", "team_id": None, "user_id": "W111", "is_bot": True, "is_enterprise_install": True, }], "is_ext_shared_channel": False, } result = Result() @app.event("app_home_opened") async def handle_app_mention(body): assert body == event_payload result.called = True timestamp, body = str(int(time())), json.dumps(event_payload) request: AsyncBoltRequest = AsyncBoltRequest( body=body, headers=self.build_headers(timestamp, body)) response = await app.async_dispatch(request) assert response.status == 200 # auth.test API call must be skipped assert self.mock_received_requests["/auth.test"] == 1 await asyncio.sleep(1) # wait a bit after auto ack() assert result.called is True
async def test_instantiation_non_async_settings_to_app(self): with pytest.raises(BoltError): AsyncApp( signing_secret="xxx", oauth_settings=OAuthSettings( client_id="111.222", client_secret="xxx", scopes="chat:write,commands", ), )
async def test_process_before_response(self): app = AsyncApp(client=self.web_client, process_before_response=True,) app.event("app_mention")(whats_up) request = self.build_valid_app_mention_request() response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1 # no sleep here assert self.mock_received_requests["/chat.postMessage"] == 1
def test_instance(self): server = AsyncSlackAppServer( port=3001, path="/slack/events", app=AsyncApp( signing_secret="valid", token="xoxb-valid", ), ) assert server is not None
async def test_self_events_disabled(self): app = AsyncApp(client=self.web_client, ignoring_self_events_enabled=False) app.event("reaction_added")(whats_up) request = AsyncBoltRequest(body=self_event, mode="socket_mode") response = await app.async_dispatch(request) assert response.status == 200 await assert_auth_test_count_async(self, 0) await asyncio.sleep(1) # wait a bit after auto ack() # The listener should be executed assert self.mock_received_requests.get("/chat.postMessage") == 1
async def test_reaction_added(self): app = AsyncApp(client=self.web_client) app.event("reaction_added")(whats_up) request = self.build_valid_reaction_added_request() response = await app.async_dispatch(request) assert response.status == 200 await assert_auth_test_count_async(self, 1) await asyncio.sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 1
async def test_app_mention(self): app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,) app.event("app_mention")(whats_up) request = self.build_valid_app_mention_request() response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1 await asyncio.sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 1
async def test_no_next_call(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.use(no_next) app.shortcut("test-shortcut")(just_ack) response = await app.async_dispatch(self.build_request()) assert response.status == 404 assert self.mock_received_requests["/auth.test"] == 1
async def test_no_next_call(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.use(no_next) app.shortcut("test-shortcut")(just_ack) response = await app.async_dispatch(self.build_request()) assert response.status == 404 await assert_auth_test_count_async(self, 1)
async def test_success_2(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.block_action("a")(simple_listener) request = self.build_valid_request() response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1
async def test_success_2(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.view_closed("view-id")(simple_listener) request = self.build_valid_request() response = await app.async_dispatch(request) assert response.status == 200 await assert_auth_test_count_async(self, 1)
async def test_default_type(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.action({"action_id": "a", "block_id": "b"})(simple_listener) request = self.build_valid_request() response = await app.async_dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1
async def test_regexp_keyword_unmatched(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.message(re.compile("HELLO"))(whats_up) request = self.build_request() response = await app.async_dispatch(request) assert response.status == 404 assert self.mock_received_requests["/auth.test"] == 1
async def test_success(self): app = AsyncApp( client=self.web_client, signing_secret=self.signing_secret, ) app.command("/hello-world")(commander) request = self.build_valid_request() response = await app.async_dispatch(request) assert response.status == 200 await assert_auth_test_count_async(self, 1)