def test_goal_creation_saves_goal_without_spaces(): # given ack = MagicMock(spec=Ack) goal_content = "any_goal_content" team_id = "any_team_id" payload = { "team_id": team_id, "state": { "values": { CREATE_GOAL_INPUT_BLOCK: { CREATE_GOAL_INPUT: { "value": goal_content } } } }, } goal_store = MagicMock(spec=GoalStore) context = BoltContext() context[SlackMiddleware.GOAL_STORE_KEY] = goal_store # when create_goal(ack=ack, payload=payload, context=context) # then ack.assert_called_once() goal_store.create_goal.assert_called_once_with(content=goal_content, slack_team_id=team_id)
def zotero(self, ack: Ack, client: WebClient, context: BoltContext, logger: logging.Logger, payload: dict, say: Say): ack() search_term = payload.get('text') zotero = Zotero(context.get('bot_user_id')) results = zotero.read(search_term) if len(results): say(blocks=zotero.blocks(results)) else: say(f"I did not find any zotero items matching `{search_term}`")
def test_it_adds_install_store_to_ctx_and_calls_next(target: Target): # given context = BoltContext() next_func = MagicMock() # when target.slack_middleware.ctx_install_store(context=context, next=next_func) # then assert (context[SlackMiddleware.INSTALL_STORE_KEY] == target.slack_middleware.INSTALL_STORE) next_func.assert_called_once_with()
def test_it_adds_client_secret_to_ctx_and_calls_next(target: Target): # given context = BoltContext() next_func = MagicMock() # when target.slack_middleware.ctx_client_secret(context=context, next=next_func) # then assert (context[SlackMiddleware.CLIENT_SECRET_KEY] == target.slack_middleware.CLIENT_SECRET) next_func.assert_called_once_with()
def test_app_uninstalled_deletes_bot(): # given context = BoltContext() install_store = MagicMock(spec=TeamiclinkInstallStore) context[SlackMiddleware.INSTALL_STORE_KEY] = install_store context["team_id"] = "any_tema_id" # when app_uninstalled(context=context, event=Dict) # then install_store.delete_bot.assert_called_once_with( team_id=context["team_id"])
def __init__(self, ack: Ack, client: WebClient, context: BoltContext, logger: logger, request: BoltRequest, view: View): logger.info("Updating Zotero config...") super().__init__(context.get('user_id')) state: dict = view.get('state') form_fields: dict = state['values'] sql_fields: dict = {'user_id': context.get('user_id')} for i in form_fields: form_field: dict = form_fields[i] for t in form_field: field_name: str = t field = form_field[t] field_type = field.get('type') field_value: dict = field.get('value') if field_type == 'static_select': field_value = field.get('selected_option').get('value') if field_value is None and hasattr(self, field_name): field_value = getattr(self, field_name) if field_name == 'zotero_api_key': field_value = self.db.cipher.encrypt( field_value.encode('utf-8')) sql_fields[field_name] = field_value placeholders: list = [] for i in range(0, len(sql_fields)): placeholders.append("?") placeholder: str = ','.join(placeholders) field_names: str = ', '.join(sql_fields.keys()) insert_query = f"INSERT OR REPLACE INTO {self.table_name} ({field_names}) VALUES({placeholder})" self.db.cursor.execute(insert_query, list(sql_fields.values())) self.db.connection.commit() ack()
def test_it_handles_no_goals(): # given ack = MagicMock(spec=Ack) say = MagicMock(spec=Say) context = BoltContext() goal_store = MagicMock(spec=GoalStore) goal_store.read_goals.return_value = [] context[SlackMiddleware.GOAL_STORE_KEY] = goal_store context["team_id"] = "any_team_id" # when read_goals(ack=ack, say=say, context=context) say_calls = say.call_args.kwargs # then assert say_calls["text"] is not None
def test_it_calls_uninstall_with_client_variables(): # given ack = MagicMock(spec=Ack) client = MagicMock(spec=WebClient) context = BoltContext() context[SlackMiddleware.CLIENT_ID_KEY] = "any_client_id" context[SlackMiddleware.CLIENT_SECRET_KEY] = "any_client_secret" # when uninstall(ack=ack, client=client, context=context) # then ack.assert_called_once() client.apps_uninstall.assert_called_once_with( client_id=context[SlackMiddleware.CLIENT_ID_KEY], client_secret=context[SlackMiddleware.CLIENT_SECRET_KEY], )
def __init__(self, ack: Ack, event: dict, client: WebClient, context: BoltContext, logger: logging.Logger, payload: dict, request: BoltRequest, response: BoltResponse): self.herald = herald text = get_bot_mention_text(context.get('bot_user_id'), payload.get('text')) keyword, sep, payload_text = text.partition(" ") payload['text'] = payload_text if hasattr(self, keyword): event_handler = getattr(self, keyword) arg_names = inspect.getfullargspec(event_handler).args event_handler(**build_required_kwargs( logger=logger, request=request, response=response, required_arg_names=arg_names, this_func=event_handler, ))
def test_it_deletes_goal(): # given ack = MagicMock(spec=Ack) context = BoltContext() goal_store = MagicMock(spec=GoalStore) context[SlackMiddleware.GOAL_STORE_KEY] = goal_store context["user_id"] = "any_user_id" context["channel_id"] = "any_channel_id" payload = dict(value=str(uuid4())) client = MagicMock(spec=WebClient) # when delete_goal(ack=ack, payload=payload, context=context, client=client) # then ack.assert_called_once() goal_store.delete_goal.assert_called_once_with(id=UUID(payload["value"])) client.chat_postEphemeral.assert_called_once_with( text=ANY, user=context["user_id"], channel=context["channel_id"])
def __init__(self, ack: Ack, client: WebClient, context: BoltContext, payload: dict, request: BoltRequest, respond: Respond, say: Say): ack() self.user_id = context.get('user_id') if payload.get('text') is not None: who_to_herald, sep, payload_text = payload.get('text').partition( " ") if who_to_herald != "me": user_token = os.environ.get("JIBOT_SLACK_USER_TOKEN", None) user_response: slack_response = client.users_identity( token=user_token, name=who_to_herald) if user_response.get('ok'): self.user_id = user_response.get('user').get('id') if respond.response_url is None: say(blocks=self.blocks()) else: respond(blocks=self.blocks())
def __init__(self, ack: Ack, context: BoltContext, client: WebClient, event: dict, logger: logging.Logger, payload: dict, request: BoltRequest, response: BoltResponse): ack() view = event.get('view', None) view_id = view.get('id') if view is not None else None herald_function = herald(**build_required_kwargs( logger=logger, request=request, response=response, required_arg_names=inspect.getfullargspec(herald).args, this_func=herald, )) app_home_view = {"type": "home", "blocks": herald_function.blocks()} app_home_view['blocks'].append({"type": "divider"}) app_home_view['blocks'].extend(shared_links().blocks()) if view_id is None: client.views_publish(user_id=context.get('user_id'), view=json.dumps(app_home_view)) else: client.views_update(view_id=view.get('id'), view=json.dumps(app_home_view))
def test_it_reads_goals(): # given ack = MagicMock(spec=Ack) say = MagicMock(spec=Say) context = BoltContext() goal_store = MagicMock(spec=GoalStore) goal1 = Goal(content="any_content", slack_team_id="any_team_id", id=uuid4()) goal_store.read_goals.return_value = [goal1] context[SlackMiddleware.GOAL_STORE_KEY] = goal_store context["team_id"] = "any_team_id" # when read_goals(ack=ack, say=say, context=context) say_calls = say.call_args.kwargs # then ack.assert_called_once() goal_store.read_goals.assert_called_once_with( slack_team_id=context["team_id"]) assert say_calls["text"] == "" assert say_calls["blocks"] == [make_goal_block(goal=goal1)]
def test_goal_creation_returns_errors_for_invalid_goal(goal_content, goal_error): # given ack = MagicMock(spec=Ack) payload = { "state": { "values": { CREATE_GOAL_INPUT_BLOCK: { CREATE_GOAL_INPUT: { "value": goal_content } } } } } context = BoltContext() # when create_goal(ack=ack, payload=payload, context=context) ack_calls = ack.call_args.kwargs # then assert ack_calls["response_action"] == "errors" assert ack_calls["errors"] == {CREATE_GOAL_INPUT_BLOCK: goal_error}
def mention(context: BoltContext): context.say(":wave: Hi there!")
def __init__(self, ack: Ack, client: WebClient, context: BoltContext, logger: logger, payload: dict, request: BoltRequest): logger.info("Init Zotero UI...") super().__init__(context.get('user_id')) container = request.body.get('container', None) view: dict = request.body.get(container.get('type')) title: dict = view.get('title') title.update(text="Zotero Integration") close_button = view.get('close') close_button.update(text="Go Back") blocks: list = list() intro = { "type": "header", "text": { "type": "plain_text", "text": "The area is used to configure your slack / zotero integration." } } link = { "type": "section", "text": { "type": "mrkdwn", "text": "You can create and configure Zotero API settings at <https://www.zotero.org/settings/keys|Zotero API Settings>" } } library_id = { "type": "input", "element": { "type": "plain_text_input", "action_id": "zotero_library_id", # "placeholder": { # "type": "plain_text", # "emoji": True # }, }, "label": { "type": "plain_text", "text": ":id: Library ID", "emoji": True } } library_type_options = [{ "text": { "type": "plain_text", "text": ":bust_in_silhouette: User", "emoji": True }, "value": "user", }, { "text": { "type": "plain_text", "text": ":busts_in_silhouette: Group", "emoji": True }, "value": "group", }] library_type = { "type": "input", "element": { "type": "static_select", "placeholder": { "type": "plain_text", "text": "Library Type", "emoji": True }, "options": library_type_options, "action_id": "zotero_library_type" }, "label": { "type": "plain_text", "text": ":books: Library Type", "emoji": True } } if self.zotero_library_type is not None: current_library_type = next( (x for x in library_type_options if x.get('value') == self.zotero_library_type), library_type_options[0]) library_type['element']["initial_option"] = current_library_type if self.zotero_library_id is not None: library_id['element']["initial_value"] = self.zotero_library_id api_key = { "type": "input", "element": { "type": "plain_text_input", "action_id": "zotero_api_key", "placeholder": { "type": "plain_text", "text": "HIDDEN FOR PRIVACY", "emoji": True }, }, "label": { "type": "plain_text", "text": ":key: Api Key", "emoji": True }, "optional": True } blocks.extend([intro, link, library_type, library_id, api_key]) client.views_push(trigger_id=request.body.get('trigger_id'), view={ "type": view.get('type'), "title": title, "close": close_button, "callback_id": self.keyword, "submit": { "type": "plain_text", "text": "Submit", "emoji": True, }, "blocks": blocks }) ack()