Skip to content

Commit d3c1866

Browse files
different tests
1 parent a04898a commit d3c1866

1 file changed

Lines changed: 123 additions & 138 deletions

File tree

tests/unit/test_usage_alerts.py

Lines changed: 123 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,54 @@
1-
import json
1+
#
2+
# Copyright (c) 2025 NSONE, Inc.
3+
#
4+
# License under The MIT License (MIT). See LICENSE in project root.
5+
#
26
import pytest
3-
import responses
47

5-
from ns1.alerting import UsageAlertsAPI, USAGE_SUBTYPES
8+
try: # Python 3.3 +
9+
import unittest.mock as mock
10+
except ImportError:
11+
import mock
12+
13+
import json
614

715

816
@pytest.fixture
9-
def usage_alerts_client():
17+
def usage_alerts_client(config):
18+
config.loadFromDict(
19+
{
20+
"endpoint": "api.nsone.net",
21+
"default_key": "test1",
22+
"keys": {
23+
"test1": {
24+
"key": "key-1",
25+
"desc": "test key number 1",
26+
}
27+
},
28+
}
29+
)
1030
from ns1 import NS1
11-
client = NS1(apiKey="test1")
12-
client.config["endpoint"] = "https://api.nsone.net"
31+
client = NS1(config=config)
1332
return client
1433

1534

16-
@responses.activate
1735
def test_create_usage_alert(usage_alerts_client):
1836
"""Test creating a usage alert"""
1937
client = usage_alerts_client
2038

21-
# Mock response for create
22-
responses.add(
23-
responses.POST,
24-
"https://api.nsone.net/alerting/v1/alerts",
25-
json={
26-
"id": "a1b2c3",
27-
"name": "Test Alert",
28-
"type": "account",
29-
"subtype": "query_usage",
30-
"data": {"alert_at_percent": 85},
31-
"notifier_list_ids": ["n1"],
32-
"zone_names": [],
33-
"created_at": 1597937213,
34-
"updated_at": 1597937213
35-
},
36-
status=200,
37-
)
39+
# Create a mock for the _post method in alerting().usage
40+
client.alerting()._c._post = mock.MagicMock()
41+
client.alerting()._c._post.return_value = {
42+
"id": "a1b2c3",
43+
"name": "Test Alert",
44+
"type": "account",
45+
"subtype": "query_usage",
46+
"data": {"alert_at_percent": 85},
47+
"notifier_list_ids": ["n1"],
48+
"zone_names": [],
49+
"created_at": 1597937213,
50+
"updated_at": 1597937213
51+
}
3852

3953
alert = client.alerting().usage.create(
4054
name="Test Alert",
@@ -43,139 +57,142 @@ def test_create_usage_alert(usage_alerts_client):
4357
notifier_list_ids=["n1"]
4458
)
4559

60+
# Verify _post was called with correct arguments
61+
expected_body = {
62+
"name": "Test Alert",
63+
"type": "account",
64+
"subtype": "query_usage",
65+
"data": {"alert_at_percent": 85},
66+
"notifier_list_ids": ["n1"],
67+
"zone_names": []
68+
}
69+
client.alerting()._c._post.assert_called_once_with("/alerting/v1/alerts", json=expected_body)
70+
71+
# Verify result
4672
assert alert["id"] == "a1b2c3"
4773
assert alert["name"] == "Test Alert"
4874
assert alert["type"] == "account"
4975
assert alert["subtype"] == "query_usage"
5076
assert alert["data"]["alert_at_percent"] == 85
51-
assert alert["notifier_list_ids"] == ["n1"]
5277

5378

54-
@responses.activate
5579
def test_get_usage_alert(usage_alerts_client):
5680
"""Test retrieving a usage alert"""
5781
client = usage_alerts_client
5882
alert_id = "a1b2c3"
5983

