import asyncio import importlib.util import sys import types from pathlib import Path from unittest.mock import AsyncMock import pytest from quart import Quart def load_share_module(monkeypatch): stubs = { 'my_modules.decoratory.header': {'login_required': lambda fn: fn}, 'my_modules.functions': {'get_ip': lambda: '192.0.2.1'}, 'my_modules.app.setup': { 'LIMITER': types.SimpleNamespace(limit=lambda *args, **kwargs: lambda fn: fn), }, 'my_modules.app.logger': {'logger': None}, 'my_modules.expiry': {'parse_expires': lambda value: value}, 'quart_common.web.wide_event': {'add_wide_event_context': lambda **kwargs: None}, } for name, values in stubs.items(): module = types.ModuleType(name) module.__dict__.update(values) monkeypatch.setitem(sys.modules, name, module) path = Path(__file__).resolve().parents[1] / 'routes/side/main.py' spec = importlib.util.spec_from_file_location('share_route_under_test', path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module @pytest.mark.parametrize('suffix', [ '', ' in female shape like https:/example.com/-kzmIlsf7uUe', '%20in%20female%20shape%20like%20https:/example.com/-kzmIlsf7uUe', ]) def test_share_link_looks_up_only_id(monkeypatch, suffix): async def run_test(): module = load_share_module(monkeypatch) app = Quart(__name__) app.secret_key = 'test-secret' app.convex = types.SimpleNamespace(get_file=AsyncMock(return_value=None)) app.register_blueprint(module.side_main_bp) response = await app.test_client().get('/-eluTduc-npP' + suffix) assert response.status_code == 404 app.convex.get_file.assert_awaited_once_with(file_id='eluTduc-npP') asyncio.run(run_test()) @pytest.mark.parametrize('path', ['/-/other', '/-%20text', '/-file/other']) def test_invalid_share_id_does_not_query_storage(monkeypatch, path): async def run_test(): module = load_share_module(monkeypatch) app = Quart(__name__) app.convex = types.SimpleNamespace(get_file=AsyncMock()) app.register_blueprint(module.side_main_bp) response = await app.test_client().get(path) assert response.status_code == 404 app.convex.get_file.assert_not_awaited() asyncio.run(run_test())