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

Fix notification response check and add tests #18

Merged
merged 3 commits into from
Nov 20, 2024
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
240 changes: 238 additions & 2 deletions files/test.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,248 @@
import unittest
from unittest.mock import patch
from datetime import datetime, timedelta
import pathlib
import tempfile
from walle import NotificationHistory
from walle import NotificationHistory, GalaxyAPI, Severity
import json

SLACK_NOTIFY_PERIOD_DAYS = 7

from unittest.mock import patch, Mock

ONLY_ONE_INSTANCE = "The other must be an instance of the Severity class"


class TestSeverity(unittest.TestCase):
def setUp(self):
self.low = Severity(1, "Low")
self.medium = Severity(2, "Medium")
self.high = Severity(3, "High")

def test_equality_same_values(self):
# Arrange
other_low = Severity(1, "Low")

# Act & Assert
self.assertEqual(self.low, other_low)

def test_equality_different_values(self):
# Arrange
other_medium = Severity(2, "Medium")

# Act & Assert
self.assertNotEqual(self.low, other_medium)

def test_equality_raises_value_error(self):
# Arrange
invalid_comparison = "Not a Severity"

# Act & Assert
with self.assertRaises(ValueError) as context:
self.low == invalid_comparison

Check warning on line 41 in files/test.py

View workflow job for this annotation

GitHub Actions / pyright

Expression value is unused (reportUnusedExpression)
self.assertEqual(str(context.exception), ONLY_ONE_INSTANCE)

def test_less_than_or_equal_success(self):
# Act & Assert
self.assertTrue(self.low <= self.medium)
self.assertTrue(self.low <= self.low)
self.assertFalse(self.medium <= self.low)

def test_less_than_or_equal_raises_value_error(self):
# Arrange
invalid_comparison = "Not a Severity"

# Act & Assert
with self.assertRaises(ValueError) as context:
self.low <= invalid_comparison

Check warning on line 56 in files/test.py

View workflow job for this annotation

GitHub Actions / pyright

Expression value is unused (reportUnusedExpression)
self.assertEqual(str(context.exception), ONLY_ONE_INSTANCE)

def test_greater_than_or_equal_success(self):
# Act & Assert
self.assertTrue(self.medium >= self.low)
self.assertTrue(self.high >= self.high)
self.assertFalse(self.low >= self.medium)

def test_greater_than_or_equal_raises_value_error(self):
# Arrange
invalid_comparison = "Not a Severity"

# Act & Assert
with self.assertRaises(ValueError) as context:
self.low >= invalid_comparison

Check warning on line 71 in files/test.py

View workflow job for this annotation

GitHub Actions / pyright

Expression value is unused (reportUnusedExpression)
self.assertEqual(str(context.exception), ONLY_ONE_INSTANCE)


class TestGalaxyAPI(unittest.TestCase):
def setUp(self):
self.api = GalaxyAPI(
base_url="http://example.com",
api_key="test_key",
delete_subject="Account Deletion",
delete_message="Your account has been deleted.",
)

@patch("walle.requests.post")
def test_notify_user_success(self, mock_post):
# Arrange
mock_response = Mock()
mock_response.status_code = 200
mock_post.return_value = mock_response
encoded_user_id = "encoded123"

# Act
result = self.api.notify_user(encoded_user_id)

# Assert
self.assertTrue(result)
# Validate JSON body
expected_json = {
"recipients": {"user_ids": ["encoded123"], "group_ids": [], "role_ids": []},
"notification": {
"source": "WALLE",
"category": "message",
"variant": "urgent",
"content": {
"subject": "Account Deletion",
"message": "Your account has been deleted.",
"category": "message",
},
},
}
# Validate JSON structure
try:
# Extract the actual JSON passed to the mock
actual_json = mock_post.call_args.kwargs["json"]
# Check if it matches expected JSON structure
self.assertEqual(
json.dumps(actual_json, sort_keys=True),
json.dumps(expected_json, sort_keys=True),
)
except json.JSONDecodeError as e:
self.fail(f"Invalid JSON structure: {e}")

