Adding basic test for socket.io
This commit is contained in:
@@ -34,7 +34,6 @@
|
||||
<script src="{{url_for('static_content', group='js', filename='jquery-3.6.0.min.js')}}"></script>
|
||||
<script src="{{url_for('static_content', group='js', filename='csrf.js')}}" defer></script>
|
||||
<script src="https://cdn.socket.io/4.6.0/socket.io.min.js" integrity="sha384-c79GN5VsunZvi+Q/WObgk2in0CbZsHnjEqvFxC5DxHn9lTfNce2WW6h2pH6u/kF+" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/timeago.js/4.0.2/timeago.min.js" integrity="sha512-SVDh1zH5N9ChofSlNAK43lcNS7lWze6DTVx1JCXH1Tmno+0/1jMpdbR8YDgDUfcUrPp1xyE53G42GFrcM0CMVg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="{{url_for('static_content', group='js', filename='socket.js')}}" defer></script>
|
||||
<script src="{{url_for('static_content', group='js', filename='timeago-init.js')}}" defer></script>
|
||||
</head>
|
||||
|
||||
@@ -2,9 +2,9 @@ import asyncio
|
||||
import socketio
|
||||
from aiohttp import web
|
||||
|
||||
SOCKETIO_URL = "http://localhost:5000"
|
||||
SOCKETIO_URL = 'ws://localhost.localdomain:5005'
|
||||
SOCKETIO_PATH = "/socket.io"
|
||||
NUM_CLIENTS = 100
|
||||
NUM_CLIENTS = 1
|
||||
|
||||
clients = []
|
||||
shutdown_event = asyncio.Event()
|
||||
@@ -13,7 +13,7 @@ class WatchClient:
|
||||
def __init__(self, client_id: int):
|
||||
self.client_id = client_id
|
||||
self.i_got_watch_update_event = False
|
||||
self.sio = socketio.AsyncClient(reconnection_attempts=5, reconnection_delay=1)
|
||||
self.sio = socketio.AsyncClient(reconnection_attempts=50, reconnection_delay=1)
|
||||
|
||||
@self.sio.event
|
||||
async def connect():
|
||||
@@ -51,7 +51,7 @@ async def start_http_server():
|
||||
await site.start()
|
||||
|
||||
async def main():
|
||||
await start_http_server()
|
||||
#await start_http_server()
|
||||
|
||||
for i in range(NUM_CLIENTS):
|
||||
client = WatchClient(i)
|
||||
|
||||
115
changedetectionio/tests/test_basic_socketio.py
Normal file
115
changedetectionio/tests/test_basic_socketio.py
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import time
|
||||
from flask import url_for
|
||||
from .util import (
|
||||
set_original_response,
|
||||
set_modified_response,
|
||||
live_server_setup,
|
||||
wait_for_all_checks
|
||||
)
|
||||
|
||||
class TestSocketIO:
|
||||
"""Test class for Socket.IO functionality"""
|
||||
|
||||
def test_socketio_watch_update(self, client, live_server):
|
||||
"""Test that the socketio emits a watch update event when content changes"""
|
||||
|
||||
# Set up the test server
|
||||
set_original_response()
|
||||
live_server_setup(live_server)
|
||||
|
||||
# Get the SocketIO instance from the app
|
||||
from changedetectionio.flask_app import app
|
||||
socketio = app.extensions['socketio']
|
||||
|
||||
# Create a test client for SocketIO
|
||||
socketio_test_client = socketio.test_client(app, flask_test_client=client)
|
||||
assert socketio_test_client.is_connected(), "Failed to connect to Socket.IO server"
|
||||
print("Successfully connected to Socket.IO server")
|
||||
|
||||
# Add our URL to the import page
|
||||
res = client.post(
|
||||
url_for("imports.import_page"),
|
||||
data={"urls": url_for('test_endpoint', _external=True)},
|
||||
follow_redirects=True
|
||||
)
|
||||
assert b"1 Imported" in res.data
|
||||
|
||||
res = client.get(url_for("watchlist.index"))
|
||||
assert url_for('test_endpoint', _external=True).encode() in res.data
|
||||
|
||||
# Wait for initial check to complete
|
||||
wait_for_all_checks(client)
|
||||
|
||||
# Clear any initial messages
|
||||
socketio_test_client.get_received()
|
||||
|
||||
# Make a change to trigger an update
|
||||
set_modified_response()
|
||||
|
||||
# Force recheck
|
||||
res = client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
|
||||
assert b'Queued 1 watch for rechecking.' in res.data
|
||||
|
||||
# Wait for the watch to be checked
|
||||
wait_for_all_checks(client)
|
||||
|
||||
# Wait for events to be emitted and received (up to 20 seconds)
|
||||
max_wait = 20
|
||||
has_watch_update = False
|
||||
has_unviewed_update = False
|
||||
|
||||
for i in range(max_wait):
|
||||
# Get received events
|
||||
received = socketio_test_client.get_received()
|
||||
|
||||
if received:
|
||||
print(f"Received {len(received)} events after {i+1} seconds")
|
||||
|
||||
# Check for watch_update events with unviewed=True
|
||||
for event in received:
|
||||
if event['name'] == 'watch_update':
|
||||
has_watch_update = True
|
||||
if event['args'][0].get('unviewed', False):
|
||||
has_unviewed_update = True
|
||||
print("Found unviewed update event!")
|
||||
break
|
||||
|
||||
if has_unviewed_update:
|
||||
break
|
||||
|
||||
# Force a recheck every 5 seconds to ensure events are emitted
|
||||
if i > 0 and i % 5 == 0:
|
||||
print(f"Still waiting for events, forcing another recheck...")
|
||||
res = client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
|
||||
assert b'Queued 1 watch for rechecking.' in res.data
|
||||
wait_for_all_checks(client)
|
||||
|
||||
print(f"Waiting for unviewed update event... {i+1}/{max_wait}")
|
||||
time.sleep(1)
|
||||
|
||||
# Verify we received watch_update events
|
||||
assert has_watch_update, "No watch_update events received"
|
||||
|
||||
# Verify we received an unviewed event
|
||||
assert has_unviewed_update, "No watch_update event with unviewed=True received"
|
||||
|
||||
# Alternatively, check directly if the watch in the datastore is marked as unviewed
|
||||
from changedetectionio.flask_app import app
|
||||
datastore = app.config.get('DATASTORE')
|
||||
|
||||
# Extract the watch UUID from the watchlist page
|
||||
res = client.get(url_for("watchlist.index"))
|
||||
import re
|
||||
m = re.search('edit/(.+?)[#"]', str(res.data))
|
||||
assert m, "Could not find watch UUID in page"
|
||||
watch_uuid = m.group(1).strip()
|
||||
|
||||
# Get the watch from the datastore
|
||||
watch = datastore.data['watching'].get(watch_uuid)
|
||||
assert watch, f"Watch {watch_uuid} not found in datastore"
|
||||
assert watch.has_unviewed, "The watch was not marked as unviewed after content change"
|
||||
|
||||
# Clean up
|
||||
client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True)
|
||||
@@ -139,8 +139,7 @@ def wait_for_all_checks(client=None):
|
||||
attempt = 0
|
||||
i=0
|
||||
max_attempts = 60
|
||||
wait_between_attempts = 2
|
||||
required_empty_duration = 2
|
||||
required_empty_duration = 0.8
|
||||
|
||||
logger = logging.getLogger()
|
||||
time.sleep(1.2)
|
||||
@@ -329,6 +328,8 @@ def live_server_setup(live_server):
|
||||
|
||||
live_server.start()
|
||||
|
||||
|
||||
|
||||
def get_index(client):
|
||||
import inspect
|
||||
# Get the caller's frame (parent function)
|
||||
|
||||
Reference in New Issue
Block a user