Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved test coverage and fixed broken tests #137

Merged
merged 1 commit into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 139 additions & 10 deletions apprise_api/api/tests/test_stateful_notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
# THE SOFTWARE.
from django.test import SimpleTestCase
from django.test.utils import override_settings
from unittest.mock import patch
from unittest.mock import patch, Mock
from ..forms import NotifyForm
from ..utils import ConfigCache
import os
import re
import apprise
import requests


class StatefulNotifyTests(SimpleTestCase):
Expand All @@ -51,8 +52,8 @@ def test_stateful_configuration_with_lock(self):
response = self.client.post('/get/{}'.format(key))
assert response.status_code == 403

@patch('apprise.Apprise.notify')
def test_stateful_configuration_io(self, mock_notify):
@patch('requests.post')
def test_stateful_configuration_io(self, mock_post):
"""
Test the writing, removal, writing and removal of configuration to
verify it persists and is removed when expected
Expand All @@ -61,16 +62,26 @@ def test_stateful_configuration_io(self, mock_notify):
# our key to use
key = 'test_stateful'

# Set our return value
mock_notify.return_value = True
request = Mock()
request.content = b'ok'
request.status_code = requests.codes.ok
mock_post.return_value = request

# Monkey Patch
apprise.plugins.NotifyEmail.NotifyEmail.enabled = True

# Preare our list of URLs we want to save
urls = [
'mail=mailto://user:[email protected]',
'devops=slack://TokenA/TokenB/TokenC',
'pusbullet=pbul://tokendetails',
'general,json=json://hostname',
]

# Monkey Patch
apprise.plugins.NotifySlack.NotifySlack.enabled = True
apprise.plugins.NotifyPushBullet.NotifyPushBullet.enabled = True
apprise.plugins.NotifyJSON.NotifyJSON.enabled = True

# For 10 iterations, repeat these tests to verify that don't change
# and our saved content is not different on subsequent calls.
for _ in range(10):
Expand All @@ -94,6 +105,7 @@ def test_stateful_configuration_io(self, mock_notify):
form_data = {
'body': '## test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
'tag': 'general',
}

form = NotifyForm(data=form_data)
Expand All @@ -103,10 +115,34 @@ def test_stateful_configuration_io(self, mock_notify):
# self.client.post()
del form.cleaned_data['attachment']

# We sent the notification successfully
response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
assert response.status_code == 200
assert mock_notify.call_count == 1
assert mock_post.call_count == 1

mock_post.reset_mock()

form_data = {
'body': '## test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
'tag': 'no-on-with-this-tag',
}

form = NotifyForm(data=form_data)
assert form.is_valid()

# Required to prevent None from being passed into
# self.client.post()
del form.cleaned_data['attachment']

# No one to notify
response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
assert response.status_code == 424
assert mock_post.call_count == 0

mock_post.reset_mock()

# Now empty our data
response = self.client.post('/del/{}'.format(key))
Expand All @@ -117,7 +153,7 @@ def test_stateful_configuration_io(self, mock_notify):
assert response.status_code == 204

# Reset our count
mock_notify.reset_mock()
mock_post.reset_mock()

# Now we do a similar approach as the above except we remove the
# configuration from under the application
Expand Down Expand Up @@ -151,10 +187,103 @@ def test_stateful_configuration_io(self, mock_notify):
# self.client.post()
del form.cleaned_data['attachment']

# No one to notify (no tag specified)
response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
assert response.status_code == 424
assert mock_post.call_count == 0

# Reset our configuration
mock_post.reset_mock()

#
# Test tagging now
#
form_data = {
'body': '## test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
'tag': 'general+json',
}

form = NotifyForm(data=form_data)
assert form.is_valid()

# Required to prevent None from being passed into
# self.client.post()
del form.cleaned_data['attachment']

response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
# + (plus) not supported at this time
assert response.status_code == 400
assert mock_post.call_count == 0

# Reset our configuration
mock_post.reset_mock()

form_data = {
'body': '## test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
# Plus with space inbetween
'tag': 'general + json',
}

form = NotifyForm(data=form_data)
assert form.is_valid()

# Required to prevent None from being passed into
# self.client.post()
del form.cleaned_data['attachment']

response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
# + (plus) not supported at this time
assert response.status_code == 400
assert mock_post.call_count == 0

mock_post.reset_mock()

form_data = {
'body': '## test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
# Space (AND)
'tag': 'general json',
}

form = NotifyForm(data=form_data)
assert form.is_valid()

# Required to prevent None from being passed into
# self.client.post()
del form.cleaned_data['attachment']

response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
assert response.status_code == 200
assert mock_notify.call_count == 1
assert mock_post.call_count == 1

mock_post.reset_mock()

form_data = {
'body': '## test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
# Comma (OR)
'tag': 'general, devops',
}

form = NotifyForm(data=form_data)
assert form.is_valid()

# Required to prevent None from being passed into
# self.client.post()
del form.cleaned_data['attachment']

response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data)
assert response.status_code == 200

# 2 endpoints hit
assert mock_post.call_count == 2

# Now remove the file directly (as though one
# removed the configuration directory)
Expand All @@ -171,4 +300,4 @@ def test_stateful_configuration_io(self, mock_notify):
assert response.status_code == 204

# Reset our count
mock_notify.reset_mock()
mock_post.reset_mock()
3 changes: 3 additions & 0 deletions apprise_api/api/tests/test_stateless_notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ def test_stateless_notify_recursion(self, mock_notify):
'body': 'test notifiction',
}

# Monkey Patch
apprise.plugins.NotifyEmail.NotifyEmail.enabled = True

# At a minimum 'body' is requred
form = NotifyByUrlForm(data=form_data)
assert form.is_valid()
Expand Down
4 changes: 2 additions & 2 deletions apprise_api/gunicorn.conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
# Our worker type to use; over-ride the default `sync`
worker_class = 'gevent'

# Get workers memory consumption under control by leveraging gunicorn worker recycling
# timeout
# Get workers memory consumption under control by leveraging gunicorn
# worker recycling timeout
max_requests = 1000
max_requests_jitter = 50

Expand Down