Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

246 lines
9.0 KiB
Python

# allow: no-sut-import — black-box HTTP test; drives real routes through the Flask test client
"""
Tests for chat end-to-end flows.
These tests verify complete workflows through the chat system,
from session creation through message exchange.
"""
import json
class TestChatE2EFlows:
"""End-to-end flow tests for chat feature."""
def test_full_conversation_flow_create_send_receive(
self, authenticated_client
):
"""Test complete flow: create session -> send message -> get messages."""
# Step 1: Create session
create_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "What is machine learning?"},
content_type="application/json",
)
assert create_response.status_code == 200
create_data = json.loads(create_response.data)
assert create_data["success"] is True
session_id = create_data["session_id"]
# Step 2: Send a message
send_response = authenticated_client.post(
f"/api/chat/sessions/{session_id}/messages",
json={
"content": "Tell me about neural networks",
"trigger_research": False,
},
content_type="application/json",
)
assert send_response.status_code == 200
send_data = json.loads(send_response.data)
assert send_data["success"] is True
message_id = send_data["message_id"]
# Step 3: Get messages
get_response = authenticated_client.get(
f"/api/chat/sessions/{session_id}/messages"
)
assert get_response.status_code == 200
get_data = json.loads(get_response.data)
assert get_data["success"] is True
assert len(get_data["messages"]) >= 1
# Verify our message is in the list
message_ids = [m["id"] for m in get_data["messages"]]
assert message_id in message_ids
def test_multi_turn_conversation_flow(self, authenticated_client):
"""Test multiple messages in a conversation."""
# Create session
create_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "Learning about AI"},
content_type="application/json",
)
session_id = json.loads(create_response.data)["session_id"]
# Send multiple messages
messages = [
"What is artificial intelligence?",
"How does deep learning work?",
"What are transformers in NLP?",
]
for i, content in enumerate(messages):
response = authenticated_client.post(
f"/api/chat/sessions/{session_id}/messages",
json={"content": content, "trigger_research": False},
content_type="application/json",
)
assert response.status_code == 200
# Verify all messages are stored
get_response = authenticated_client.get(
f"/api/chat/sessions/{session_id}/messages"
)
get_data = json.loads(get_response.data)
assert len(get_data["messages"]) == len(messages)
# Verify session message count
session_response = authenticated_client.get(
f"/api/chat/sessions/{session_id}"
)
session_data = json.loads(session_response.data)
assert session_data["session"]["message_count"] == len(messages)
def test_session_update_and_archive_flow(self, authenticated_client):
"""Test session update and archive flow."""
# Create session
create_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "Test session"},
content_type="application/json",
)
session_id = json.loads(create_response.data)["session_id"]
# Update title
update_response = authenticated_client.patch(
f"/api/chat/sessions/{session_id}",
json={"title": "Updated Title"},
content_type="application/json",
)
assert update_response.status_code == 200
update_data = json.loads(update_response.data)
assert update_data["session"]["title"] == "Updated Title"
# Archive session
archive_response = authenticated_client.patch(
f"/api/chat/sessions/{session_id}",
json={"status": "archived"},
content_type="application/json",
)
assert archive_response.status_code == 200
archive_data = json.loads(archive_response.data)
assert archive_data["session"]["status"] == "archived"
# Verify archived session not in default list
list_response = authenticated_client.get(
"/api/chat/sessions?status=active"
)
list_data = json.loads(list_response.data)
session_ids = [s["id"] for s in list_data["sessions"]]
assert session_id not in session_ids
# But appears in archived list
archived_response = authenticated_client.get(
"/api/chat/sessions?status=archived"
)
archived_data = json.loads(archived_response.data)
archived_ids = [s["id"] for s in archived_data["sessions"]]
assert session_id in archived_ids
def test_concurrent_sessions_isolated(self, authenticated_client):
"""Test that multiple sessions are properly isolated."""
# Create two sessions
session1_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "Session 1 topic"},
content_type="application/json",
)
session1_id = json.loads(session1_response.data)["session_id"]
session2_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "Session 2 topic"},
content_type="application/json",
)
session2_id = json.loads(session2_response.data)["session_id"]
# Add messages to session 1
authenticated_client.post(
f"/api/chat/sessions/{session1_id}/messages",
json={
"content": "Message for session 1",
"trigger_research": False,
},
content_type="application/json",
)
authenticated_client.post(
f"/api/chat/sessions/{session1_id}/messages",
json={
"content": "Another message for session 1",
"trigger_research": False,
},
content_type="application/json",
)
# Add different message to session 2
authenticated_client.post(
f"/api/chat/sessions/{session2_id}/messages",
json={
"content": "Message for session 2",
"trigger_research": False,
},
content_type="application/json",
)
# Verify messages are isolated
session1_messages = json.loads(
authenticated_client.get(
f"/api/chat/sessions/{session1_id}/messages"
).data
)["messages"]
session2_messages = json.loads(
authenticated_client.get(
f"/api/chat/sessions/{session2_id}/messages"
).data
)["messages"]
assert len(session1_messages) == 2
assert len(session2_messages) == 1
# Verify message content is isolated
session1_contents = [m["content"] for m in session1_messages]
session2_contents = [m["content"] for m in session2_messages]
assert "Message for session 1" in session1_contents
assert "Message for session 2" not in session1_contents
assert "Message for session 2" in session2_contents
def test_delete_and_list_flow(self, authenticated_client):
"""Test session deletion flow."""
# Create session
create_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "To be deleted"},
content_type="application/json",
)
session_id = json.loads(create_response.data)["session_id"]
# Verify session exists
get_response = authenticated_client.get(
f"/api/chat/sessions/{session_id}"
)
assert get_response.status_code == 200
# Delete session
delete_response = authenticated_client.delete(
f"/api/chat/sessions/{session_id}"
)
assert delete_response.status_code == 200
assert json.loads(delete_response.data)["success"] is True
# Session should be permanently deleted (hard delete)
get_deleted_response = authenticated_client.get(
f"/api/chat/sessions/{session_id}"
)
assert get_deleted_response.status_code == 404
# Should not appear in active sessions list
list_response = authenticated_client.get(
"/api/chat/sessions?status=active"
)
list_data = json.loads(list_response.data)
active_ids = [s["id"] for s in list_data["sessions"]]
assert session_id not in active_ids