mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-18 00:09:56 +00:00
provide service api endpoints
This commit is contained in:
@ -19,13 +19,17 @@
|
|||||||
#
|
#
|
||||||
from aiohttp.web import Application
|
from aiohttp.web import Application
|
||||||
|
|
||||||
from ahriman.web.views.ahriman import AhrimanView
|
|
||||||
from ahriman.web.views.index import IndexView
|
from ahriman.web.views.index import IndexView
|
||||||
from ahriman.web.views.login import LoginView
|
from ahriman.web.views.service.add import AddView
|
||||||
from ahriman.web.views.logout import LogoutView
|
from ahriman.web.views.service.remove import RemoveView
|
||||||
from ahriman.web.views.package import PackageView
|
from ahriman.web.views.service.search import SearchView
|
||||||
from ahriman.web.views.packages import PackagesView
|
from ahriman.web.views.service.update import UpdateView
|
||||||
from ahriman.web.views.status import StatusView
|
from ahriman.web.views.status.ahriman import AhrimanView
|
||||||
|
from ahriman.web.views.status.package import PackageView
|
||||||
|
from ahriman.web.views.status.packages import PackagesView
|
||||||
|
from ahriman.web.views.status.status import StatusView
|
||||||
|
from ahriman.web.views.user.login import LoginView
|
||||||
|
from ahriman.web.views.user.logout import LogoutView
|
||||||
|
|
||||||
|
|
||||||
def setup_routes(application: Application) -> None:
|
def setup_routes(application: Application) -> None:
|
||||||
@ -37,8 +41,13 @@ def setup_routes(application: Application) -> None:
|
|||||||
GET / get build status page
|
GET / get build status page
|
||||||
GET /index.html same as above
|
GET /index.html same as above
|
||||||
|
|
||||||
POST /user-api/v1/login login to service
|
POST /service-api/v1/add add new packages to repository
|
||||||
POST /user-api/v1/logout logout from service
|
|
||||||
|
POST /service-api/v1/remove remove existing package from repository
|
||||||
|
|
||||||
|
GET /service-api/v1/search search for substring in AUR
|
||||||
|
|
||||||
|
POST /service-api/v1/update update existing package in repository
|
||||||
|
|
||||||
GET /status-api/v1/ahriman get current service status
|
GET /status-api/v1/ahriman get current service status
|
||||||
POST /status-api/v1/ahriman update service status
|
POST /status-api/v1/ahriman update service status
|
||||||
@ -52,13 +61,21 @@ def setup_routes(application: Application) -> None:
|
|||||||
|
|
||||||
GET /status-api/v1/status get web service status itself
|
GET /status-api/v1/status get web service status itself
|
||||||
|
|
||||||
|
POST /user-api/v1/login login to service
|
||||||
|
POST /user-api/v1/logout logout from service
|
||||||
|
|
||||||
:param application: web application instance
|
:param application: web application instance
|
||||||
"""
|
"""
|
||||||
application.router.add_get("/", IndexView, allow_head=True)
|
application.router.add_get("/", IndexView, allow_head=True)
|
||||||
application.router.add_get("/index.html", IndexView, allow_head=True)
|
application.router.add_get("/index.html", IndexView, allow_head=True)
|
||||||
|
|
||||||
application.router.add_post("/user-api/v1/login", LoginView)
|
application.router.add_post("/service-api/v1/add", AddView)
|
||||||
application.router.add_post("/user-api/v1/logout", LogoutView)
|
|
||||||
|
application.router.add_post("/service-api/v1/remove", RemoveView)
|
||||||
|
|
||||||
|
application.router.add_get("/service-api/v1/search", SearchView, allow_head=False)
|
||||||
|
|
||||||
|
application.router.add_post("/service-api/v1/update", UpdateView)
|
||||||
|
|
||||||
application.router.add_get("/status-api/v1/ahriman", AhrimanView, allow_head=True)
|
application.router.add_get("/status-api/v1/ahriman", AhrimanView, allow_head=True)
|
||||||
application.router.add_post("/status-api/v1/ahriman", AhrimanView)
|
application.router.add_post("/status-api/v1/ahriman", AhrimanView)
|
||||||
@ -71,3 +88,6 @@ def setup_routes(application: Application) -> None:
|
|||||||
application.router.add_post("/status-api/v1/packages/{package}", PackageView)
|
application.router.add_post("/status-api/v1/packages/{package}", PackageView)
|
||||||
|
|
||||||
application.router.add_get("/status-api/v1/status", StatusView, allow_head=True)
|
application.router.add_get("/status-api/v1/status", StatusView, allow_head=True)
|
||||||
|
|
||||||
|
application.router.add_post("/user-api/v1/login", LoginView)
|
||||||
|
application.router.add_post("/user-api/v1/logout", LogoutView)
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from aiohttp.web import View
|
from aiohttp.web import View
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from ahriman.core.auth.auth import Auth
|
from ahriman.core.auth.auth import Auth
|
||||||
from ahriman.core.spawn import Spawn
|
from ahriman.core.spawn import Spawn
|
||||||
@ -54,20 +54,22 @@ class BaseView(View):
|
|||||||
validator: Auth = self.request.app["validator"]
|
validator: Auth = self.request.app["validator"]
|
||||||
return validator
|
return validator
|
||||||
|
|
||||||
async def extract_data(self) -> Dict[str, Any]:
|
async def extract_data(self, list_keys: Optional[List[str]] = None) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
extract json data from either json or form data
|
extract json data from either json or form data
|
||||||
|
:param list_keys: optional list of keys which must be forced to list from form data
|
||||||
:return: raw json object or form data converted to json
|
:return: raw json object or form data converted to json
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
json: Dict[str, Any] = await self.request.json()
|
json: Dict[str, Any] = await self.request.json()
|
||||||
return json
|
return json
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return await self.data_as_json()
|
return await self.data_as_json(list_keys or [])
|
||||||
|
|
||||||
async def data_as_json(self) -> Dict[str, Any]:
|
async def data_as_json(self, list_keys: List[str]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
extract form data and convert it to json object
|
extract form data and convert it to json object
|
||||||
|
:param list_keys: list of keys which must be forced to list from form data
|
||||||
:return: form data converted to json. In case if a key is found multiple times it will be returned as list
|
:return: form data converted to json. In case if a key is found multiple times it will be returned as list
|
||||||
"""
|
"""
|
||||||
raw = await self.request.post()
|
raw = await self.request.post()
|
||||||
@ -77,6 +79,8 @@ class BaseView(View):
|
|||||||
json[key].append(value)
|
json[key].append(value)
|
||||||
elif key in json:
|
elif key in json:
|
||||||
json[key] = [json[key], value]
|
json[key] = [json[key], value]
|
||||||
|
elif key in list_keys:
|
||||||
|
json[key] = [value]
|
||||||
else:
|
else:
|
||||||
json[key] = value
|
json[key] = value
|
||||||
return json
|
return json
|
||||||
|
19
src/ahriman/web/views/service/__init__.py
Normal file
19
src/ahriman/web/views/service/__init__.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
52
src/ahriman/web/views/service/add.py
Normal file
52
src/ahriman/web/views/service/add.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from aiohttp.web import HTTPFound, Response, json_response
|
||||||
|
|
||||||
|
from ahriman.web.views.base import BaseView
|
||||||
|
|
||||||
|
|
||||||
|
class AddView(BaseView):
|
||||||
|
"""
|
||||||
|
add package web view
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def post(self) -> Response:
|
||||||
|
"""
|
||||||
|
add new package
|
||||||
|
|
||||||
|
JSON body must be supplied, the following model is used:
|
||||||
|
{
|
||||||
|
"packages": "ahriman", # either list of packages or package name as in AUR
|
||||||
|
"build_now": true # optional flag which runs build
|
||||||
|
}
|
||||||
|
|
||||||
|
:return: redirect to main page on success
|
||||||
|
"""
|
||||||
|
data = await self.extract_data(["packages"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
now = data.get("build_now") or False
|
||||||
|
packages = data["packages"]
|
||||||
|
except Exception as e:
|
||||||
|
return json_response(text=str(e), status=400)
|
||||||
|
|
||||||
|
self.spawner.packages_add(packages, now)
|
||||||
|
|
||||||
|
return HTTPFound("/")
|
50
src/ahriman/web/views/service/remove.py
Normal file
50
src/ahriman/web/views/service/remove.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from aiohttp.web import HTTPFound, Response, json_response
|
||||||
|
|
||||||
|
from ahriman.web.views.base import BaseView
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveView(BaseView):
|
||||||
|
"""
|
||||||
|
remove package web view
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def post(self) -> Response:
|
||||||
|
"""
|
||||||
|
remove existing packages
|
||||||
|
|
||||||
|
JSON body must be supplied, the following model is used:
|
||||||
|
{
|
||||||
|
"packages": "ahriman", # either list of packages or package name
|
||||||
|
}
|
||||||
|
|
||||||
|
:return: redirect to main page on success
|
||||||
|
"""
|
||||||
|
data = await self.extract_data(["packages"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
packages = data["packages"]
|
||||||
|
except Exception as e:
|
||||||
|
return json_response(text=str(e), status=400)
|
||||||
|
|
||||||
|
self.spawner.packages_remove(packages)
|
||||||
|
|
||||||
|
return HTTPFound("/")
|
48
src/ahriman/web/views/service/search.py
Normal file
48
src/ahriman/web/views/service/search.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
import aur # type: ignore
|
||||||
|
|
||||||
|
from aiohttp.web import Response, json_response
|
||||||
|
from typing import Iterator
|
||||||
|
|
||||||
|
from ahriman.web.views.base import BaseView
|
||||||
|
|
||||||
|
|
||||||
|
class SearchView(BaseView):
|
||||||
|
"""
|
||||||
|
AUR search web view
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def get(self) -> Response:
|
||||||
|
"""
|
||||||
|
search packages in AUR
|
||||||
|
|
||||||
|
search string (non empty) must be supplied as `for` parameter
|
||||||
|
|
||||||
|
:return: 200 with found package bases sorted by name
|
||||||
|
"""
|
||||||
|
search: Iterator[str] = filter(lambda s: len(s) > 3, self.request.query.getall("for", default=[]))
|
||||||
|
search_string = " ".join(search)
|
||||||
|
|
||||||
|
if not search_string:
|
||||||
|
return json_response(text="Search string must not be empty", status=400)
|
||||||
|
packages = aur.search(search_string)
|
||||||
|
|
||||||
|
return json_response(sorted(package.package_base for package in packages))
|
50
src/ahriman/web/views/service/update.py
Normal file
50
src/ahriman/web/views/service/update.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from aiohttp.web import HTTPFound, Response, json_response
|
||||||
|
|
||||||
|
from ahriman.web.views.base import BaseView
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateView(BaseView):
|
||||||
|
"""
|
||||||
|
update package web view
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def post(self) -> Response:
|
||||||
|
"""
|
||||||
|
update existing packages
|
||||||
|
|
||||||
|
JSON body must be supplied, the following model is used:
|
||||||
|
{
|
||||||
|
"packages": "ahriman", # either list of packages or package name
|
||||||
|
}
|
||||||
|
|
||||||
|
:return: redirect to main page on success
|
||||||
|
"""
|
||||||
|
data = await self.extract_data(["packages"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
packages = data["packages"]
|
||||||
|
except Exception as e:
|
||||||
|
return json_response(text=str(e), status=400)
|
||||||
|
|
||||||
|
self.spawner.packages_update(packages)
|
||||||
|
|
||||||
|
return HTTPFound("/")
|
19
src/ahriman/web/views/status/__init__.py
Normal file
19
src/ahriman/web/views/status/__init__.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response
|
from aiohttp.web import HTTPNoContent, Response, json_response
|
||||||
|
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
from ahriman.web.views.base import BaseView
|
from ahriman.web.views.base import BaseView
|
||||||
@ -51,7 +51,7 @@ class AhrimanView(BaseView):
|
|||||||
try:
|
try:
|
||||||
status = BuildStatusEnum(data["status"])
|
status = BuildStatusEnum(data["status"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPBadRequest(text=str(e))
|
return json_response(text=str(e), status=400)
|
||||||
|
|
||||||
self.service.update_self(status)
|
self.service.update_self(status)
|
||||||
|
|
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from aiohttp.web import HTTPBadRequest, HTTPNoContent, HTTPNotFound, Response, json_response
|
from aiohttp.web import HTTPNoContent, HTTPNotFound, Response, json_response
|
||||||
|
|
||||||
from ahriman.core.exceptions import UnknownPackage
|
from ahriman.core.exceptions import UnknownPackage
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
@ -80,11 +80,11 @@ class PackageView(BaseView):
|
|||||||
package = Package.from_json(data["package"]) if "package" in data else None
|
package = Package.from_json(data["package"]) if "package" in data else None
|
||||||
status = BuildStatusEnum(data["status"])
|
status = BuildStatusEnum(data["status"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPBadRequest(text=str(e))
|
return json_response(text=str(e), status=400)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.service.update(base, status, package)
|
self.service.update(base, status, package)
|
||||||
except UnknownPackage:
|
except UnknownPackage:
|
||||||
raise HTTPBadRequest(text=f"Package {base} is unknown, but no package body set")
|
return json_response(text=f"Package {base} is unknown, but no package body set", status=400)
|
||||||
|
|
||||||
return HTTPNoContent()
|
return HTTPNoContent()
|
19
src/ahriman/web/views/user/__init__.py
Normal file
19
src/ahriman/web/views/user/__init__.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
@ -1,5 +1,4 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import aur
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
@ -8,7 +7,6 @@ from ahriman.application.ahriman import _parser
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.lock import Lock
|
from ahriman.application.lock import Lock
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.models.package import Package
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -32,31 +30,6 @@ def args() -> argparse.Namespace:
|
|||||||
return argparse.Namespace(lock=None, force=False, unsafe=False, no_report=True)
|
return argparse.Namespace(lock=None, force=False, unsafe=False, no_report=True)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def aur_package_ahriman(package_ahriman: Package) -> aur.Package:
|
|
||||||
"""
|
|
||||||
fixture for AUR package
|
|
||||||
:param package_ahriman: package fixture
|
|
||||||
:return: AUR package test instance
|
|
||||||
"""
|
|
||||||
return aur.Package(
|
|
||||||
num_votes=None,
|
|
||||||
description=package_ahriman.packages[package_ahriman.base].description,
|
|
||||||
url_path=package_ahriman.web_url,
|
|
||||||
last_modified=None,
|
|
||||||
name=package_ahriman.base,
|
|
||||||
out_of_date=None,
|
|
||||||
id=None,
|
|
||||||
first_submitted=None,
|
|
||||||
maintainer=None,
|
|
||||||
version=package_ahriman.version,
|
|
||||||
license=package_ahriman.packages[package_ahriman.base].licenses,
|
|
||||||
url=None,
|
|
||||||
package_base=package_ahriman.base,
|
|
||||||
package_base_id=None,
|
|
||||||
category_id=None)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
|
def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
|
||||||
"""
|
"""
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import aur
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -46,6 +47,31 @@ def anyvar(cls: Type[T], strict: bool = False) -> T:
|
|||||||
|
|
||||||
|
|
||||||
# generic fixtures
|
# generic fixtures
|
||||||
|
@pytest.fixture
|
||||||
|
def aur_package_ahriman(package_ahriman: Package) -> aur.Package:
|
||||||
|
"""
|
||||||
|
fixture for AUR package
|
||||||
|
:param package_ahriman: package fixture
|
||||||
|
:return: AUR package test instance
|
||||||
|
"""
|
||||||
|
return aur.Package(
|
||||||
|
num_votes=None,
|
||||||
|
description=package_ahriman.packages[package_ahriman.base].description,
|
||||||
|
url_path=package_ahriman.web_url,
|
||||||
|
last_modified=None,
|
||||||
|
name=package_ahriman.base,
|
||||||
|
out_of_date=None,
|
||||||
|
id=None,
|
||||||
|
first_submitted=None,
|
||||||
|
maintainer=None,
|
||||||
|
version=package_ahriman.version,
|
||||||
|
license=package_ahriman.packages[package_ahriman.base].licenses,
|
||||||
|
url=None,
|
||||||
|
package_base=package_ahriman.base,
|
||||||
|
package_base_id=None,
|
||||||
|
category_id=None)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def auth(configuration: Configuration) -> Auth:
|
def auth(configuration: Configuration) -> Auth:
|
||||||
"""
|
"""
|
||||||
|
35
tests/ahriman/web/views/service/test_views_service_add.py
Normal file
35
tests/ahriman/web/views/service/test_views_service_add.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from aiohttp.test_utils import TestClient
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call post request correctly
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_add")
|
||||||
|
response = await client.post("/service-api/v1/add", json={"packages": ["ahriman"]})
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
add_mock.assert_called_with(["ahriman"], False)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post_now(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call post and run build
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_add")
|
||||||
|
response = await client.post("/service-api/v1/add", json={"packages": ["ahriman"], "build_now": True})
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
add_mock.assert_called_with(["ahriman"], True)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post_exception(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must raise exception on missing packages payload
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_add")
|
||||||
|
response = await client.post("/service-api/v1/add")
|
||||||
|
|
||||||
|
assert response.status == 400
|
||||||
|
add_mock.assert_not_called()
|
24
tests/ahriman/web/views/service/test_views_service_remove.py
Normal file
24
tests/ahriman/web/views/service/test_views_service_remove.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from aiohttp.test_utils import TestClient
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call post request correctly
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_remove")
|
||||||
|
response = await client.post("/service-api/v1/remove", json={"packages": ["ahriman"]})
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
add_mock.assert_called_with(["ahriman"])
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post_exception(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must raise exception on missing packages payload
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_remove")
|
||||||
|
response = await client.post("/service-api/v1/remove")
|
||||||
|
|
||||||
|
assert response.status == 400
|
||||||
|
add_mock.assert_not_called()
|
59
tests/ahriman/web/views/service/test_views_service_search.py
Normal file
59
tests/ahriman/web/views/service/test_views_service_search.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import aur
|
||||||
|
|
||||||
|
from aiohttp.test_utils import TestClient
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get(client: TestClient, aur_package_ahriman: aur.Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call get request correctly
|
||||||
|
"""
|
||||||
|
mocker.patch("aur.search", return_value=[aur_package_ahriman])
|
||||||
|
response = await client.get("/service-api/v1/search", params={"for": "ahriman"})
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
assert await response.json() == ["ahriman"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_exception(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must raise 400 on empty search string
|
||||||
|
"""
|
||||||
|
search_mock = mocker.patch("aur.search")
|
||||||
|
response = await client.get("/service-api/v1/search")
|
||||||
|
|
||||||
|
assert response.status == 400
|
||||||
|
search_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_join(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must join search args with space
|
||||||
|
"""
|
||||||
|
search_mock = mocker.patch("aur.search")
|
||||||
|
response = await client.get("/service-api/v1/search", params=[("for", "ahriman"), ("for", "maybe")])
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
search_mock.assert_called_with("ahriman maybe")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_join_filter(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must filter search parameters with less than 3 symbols
|
||||||
|
"""
|
||||||
|
search_mock = mocker.patch("aur.search")
|
||||||
|
response = await client.get("/service-api/v1/search", params=[("for", "ah"), ("for", "maybe")])
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
search_mock.assert_called_with("maybe")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_join_filter_empty(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must filter search parameters with less than 3 symbols (empty result)
|
||||||
|
"""
|
||||||
|
search_mock = mocker.patch("aur.search")
|
||||||
|
response = await client.get("/service-api/v1/search", params=[("for", "ah"), ("for", "ma")])
|
||||||
|
|
||||||
|
assert response.status == 400
|
||||||
|
search_mock.assert_not_called()
|
24
tests/ahriman/web/views/service/test_views_service_update.py
Normal file
24
tests/ahriman/web/views/service/test_views_service_update.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from aiohttp.test_utils import TestClient
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call post request correctly
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_update")
|
||||||
|
response = await client.post("/service-api/v1/update", json={"packages": ["ahriman"]})
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
add_mock.assert_called_with(["ahriman"])
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post_exception(client: TestClient, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must raise exception on missing packages payload
|
||||||
|
"""
|
||||||
|
add_mock = mocker.patch("ahriman.core.spawn.Spawn.packages_update")
|
||||||
|
response = await client.post("/service-api/v1/update")
|
||||||
|
|
||||||
|
assert response.status == 400
|
||||||
|
add_mock.assert_not_called()
|
@ -61,9 +61,6 @@ async def test_data_as_json(base: BaseView) -> None:
|
|||||||
"""
|
"""
|
||||||
json = {"key1": "value1", "key2": ["value2", "value3"], "key3": ["value4", "value5", "value6"]}
|
json = {"key1": "value1", "key2": ["value2", "value3"], "key3": ["value4", "value5", "value6"]}
|
||||||
|
|
||||||
async def get_json():
|
|
||||||
raise ValueError()
|
|
||||||
|
|
||||||
async def get_data():
|
async def get_data():
|
||||||
result = MultiDict()
|
result = MultiDict()
|
||||||
for key, values in json.items():
|
for key, values in json.items():
|
||||||
@ -74,5 +71,18 @@ async def test_data_as_json(base: BaseView) -> None:
|
|||||||
result.add(key, values)
|
result.add(key, values)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
base._request = pytest.helpers.request(base.request.app, "", "", json=get_json, data=get_data)
|
base._request = pytest.helpers.request(base.request.app, "", "", data=get_data)
|
||||||
assert await base.data_as_json() == json
|
assert await base.data_as_json([]) == json
|
||||||
|
|
||||||
|
|
||||||
|
async def test_data_as_json_with_list_keys(base: BaseView) -> None:
|
||||||
|
"""
|
||||||
|
must parse multi value form payload with forced list
|
||||||
|
"""
|
||||||
|
json = {"key1": "value1"}
|
||||||
|
|
||||||
|
async def get_data():
|
||||||
|
return json
|
||||||
|
|
||||||
|
base._request = pytest.helpers.request(base.request.app, "", "", data=get_data)
|
||||||
|
assert await base.data_as_json(["key1"]) == {"key1": ["value1"]}
|
Reference in New Issue
Block a user