mirror of https://github.com/caronc/apprise
improved test coverage
parent
8a18e6b6e4
commit
e483ffa130
|
@ -38,7 +38,7 @@ import pytest
|
|||
import requests
|
||||
|
||||
from apprise import Apprise, AppriseAttachment, NotifyType
|
||||
from apprise.plugins.slack import NotifySlack, SlackMode
|
||||
from apprise.plugins.slack import NotifySlack
|
||||
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
|
@ -565,48 +565,6 @@ def test_plugin_slack_oauth_access_token(mock_request):
|
|||
# We'll fail now because of an internal exception
|
||||
assert obj.send(body="test") is False
|
||||
|
||||
# --- Simulate failure to send file to channel (missing 'files') ---
|
||||
mock_request.reset_mock()
|
||||
mock_request.side_effect = [
|
||||
request, # chat.postMessage
|
||||
mock.Mock(**{ # getUploadURLExternal
|
||||
"content": dumps({
|
||||
"ok": True,
|
||||
"upload_url": "https://files.slack.com/upload/v1/ABC123",
|
||||
"file_id": "F123ABC456",
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
mock.Mock(**{ # File upload
|
||||
"content": b"OK - 123",
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
mock.Mock(**{ # completeUploadExternal returns invalid response
|
||||
"content": dumps({
|
||||
"ok": True,
|
||||
"files": [], # <== This triggers the unhit block
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
]
|
||||
|
||||
path = os.path.join(TEST_VAR_DIR, "apprise-test.gif")
|
||||
attach = AppriseAttachment(path)
|
||||
|
||||
# Test via BOT Mode
|
||||
obj.mode = SlackMode.BOT
|
||||
|
||||
# This will now fail on 'response.get("files")' being empty
|
||||
assert (
|
||||
obj.notify(
|
||||
body="body",
|
||||
title="title",
|
||||
notify_type=NotifyType.INFO,
|
||||
attach=attach,
|
||||
)
|
||||
is False
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("requests.request")
|
||||
def test_plugin_slack_webhook_mode(mock_request):
|
||||
|
@ -1040,3 +998,105 @@ def test_plugin_slack_multiple_thread_reply(mock_request):
|
|||
assert loads(mock_request.call_args_list[1][1]["data"]).get(
|
||||
"thread_ts"
|
||||
) == str(thread_id_2)
|
||||
|
||||
|
||||
@mock.patch("requests.request")
|
||||
def test_plugin_slack_file_upload_success(mock_request):
|
||||
"""Test Slack BOT attachment upload success path."""
|
||||
|
||||
token = "xoxb-1234-1234-abc124"
|
||||
path = os.path.join(TEST_VAR_DIR, "apprise-test.gif")
|
||||
attach = AppriseAttachment(path)
|
||||
|
||||
# Simulate all successful Slack API responses
|
||||
mock_request.side_effect = [
|
||||
mock.Mock(**{
|
||||
"content": dumps({
|
||||
"ok": True,
|
||||
"channel": "C123456",
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
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": "apprise-test"}],
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
]
|
||||
|
||||
obj = NotifySlack(access_token=token, targets=["#general"])
|
||||
assert obj.notify(
|
||||
body="Success path test",
|
||||
title="Slack Upload OK",
|
||||
notify_type=NotifyType.INFO,
|
||||
attach=attach,
|
||||
) is True
|
||||
|
||||
|
||||
@mock.patch("requests.request")
|
||||
def test_plugin_slack_file_upload_fails_missing_files(mock_request):
|
||||
"""Test that file upload fails when 'files' is missing or empty."""
|
||||
|
||||
token = "xoxb-1234-1234-abc124"
|
||||
path = os.path.join(TEST_VAR_DIR, "apprise-test.gif")
|
||||
attach = AppriseAttachment(path)
|
||||
|
||||
# Mock sequence:
|
||||
# 1. chat.postMessage returns valid channel
|
||||
# 2. files.getUploadURLExternal returns file_id and upload_url
|
||||
# 3. Upload returns 'OK'
|
||||
# 4. files.completeUploadExternal returns missing/empty 'files'
|
||||
|
||||
mock_request.side_effect = [
|
||||
mock.Mock(**{
|
||||
"content": dumps({
|
||||
"ok": True,
|
||||
"channel": "C555555",
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
mock.Mock(**{
|
||||
"content": dumps({
|
||||
"ok": True,
|
||||
"upload_url": "https://files.slack.com/upload/v1/X99999",
|
||||
"file_id": "F999XYZ888",
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
mock.Mock(**{
|
||||
"content": b"OK - 2048",
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
# <== This response will trigger the error condition
|
||||
mock.Mock(**{
|
||||
"content": dumps({
|
||||
"ok": True,
|
||||
"files": [],
|
||||
}),
|
||||
"status_code": requests.codes.ok,
|
||||
}),
|
||||
]
|
||||
|
||||
obj = NotifySlack(access_token=token, targets=["#fail-channel"])
|
||||
result = obj.notify(
|
||||
body="This should trigger a failed file upload",
|
||||
title="Trigger failure",
|
||||
notify_type=NotifyType.INFO,
|
||||
attach=attach,
|
||||
)
|
||||
|
||||
assert result is False
|
||||
|
|
|
@ -35,11 +35,45 @@ import pytest
|
|||
|
||||
import apprise
|
||||
|
||||
logging.disable(logging.CRITICAL)
|
||||
try:
|
||||
import syslog
|
||||
|
||||
# Skip tests when Python environment does not provide the `syslog` package.
|
||||
if "syslog" not in sys.modules:
|
||||
pytest.skip("Skipping syslog based tests", allow_module_level=True)
|
||||
except ImportError:
|
||||
# Shim so that test cases can run in environments that
|
||||
# do not have syslog
|
||||
import types
|
||||
syslog = types.SimpleNamespace(
|
||||
LOG_PID=0x01,
|
||||
LOG_PERROR=0x02,
|
||||
LOG_INFO=6,
|
||||
LOG_NOTICE=5,
|
||||
LOG_CRIT=2,
|
||||
LOG_WARNING=4,
|
||||
LOG_KERN=0,
|
||||
LOG_USER=1,
|
||||
LOG_MAIL=2,
|
||||
LOG_DAEMON=3,
|
||||
LOG_AUTH=4,
|
||||
LOG_SYSLOG=5,
|
||||
LOG_LPR=6,
|
||||
LOG_NEWS=7,
|
||||
LOG_UUCP=8,
|
||||
LOG_CRON=9,
|
||||
LOG_LOCAL0=16,
|
||||
LOG_LOCAL1=17,
|
||||
LOG_LOCAL2=18,
|
||||
LOG_LOCAL3=19,
|
||||
LOG_LOCAL4=20,
|
||||
LOG_LOCAL5=21,
|
||||
LOG_LOCAL6=22,
|
||||
LOG_LOCAL7=23,
|
||||
openlog=lambda *a, **kw: None,
|
||||
syslog=lambda *a, **kw: None,
|
||||
)
|
||||
sys.modules["syslog"] = syslog
|
||||
|
||||
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
from apprise.plugins.syslog import NotifySyslog # noqa E402
|
||||
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -97,7 +97,7 @@ commands =
|
|||
find . -type f -name "*.pyc" -delete
|
||||
find . -type f -name "*.pyo" -delete
|
||||
find . -type d -name "__pycache__" -delete
|
||||
rm -rf BUILD SOURCES SRPMS BUILDROOT .ruff_cache .coverage-reports .coverage coverage.xml dist build apprise.egg-info .mypy_cache .pytest_cache
|
||||
rm -rf BUILD SOURCES SRPMS BUILDROOT .cache .ruff_cache .coverage-reports .coverage coverage.xml dist build apprise.egg-info .mypy_cache .pytest_cache
|
||||
|
||||
[testenv:i18n]
|
||||
description = Extract and update .pot/.po files for translation
|
||||
|
|
Loading…
Reference in New Issue