60-
# Mock response for get
61-
responses.add(
62-
responses.GET,
63-
f"https://api.nsone.net/alerting/v1/alerts/{alert_id}",
64-
json={
65-
"id": alert_id,
66-
"name": "Test Alert",
67-
"type": "account",
68-
"subtype": "query_usage",
69-
"data": {"alert_at_percent": 85},
70-
"notifier_list_ids": ["n1"],
71-
"zone_names": []
72-
},
73-
status=200,
74-
)
84+
# Create a mock for the _get method
85+
client.alerting()._c._get = mock.MagicMock()
86+
client.alerting()._c._get.return_value = {
87+
"id": alert_id,
88+
"name": "Test Alert",
89+
"type": "account",
90+
"subtype": "query_usage",
91+
"data": {"alert_at_percent": 85},
92+
"notifier_list_ids": ["n1"],
93+
"zone_names": []
94+
}
7595

7696
alert = client.alerting().usage.get(alert_id)
7797

98+
# Verify _get was called with correct URL
99+
client.alerting()._c._get.assert_called_once_with(f"/alerting/v1/alerts/{alert_id}")
100+
101+
# Verify result
78102
assert alert["id"] == alert_id
79103
assert alert["name"] == "Test Alert"
80104
assert alert["data"]["alert_at_percent"] == 85
81105

82106

83-
@responses.activate
84107
def test_patch_usage_alert(usage_alerts_client):
85108
"""Test patching a usage alert - verify type/subtype are not sent"""
86109
client = usage_alerts_client
87110
alert_id = "a1b2c3"
88111

89-
def request_callback(request):
90-
payload = json.loads(request.body)
91-
# Verify type and subtype are not in the request
92-
assert "type" not in payload
93-
assert "subtype" not in payload
94-
# Verify data contains the right alert_at_percent
95-
assert payload["data"]["alert_at_percent"] == 90
96-
97-
resp_body = {
98-
"id": alert_id,
99-
"name": "Updated Alert",
100-
"type": "account",
101-
"subtype": "query_usage",
102-
"data": {"alert_at_percent": 90},
103-
"notifier_list_ids": ["n1"],
104-
"zone_names": []
105-
}
106-
return (200, {}, json.dumps(resp_body))
107-
108-
responses.add_callback(
109-
responses.PATCH,
110-
f"https://api.nsone.net/alerting/v1/alerts/{alert_id}",
111-
callback=request_callback,
112-
content_type="application/json",
113-
)
112+
# Create a mock for the _patch method
113+
client.alerting()._c._patch = mock.MagicMock()
114+
client.alerting()._c._patch.return_value = {
115+
"id": alert_id,
116+
"name": "Updated Alert",
117+
"type": "account",
118+
"subtype": "query_usage",
119+
"data": {"alert_at_percent": 90},
120+
"notifier_list_ids": ["n1"],
121+
"zone_names": []
122+
}
114123

115124
alert = client.alerting().usage.patch(
116125
alert_id,
117126
name="Updated Alert",
118127
alert_at_percent=90
119128
)
120129

130+
# Verify _patch was called with correct arguments
131+
expected_body = {
132+
"name": "Updated Alert",
133+
"data": {"alert_at_percent": 90}
134+
}
135+
client.alerting()._c._patch.assert_called_once_with(f"/alerting/v1/alerts/{alert_id}", json=expected_body)
136+
137+
# Verify type/subtype are not in the arguments
138+
call_args = client.alerting()._c._patch.call_args[1]["json"]
139+
assert "type" not in call_args
140+
assert "subtype" not in call_args
141+
142+
# Verify result
121143
assert alert["id"] == alert_id
122144
assert alert["name"] == "Updated Alert"
123145
assert alert["data"]["alert_at_percent"] == 90
124146

125147

126-
@responses.activate
127148
def test_delete_usage_alert(usage_alerts_client):
128149
"""Test deleting a usage alert"""
129150
client = usage_alerts_client
130151
alert_id = "a1b2c3"
131152

132-
responses.add(
133-
responses.DELETE,
134-
f"https://api.nsone.net/alerting/v1/alerts/{alert_id}",
135-
status=204,
136-
)
153+
# Create a mock for the _delete method
154+
client.alerting()._c._delete = mock.MagicMock()
137155

138156
client.alerting().usage.delete(alert_id)
139157

140-
# If we got here without exception, the test passes
158+
# Verify _delete was called with correct URL
159+
client.alerting()._c._delete.assert_called_once_with(f"/alerting/v1/alerts/{alert_id}")
141160

