API - Improvements, support PUT for updating existing watch, set muted state, set paused state, see https://changedetection.io/docs/api_v1/index.html (#1213)
This commit is contained in:
@@ -53,14 +53,15 @@ def is_valid_uuid(val):
|
||||
return False
|
||||
|
||||
|
||||
def test_api_simple(client, live_server):
|
||||
def test_setup(client, live_server):
|
||||
live_server_setup(live_server)
|
||||
|
||||
def test_api_simple(client, live_server):
|
||||
|
||||
api_key = extract_api_key_from_UI(client)
|
||||
|
||||
# Create a watch
|
||||
set_original_response()
|
||||
watch_uuid = None
|
||||
|
||||
# Validate bad URL
|
||||
test_url = url_for('test_endpoint', _external=True,
|
||||
@@ -80,25 +81,34 @@ def test_api_simple(client, live_server):
|
||||
headers={'content-type': 'application/json', 'x-api-key': api_key},
|
||||
follow_redirects=True
|
||||
)
|
||||
s = json.loads(res.data)
|
||||
assert is_valid_uuid(s['uuid'])
|
||||
watch_uuid = s['uuid']
|
||||
|
||||
assert is_valid_uuid(res.json.get('uuid'))
|
||||
watch_uuid = res.json.get('uuid')
|
||||
assert res.status_code == 201
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# Verify its in the list and that recheck worked
|
||||
res = client.get(
|
||||
url_for("createwatch"),
|
||||
url_for("createwatch", tag="OnE"),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert watch_uuid in json.loads(res.data).keys()
|
||||
before_recheck_info = json.loads(res.data)[watch_uuid]
|
||||
assert watch_uuid in res.json.keys()
|
||||
before_recheck_info = res.json[watch_uuid]
|
||||
assert before_recheck_info['last_checked'] != 0
|
||||
#705 `last_changed` should be zero on the first check
|
||||
assert before_recheck_info['last_changed'] == 0
|
||||
assert before_recheck_info['title'] == 'My test URL'
|
||||
|
||||
# Check the limit by tag doesnt return anything when nothing found
|
||||
res = client.get(
|
||||
url_for("createwatch", tag="Something else entirely"),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert len(res.json) == 0
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
set_modified_response()
|
||||
# Trigger recheck of all ?recheck_all=1
|
||||
client.get(
|
||||
@@ -112,7 +122,7 @@ def test_api_simple(client, live_server):
|
||||
url_for("createwatch"),
|
||||
headers={'x-api-key': api_key},
|
||||
)
|
||||
after_recheck_info = json.loads(res.data)[watch_uuid]
|
||||
after_recheck_info = res.json[watch_uuid]
|
||||
assert after_recheck_info['last_checked'] != before_recheck_info['last_checked']
|
||||
assert after_recheck_info['last_changed'] != 0
|
||||
|
||||
@@ -121,12 +131,11 @@ def test_api_simple(client, live_server):
|
||||
url_for("watchhistory", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key},
|
||||
)
|
||||
history = json.loads(res.data)
|
||||
assert len(history) == 2, "Should have two history entries (the original and the changed)"
|
||||
assert len(res.json) == 2, "Should have two history entries (the original and the changed)"
|
||||
|
||||
# Fetch a snapshot by timestamp, check the right one was found
|
||||
res = client.get(
|
||||
url_for("watchsinglehistory", uuid=watch_uuid, timestamp=list(history.keys())[-1]),
|
||||
url_for("watchsinglehistory", uuid=watch_uuid, timestamp=list(res.json.keys())[-1]),
|
||||
headers={'x-api-key': api_key},
|
||||
)
|
||||
assert b'which has this one new line' in res.data
|
||||
@@ -143,7 +152,7 @@ def test_api_simple(client, live_server):
|
||||
url_for("watch", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
watch = json.loads(res.data)
|
||||
watch = res.json
|
||||
# @todo how to handle None/default global values?
|
||||
assert watch['history_n'] == 2, "Found replacement history section, which is in its own API"
|
||||
|
||||
@@ -152,10 +161,46 @@ def test_api_simple(client, live_server):
|
||||
url_for("systeminfo"),
|
||||
headers={'x-api-key': api_key},
|
||||
)
|
||||
info = json.loads(res.data)
|
||||
assert info.get('watch_count') == 1
|
||||
assert info.get('uptime') > 0.5
|
||||
assert res.json.get('watch_count') == 1
|
||||
assert res.json.get('uptime') > 0.5
|
||||
|
||||
######################################################
|
||||
# Mute and Pause, check it worked
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid, paused='paused'),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert b'OK' in res.data
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid, muted='muted'),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert b'OK' in res.data
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert res.json.get('paused') == True
|
||||
assert res.json.get('notification_muted') == True
|
||||
|
||||
# Now unpause, unmute
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid, muted='unmuted'),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert b'OK' in res.data
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid, paused='unpaused'),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert b'OK' in res.data
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert res.json.get('paused') == 0
|
||||
assert res.json.get('notification_muted') == 0
|
||||
######################################################
|
||||
|
||||
# Finally delete the watch
|
||||
res = client.delete(
|
||||
@@ -169,9 +214,7 @@ def test_api_simple(client, live_server):
|
||||
url_for("createwatch"),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
watch_list = json.loads(res.data)
|
||||
assert len(watch_list) == 0, "Watch list should be empty"
|
||||
|
||||
assert len(res.json) == 0, "Watch list should be empty"
|
||||
|
||||
def test_access_denied(client, live_server):
|
||||
# `config_api_token_enabled` Should be On by default
|
||||
@@ -203,3 +246,97 @@ def test_access_denied(client, live_server):
|
||||
url_for("createwatch")
|
||||
)
|
||||
assert res.status_code == 200
|
||||
|
||||
# Cleanup everything
|
||||
res = client.get(url_for("form_delete", uuid="all"), follow_redirects=True)
|
||||
assert b'Deleted' in res.data
|
||||
|
||||
res = client.post(
|
||||
url_for("settings_page"),
|
||||
data={
|
||||
"requests-time_between_check-minutes": 180,
|
||||
"application-fetch_backend": "html_requests",
|
||||
"application-api_access_token_enabled": "y"
|
||||
},
|
||||
follow_redirects=True
|
||||
)
|
||||
assert b"Settings updated." in res.data
|
||||
|
||||
def test_api_watch_PUT_update(client, live_server):
|
||||
|
||||
#live_server_setup(live_server)
|
||||
api_key = extract_api_key_from_UI(client)
|
||||
time.sleep(1)
|
||||
# Create a watch
|
||||
set_original_response()
|
||||
test_url = url_for('test_endpoint', _external=True,
|
||||
headers={'x-api-key': api_key}, )
|
||||
|
||||
# Create new
|
||||
res = client.post(
|
||||
url_for("createwatch"),
|
||||
data=json.dumps({"url": test_url, 'tag': "One, Two", "title": "My test URL", 'headers': {'cookie': 'yum'} }),
|
||||
headers={'content-type': 'application/json', 'x-api-key': api_key},
|
||||
follow_redirects=True
|
||||
)
|
||||
|
||||
assert res.status_code == 201
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# Get a listing, it will be the first one
|
||||
res = client.get(
|
||||
url_for("createwatch"),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
|
||||
watch_uuid = list(res.json.keys())[0]
|
||||
|
||||
# Check in the edit page just to be sure
|
||||
res = client.get(
|
||||
url_for("edit_page", uuid=watch_uuid),
|
||||
)
|
||||
assert b"cookie: yum" in res.data, "'cookie: yum' found in 'headers' section"
|
||||
|
||||
# HTTP PUT ( UPDATE an existing watch )
|
||||
res = client.put(
|
||||
url_for("watch", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key, 'content-type': 'application/json'},
|
||||
data=json.dumps({"title": "new title", 'time_between_check': {'minutes': 552}, 'headers': {'cookie': 'all eaten'}}),
|
||||
)
|
||||
assert res.status_code == 200, "HTTP PUT update was sent OK"
|
||||
|
||||
# HTTP GET single watch, title should be updated
|
||||
res = client.get(
|
||||
url_for("watch", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key}
|
||||
)
|
||||
assert res.json.get('title') == 'new title'
|
||||
|
||||
# Check in the edit page just to be sure
|
||||
res = client.get(
|
||||
url_for("edit_page", uuid=watch_uuid),
|
||||
)
|
||||
assert b"new title" in res.data, "new title found in edit page"
|
||||
assert b"552" in res.data, "552 minutes found in edit page"
|
||||
assert b"One, Two" in res.data, "Tag 'One, Two' was found"
|
||||
assert b"cookie: all eaten" in res.data, "'cookie: all eaten' found in 'headers' section"
|
||||
|
||||
######################################################
|
||||
|
||||
# HTTP PUT try a field that doenst exist
|
||||
|
||||
# HTTP PUT an update
|
||||
res = client.put(
|
||||
url_for("watch", uuid=watch_uuid),
|
||||
headers={'x-api-key': api_key, 'content-type': 'application/json'},
|
||||
data=json.dumps({"title": "new title", "some other field": "uh oh"}),
|
||||
)
|
||||
|
||||
assert res.status_code == 400, "Should get error 400 when we give a field that doesnt exist"
|
||||
# Message will come from `flask_expects_json`
|
||||
assert b'Additional properties are not allowed' in res.data
|
||||
|
||||
# Cleanup everything
|
||||
res = client.get(url_for("form_delete", uuid="all"), follow_redirects=True)
|
||||
assert b'Deleted' in res.data
|
||||
|
||||
Reference in New Issue
Block a user