# retoor import time import pytest import requests from devplacepy.database import REPORTABLE_TARGETS, get_table, refresh_snapshot from tests.conftest import BASE_URL JSON = {"Accept": "application/json"} _counter = [0] def _unique(prefix="rep"): _counter[0] += 1 return f"{prefix}{int(time.time() * 1000)}{_counter[0]}" def _member(): name = _unique() session = requests.Session() session.post( f"{BASE_URL}/auth/signup", data={ "username": name, "email": f"{name}@t.dev", "password": "secret123", "confirm_password": "secret123", "birth_date": "1990-01-01", "accept_terms": "1", }, allow_redirects=True, ) return session, name def _post(session, title="Reportable post"): response = session.post( f"{BASE_URL}/posts/create", data={"title": title, "content": "A post that can be reported by others."}, headers=JSON, ) assert response.status_code == 200, response.text return response.json()["data"]["uid"] def _reports_for(target_type, target_uid): refresh_snapshot() return list( get_table("content_reports").find( target_type=target_type, target_uid=target_uid, deleted_at=None ) ) @pytest.fixture(scope="module") def author(app_server): return _member() def test_report_reasons_are_public(app_server): response = requests.get(f"{BASE_URL}/reports/reasons", headers=JSON) assert response.status_code == 200 keys = {entry["key"] for entry in response.json()["reasons"]} assert {"harassment", "spam", "intellectual_property", "other"} <= keys def test_the_reasons_page_is_indexable_with_breadcrumbs_and_a_site_schema(app_server): html = requests.get(f"{BASE_URL}/reports/reasons").text assert '' in html assert 'class="breadcrumb"' in html assert "Report reasons" in html assert '"@type": "WebSite"' in html def test_the_reasons_page_title_carries_one_site_suffix(app_server): html = requests.get(f"{BASE_URL}/reports/reasons").text start = html.index("") + len("<title>") title = html[start : html.index("", start)] assert title == "Report reasons - DevPlace", title def test_reporting_a_post_records_one_row_with_the_owner(author): author_session, author_name = author post_uid = _post(author_session) reporter, _ = _member() response = reporter.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "harassment", "detail": "Targets me personally."}, headers=JSON, ) assert response.status_code == 200, response.text assert response.json()["data"]["status"] == "open" rows = _reports_for("post", post_uid) assert len(rows) == 1 owner = get_table("users").find_one(username=author_name) assert rows[0]["owner_uid"] == owner["uid"] assert rows[0]["origin"] == "member" def test_second_report_by_the_same_reporter_updates_instead_of_duplicating(author): author_session, _ = author post_uid = _post(author_session) reporter, _ = _member() for reason in ("spam", "harassment"): response = reporter.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": reason}, headers=JSON, ) assert response.status_code == 200 rows = _reports_for("post", post_uid) assert len(rows) == 1 assert rows[0]["reason"] == "harassment" def test_a_different_reporter_creates_a_second_row(author): author_session, _ = author post_uid = _post(author_session) for _ in range(2): reporter, _ = _member() reporter.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "spam"}, headers=JSON, ) assert len(_reports_for("post", post_uid)) == 2 def test_guests_cannot_report(author): author_session, _ = author post_uid = _post(author_session) response = requests.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "spam"}, headers=JSON, ) assert response.status_code == 401 def test_reporting_your_own_content_is_refused(author): author_session, _ = author post_uid = _post(author_session) response = author_session.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "spam"}, headers=JSON, ) assert response.status_code == 400 assert _reports_for("post", post_uid) == [] def test_an_unknown_target_type_is_refused(author): reporter, _ = _member() response = reporter.post( f"{BASE_URL}/reports/not_a_surface/whatever", data={"reason": "spam"}, headers=JSON, ) assert response.status_code == 400 def test_an_unknown_reason_is_refused(author): author_session, _ = author post_uid = _post(author_session) reporter, _ = _member() response = reporter.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "not_a_reason"}, headers=JSON, ) assert response.status_code == 422 def test_every_registry_target_type_is_accepted_by_the_route(author): author_session, _ = author reporter, _ = _member() for target_type in REPORTABLE_TARGETS: response = reporter.post( f"{BASE_URL}/reports/{target_type}/missing-{target_type}", data={"reason": "other"}, headers=JSON, ) assert response.status_code == 200, f"{target_type}: {response.text}" def test_the_report_dialog_uses_the_shared_auth_field_classes(app_server): reporter, _ = _member() html = reporter.get(f"{BASE_URL}/feed").text assert 'id="report-dialog"' in html assert 'class="auth-field auth-field-gap"' in html assert 'class="modal-footer"' in html assert 'id="report-reason"' in html assert 'id="report-detail"' in html def test_your_reports_page_loads_the_admin_table_styles(author): author_session, _ = author post_uid = _post(author_session) reporter, _ = _member() reporter.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "spam"}, headers=JSON ) html = reporter.get(f"{BASE_URL}/reports/mine").text assert "css/admin.css" in html assert 'class="admin-table"' in html def test_mine_lists_only_your_own_reports(author): author_session, _ = author post_uid = _post(author_session) mine, _ = _member() other, _ = _member() mine.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "spam"}, headers=JSON ) other.post( f"{BASE_URL}/reports/post/{post_uid}", data={"reason": "harassment"}, headers=JSON, ) payload = mine.get(f"{BASE_URL}/reports/mine", headers=JSON).json() reasons = {entry["reason"] for entry in payload["reports"]} assert "spam" in reasons assert "harassment" not in reasons assert requests.get(f"{BASE_URL}/reports/mine", headers=JSON).status_code == 401