mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 14:51:43 +00:00
feat: make apispec dependency optional (#138)
This commit is contained in:
@ -10,33 +10,21 @@ def test_import_aiohttp_security() -> None:
|
||||
"""
|
||||
must import aiohttp_security correctly
|
||||
"""
|
||||
assert helpers._has_aiohttp_security
|
||||
|
||||
|
||||
def test_import_aiohttp_security_missing(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set missing flag if no aiohttp_security module found
|
||||
"""
|
||||
mocker.patch.dict(sys.modules, {"aiohttp_security": None})
|
||||
importlib.reload(helpers)
|
||||
assert not helpers._has_aiohttp_security
|
||||
assert helpers.aiohttp_security
|
||||
|
||||
|
||||
async def test_authorized_userid_dummy(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not call authorized_userid from library if not enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", False)
|
||||
authorized_userid_mock = mocker.patch("aiohttp_security.authorized_userid")
|
||||
mocker.patch.object(helpers, "aiohttp_security", None)
|
||||
await helpers.authorized_userid()
|
||||
authorized_userid_mock.assert_not_called()
|
||||
|
||||
|
||||
async def test_authorized_userid_library(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call authorized_userid from library if enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", True)
|
||||
authorized_userid_mock = mocker.patch("aiohttp_security.authorized_userid")
|
||||
await helpers.authorized_userid()
|
||||
authorized_userid_mock.assert_called_once_with()
|
||||
@ -46,17 +34,14 @@ async def test_check_authorized_dummy(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not call check_authorized from library if not enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", False)
|
||||
check_authorized_mock = mocker.patch("aiohttp_security.check_authorized")
|
||||
mocker.patch.object(helpers, "aiohttp_security", None)
|
||||
await helpers.check_authorized()
|
||||
check_authorized_mock.assert_not_called()
|
||||
|
||||
|
||||
async def test_check_authorized_library(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call check_authorized from library if enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", True)
|
||||
check_authorized_mock = mocker.patch("aiohttp_security.check_authorized")
|
||||
await helpers.check_authorized()
|
||||
check_authorized_mock.assert_called_once_with()
|
||||
@ -66,17 +51,14 @@ async def test_forget_dummy(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not call forget from library if not enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", False)
|
||||
forget_mock = mocker.patch("aiohttp_security.forget")
|
||||
mocker.patch.object(helpers, "aiohttp_security", None)
|
||||
await helpers.forget()
|
||||
forget_mock.assert_not_called()
|
||||
|
||||
|
||||
async def test_forget_library(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call forget from library if enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", True)
|
||||
forget_mock = mocker.patch("aiohttp_security.forget")
|
||||
await helpers.forget()
|
||||
forget_mock.assert_called_once_with()
|
||||
@ -86,17 +68,23 @@ async def test_remember_dummy(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not call remember from library if not enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", False)
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
mocker.patch.object(helpers, "aiohttp_security", None)
|
||||
await helpers.remember()
|
||||
remember_mock.assert_not_called()
|
||||
|
||||
|
||||
async def test_remember_library(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must call remember from library if enabled
|
||||
"""
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", True)
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
await helpers.remember()
|
||||
remember_mock.assert_called_once_with()
|
||||
|
||||
|
||||
def test_import_aiohttp_security_missing(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set missing flag if no aiohttp_security module found
|
||||
"""
|
||||
mocker.patch.dict(sys.modules, {"aiohttp_security": None})
|
||||
importlib.reload(helpers)
|
||||
assert helpers.aiohttp_security is None
|
||||
|
24
tests/ahriman/web/apispec/test_apispec.py
Normal file
24
tests/ahriman/web/apispec/test_apispec.py
Normal file
@ -0,0 +1,24 @@
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
from ahriman.web import apispec
|
||||
|
||||
|
||||
def test_import_apispec() -> None:
|
||||
"""
|
||||
must correctly import apispec
|
||||
"""
|
||||
assert apispec.aiohttp_apispec
|
||||
|
||||
|
||||
def test_import_apispec_missing(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly process missing module
|
||||
"""
|
||||
mocker.patch.dict(sys.modules, {"aiohttp_apispec": None})
|
||||
importlib.reload(apispec)
|
||||
|
||||
assert apispec.aiohttp_apispec is None
|
||||
assert apispec.Schema
|
||||
assert apispec.fields("arg", kwargs=42)
|
161
tests/ahriman/web/apispec/test_decorators.py
Normal file
161
tests/ahriman/web/apispec/test_decorators.py
Normal file
@ -0,0 +1,161 @@
|
||||
from aiohttp.web import HTTPFound
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.apispec import decorators
|
||||
from ahriman.web.apispec.decorators import _response_schema, apidocs
|
||||
from ahriman.web.schemas import LoginSchema
|
||||
|
||||
|
||||
def test_response_schema() -> None:
|
||||
"""
|
||||
must generate response schema
|
||||
"""
|
||||
schema = _response_schema(None)
|
||||
assert schema.pop(204)
|
||||
assert schema.pop(401)
|
||||
assert schema.pop(403)
|
||||
assert schema.pop(500)
|
||||
|
||||
|
||||
def test_response_schema_no_403() -> None:
|
||||
"""
|
||||
must generate response schema without 403 error
|
||||
"""
|
||||
schema = _response_schema(None, error_403_enabled=False)
|
||||
assert 403 not in schema
|
||||
|
||||
|
||||
def test_response_schema_400() -> None:
|
||||
"""
|
||||
must generate response schema with 400 error
|
||||
"""
|
||||
schema = _response_schema(None, error_400_enabled=True)
|
||||
assert schema.pop(400)
|
||||
|
||||
|
||||
def test_response_schema_404() -> None:
|
||||
"""
|
||||
must generate response schema with 404 error
|
||||
"""
|
||||
schema = _response_schema(None, error_404_description="description")
|
||||
assert schema.pop(404)
|
||||
|
||||
|
||||
def test_response_schema_200() -> None:
|
||||
"""
|
||||
must generate response schema with 200 response
|
||||
"""
|
||||
schema = _response_schema(LoginSchema)
|
||||
response = schema.pop(200)
|
||||
assert response["schema"] == LoginSchema
|
||||
assert 204 not in schema
|
||||
|
||||
|
||||
def test_response_schema_code() -> None:
|
||||
"""
|
||||
must override status code
|
||||
"""
|
||||
schema = _response_schema(None, response_code=HTTPFound)
|
||||
assert schema.pop(302)
|
||||
assert 204 not in schema
|
||||
|
||||
|
||||
def test_apidocs() -> None:
|
||||
"""
|
||||
must return decorated function
|
||||
"""
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Unauthorized,
|
||||
)(MagicMock())
|
||||
assert annotated.__apispec__
|
||||
|
||||
|
||||
def test_apidocs_authorization() -> None:
|
||||
"""
|
||||
must return decorated function with authorization details
|
||||
"""
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Full,
|
||||
)(MagicMock())
|
||||
assert any(schema["put_into"] == "cookies" for schema in annotated.__schemas__)
|
||||
|
||||
|
||||
def test_apidocs_match() -> None:
|
||||
"""
|
||||
must return decorated function with match details
|
||||
"""
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Unauthorized,
|
||||
match_schema=LoginSchema,
|
||||
)(MagicMock())
|
||||
assert any(schema["put_into"] == "match_info" for schema in annotated.__schemas__)
|
||||
|
||||
|
||||
def test_apidocs_querystring() -> None:
|
||||
"""
|
||||
must return decorated function with query string details
|
||||
"""
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Unauthorized,
|
||||
query_schema=LoginSchema,
|
||||
)(MagicMock())
|
||||
assert any(schema["put_into"] == "querystring" for schema in annotated.__schemas__)
|
||||
|
||||
|
||||
def test_apidocs_json() -> None:
|
||||
"""
|
||||
must return decorated function with json details
|
||||
"""
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Unauthorized,
|
||||
body_schema=LoginSchema,
|
||||
)(MagicMock())
|
||||
assert any(schema["put_into"] == "json" for schema in annotated.__schemas__)
|
||||
|
||||
|
||||
def test_apidocs_form() -> None:
|
||||
"""
|
||||
must return decorated function with generic body details
|
||||
"""
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Unauthorized,
|
||||
body_schema=LoginSchema,
|
||||
body_location="form",
|
||||
)(MagicMock())
|
||||
assert any(schema["put_into"] == "form" for schema in annotated.__schemas__)
|
||||
|
||||
|
||||
def test_apidocs_import_error(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return same function if no apispec module available
|
||||
"""
|
||||
mocker.patch.object(decorators, "aiohttp_apispec", None)
|
||||
mock = MagicMock()
|
||||
|
||||
annotated = apidocs(
|
||||
tags=["tags"],
|
||||
summary="summary",
|
||||
description="description",
|
||||
permission=UserAccess.Unauthorized,
|
||||
)(mock)
|
||||
assert annotated == mock
|
@ -4,7 +4,8 @@ from aiohttp.web import Application
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman import __version__
|
||||
from ahriman.web.apispec import _info, _security, _servers, setup_apispec
|
||||
from ahriman.web.apispec import info
|
||||
from ahriman.web.apispec.info import _info, _security, _servers, setup_apispec
|
||||
from ahriman.web.keys import ConfigurationKey
|
||||
|
||||
|
||||
@ -47,7 +48,7 @@ def test_setup_apispec(application: Application, mocker: MockerFixture) -> None:
|
||||
must set api specification
|
||||
"""
|
||||
apispec_mock = mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
|
||||
setup_apispec(application)
|
||||
assert setup_apispec(application)
|
||||
apispec_mock.assert_called_once_with(
|
||||
application,
|
||||
url="/api-docs/swagger.json",
|
||||
@ -56,3 +57,11 @@ def test_setup_apispec(application: Application, mocker: MockerFixture) -> None:
|
||||
servers=pytest.helpers.anyvar(int),
|
||||
security=pytest.helpers.anyvar(int),
|
||||
)
|
||||
|
||||
|
||||
def test_setup_apispec_import_error(application: Application, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return none if apispec is not available
|
||||
"""
|
||||
mocker.patch.object(info, "aiohttp_apispec", None)
|
||||
assert setup_apispec(application) is None
|
@ -129,7 +129,7 @@ def application(configuration: Configuration, spawner: Spawn, database: SQLite,
|
||||
configuration.set_option("web", "port", "8080")
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", False)
|
||||
mocker.patch.object(helpers, "aiohttp_security", None)
|
||||
_, repository_id = configuration.check_loaded()
|
||||
|
||||
return setup_server(configuration, spawner, [repository_id])
|
||||
@ -155,7 +155,6 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
|
||||
configuration.set_option("web", "port", "8080")
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", True)
|
||||
_, repository_id = configuration.check_loaded()
|
||||
application = setup_server(configuration, spawner, [repository_id])
|
||||
|
||||
@ -165,31 +164,6 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
|
||||
return application
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def application_with_debug(configuration: Configuration, spawner: Spawn, database: SQLite,
|
||||
mocker: MockerFixture) -> Application:
|
||||
"""
|
||||
application fixture with debug enabled
|
||||
|
||||
Args:
|
||||
configuration(Configuration): configuration fixture
|
||||
spawner(Spawn): spawner fixture
|
||||
database(SQLite): database fixture
|
||||
mocker(MockerFixture): mocker object
|
||||
|
||||
Returns:
|
||||
Application: application test instance
|
||||
"""
|
||||
configuration.set_option("web", "debug", "yes")
|
||||
configuration.set_option("web", "port", "8080")
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
|
||||
mocker.patch.object(helpers, "_has_aiohttp_security", False)
|
||||
_, repository_id = configuration.check_loaded()
|
||||
|
||||
return setup_server(configuration, spawner, [repository_id])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(application: Application, event_loop: BaseEventLoop, aiohttp_client: Any,
|
||||
mocker: MockerFixture) -> TestClient:
|
||||
|
@ -1,7 +1,9 @@
|
||||
import pytest
|
||||
|
||||
from aiohttp.test_utils import TestClient
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.api.docs import DocsView
|
||||
|
||||
@ -15,6 +17,28 @@ async def test_get_permission() -> None:
|
||||
assert await DocsView.get_permission(request) == UserAccess.Unauthorized
|
||||
|
||||
|
||||
def test_routes() -> None:
|
||||
"""
|
||||
must return correct routes
|
||||
"""
|
||||
assert DocsView.ROUTES == ["/api-docs"]
|
||||
|
||||
|
||||
def test_routes_dynamic(configuration: Configuration) -> None:
|
||||
"""
|
||||
must correctly return docs route
|
||||
"""
|
||||
assert DocsView.ROUTES == DocsView.routes(configuration)
|
||||
|
||||
|
||||
def test_routes_dynamic_not_found(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must disable docs route if no apispec package found
|
||||
"""
|
||||
mocker.patch("ahriman.web.views.api.docs.aiohttp_apispec", None)
|
||||
assert DocsView.routes(configuration) == []
|
||||
|
||||
|
||||
async def test_get(client: TestClient) -> None:
|
||||
"""
|
||||
must generate api-docs correctly
|
||||
|
@ -4,6 +4,7 @@ from aiohttp.test_utils import TestClient
|
||||
from pytest_mock import MockerFixture
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.api.swagger import SwaggerView
|
||||
|
||||
@ -86,6 +87,28 @@ async def test_get_permission() -> None:
|
||||
assert await SwaggerView.get_permission(request) == UserAccess.Unauthorized
|
||||
|
||||
|
||||
def test_routes() -> None:
|
||||
"""
|
||||
must return correct routes
|
||||
"""
|
||||
assert SwaggerView.ROUTES == ["/api-docs/swagger.json"]
|
||||
|
||||
|
||||
def test_routes_dynamic(configuration: Configuration) -> None:
|
||||
"""
|
||||
must correctly return openapi url
|
||||
"""
|
||||
assert SwaggerView.ROUTES == SwaggerView.routes(configuration)
|
||||
|
||||
|
||||
def test_routes_dynamic_not_found(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must disable openapi route if no apispec package found
|
||||
"""
|
||||
mocker.patch("ahriman.web.views.api.swagger.aiohttp_apispec", None)
|
||||
assert SwaggerView.routes(configuration) == []
|
||||
|
||||
|
||||
async def test_get(client: TestClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate api-docs correctly
|
||||
|
@ -8,6 +8,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import AsyncMock, MagicMock, call as MockCall
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.v1.service.upload import UploadView
|
||||
@ -29,6 +30,21 @@ def test_routes() -> None:
|
||||
assert UploadView.ROUTES == ["/api/v1/service/upload"]
|
||||
|
||||
|
||||
def test_routes_dynamic(configuration: Configuration) -> None:
|
||||
"""
|
||||
must correctly return upload url
|
||||
"""
|
||||
assert UploadView.ROUTES == UploadView.routes(configuration)
|
||||
|
||||
|
||||
def test_routes_dynamic_not_found(configuration: Configuration) -> None:
|
||||
"""
|
||||
must disable upload route if option is not set
|
||||
"""
|
||||
configuration.set_option("web", "enable_archive_upload", "no")
|
||||
assert UploadView.routes(configuration) == []
|
||||
|
||||
|
||||
async def test_save_file(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly save file
|
||||
@ -134,20 +150,6 @@ async def test_post_with_sig(client: TestClient, repository_paths: RepositoryPat
|
||||
])
|
||||
|
||||
|
||||
async def test_post_not_found(client: TestClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must return 404 if request was disabled
|
||||
"""
|
||||
mocker.patch("ahriman.core.configuration.Configuration.getboolean", return_value=False)
|
||||
data = FormData()
|
||||
data.add_field("package", BytesIO(b"content"), filename="filename", content_type="application/octet-stream")
|
||||
response_schema = pytest.helpers.schema_response(UploadView.post, code=404)
|
||||
|
||||
response = await client.post("/api/v1/service/upload", data=data)
|
||||
assert response.status == 404
|
||||
assert not response_schema.validate(await response.json())
|
||||
|
||||
|
||||
async def test_post_not_multipart(client: TestClient) -> None:
|
||||
"""
|
||||
must return 400 on invalid payload
|
||||
|
@ -81,7 +81,7 @@ async def test_get(client_with_oauth_auth: TestClient, mocker: MockerFixture) ->
|
||||
oauth.known_username.return_value = True
|
||||
oauth.enabled = False # lol
|
||||
oauth.max_age = 60
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
||||
request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring")
|
||||
|
||||
payload = {"code": "code"}
|
||||
@ -102,7 +102,7 @@ async def test_get_unauthorized(client_with_oauth_auth: TestClient, mocker: Mock
|
||||
oauth = client_with_oauth_auth.app[AuthKey]
|
||||
oauth.known_username.return_value = False
|
||||
oauth.max_age = 60
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
||||
response_schema = pytest.helpers.schema_response(LoginView.post, code=401)
|
||||
|
||||
response = await client_with_oauth_auth.get(
|
||||
@ -118,7 +118,7 @@ async def test_post(client_with_auth: TestClient, user: User, mocker: MockerFixt
|
||||
must log in user correctly
|
||||
"""
|
||||
payload = {"username": user.username, "password": user.password}
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
||||
request_schema = pytest.helpers.schema_request(LoginView.post)
|
||||
|
||||
assert not request_schema.validate(payload)
|
||||
@ -148,7 +148,7 @@ async def test_post_unauthorized(client_with_auth: TestClient, user: User, mocke
|
||||
response_schema = pytest.helpers.schema_response(LoginView.post, code=401)
|
||||
|
||||
payload = {"username": user.username, "password": ""}
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
||||
|
||||
response = await client_with_auth.post("/api/v1/login", json=payload, headers={"accept": "application/json"})
|
||||
assert response.status == 401
|
||||
@ -161,7 +161,7 @@ async def test_post_invalid_json(client_with_auth: TestClient, mocker: MockerFix
|
||||
must return unauthorized on invalid payload
|
||||
"""
|
||||
response_schema = pytest.helpers.schema_response(LoginView.post, code=400)
|
||||
remember_mock = mocker.patch("aiohttp_security.remember")
|
||||
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
||||
|
||||
response = await client_with_auth.post("/api/v1/login")
|
||||
assert response.status == 400
|
||||
|
@ -28,8 +28,8 @@ async def test_post(client_with_auth: TestClient, mocker: MockerFixture) -> None
|
||||
"""
|
||||
must log out user correctly
|
||||
"""
|
||||
mocker.patch("aiohttp_security.check_authorized")
|
||||
forget_mock = mocker.patch("aiohttp_security.forget")
|
||||
mocker.patch("ahriman.web.views.v1.user.logout.check_authorized")
|
||||
forget_mock = mocker.patch("ahriman.web.views.v1.user.logout.forget")
|
||||
|
||||
response = await client_with_auth.post("/api/v1/logout")
|
||||
assert response.ok
|
||||
@ -40,8 +40,8 @@ async def test_post_unauthorized(client_with_auth: TestClient, mocker: MockerFix
|
||||
"""
|
||||
must raise exception if unauthorized
|
||||
"""
|
||||
mocker.patch("aiohttp_security.check_authorized", side_effect=HTTPUnauthorized())
|
||||
forget_mock = mocker.patch("aiohttp_security.forget")
|
||||
mocker.patch("ahriman.web.views.v1.user.logout.check_authorized", side_effect=HTTPUnauthorized())
|
||||
forget_mock = mocker.patch("ahriman.web.views.v1.user.logout.forget")
|
||||
response_schema = pytest.helpers.schema_response(LogoutView.post, code=401)
|
||||
|
||||
response = await client_with_auth.post("/api/v1/logout", headers={"accept": "application/json"})
|
||||
|
Reference in New Issue
Block a user