Molodetz blogrol volgens DPP-template
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
@@ -0,0 +1,33 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
import io
|
||||
|
||||
from pypdf import PdfWriter
|
||||
|
||||
from molodetz.cli import build_parser
|
||||
from molodetz.cli.commands import read_source
|
||||
|
||||
|
||||
def test_parser_groups():
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(["posts", "import", "notitie.md", "--topic", "standaard"])
|
||||
assert args.topic == "standaard" and args.path == "notitie.md"
|
||||
args = parser.parse_args(["system", "prune", "--dry-run"])
|
||||
assert args.dry_run is True
|
||||
args = parser.parse_args(["role", "set", "retoor", "Admin"])
|
||||
assert args.role == "Admin"
|
||||
|
||||
|
||||
def test_read_markdown(tmp_path):
|
||||
path = tmp_path / "x.md"
|
||||
path.write_text("# Kop\n\nTekst", encoding="utf-8")
|
||||
assert read_source(path).startswith("# Kop")
|
||||
|
||||
|
||||
def test_read_pdf(tmp_path):
|
||||
writer = PdfWriter()
|
||||
writer.add_blank_page(width=200, height=200)
|
||||
buffer = io.BytesIO()
|
||||
writer.write(buffer)
|
||||
path = tmp_path / "x.pdf"
|
||||
path.write_bytes(buffer.getvalue())
|
||||
assert read_source(path) == ""
|
||||
@@ -0,0 +1,18 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
from molodetz import config
|
||||
from molodetz.gallery import GALLERY
|
||||
|
||||
BANNED = ("selfie", "mirror", "devplace", "nigel", "nldr", "waifu", "zwem")
|
||||
|
||||
|
||||
def test_gallery_files_exist_and_are_allowed():
|
||||
assert GALLERY
|
||||
for entry in GALLERY:
|
||||
name = entry["file"] if isinstance(entry, dict) else entry[0]
|
||||
assert (config.MEDIA_SOURCE_DIR / name).is_file(), name
|
||||
assert not any(word in name.lower() for word in BANNED), name
|
||||
|
||||
|
||||
def test_both_kinds_present():
|
||||
kinds = {entry["kind"] if isinstance(entry, dict) else entry[1] for entry in GALLERY}
|
||||
assert {"flyer", "meme"} <= kinds
|
||||
@@ -0,0 +1,34 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
from molodetz import gates
|
||||
|
||||
|
||||
def test_gate_1_template_environment_only_in_templating():
|
||||
assert gates.gate_template_environment() == set()
|
||||
|
||||
|
||||
def test_gate_2_breakpoints_closed_set():
|
||||
assert gates.gate_breakpoints() == gates.BREAKPOINTS
|
||||
|
||||
|
||||
def test_gate_3_http_client_allowlist():
|
||||
assert gates.gate_http_clients() == gates.HTTP_CLIENT_ALLOWLIST
|
||||
|
||||
|
||||
def test_gate_4_client_render_allowlist():
|
||||
assert gates.gate_client_render_templates() == gates.CLIENT_RENDER_ALLOWLIST
|
||||
|
||||
|
||||
def test_gate_5_no_bare_static():
|
||||
assert gates.gate_bare_static() == []
|
||||
|
||||
|
||||
def test_gate_6_no_manual_loading_toggles():
|
||||
assert gates.gate_loading_toggles() == []
|
||||
|
||||
|
||||
def test_no_em_dashes():
|
||||
assert gates.gate_em_dashes() == []
|
||||
|
||||
|
||||
def test_json_error_status_first():
|
||||
assert gates.gate_json_error_order() == []
|
||||
@@ -0,0 +1,12 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
import asyncio
|
||||
|
||||
import pytest
|
||||
|
||||
from molodetz.net_guard import UnsafeURL, guard_public_url
|
||||
|
||||
|
||||
@pytest.mark.parametrize("url", ["http://127.0.0.1/", "http://localhost:8088/", "http://10.0.0.1/", "http://169.254.169.254/", "file:///etc/passwd", "ftp://example.com/"])
|
||||
def test_private_and_odd_urls_are_refused(url):
|
||||
with pytest.raises(UnsafeURL):
|
||||
asyncio.run(guard_public_url(url))
|
||||
@@ -0,0 +1,34 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
from molodetz.constants import REPORTABLE_TARGETS, SOFT_DELETE_TABLES, UNREPORTABLE_TABLES
|
||||
from molodetz.docs_api import all_endpoints
|
||||
from molodetz.docs_api.registry import TARGET_TYPES
|
||||
|
||||
|
||||
def test_soft_delete_tables_partition():
|
||||
tables = set(SOFT_DELETE_TABLES)
|
||||
assert tables == set(REPORTABLE_TARGETS) | set(UNREPORTABLE_TABLES)
|
||||
assert not set(REPORTABLE_TARGETS) & set(UNREPORTABLE_TABLES)
|
||||
|
||||
|
||||
def test_documented_endpoints_are_unique():
|
||||
keys = [(item["method"], item["path"]) for item in all_endpoints()]
|
||||
assert len(keys) == len(set(keys))
|
||||
|
||||
|
||||
def test_documented_endpoints_exist_in_app():
|
||||
from molodetz.main import app
|
||||
|
||||
routes = {(method.upper(), path) for path, methods in app.openapi()["paths"].items() for method in methods}
|
||||
missing = [(item["method"], item["path"]) for item in all_endpoints() if (item["method"], item["path"]) not in routes]
|
||||
assert missing == []
|
||||
|
||||
|
||||
def test_target_types_known():
|
||||
assert set(TARGET_TYPES) == {"post", "join_request", "user"}
|
||||
|
||||
|
||||
def test_no_oauth_redirect_route():
|
||||
from molodetz.main import app
|
||||
|
||||
assert "/docs/oauth2-redirect" not in app.openapi()["paths"]
|
||||
assert app.swagger_ui_oauth2_redirect_url is None
|
||||
@@ -0,0 +1,34 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
from molodetz.rendering import content_preview, normalize_dashes, plain_title, render_content, render_title
|
||||
|
||||
|
||||
def test_markdown_renders_and_escapes_html():
|
||||
html = render_content("**vet** <script>alert(1)</script>")
|
||||
assert "<strong>vet</strong>" in html
|
||||
assert "<script>" not in html
|
||||
|
||||
|
||||
def test_dashes_are_normalized():
|
||||
long_dash = chr(0x2014)
|
||||
assert normalize_dashes(f"a {long_dash} b") == "a - b"
|
||||
assert long_dash not in render_content(f"x {long_dash} y")
|
||||
|
||||
|
||||
def test_javascript_urls_are_dropped():
|
||||
html = render_content("[klik](javascript:alert(1))")
|
||||
assert "javascript:" not in html
|
||||
|
||||
|
||||
def test_emoji_shortcodes():
|
||||
assert "\U0001F44D" in render_content(":thumbsup:")
|
||||
|
||||
|
||||
def test_title_is_inline_only():
|
||||
html = render_title("# Kop *nadruk*")
|
||||
assert "<h1>" not in html
|
||||
assert plain_title("**Vet** titel") == "Vet titel"
|
||||
|
||||
|
||||
def test_preview_truncates():
|
||||
preview = content_preview("woord " * 200, 50)
|
||||
assert len(preview) <= 52
|
||||
@@ -0,0 +1,20 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
import pytest
|
||||
|
||||
from molodetz.utils.request_meta import safe_next
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value,expected",
|
||||
[
|
||||
("/admin", "/admin"),
|
||||
("/rol?page=2", "/rol?page=2"),
|
||||
("https://evil.example/", "/"),
|
||||
("//evil.example/", "/"),
|
||||
("/\\evil.example", "/"),
|
||||
("", "/"),
|
||||
(None, "/"),
|
||||
],
|
||||
)
|
||||
def test_safe_next(value, expected):
|
||||
assert safe_next(value) == expected
|
||||
@@ -0,0 +1,7 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
from molodetz.database.sql_lint import collect_sql, lint
|
||||
|
||||
|
||||
def test_raw_sql_parses_with_sqlglot():
|
||||
assert collect_sql(), "expected raw SQL literals to lint"
|
||||
assert lint() == []
|
||||
Reference in New Issue
Block a user