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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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)
Example #6
0
    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
Example #7
0
    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
Example #8
0
    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)
Example #9
0
    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)
Example #10
0
    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)
Example #12
0
    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
Example #13
0
 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
Example #14
0
    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
Example #15
0
    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
Example #16
0
    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)
Example #17
0
    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",
             ),
         )
Example #19
0
    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
Example #20
0
 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
Example #23
0
    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
Example #24
0
    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
Example #25
0
    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)
Example #26
0
    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
Example #27
0
    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
Example #29
0
    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)