# retoor <retoor@molodetz.nl>
from datetime import date
import pytest
from devplacepy.database import (
AGE_BANDS,
MATURITY_TARGETS,
REPORTABLE_TARGETS,
REPORT_REASONS,
SOFT_DELETE_TABLES,
UNREPORTABLE_TABLES,
age_band_for,
years_between,
)
from devplacepy.database.moderation import MODERATION_TABLES
GUIDELINE_REASONS = (
"hate",
"violence",
"weapons",
"sexual",
"religious",
"misinformation",
"exploitative",
)
def test_every_visible_soft_delete_table_is_reportable():
reportable_tables = set(REPORTABLE_TARGETS.values())
excluded = set(UNREPORTABLE_TABLES) | set(MODERATION_TABLES)
unclassified = [
table
for table in SOFT_DELETE_TABLES
if table not in reportable_tables and table not in excluded
]
assert unclassified == []
def test_exclusion_list_only_names_real_soft_delete_tables():
unknown = [table for table in UNREPORTABLE_TABLES if table not in SOFT_DELETE_TABLES]
assert unknown == []
def test_registry_tables_are_unique_and_maturity_is_a_subset():
assert len(set(REPORTABLE_TARGETS.values())) == len(REPORTABLE_TARGETS)
assert MATURITY_TARGETS <= set(REPORTABLE_TARGETS)
def test_report_reasons_cover_every_guideline_category():
for reason in GUIDELINE_REASONS:
assert reason in REPORT_REASONS
assert REPORT_REASONS["intellectual_property"]
assert REPORT_REASONS["other"]
def test_every_registry_target_resolves_to_a_url(local_db):
from devplacepy.database import resolve_object_url
for target_type in REPORTABLE_TARGETS:
url = resolve_object_url(target_type, "missing-uid")
assert url.startswith("/")
def test_resolve_object_url_points_at_the_owning_surface(local_db):
from devplacepy.database import get_table, resolve_object_url
get_table("users").insert(
{"uid": "mod-user-1", "username": "mod_user_1", "deleted_at": None}
)
get_table("messages").insert(
{
"uid": "mod-msg-1",
"sender_uid": "mod-user-1",
"receiver_uid": "mod-user-2",
"content": "hello",
}
)
try:
assert resolve_object_url("user", "mod-user-1") == "/profile/mod_user_1"
assert (
resolve_object_url("message", "mod-msg-1")
== "/messages?with_uid=mod-user-1"
)
assert resolve_object_url("devii_output", "anything") == "/devii"
finally:
get_table("users").delete(uid="mod-user-1")
get_table("messages").delete(uid="mod-msg-1")
@pytest.mark.parametrize(
"age,expected",
[
(0, "under_min"),
(12, "under_min"),
(13, "13_15"),
(15, "13_15"),
(16, "16_17"),
(17, "16_17"),
(18, "adult"),
(120, "adult"),
],
)
def test_age_band_boundaries(age, expected):
assert age_band_for(age) == expected
def test_age_band_is_monotonic_across_the_whole_domain():
order = {band: index for index, band in enumerate(AGE_BANDS)}
previous = -1
for age in range(0, 150):
current = order[age_band_for(age)]
assert current >= previous
previous = current
def test_years_between_handles_leap_days_and_exact_boundaries():
assert years_between(date(2000, 2, 29), date(2018, 2, 28)) == 17
assert years_between(date(2000, 2, 29), date(2018, 3, 1)) == 18
assert years_between(date(2008, 1, 1), date(2026, 1, 1)) == 18
assert years_between(date(2008, 1, 2), date(2026, 1, 1)) == 17
def test_years_between_never_exceeds_the_calendar_difference():
born = date(2005, 6, 15)
for offset in range(0, 4000, 7):
today = date.fromordinal(born.toordinal() + offset)
years = years_between(born, today)
assert 0 <= years <= today.year - born.year