"""Tests for resolve_view_marker across function views and MethodView routes.""" from flask import Flask from flask.views import MethodView from core.hardening.view_markers import resolve_view_marker _ATTR = '_tag' def _mark(value): def deco(view): setattr(view, _ATTR, value) return view return deco def _app() -> Flask: app = Flask(__name__) @app.get('/fn') @_mark('fn-tag') def fn() -> str: return 'ok' class _MV(MethodView): @_mark('mv-get-tag') def get(self) -> str: return 'ok' app.add_url_rule('/mv', view_func=_MV.as_view('mv')) @app.get('/plain') def plain() -> str: return 'ok' return app def test_resolves_marker_on_function_view() -> None: """A function view's own marker attribute is returned.""" app = _app() with app.test_request_context('/fn'): assert resolve_view_marker(app, 'fn', 'GET', _ATTR, None) == 'fn-tag' def test_resolves_marker_on_methodview_method() -> None: """A marker on a MethodView get() is resolved via view_class (not the as_view closure).""" app = _app() assert resolve_view_marker(app, 'mv', 'GET', _ATTR, None) == 'mv-get-tag' def test_head_falls_back_to_get_on_methodview() -> None: """HEAD resolves the GET marker, mirroring Flask's HEAD->get dispatch fallback.""" app = _app() assert resolve_view_marker(app, 'mv', 'HEAD', _ATTR, None) == 'mv-get-tag' def test_returns_default_when_unmarked() -> None: """An unmarked view yields the default; a missing endpoint also yields the default.""" app = _app() assert resolve_view_marker(app, 'plain', 'GET', _ATTR, 'dflt') == 'dflt' assert resolve_view_marker(app, None, 'GET', _ATTR, 'dflt') == 'dflt'