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
86 lines
3.4 KiB
Python
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
|