# Ensure mock was called with correct arguments
mock_post.assert_called_once_with(
url="http://example.com/api/notifications",
headers={"x-api-key": "test_key"},
json=expected_json,
)

@patch("walle.requests.post")
def test_notify_user_failure(self, mock_post):
# Arrange
mock_response = Mock()
mock_response.status_code = 400
mock_post.return_value = mock_response
encoded_user_id = "encoded123"

# Act
result = self.api.notify_user(encoded_user_id)

# Assert
self.assertFalse(result)

@patch("walle.requests.delete")
def test_delete_user_success(self, mock_delete):
# Arrange
mock_response = Mock()
mock_response.status_code = 200
mock_delete.return_value = mock_response
encoded_user_id = "encoded123"

# Act
result = self.api.delete_user(encoded_user_id)

# Assert
self.assertTrue(result)
mock_delete.assert_called_once_with(
url="http://example.com/api/users/encoded123",
headers={"x-api-key": "test_key"},
)

@patch("walle.requests.delete")
def test_delete_user_failure(self, mock_delete):
# Arrange
mock_response = Mock()
mock_response.status_code = 404
mock_delete.return_value = mock_response
decoded_id = "123"

# Act
result = self.api.delete_user(decoded_id)

# Assert
self.assertFalse(result)

@patch("walle.requests.get")
def test_encode_galaxy_user_id_success(self, mock_get):
# Arrange
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"encoded_id": "encoded123"}
mock_get.return_value = mock_response
decoded_id = "123"

# Act
result = self.api.encode_galaxy_user_id(decoded_id)

# Assert
self.assertEqual(result, "encoded123")
mock_get.assert_called_once_with(
url="http://example.com/api/configuration/encode/123",
headers={"x-api-key": "test_key"},
)

@patch("walle.requests.get")
def test_encode_galaxy_user_id_failure(self, mock_get):
# Arrange
mock_response = Mock()
mock_response.status_code = 500
mock_get.return_value = mock_response
decoded_id = "decoded456"

# Act
result = self.api.encode_galaxy_user_id(decoded_id)

# Assert
self.assertEqual(result, "")

@patch("walle.GalaxyAPI.notify_user")
@patch("walle.GalaxyAPI.delete_user")
@patch("walle.GalaxyAPI.encode_galaxy_user_id")
def test_encode_id_notify_and_delete_user_success(
self, mock_encode, mock_delete, mock_notify
):
# Arrange
mock_encode.return_value = "encoded123"
mock_notify.return_value = True
mock_delete.return_value = True
user_id = "decoded456"

# Act
self.api.encode_id_notify_and_delete_user(user_id)

# Assert
mock_encode.assert_called_once_with(decoded_id=user_id)
mock_notify.assert_called_once_with("encoded123")
mock_delete.assert_called_once_with("encoded123")

@patch("walle.GalaxyAPI.notify_user")
@patch("walle.GalaxyAPI.encode_galaxy_user_id")
def test_encode_id_notify_and_delete_user_notify_failure(
self, mock_encode, mock_notify
):
# Arrange
mock_encode.return_value = "encoded123"
mock_notify.return_value = False
user_id = "decoded456"

# Act
self.api.encode_id_notify_and_delete_user(user_id)

# Assert
mock_encode.assert_called_once_with(decoded_id=user_id)
mock_notify.assert_called_once_with("encoded123")


class TestNotificationHistory(unittest.TestCase):
def setUp(self):
Expand Down
5 changes: 2 additions & 3 deletions files/walle.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ def notify_user(self, encoded_user_id: UserId) -> bool:
"role_ids": [],
},
"notification": {
"source": "string",
"source": "WALLE",
"category": "message",
"variant": "urgent",
"content": {
Expand All @@ -833,8 +833,7 @@ def notify_user(self, encoded_user_id: UserId) -> bool:
},
)
if response.status_code == 200:
if response.json()["total_notifications_sent"] == 1:
return True
return True
logger.error(
"Can not notify user %s, response from Galaxy: %s",
encoded_user_id,
Expand Down
Loading