mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-28 23:52:09 -04:00
test: localize calendar recurrence helper import (#4944)
* test: localize calendar recurrence helper import * test: share calendar route import helper
This commit is contained in:
committed by
GitHub
parent
927b1f7ecf
commit
bad9ec2f9c
@@ -0,0 +1,8 @@
|
|||||||
|
"""Shared imports for calendar route tests."""
|
||||||
|
|
||||||
|
|
||||||
|
def import_calendar_routes():
|
||||||
|
"""Import the calendar routes module after test stubs are installed."""
|
||||||
|
import routes.calendar_routes as cal
|
||||||
|
|
||||||
|
return cal
|
||||||
@@ -13,7 +13,7 @@ The fallback now normalizes to UTC and strips tz, exactly like the ISO path.
|
|||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tests.test_null_owner_gates import _import_calendar_helpers
|
from tests.helpers.calendar_routes import import_calendar_routes
|
||||||
|
|
||||||
# Inputs datetime.fromisoformat() rejects (so they hit the dateutil fallback)
|
# Inputs datetime.fromisoformat() rejects (so they hit the dateutil fallback)
|
||||||
# but that carry a numeric UTC offset dateutil resolves to tz-aware.
|
# but that carry a numeric UTC offset dateutil resolves to tz-aware.
|
||||||
@@ -25,7 +25,7 @@ _OFFSET_NONISO = [
|
|||||||
|
|
||||||
@pytest.mark.parametrize("s", _OFFSET_NONISO)
|
@pytest.mark.parametrize("s", _OFFSET_NONISO)
|
||||||
def test_parse_dt_dateutil_fallback_returns_naive(s):
|
def test_parse_dt_dateutil_fallback_returns_naive(s):
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
d = cal._parse_dt(s)
|
d = cal._parse_dt(s)
|
||||||
assert d.tzinfo is None, f"{s!r} leaked tz-aware: {d!r}"
|
assert d.tzinfo is None, f"{s!r} leaked tz-aware: {d!r}"
|
||||||
# +0900 14:00 -> 05:00 UTC, naive.
|
# +0900 14:00 -> 05:00 UTC, naive.
|
||||||
@@ -34,13 +34,13 @@ def test_parse_dt_dateutil_fallback_returns_naive(s):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("s", _OFFSET_NONISO)
|
@pytest.mark.parametrize("s", _OFFSET_NONISO)
|
||||||
def test_parse_dt_pair_fallback_returns_naive(s):
|
def test_parse_dt_pair_fallback_returns_naive(s):
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
dt, _is_utc = cal._parse_dt_pair(s)
|
dt, _is_utc = cal._parse_dt_pair(s)
|
||||||
assert dt.tzinfo is None, f"{s!r} leaked tz-aware via _parse_dt_pair: {dt!r}"
|
assert dt.tzinfo is None, f"{s!r} leaked tz-aware via _parse_dt_pair: {dt!r}"
|
||||||
|
|
||||||
|
|
||||||
def test_parse_dt_naive_input_unchanged():
|
def test_parse_dt_naive_input_unchanged():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
d = cal._parse_dt("January 5, 2026 14:00") # no offset -> stays as parsed
|
d = cal._parse_dt("January 5, 2026 14:00") # no offset -> stays as parsed
|
||||||
assert d.tzinfo is None
|
assert d.tzinfo is None
|
||||||
assert (d.hour, d.minute) == (14, 0)
|
assert (d.hour, d.minute) == (14, 0)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"""Regression tests for calendar recurrence expansion.
|
"""Regression tests for calendar recurrence expansion.
|
||||||
|
|
||||||
Tests _expand_rrule and _resolve_base_uid — imported directly from
|
Tests _expand_rrule and _resolve_base_uid — imported directly from
|
||||||
routes/calendar_routes using the same stub-friendly import pattern
|
routes/calendar_routes using the shared stub-friendly test helper.
|
||||||
as test_null_owner_gates.py. No live DB or FastAPI test client needed.
|
No live DB or FastAPI test client needed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
@@ -10,34 +10,34 @@ from types import SimpleNamespace
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tests.test_null_owner_gates import _import_calendar_helpers
|
from tests.helpers.calendar_routes import import_calendar_routes
|
||||||
|
|
||||||
|
|
||||||
# ── _resolve_base_uid ──────────────────────────────────────────────────
|
# ── _resolve_base_uid ──────────────────────────────────────────────────
|
||||||
|
|
||||||
def test_resolve_base_uid_plain_passthrough():
|
def test_resolve_base_uid_plain_passthrough():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
assert cal._resolve_base_uid("evt-123") == "evt-123"
|
assert cal._resolve_base_uid("evt-123") == "evt-123"
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_base_uid_compound_strips_suffix_date():
|
def test_resolve_base_uid_compound_strips_suffix_date():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
assert cal._resolve_base_uid("evt-123::2026-06-15") == "evt-123"
|
assert cal._resolve_base_uid("evt-123::2026-06-15") == "evt-123"
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_base_uid_compound_strips_suffix_datetime():
|
def test_resolve_base_uid_compound_strips_suffix_datetime():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
assert cal._resolve_base_uid("evt-123::2026-06-15T09:00") == "evt-123"
|
assert cal._resolve_base_uid("evt-123::2026-06-15T09:00") == "evt-123"
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_base_uid_rejects_empty():
|
def test_resolve_base_uid_rejects_empty():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
with pytest.raises(ValueError, match="empty uid"):
|
with pytest.raises(ValueError, match="empty uid"):
|
||||||
cal._resolve_base_uid("")
|
cal._resolve_base_uid("")
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_base_uid_rejects_missing_base():
|
def test_resolve_base_uid_rejects_missing_base():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
with pytest.raises(ValueError, match="malformed compound UID"):
|
with pytest.raises(ValueError, match="malformed compound UID"):
|
||||||
cal._resolve_base_uid("::2026-06-15")
|
cal._resolve_base_uid("::2026-06-15")
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ def _make_event(**overrides):
|
|||||||
|
|
||||||
def test_expand_non_recurring_returns_single():
|
def test_expand_non_recurring_returns_single():
|
||||||
"""Non-recurring events pass through unchanged with series_uid=uid."""
|
"""Non-recurring events pass through unchanged with series_uid=uid."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(rrule="")
|
ev = _make_event(rrule="")
|
||||||
results = cal._expand_rrule(ev, datetime(2026, 5, 1), datetime(2026, 7, 1))
|
results = cal._expand_rrule(ev, datetime(2026, 5, 1), datetime(2026, 7, 1))
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ def test_expand_yearly_old_dtstart_later_year_single_occurrence():
|
|||||||
|
|
||||||
This is the explicit regression case from PR review feedback.
|
This is the explicit regression case from PR review feedback.
|
||||||
"""
|
"""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-bday-001",
|
uid="evt-bday-001",
|
||||||
summary="Annual Review",
|
summary="Annual Review",
|
||||||
@@ -118,7 +118,7 @@ def test_expand_yearly_narrow_window_after_dtstart_returns_one():
|
|||||||
"""DTSTART=2020, query just two months in 2029 — should return
|
"""DTSTART=2020, query just two months in 2029 — should return
|
||||||
exactly one occurrence (the one that falls in that window).
|
exactly one occurrence (the one that falls in that window).
|
||||||
"""
|
"""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-ann",
|
uid="evt-ann",
|
||||||
dtstart=datetime(2020, 3, 1),
|
dtstart=datetime(2020, 3, 1),
|
||||||
@@ -137,7 +137,7 @@ def test_expand_yearly_strict_before_window_returns_empty():
|
|||||||
"""DTSTART=2020, query a window that ends before the yearly
|
"""DTSTART=2020, query a window that ends before the yearly
|
||||||
occurrence in that year. Should return zero.
|
occurrence in that year. Should return zero.
|
||||||
"""
|
"""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-late",
|
uid="evt-late",
|
||||||
dtstart=datetime(2020, 12, 25),
|
dtstart=datetime(2020, 12, 25),
|
||||||
@@ -154,7 +154,7 @@ def test_expand_yearly_strict_after_window_returns_empty():
|
|||||||
"""DTSTART=2020. Query a window that starts after the occurrence in
|
"""DTSTART=2020. Query a window that starts after the occurrence in
|
||||||
that year. Should return zero.
|
that year. Should return zero.
|
||||||
"""
|
"""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-early",
|
uid="evt-early",
|
||||||
dtstart=datetime(2020, 1, 15),
|
dtstart=datetime(2020, 1, 15),
|
||||||
@@ -171,7 +171,7 @@ def test_expand_weekly_unique_no_overwrites():
|
|||||||
"""Multiple occurrences from the same series must have unique UIDs
|
"""Multiple occurrences from the same series must have unique UIDs
|
||||||
so _allEvents[uid] = ev doesn't overwrite earlier ones.
|
so _allEvents[uid] = ev doesn't overwrite earlier ones.
|
||||||
"""
|
"""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-wk",
|
uid="evt-wk",
|
||||||
dtstart=datetime(2026, 6, 1, 9, 0),
|
dtstart=datetime(2026, 6, 1, 9, 0),
|
||||||
@@ -192,7 +192,7 @@ def test_expand_weekly_unique_no_overwrites():
|
|||||||
|
|
||||||
|
|
||||||
def test_expand_monthly_all_day():
|
def test_expand_monthly_all_day():
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-rent",
|
uid="evt-rent",
|
||||||
dtstart=datetime(2026, 1, 1),
|
dtstart=datetime(2026, 1, 1),
|
||||||
@@ -210,7 +210,7 @@ def test_expand_monthly_all_day():
|
|||||||
def test_expand_bad_rrule_graceful():
|
def test_expand_bad_rrule_graceful():
|
||||||
"""Malformed rrule should fall back to returning the base event,
|
"""Malformed rrule should fall back to returning the base event,
|
||||||
but only when the base event overlaps the requested window."""
|
but only when the base event overlaps the requested window."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-broken",
|
uid="evt-broken",
|
||||||
rrule="FREQ=GARBAGE",
|
rrule="FREQ=GARBAGE",
|
||||||
@@ -225,7 +225,7 @@ def test_expand_bad_rrule_graceful():
|
|||||||
def test_expand_bad_rrule_fallback_rejects_non_overlapping():
|
def test_expand_bad_rrule_fallback_rejects_non_overlapping():
|
||||||
"""Malformed rrule with a base event outside the requested window
|
"""Malformed rrule with a base event outside the requested window
|
||||||
must return zero results, not leak the event into an unrelated range."""
|
must return zero results, not leak the event into an unrelated range."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-old-broken",
|
uid="evt-old-broken",
|
||||||
dtstart=datetime(2020, 1, 1, 9, 0),
|
dtstart=datetime(2020, 1, 1, 9, 0),
|
||||||
@@ -243,7 +243,7 @@ def test_expand_bad_rrule_fallback_rejects_non_overlapping():
|
|||||||
def test_expand_exclusive_end_boundary():
|
def test_expand_exclusive_end_boundary():
|
||||||
"""An occurrence whose start equals the window end must be excluded.
|
"""An occurrence whose start equals the window end must be excluded.
|
||||||
The contract is [start, end), same as the non-recurring SQL filter."""
|
The contract is [start, end), same as the non-recurring SQL filter."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-daily",
|
uid="evt-daily",
|
||||||
dtstart=datetime(2026, 6, 1, 9, 0),
|
dtstart=datetime(2026, 6, 1, 9, 0),
|
||||||
@@ -260,7 +260,7 @@ def test_expand_exclusive_end_boundary():
|
|||||||
def test_expand_multi_day_crossing_range_start():
|
def test_expand_multi_day_crossing_range_start():
|
||||||
"""A multi-day occurrence that starts before the window but ends inside
|
"""A multi-day occurrence that starts before the window but ends inside
|
||||||
it must be included (matching non-recurring overlap: dtend > start)."""
|
it must be included (matching non-recurring overlap: dtend > start)."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-weekly-multi",
|
uid="evt-weekly-multi",
|
||||||
summary="Weekend Trip",
|
summary="Weekend Trip",
|
||||||
@@ -285,7 +285,7 @@ def test_expand_multi_day_crossing_range_start():
|
|||||||
def test_expand_multi_day_fully_before_window():
|
def test_expand_multi_day_fully_before_window():
|
||||||
"""A multi-day occurrence that ends exactly at the window start
|
"""A multi-day occurrence that ends exactly at the window start
|
||||||
must be excluded (occ_end <= start)."""
|
must be excluded (occ_end <= start)."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-multi",
|
uid="evt-multi",
|
||||||
dtstart=datetime(2026, 5, 29, 18, 0),
|
dtstart=datetime(2026, 5, 29, 18, 0),
|
||||||
@@ -301,7 +301,7 @@ def test_expand_multi_day_fully_before_window():
|
|||||||
def test_expand_metadata_inheritance():
|
def test_expand_metadata_inheritance():
|
||||||
"""Occurrence dicts must carry the base event's metadata
|
"""Occurrence dicts must carry the base event's metadata
|
||||||
(summary, importance, event_type, color, location)."""
|
(summary, importance, event_type, color, location)."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-meta",
|
uid="evt-meta",
|
||||||
summary="Board Meeting",
|
summary="Board Meeting",
|
||||||
@@ -323,7 +323,7 @@ def test_expand_metadata_inheritance():
|
|||||||
|
|
||||||
def test_expand_daily_rrule_large_window_is_capped_and_marked_truncated():
|
def test_expand_daily_rrule_large_window_is_capped_and_marked_truncated():
|
||||||
"""Wide recurring windows must not materialize unbounded occurrence lists."""
|
"""Wide recurring windows must not materialize unbounded occurrence lists."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(
|
ev = _make_event(
|
||||||
uid="evt-daily-cap",
|
uid="evt-daily-cap",
|
||||||
dtstart=datetime(2020, 1, 1, 9, 0),
|
dtstart=datetime(2020, 1, 1, 9, 0),
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ UNTIL must expand to all of its occurrences.
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from tests.test_null_owner_gates import _import_calendar_helpers
|
from tests.helpers.calendar_routes import import_calendar_routes
|
||||||
|
|
||||||
|
|
||||||
_MOCK_CAL = SimpleNamespace(name="Personal", color="#5b8abf")
|
_MOCK_CAL = SimpleNamespace(name="Personal", color="#5b8abf")
|
||||||
@@ -55,7 +55,7 @@ def _make_event(**overrides):
|
|||||||
def test_expand_rrule_with_utc_until_keeps_all_occurrences():
|
def test_expand_rrule_with_utc_until_keeps_all_occurrences():
|
||||||
"""FREQ=DAILY;UNTIL=...Z must expand to every occurrence, not collapse
|
"""FREQ=DAILY;UNTIL=...Z must expand to every occurrence, not collapse
|
||||||
to a single non-recurring event."""
|
to a single non-recurring event."""
|
||||||
cal = _import_calendar_helpers()
|
cal = import_calendar_routes()
|
||||||
ev = _make_event(rrule="FREQ=DAILY;UNTIL=20240105T090000Z")
|
ev = _make_event(rrule="FREQ=DAILY;UNTIL=20240105T090000Z")
|
||||||
|
|
||||||
results = cal._expand_rrule(ev, datetime(2024, 1, 1), datetime(2024, 1, 10))
|
results = cal._expand_rrule(ev, datetime(2024, 1, 1), datetime(2024, 1, 10))
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"""Tests for iCalendar TEXT escaping in calendar export (RFC 5545 §3.3.11)."""
|
"""Tests for iCalendar TEXT escaping in calendar export (RFC 5545 §3.3.11)."""
|
||||||
from tests.test_null_owner_gates import _import_calendar_helpers
|
from tests.helpers.calendar_routes import import_calendar_routes
|
||||||
|
|
||||||
|
|
||||||
def _esc():
|
def _esc():
|
||||||
return _import_calendar_helpers()._ics_escape
|
return import_calendar_routes()._ics_escape
|
||||||
|
|
||||||
|
|
||||||
def test_escapes_comma_and_semicolon():
|
def test_escapes_comma_and_semicolon():
|
||||||
@@ -26,7 +26,7 @@ def test_empty_and_none_safe():
|
|||||||
|
|
||||||
|
|
||||||
def test_safe_ics_filename_strips_header_metacharacters():
|
def test_safe_ics_filename_strips_header_metacharacters():
|
||||||
safe_filename = _import_calendar_helpers()._safe_ics_filename
|
safe_filename = import_calendar_routes()._safe_ics_filename
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
safe_filename('Work\r\nX-Injected: yes";/..\\evil')
|
safe_filename('Work\r\nX-Injected: yes";/..\\evil')
|
||||||
@@ -35,7 +35,7 @@ def test_safe_ics_filename_strips_header_metacharacters():
|
|||||||
|
|
||||||
|
|
||||||
def test_safe_ics_filename_falls_back_for_empty_names():
|
def test_safe_ics_filename_falls_back_for_empty_names():
|
||||||
safe_filename = _import_calendar_helpers()._safe_ics_filename
|
safe_filename = import_calendar_routes()._safe_ics_filename
|
||||||
|
|
||||||
assert safe_filename("////") == "calendar.ics"
|
assert safe_filename("////") == "calendar.ics"
|
||||||
assert safe_filename(None) == "calendar.ics"
|
assert safe_filename(None) == "calendar.ics"
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import pytest
|
|||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from tests.helpers.calendar_routes import import_calendar_routes
|
||||||
|
|
||||||
# `tests/conftest.py` stubs the heavy optional deps. We additionally
|
# `tests/conftest.py` stubs the heavy optional deps. We additionally
|
||||||
# stub `core.database` here because the real module instantiates
|
# stub `core.database` here because the real module instantiates
|
||||||
# SQLAlchemy declarative classes at import-time — which blows up under
|
# SQLAlchemy declarative classes at import-time — which blows up under
|
||||||
@@ -64,20 +66,8 @@ from fastapi import HTTPException
|
|||||||
# calendar._get_or_404_calendar / _get_or_404_event
|
# calendar._get_or_404_calendar / _get_or_404_event
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def _import_calendar_helpers():
|
|
||||||
"""Import the two private gate helpers without booting the full
|
|
||||||
calendar router. We patch sys.modules so the module-load side
|
|
||||||
effects (DB import) don't blow up under the conftest stubs."""
|
|
||||||
mod_name = "routes.calendar_routes"
|
|
||||||
if mod_name in sys.modules:
|
|
||||||
return sys.modules[mod_name]
|
|
||||||
# core.database is stubbed by conftest already; the module should
|
|
||||||
# import cleanly.
|
|
||||||
return __import__(mod_name, fromlist=["_get_or_404_calendar", "_get_or_404_event"])
|
|
||||||
|
|
||||||
|
|
||||||
def test_calendar_gate_rejects_null_owner_for_authenticated_user():
|
def test_calendar_gate_rejects_null_owner_for_authenticated_user():
|
||||||
cal_mod = _import_calendar_helpers()
|
cal_mod = import_calendar_routes()
|
||||||
db = MagicMock()
|
db = MagicMock()
|
||||||
cal = SimpleNamespace(id="c1", owner=None)
|
cal = SimpleNamespace(id="c1", owner=None)
|
||||||
db.query.return_value.filter.return_value.first.return_value = cal
|
db.query.return_value.filter.return_value.first.return_value = cal
|
||||||
@@ -87,7 +77,7 @@ def test_calendar_gate_rejects_null_owner_for_authenticated_user():
|
|||||||
|
|
||||||
|
|
||||||
def test_calendar_gate_rejects_cross_owner():
|
def test_calendar_gate_rejects_cross_owner():
|
||||||
cal_mod = _import_calendar_helpers()
|
cal_mod = import_calendar_routes()
|
||||||
db = MagicMock()
|
db = MagicMock()
|
||||||
cal = SimpleNamespace(id="c1", owner="bob")
|
cal = SimpleNamespace(id="c1", owner="bob")
|
||||||
db.query.return_value.filter.return_value.first.return_value = cal
|
db.query.return_value.filter.return_value.first.return_value = cal
|
||||||
@@ -97,7 +87,7 @@ def test_calendar_gate_rejects_cross_owner():
|
|||||||
|
|
||||||
|
|
||||||
def test_calendar_gate_accepts_matching_owner():
|
def test_calendar_gate_accepts_matching_owner():
|
||||||
cal_mod = _import_calendar_helpers()
|
cal_mod = import_calendar_routes()
|
||||||
db = MagicMock()
|
db = MagicMock()
|
||||||
cal = SimpleNamespace(id="c1", owner="alice")
|
cal = SimpleNamespace(id="c1", owner="alice")
|
||||||
db.query.return_value.filter.return_value.first.return_value = cal
|
db.query.return_value.filter.return_value.first.return_value = cal
|
||||||
@@ -106,7 +96,7 @@ def test_calendar_gate_accepts_matching_owner():
|
|||||||
|
|
||||||
|
|
||||||
def test_calendar_event_gate_rejects_null_owner_calendar():
|
def test_calendar_event_gate_rejects_null_owner_calendar():
|
||||||
cal_mod = _import_calendar_helpers()
|
cal_mod = import_calendar_routes()
|
||||||
db = MagicMock()
|
db = MagicMock()
|
||||||
cal = SimpleNamespace(owner=None)
|
cal = SimpleNamespace(owner=None)
|
||||||
ev = SimpleNamespace(uid="e1", calendar=cal)
|
ev = SimpleNamespace(uid="e1", calendar=cal)
|
||||||
@@ -117,7 +107,7 @@ def test_calendar_event_gate_rejects_null_owner_calendar():
|
|||||||
|
|
||||||
|
|
||||||
def test_calendar_event_gate_rejects_cross_owner():
|
def test_calendar_event_gate_rejects_cross_owner():
|
||||||
cal_mod = _import_calendar_helpers()
|
cal_mod = import_calendar_routes()
|
||||||
db = MagicMock()
|
db = MagicMock()
|
||||||
cal = SimpleNamespace(owner="bob")
|
cal = SimpleNamespace(owner="bob")
|
||||||
ev = SimpleNamespace(uid="e1", calendar=cal)
|
ev = SimpleNamespace(uid="e1", calendar=cal)
|
||||||
|
|||||||
Reference in New Issue
Block a user