Fixed Slack file upload deprecation (#1130)

This commit is contained in:
Delena Malan 2024-05-28 02:10:34 +02:00 committed by GitHub
parent d3c13fd619
commit da14b3a54f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 231 additions and 167 deletions

View File

@ -603,16 +603,17 @@ class NotifySlack(NotifyBase):
channel if channel[0] == '#' \
else '#{}'.format(channel)
# Store the valid and massaged payload that is recognizable by
# slack. This list is used for sending attachments later.
attach_channel_list.append(payload['channel'])
response = self._send(url, payload)
if not response:
# Handle any error
has_error = True
continue
# Store the valid channel or chat ID (for DMs) that will
# be accepted by Slack's attachment method later.
if response.get('channel'):
attach_channel_list.append(response.get('channel'))
self.logger.info(
'Sent Slack notification{}.'.format(
' to {}'.format(channel)
@ -635,21 +636,58 @@ class NotifySlack(NotifyBase):
'Posting Slack attachment {}'.format(
attachment.url(privacy=True)))
# Prepare API Upload Payload
_payload = {
# Get the URL to which to upload the file.
# https://api.slack.com/methods/files.getUploadURLExternal
_params = {
'filename': attachment.name,
'channels': ','.join(attach_channel_list)
'length': len(attachment),
}
# Our URL
_url = self.api_url.format('files.upload')
response = self._send(_url, _payload, attach=attachment)
if not (response and response.get('file') and
response['file'].get('url_private')):
# We failed to post our attachments, take an early exit
_url = self.api_url.format('files.getUploadURLExternal')
response = self._send(
_url, {}, http_method='get', params=_params
)
if not (
response and response.get('file_id')
and response.get('upload_url')
):
self.logger.error('Could retrieve file upload URL.')
# We failed to get an upload URL, take an early exit
return False
file_id = response.get('file_id')
upload_url = response.get('upload_url')
# Upload file
response = self._send(upload_url, {}, attach=attachment)
# Send file to channels
# https://api.slack.com/methods/files.completeUploadExternal
for channel_id in attach_channel_list:
_payload = {
'files': [{
"id": file_id,
"title": attachment.name,
}],
'channel_id': channel_id
}
_url = self.api_url.format('files.completeUploadExternal')
response = self._send(_url, _payload)
# Expected response
# {
# "ok": true,
# "files": [
# {
# "id": "F123ABC456",
# "title": "slack-test"
# }
# ]
# }
if not (response and response.get('files')):
self.logger.error('Failed to send file to channel.')
# We failed to send the file to the channel,
# take an early exit
return False
return not has_error
def lookup_userid(self, email):
@ -808,7 +846,8 @@ class NotifySlack(NotifyBase):
return user_id
def _send(self, url, payload, attach=None, **kwargs):
def _send(self, url, payload, attach=None, http_method='post', params=None,
**kwargs):
"""
Wrapper to the requests (post) object
"""
@ -842,13 +881,15 @@ class NotifySlack(NotifyBase):
if attach:
files = {'file': (attach.name, open(attach.path, 'rb'))}
r = requests.post(
r = requests.request(
http_method,
url,
data=payload if attach else dumps(payload),
headers=headers,
files=files,
verify=self.verify_certificate,
timeout=self.request_timeout,
params=params if params else None,
)
# Posts return a JSON string
@ -866,11 +907,22 @@ class NotifySlack(NotifyBase):
# 'ok': False,
# 'error': 'not_in_channel',
# }
#
# The text 'ok' is returned if this is a Webhook request
# So the below captures that as well.
status_okay = (response and response.get('ok', False)) \
if self.mode is SlackMode.BOT else r.content == b'ok'
status_okay = False
if self.mode is SlackMode.BOT:
status_okay = (
(response and response.get('ok', False)) or
# Responses for file uploads look like this
# 'OK - <file length>'
(
r.content and
isinstance(r.content, bytes) and
b'OK' in r.content
)
)
elif r.content == b'ok':
# The text 'ok' is returned if this is a Webhook request
# So the below captures that as well.
status_okay = True
if r.status_code != requests.codes.ok or not status_okay:
# We had a problem
@ -879,9 +931,9 @@ class NotifySlack(NotifyBase):
r.status_code, SLACK_HTTP_ERROR_MAP)
self.logger.warning(
'Failed to send {}to Slack: '
'Failed to send{} to Slack: '
'{}{}error={}.'.format(
attach.name if attach else '',
(' ' + attach.name) if attach else '',
status_str,
', ' if status_str else '',
r.status_code))
@ -913,53 +965,15 @@ class NotifySlack(NotifyBase):
# "username": "Apprise"
# }
# File Attachment Responses look like this
# files.completeUploadExternal responses look like this:
# {
# "file": {
# "channels": [],
# "comments_count": 0,
# "created": 1573617523,
# "display_as_bot": false,
# "editable": false,
# "external_type": "",
# "filetype": "png",
# "groups": [],
# "has_rich_preview": false,
# "id": "FQJJLDAHM",
# "image_exif_rotation": 1,
# "ims": [],
# "is_external": false,
# "is_public": false,
# "is_starred": false,
# "mimetype": "image/png",
# "mode": "hosted",
# "name": "apprise-test.png",
# "original_h": 640,
# "original_w": 640,
# "permalink": "https://{name}.slack.com/files/...
# "permalink_public": "https://slack-files.com/...
# "pretty_type": "PNG",
# "public_url_shared": false,
# "shares": {},
# "size": 238810,
# "thumb_160": "https://files.slack.com/files-tmb/...
# "thumb_360": "https://files.slack.com/files-tmb/...
# "thumb_360_h": 360,
# "thumb_360_w": 360,
# "thumb_480": "https://files.slack.com/files-tmb/...
# "thumb_480_h": 480,
# "thumb_480_w": 480,
# "thumb_64": "https://files.slack.com/files-tmb/...
# "thumb_80": "https://files.slack.com/files-tmb/...
# "thumb_tiny": abcd...
# "timestamp": 1573617523,
# "title": "apprise-test",
# "url_private": "https://files.slack.com/files-pri/...
# "url_private_download": "https://files.slack.com/files-...
# "user": "UADKLLMJT",
# "username": ""
# },
# "ok": true
# "ok": true,
# "files": [
# {
# "id": "F123ABC456",
# "title": "slack-test"
# }
# ]
# }
except requests.RequestException as e:
self.logger.warning(

View File

@ -115,7 +115,8 @@ class AppriseURLTester:
@mock.patch('requests.get')
@mock.patch('requests.post')
def run(self, url, meta, mock_post, mock_get):
@mock.patch('requests.request')
def run(self, url, meta, mock_request, mock_post, mock_get):
"""
Run a specific test
"""
@ -150,6 +151,7 @@ class AppriseURLTester:
robj.content = u''
mock_get.return_value = robj
mock_post.return_value = robj
mock_request.return_value = robj
try:
# We can now instantiate our object:
@ -276,8 +278,21 @@ class AppriseURLTester:
@mock.patch('requests.put')
@mock.patch('requests.delete')
@mock.patch('requests.patch')
def __notify(self, url, obj, meta, asset, mock_patch, mock_del, mock_put,
mock_head, mock_post, mock_get):
@mock.patch('requests.request')
def __notify(
self,
url,
obj,
meta,
asset,
mock_request,
mock_patch,
mock_del,
mock_put,
mock_head,
mock_post,
mock_get
):
"""
Perform notification testing against object specified
"""
@ -342,6 +357,7 @@ class AppriseURLTester:
mock_patch.return_value = robj
mock_del.return_value = robj
mock_put.return_value = robj
mock_request.return_value = robj
if test_requests_exceptions is False:
# Handle our default response
@ -351,6 +367,7 @@ class AppriseURLTester:
mock_post.return_value.status_code = requests_response_code
mock_get.return_value.status_code = requests_response_code
mock_patch.return_value.status_code = requests_response_code
mock_request.return_value.status_code = requests_response_code
# Handle our default text response
mock_get.return_value.content = requests_response_content
@ -359,6 +376,7 @@ class AppriseURLTester:
mock_put.return_value.content = requests_response_content
mock_head.return_value.content = requests_response_content
mock_patch.return_value.content = requests_response_content
mock_request.return_value.content = requests_response_content
mock_get.return_value.text = requests_response_text
mock_post.return_value.text = requests_response_text
@ -366,6 +384,7 @@ class AppriseURLTester:
mock_del.return_value.text = requests_response_text
mock_head.return_value.text = requests_response_text
mock_patch.return_value.text = requests_response_text
mock_request.return_value.text = requests_response_text
# Ensure there is no side effect set
mock_post.side_effect = None
@ -374,6 +393,7 @@ class AppriseURLTester:
mock_head.side_effect = None
mock_get.side_effect = None
mock_patch.side_effect = None
mock_request.side_effect = None
else:
# Handle exception testing; first we turn the boolean flag
@ -532,6 +552,7 @@ class AppriseURLTester:
mock_put.side_effect = _exception
mock_get.side_effect = _exception
mock_patch.side_effect = _exception
mock_request.side_effect = _exception
try:
assert obj.notify(
@ -577,6 +598,7 @@ class AppriseURLTester:
mock_head.side_effect = _exception
mock_get.side_effect = _exception
mock_patch.side_effect = _exception
mock_request.side_effect = _exception
try:
assert obj.notify(

View File

@ -131,10 +131,6 @@ apprise_url_tests = (
'requests_response_text': {
'ok': True,
'message': '',
# support attachments
'file': {
'url_private': 'http://localhost/',
},
},
}),
# Test blocks mode
@ -170,10 +166,6 @@ apprise_url_tests = (
'requests_response_text': {
'ok': True,
'message': '',
# support attachments
'file': {
'url_private': 'http://localhost/',
},
},
# Our expected url(privacy=True) startswith() response:
'privacy_url': 'slack://test@x...4/nuxref/',
@ -184,10 +176,6 @@ apprise_url_tests = (
'requests_response_text': {
'ok': True,
'message': '',
# support attachments
'file': {
'url_private': 'http://localhost/',
},
},
# We fail because of the empty channel #$ and #-
'notify_response': False,
@ -289,8 +277,8 @@ def test_plugin_slack_urls():
AppriseURLTester(tests=apprise_url_tests).run_all()
@mock.patch('requests.post')
def test_plugin_slack_oauth_access_token(mock_post):
@mock.patch('requests.request')
def test_plugin_slack_oauth_access_token(mock_request):
"""
NotifySlack() OAuth Access Token Tests
@ -303,11 +291,7 @@ def test_plugin_slack_oauth_access_token(mock_post):
request.content = dumps({
'ok': True,
'message': '',
# Attachment support
'file': {
'url_private': 'http://localhost',
}
'channel': 'C123456',
})
request.status_code = requests.codes.ok
@ -319,8 +303,7 @@ def test_plugin_slack_oauth_access_token(mock_post):
token = 'xoxb-1234-1234-abc124'
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
# Variation Initializations
obj = NotifySlack(access_token=token, targets='#apprise')
assert isinstance(obj, NotifySlack) is True
@ -330,7 +313,34 @@ def test_plugin_slack_oauth_access_token(mock_post):
assert obj.send(body="test") is True
# Test Valid Attachment
mock_post.reset_mock()
mock_request.reset_mock()
mock_request.side_effect = [
request,
mock.Mock(**{
'content': dumps({
"ok": True,
"upload_url": "https://files.slack.com/upload/v1/ABC123",
"file_id": "F123ABC456"
}),
'status_code': requests.codes.ok
}),
mock.Mock(**{
'content': b'OK - 123',
'status_code': requests.codes.ok
}),
mock.Mock(**{
'content': dumps({
"ok": True,
"files": [
{
"id": "F123ABC456",
"title": "slack-test"
}
]
}),
'status_code': requests.codes.ok
}),
]
path = os.path.join(TEST_VAR_DIR, 'apprise-test.gif')
attach = AppriseAttachment(path)
@ -338,30 +348,42 @@ def test_plugin_slack_oauth_access_token(mock_post):
body='body', title='title', notify_type=NotifyType.INFO,
attach=attach) is True
assert mock_post.call_count == 2
assert mock_post.call_args_list[0][0][0] == \
assert mock_request.call_count == 4
assert mock_request.call_args_list[0][0][0] == \
'post'
assert mock_request.call_args_list[0][0][1] == \
'https://slack.com/api/chat.postMessage'
assert mock_post.call_args_list[1][0][0] == \
'https://slack.com/api/files.upload'
assert mock_request.call_args_list[1][0][0] == \
'get'
assert mock_request.call_args_list[1][0][1] == \
'https://slack.com/api/files.getUploadURLExternal'
assert mock_request.call_args_list[2][0][0] == \
'post'
assert mock_request.call_args_list[2][0][1] == \
'https://files.slack.com/upload/v1/ABC123'
assert mock_request.call_args_list[3][0][0] == \
'post'
assert mock_request.call_args_list[3][0][1] == \
'https://slack.com/api/files.completeUploadExternal'
# Test a valid attachment that throws an Connection Error
mock_post.return_value = None
mock_post.side_effect = (request, requests.ConnectionError(
mock_request.return_value = None
mock_request.side_effect = (request, requests.ConnectionError(
0, 'requests.ConnectionError() not handled'))
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO,
attach=attach) is False
# Test a valid attachment that throws an OSError
mock_post.return_value = None
mock_post.side_effect = (request, OSError(0, 'OSError'))
mock_request.return_value = None
mock_request.side_effect = (request, OSError(0, 'OSError'))
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO,
attach=attach) is False
# Reset our mock object back to how it was
mock_post.return_value = request
mock_post.side_effect = None
mock_request.return_value = request
mock_request.side_effect = None
# Test invalid attachment
path = os.path.join(TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg')
@ -370,13 +392,16 @@ def test_plugin_slack_oauth_access_token(mock_post):
attach=path) is False
# Test case where expected return attachment payload is invalid
request.content = dumps({
'ok': True,
'message': '',
# Attachment support
'file': None
})
mock_request.reset_mock()
mock_request.side_effect = [
request,
mock.Mock(**{
'content': dumps({
"ok": False,
}),
'status_code': requests.codes.internal_server_error
}),
]
path = os.path.join(TEST_VAR_DIR, 'apprise-test.gif')
attach = AppriseAttachment(path)
# We'll fail because of the bad 'file' response
@ -387,6 +412,9 @@ def test_plugin_slack_oauth_access_token(mock_post):
# Slack requests pay close attention to the response to determine
# if things go well... this is not a good JSON response:
request.content = '{'
mock_request.reset_mock()
mock_request.return_value = request
mock_request.side_effect = None
# As a result, we'll fail to send our notification
assert obj.send(body="test", attach=attach) is False
@ -401,8 +429,8 @@ def test_plugin_slack_oauth_access_token(mock_post):
assert obj.send(body="test", attach=attach) is False
# Handle exceptions reading our attachment from disk (should it happen)
mock_post.side_effect = OSError("Attachment Error")
mock_post.return_value = None
mock_request.side_effect = OSError("Attachment Error")
mock_request.return_value = None
# We'll fail now because of an internal exception
assert obj.send(body="test") is False
@ -410,18 +438,18 @@ def test_plugin_slack_oauth_access_token(mock_post):
# Test Email Lookup
@mock.patch('requests.post')
def test_plugin_slack_webhook_mode(mock_post):
@mock.patch('requests.request')
def test_plugin_slack_webhook_mode(mock_request):
"""
NotifySlack() Webhook Mode Tests
"""
# Prepare Mock
mock_post.return_value = requests.Request()
mock_post.return_value.status_code = requests.codes.ok
mock_post.return_value.content = b'ok'
mock_post.return_value.text = 'ok'
mock_request.return_value = requests.Request()
mock_request.return_value.status_code = requests.codes.ok
mock_request.return_value.content = b'ok'
mock_request.return_value.text = 'ok'
# Initialize some generic (but valid) tokens
token_a = 'A' * 9
@ -455,9 +483,9 @@ def test_plugin_slack_webhook_mode(mock_post):
body='body', title='title', notify_type=NotifyType.INFO) is True
@mock.patch('requests.post')
@mock.patch('requests.request')
@mock.patch('requests.get')
def test_plugin_slack_send_by_email(mock_get, mock_post):
def test_plugin_slack_send_by_email(mock_get, mock_request):
"""
NotifySlack() Send by Email Tests
@ -477,7 +505,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
request.status_code = requests.codes.ok
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.return_value = request
# Variation Initializations
@ -486,7 +514,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_count == 0
# Send our notification
@ -496,18 +524,18 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
# 2 calls were made, one to perform an email lookup, the second
# was the notification itself
assert mock_get.call_count == 1
assert mock_post.call_count == 1
assert mock_request.call_count == 1
assert mock_get.call_args_list[0][0][0] == \
'https://slack.com/api/users.lookupByEmail'
assert mock_post.call_args_list[0][0][0] == \
assert mock_request.call_args_list[0][0][1] == \
'https://slack.com/api/chat.postMessage'
# Reset our mock object
mock_post.reset_mock()
mock_request.reset_mock()
mock_get.reset_mock()
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.return_value = request
# Send our notification again (cached copy of user id associated with
@ -516,8 +544,8 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
body='body', title='title', notify_type=NotifyType.INFO) is True
assert mock_get.call_count == 0
assert mock_post.call_count == 1
assert mock_post.call_args_list[0][0][0] == \
assert mock_request.call_count == 1
assert mock_request.call_args_list[0][0][1] == \
'https://slack.com/api/chat.postMessage'
#
@ -529,11 +557,11 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
})
# Reset our mock object
mock_post.reset_mock()
mock_request.reset_mock()
mock_get.reset_mock()
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.return_value = request
# Variation Initializations
@ -542,7 +570,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_count == 0
# Send our notification; it will fail because we failed to look up
@ -553,7 +581,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
# We would have failed to look up the email, therefore we wouldn't have
# even bothered to attempt to send the notification
assert mock_get.call_count == 1
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_args_list[0][0][0] == \
'https://slack.com/api/users.lookupByEmail'
@ -563,11 +591,11 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
request.content = '}'
# Reset our mock object
mock_post.reset_mock()
mock_request.reset_mock()
mock_get.reset_mock()
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.return_value = request
# Variation Initializations
@ -576,7 +604,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_count == 0
# Send our notification; it will fail because we failed to look up
@ -587,7 +615,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
# We would have failed to look up the email, therefore we wouldn't have
# even bothered to attempt to send the notification
assert mock_get.call_count == 1
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_args_list[0][0][0] == \
'https://slack.com/api/users.lookupByEmail'
@ -597,11 +625,11 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
request.content = '}'
# Reset our mock object
mock_post.reset_mock()
mock_request.reset_mock()
mock_get.reset_mock()
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.return_value = request
# Variation Initializations
@ -610,7 +638,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_count == 0
# Send our notification; it will fail because we failed to look up
@ -621,7 +649,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
# We would have failed to look up the email, therefore we wouldn't have
# even bothered to attempt to send the notification
assert mock_get.call_count == 1
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_args_list[0][0][0] == \
'https://slack.com/api/users.lookupByEmail'
@ -640,11 +668,11 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
request.status_code = requests.codes.ok
# Reset our mock object
mock_post.reset_mock()
mock_request.reset_mock()
mock_get.reset_mock()
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.side_effect = requests.ConnectionError(
0, 'requests.ConnectionError() not handled')
@ -654,7 +682,7 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_count == 0
# Send our notification; it will fail because we failed to look up
@ -665,14 +693,14 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
# We would have failed to look up the email, therefore we wouldn't have
# even bothered to attempt to send the notification
assert mock_get.call_count == 1
assert mock_post.call_count == 0
assert mock_request.call_count == 0
assert mock_get.call_args_list[0][0][0] == \
'https://slack.com/api/users.lookupByEmail'
@mock.patch('requests.post')
@mock.patch('requests.request')
@mock.patch('requests.get')
def test_plugin_slack_markdown(mock_get, mock_post):
def test_plugin_slack_markdown(mock_get, mock_request):
"""
NotifySlack() Markdown tests
@ -683,7 +711,7 @@ def test_plugin_slack_markdown(mock_get, mock_post):
request.status_code = requests.codes.ok
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
mock_get.return_value = request
# Variation Initializations
@ -712,12 +740,12 @@ def test_plugin_slack_markdown(mock_get, mock_post):
# We would have failed to look up the email, therefore we wouldn't have
# even bothered to attempt to send the notification
assert mock_get.call_count == 0
assert mock_post.call_count == 1
assert mock_post.call_args_list[0][0][0] == \
assert mock_request.call_count == 1
assert mock_request.call_args_list[0][0][1] == \
'https://hooks.slack.com/services/T1JJ3T3L2/A1BRTD4JD/' \
'TIiajkdnlazkcOXrIdevi7FQ'
data = loads(mock_post.call_args_list[0][1]['data'])
data = loads(mock_request.call_args_list[0][1]['data'])
assert data['attachments'][0]['text'] == \
"Here is a <https://slack.com|Slack Link> we want to support as part "\
"of it's\nmarkdown.\n\nThis one has arguments we want to preserve:"\
@ -727,8 +755,8 @@ def test_plugin_slack_markdown(mock_get, mock_post):
"\n\nChannel Testing\n<!channelA>\n<!channelA|Description>"
@mock.patch('requests.post')
def test_plugin_slack_single_thread_reply(mock_post):
@mock.patch('requests.request')
def test_plugin_slack_single_thread_reply(mock_request):
"""
NotifySlack() Send Notification as a Reply
@ -748,7 +776,7 @@ def test_plugin_slack_single_thread_reply(mock_post):
request.status_code = requests.codes.ok
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
# Variation Initializations
obj = NotifySlack(access_token=token, targets=[f'#general:{thread_id}'])
@ -756,22 +784,22 @@ def test_plugin_slack_single_thread_reply(mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
# Send our notification
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO) is True
# Post was made
assert mock_post.call_count == 1
assert mock_post.call_args_list[0][0][0] == \
assert mock_request.call_count == 1
assert mock_request.call_args_list[0][0][1] == \
'https://slack.com/api/chat.postMessage'
assert loads(mock_post.call_args_list[0][1]['data']).get("thread_ts") \
assert loads(mock_request.call_args_list[0][1]['data']).get("thread_ts") \
== str(thread_id)
@mock.patch('requests.post')
def test_plugin_slack_multiple_thread_reply(mock_post):
@mock.patch('requests.request')
def test_plugin_slack_multiple_thread_reply(mock_request):
"""
NotifySlack() Send Notification to multiple channels as Reply
@ -791,7 +819,7 @@ def test_plugin_slack_multiple_thread_reply(mock_post):
request.status_code = requests.codes.ok
# Prepare Mock
mock_post.return_value = request
mock_request.return_value = request
# Variation Initializations
obj = NotifySlack(access_token=token,
@ -802,17 +830,17 @@ def test_plugin_slack_multiple_thread_reply(mock_post):
assert isinstance(obj.url(), str) is True
# No calls made yet
assert mock_post.call_count == 0
assert mock_request.call_count == 0
# Send our notification
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO) is True
# Post was made
assert mock_post.call_count == 2
assert mock_post.call_args_list[0][0][0] == \
assert mock_request.call_count == 2
assert mock_request.call_args_list[0][0][1] == \
'https://slack.com/api/chat.postMessage'
assert loads(mock_post.call_args_list[0][1]['data']).get("thread_ts") \
assert loads(mock_request.call_args_list[0][1]['data']).get("thread_ts") \
== str(thread_id_1)
assert loads(mock_post.call_args_list[1][1]['data']).get("thread_ts") \
assert loads(mock_request.call_args_list[1][1]['data']).get("thread_ts") \
== str(thread_id_2)