"""§20 — list endpoints are paginated. Every tenant-scoped list is unbounded in principle: an organization can create thousands of tasks. Without a page size the API would happily serialize all of them, so these tests pin the contract that a list is capped and that ``offset`` walks the result set. """ from __future__ import annotations import pytest import pytest_asyncio from httpx import AsyncClient from tests.conftest import auth_header, signup # Fixtures resolve from conftest by name, so ``seeded`` needs no import here; # importing it would shadow this parameter (ruff F811) and read as unused (F401). @pytest_asyncio.fixture(autouse=True) async def _platform_seed(seeded): return seeded async def test_tasks_list_is_paginated(client: AsyncClient): token = (await signup(client, "page-tasks@example.com"))["access_token"] headers = auth_header(token) org_id = ( await client.post("/api/organizations", json={"name": "سازمان صفحه"}, headers=headers) ).json()["id"] for index in range(5): created = await client.post( f"/api/organizations/{org_id}/tasks", json={"title": f"کار {index}"}, headers=headers, ) assert created.status_code == 201, created.text page_one = await client.get( f"/api/organizations/{org_id}/tasks", params={"limit": 2}, headers=headers ) assert page_one.status_code == 200, page_one.text assert len(page_one.json()) == 2, "limit must cap the page size" page_two = await client.get( f"/api/organizations/{org_id}/tasks", params={"limit": 2, "offset": 2}, headers=headers, ) assert len(page_two.json()) == 2 # Pages must not overlap: offset walks the ordering rather than repeating it. ids_one = {t["id"] for t in page_one.json()} ids_two = {t["id"] for t in page_two.json()} assert not (ids_one & ids_two), "consecutive pages returned the same row" everything = await client.get( f"/api/organizations/{org_id}/tasks", params={"limit": 500}, headers=headers ) assert len(everything.json()) == 5 @pytest.mark.parametrize("bad", [{"limit": 0}, {"limit": 501}, {"offset": -1}]) async def test_out_of_range_pagination_is_rejected(client: AsyncClient, bad: dict): token = (await signup(client, f"page-bad-{abs(hash(str(bad))) % 10**6}@example.com"))[ "access_token" ] headers = auth_header(token) org_id = ( await client.post( "/api/organizations", json={"name": "سازمان اعتبار"}, headers=headers ) ).json()["id"] response = await client.get( f"/api/organizations/{org_id}/tasks", params=bad, headers=headers ) assert response.status_code == 422, response.text async def test_projects_and_employees_accept_pagination(client: AsyncClient): """The parameter is accepted consistently across the tenant-scoped lists.""" token = (await signup(client, "page-multi@example.com"))["access_token"] headers = auth_header(token) org_id = ( await client.post("/api/organizations", json={"name": "سازمان چندگانه"}, headers=headers) ).json()["id"] for path in ("projects", "employees", "threads", "tasks"): response = await client.get( f"/api/organizations/{org_id}/{path}", params={"limit": 10, "offset": 0}, headers=headers, ) assert response.status_code == 200, f"{path}: {response.text}"