142161

143-
@responses.activate
144162
def test_list_usage_alerts(usage_alerts_client):
145163
"""Test listing usage alerts with pagination params"""
146164
client = usage_alerts_client
147165

148-
responses.add(
149-
responses.GET,
150-
"https://api.nsone.net/alerting/v1/alerts",
151-
json={
152-
"limit": 1,
153-
"next": "next_token",
154-
"total_results": 2,
155-
"results": [
156-
{
157-
"id": "a1",
158-
"name": "Alert 1",
159-
"type": "account",
160-
"subtype": "query_usage",
161-
"data": {"alert_at_percent": 80}
162-
}
163-
]
164-
},
165-
status=200,
166-
match=[
167-
responses.matchers.query_param_matcher({
168-
"limit": "1",
169-
"order_descending": "true"
170-
})
166+
# Create a mock for the _get method
167+
client.alerting()._c._get = mock.MagicMock()
168+
client.alerting()._c._get.return_value = {
169+
"limit": 1,
170+
"next": "next_token",
171+
"total_results": 2,
172+
"results": [
173+
{
174+
"id": "a1",
175+
"name": "Alert 1",
176+
"type": "account",
177+
"subtype": "query_usage",
178+
"data": {"alert_at_percent": 80}
179+
}
171180
]
172-
)
181+
}
173182

174183
response = client.alerting().usage.list(
175184
limit=1,
176185
order_descending=True
177186
)
178187

188+
# Verify _get was called with correct URL and params
189+
expected_params = {
190+
"limit": 1,
191+
"order_descending": "true"
192+
}
193+
client.alerting()._c._get.assert_called_once_with("/alerting/v1/alerts", params=expected_params)
194+
195+
# Verify result
179196
assert "results" in response
180197
assert "next" in response
181198
assert response["next"] == "next_token"
@@ -215,51 +232,19 @@ def test_validation_threshold_bounds(usage_alerts_client):
215232
assert "alert_at_percent must be int in 1..100" in str(excinfo.value)
216233

217234

218-
def test_validation_subtype(usage_alerts_client):
235+
def test_validation_subtype():
219236
"""Test validation of subtype values"""
220-
client = usage_alerts_client
237+
from ns1.alerting import USAGE_SUBTYPES
238+
from ns1.alerting.usage_alerts import _validate
221239

222-
# Verify all defined subtypes are accepted
240+
# Valid subtypes should pass validation
223241
for subtype in USAGE_SUBTYPES:
224242
try:
225-
# Just validate, don't make an actual request
226-
client.alerting().usage._c = None # This will cause an error if validation passes
227-
with pytest.raises(AttributeError):
228-
client.alerting().usage.create(
229-
name="Test Alert",
230-
subtype=subtype,
231-
alert_at_percent=85
232-
)
243+
_validate("Test Alert", subtype, 85)
233244
except ValueError:
234245
pytest.fail(f"Valid subtype '{subtype}' was rejected")
235246

236-
# Test invalid subtype
247+
# Invalid subtype should fail validation
237248
with pytest.raises(ValueError) as excinfo:
238-
client.alerting().usage.create(
239-
name="Test Alert",
240-
subtype="invalid_subtype",
241-
alert_at_percent=85
242-
)
249+
_validate("Test Alert", "invalid_subtype", 85)
243250
assert "invalid subtype" in str(excinfo.value)
244-
245-
246-
@responses.activate
247-
def test_404_error_handling(usage_alerts_client):
248-
"""Test proper error handling for 404 responses"""
249-
client = usage_alerts_client
250-
alert_id = "nonexistent"
251-
252-
# Mock 404 response with error message
253-
responses.add(
254-
responses.GET,
255-
f"https://api.nsone.net/alerting/v1/alerts/{alert_id}",
256-
json={"message": "alert not found"},
257-
status=404,
258-
)
259-
260-
# This should raise an exception through the REST transport
261-
with pytest.raises(Exception) as excinfo:
262-
client.alerting().usage.get(alert_id)
263-
264-
# Verify error contains the message from the server
265-
assert "alert not found" in str(excinfo.value)

0 commit comments

Comments
 (0)