mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-06-25 04:21:32 +02:00
58499c420b
Remove the meshcore_interface component in favor of external meshcore-packet-capture for data ingestion. Rename receiver_node_id to observer_node_id across all models, schemas, handlers, and API routes. Add Alembic migration for the column/table renames. Fix frontend JS property name mismatch that prevented the Receiver column from displaying observer data.
186 lines
6.8 KiB
Python
186 lines
6.8 KiB
Python
"""Tests for message API routes."""
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
class TestListMessages:
|
|
"""Tests for GET /messages endpoint."""
|
|
|
|
def test_list_messages_empty(self, client_no_auth):
|
|
"""Test listing messages when database is empty."""
|
|
response = client_no_auth.get("/api/v1/messages")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["items"] == []
|
|
assert data["total"] == 0
|
|
|
|
def test_list_messages_with_data(self, client_no_auth, sample_message):
|
|
"""Test listing messages with data in database."""
|
|
response = client_no_auth.get("/api/v1/messages")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
assert data["total"] == 1
|
|
assert data["items"][0]["text"] == sample_message.text
|
|
assert data["items"][0]["message_type"] == sample_message.message_type
|
|
|
|
def test_list_messages_filter_by_type(self, client_no_auth, sample_message):
|
|
"""Test filtering messages by type."""
|
|
response = client_no_auth.get("/api/v1/messages?message_type=direct")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
|
|
response = client_no_auth.get("/api/v1/messages?message_type=channel")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 0
|
|
|
|
def test_list_messages_pagination(self, client_no_auth):
|
|
"""Test message list pagination parameters."""
|
|
response = client_no_auth.get("/api/v1/messages?limit=25&offset=10")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["limit"] == 25
|
|
assert data["offset"] == 10
|
|
|
|
|
|
class TestGetMessage:
|
|
"""Tests for GET /messages/{id} endpoint."""
|
|
|
|
def test_get_message_success(self, client_no_auth, sample_message):
|
|
"""Test getting a specific message."""
|
|
response = client_no_auth.get(f"/api/v1/messages/{sample_message.id}")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["text"] == sample_message.text
|
|
|
|
def test_get_message_not_found(self, client_no_auth):
|
|
"""Test getting a non-existent message."""
|
|
response = client_no_auth.get("/api/v1/messages/nonexistent-id")
|
|
assert response.status_code == 404
|
|
|
|
|
|
class TestListMessagesFilters:
|
|
"""Tests for message list query filters."""
|
|
|
|
def test_filter_by_pubkey_prefix(self, client_no_auth, sample_message):
|
|
"""Test filtering messages by pubkey_prefix."""
|
|
# Match
|
|
response = client_no_auth.get("/api/v1/messages?pubkey_prefix=abc123")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
|
|
# No match
|
|
response = client_no_auth.get("/api/v1/messages?pubkey_prefix=xyz999")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 0
|
|
|
|
def test_filter_by_channel_idx(
|
|
self, client_no_auth, sample_message, sample_message_with_receiver
|
|
):
|
|
"""Test filtering messages by channel_idx."""
|
|
# Channel 1 should match sample_message_with_receiver
|
|
response = client_no_auth.get("/api/v1/messages?channel_idx=1")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
assert data["items"][0]["channel_idx"] == 1
|
|
|
|
# Channel 0 should return no results
|
|
response = client_no_auth.get("/api/v1/messages?channel_idx=0")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 0
|
|
|
|
def test_filter_by_observed_by(
|
|
self,
|
|
client_no_auth,
|
|
sample_message,
|
|
sample_message_with_receiver,
|
|
receiver_node,
|
|
):
|
|
"""Test filtering messages by receiver node."""
|
|
response = client_no_auth.get(
|
|
f"/api/v1/messages?observed_by={receiver_node.public_key}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
assert data["items"][0]["text"] == sample_message_with_receiver.text
|
|
|
|
def test_filter_by_since(self, client_no_auth, api_db_session):
|
|
"""Test filtering messages by since timestamp."""
|
|
from datetime import timedelta
|
|
|
|
from meshcore_hub.common.models import Message
|
|
|
|
now = datetime.now(timezone.utc)
|
|
old_time = now - timedelta(days=7)
|
|
|
|
# Create an old message
|
|
old_msg = Message(
|
|
message_type="direct",
|
|
pubkey_prefix="old123",
|
|
text="Old message",
|
|
received_at=old_time,
|
|
)
|
|
api_db_session.add(old_msg)
|
|
api_db_session.commit()
|
|
|
|
# Filter since yesterday - should not include old message
|
|
since = (now - timedelta(days=1)).strftime("%Y-%m-%dT%H:%M:%S")
|
|
response = client_no_auth.get(f"/api/v1/messages?since={since}")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 0
|
|
|
|
def test_filter_by_until(self, client_no_auth, api_db_session):
|
|
"""Test filtering messages by until timestamp."""
|
|
from datetime import timedelta
|
|
|
|
from meshcore_hub.common.models import Message
|
|
|
|
now = datetime.now(timezone.utc)
|
|
old_time = now - timedelta(days=7)
|
|
|
|
# Create an old message
|
|
old_msg = Message(
|
|
message_type="direct",
|
|
pubkey_prefix="old456",
|
|
text="Old message for until",
|
|
received_at=old_time,
|
|
)
|
|
api_db_session.add(old_msg)
|
|
api_db_session.commit()
|
|
|
|
# Filter until 5 days ago - should include old message
|
|
until = (now - timedelta(days=5)).strftime("%Y-%m-%dT%H:%M:%S")
|
|
response = client_no_auth.get(f"/api/v1/messages?until={until}")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
assert data["items"][0]["text"] == "Old message for until"
|
|
|
|
def test_filter_by_search(self, client_no_auth, sample_message):
|
|
"""Test filtering messages by text search."""
|
|
# Match
|
|
response = client_no_auth.get("/api/v1/messages?search=Hello")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
|
|
# Case insensitive match
|
|
response = client_no_auth.get("/api/v1/messages?search=hello")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 1
|
|
|
|
# No match
|
|
response = client_no_auth.get("/api/v1/messages?search=nonexistent")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data["items"]) == 0
|