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

86 lines
3.4 KiB
Python

"""Integration test for the GET /messages server-side pagination cap (H_TEST3).
The sibling black-box test ``test_chat_large_data.test_pagination_limits_enforced``
notes inline that it "can't directly test the limit was capped without having
100+ messages". This module closes that gap by seeding 100+ real messages for
an authenticated user and asserting the route clamps an oversized ``limit`` to
the 100-row maximum while reporting ``has_more``.
Seeding 100+ messages must go through the real send route (the per-user
encrypted chat DB only exists behind the authenticated client), but that route
is rate limited to 10/min. We therefore disable the shared limiter for the
seeding loop only and restore its prior state afterwards — which is why this
test lives in its own file rather than the ``no-sut-import`` black-box module.
"""
import json
import pytest
# NB: import via the non-``src`` package path — that is the module instance
# the running app (local_deep_research.web.app_factory) binds its routes to.
# The package is importable under both ``local_deep_research`` and
# ``src.local_deep_research``, which are DISTINCT module objects with separate
# ``limiter`` singletons; toggling the wrong one is a no-op against the app.
from local_deep_research.security.rate_limiter import limiter
@pytest.fixture
def _limiter_disabled():
"""Disable the global rate limiter for the duration of a test, restoring
its previous ``enabled`` state afterwards."""
previous = limiter.enabled
limiter.enabled = False
try:
yield
finally:
limiter.enabled = previous
def test_pagination_cap_fires_with_over_100_messages(
authenticated_client, _limiter_disabled
):
"""With >100 messages present, GET /messages clamps ``limit`` to 100 and
sets ``has_more``; an in-range ``limit`` is honoured exactly."""
create_response = authenticated_client.post(
"/api/chat/sessions",
json={"initial_query": "Pagination cap test"},
content_type="application/json",
)
session_id = json.loads(create_response.data)["session_id"]
# Seed 105 messages (> the 100 cap). trigger_research=False keeps each
# send to a single message INSERT (no research/LLM work).
for i in range(105):
resp = authenticated_client.post(
f"/api/chat/sessions/{session_id}/messages",
json={"content": f"Message {i}", "trigger_research": False},
content_type="application/json",
)
assert resp.status_code == 200, (
f"seed send {i} returned {resp.status_code}: {resp.data[:200]!r}"
)
# Ask for far more than the cap: the route must clamp the page to 100 and
# tell the client more rows exist.
resp = authenticated_client.get(
f"/api/chat/sessions/{session_id}/messages",
query_string={"limit": 500},
)
assert resp.status_code == 200
data = json.loads(resp.data)
assert data["success"] is True
assert len(data["messages"]) == 100, (
f"limit=500 should be capped to 100, got {len(data['messages'])}"
)
assert data["has_more"] is True
# A smaller in-range limit is honoured exactly, also with has_more.
resp = authenticated_client.get(
f"/api/chat/sessions/{session_id}/messages",
query_string={"limit": 50},
)
data = json.loads(resp.data)
assert len(data["messages"]) == 50
assert data["has_more"] is True