diff --git a/oarepo_requests/actions/delete_published_record.py b/oarepo_requests/actions/delete_published_record.py index 37dd05bd..68b384c1 100644 --- a/oarepo_requests/actions/delete_published_record.py +++ b/oarepo_requests/actions/delete_published_record.py @@ -11,11 +11,32 @@ from typing import TYPE_CHECKING, Any, override +from ..notifications.builders.delete_published_record import ( + DeletePublishedRecordRequestAcceptNotificationBuilder, + DeletePublishedRecordRequestSubmitNotificationBuilder, +) +from .cascade_events import cancel_requests_on_topic_delete +from .generic import OARepoAcceptAction, OARepoDeclineAction, OARepoSubmitAction + +if TYPE_CHECKING: + from flask_principal import Identity + from invenio_drafts_resources.records import Record + from invenio_requests.customizations import RequestType + +from typing import TYPE_CHECKING, Any + +from invenio_notifications.services.uow import NotificationOp +from invenio_records_resources.services.uow import UnitOfWork from oarepo_runtime.datastreams.utils import get_record_service_for_record from oarepo_runtime.i18n import lazy_gettext as _ -from .cascade_events import cancel_requests_on_topic_delete -from .generic import OARepoAcceptAction, OARepoDeclineAction +from .generic import OARepoAcceptAction, OARepoDeclineAction, OARepoSubmitAction + +if TYPE_CHECKING: + from flask_principal import Identity + from invenio_drafts_resources.records import Record + from invenio_requests.customizations import RequestType + if TYPE_CHECKING: from flask_principal import Identity @@ -24,6 +45,30 @@ from invenio_requests.customizations import RequestType +class DeletePublishedRecordSubmitAction(OARepoSubmitAction): + """Submit action for publishing draft requests.""" + + def apply( + self, + identity: Identity, + request_type: RequestType, + topic: Record, + uow: UnitOfWork, + *args: Any, + **kwargs: Any, + ) -> Record: + """Publish the draft.""" + + uow.register( + NotificationOp( + DeletePublishedRecordRequestSubmitNotificationBuilder.build( + request=self.request + ) + ) + ) + return super().apply(identity, request_type, topic, uow, *args, **kwargs) + + class DeletePublishedRecordAcceptAction(OARepoAcceptAction): """Accept request for deletion of a published record and delete the record.""" @@ -43,6 +88,13 @@ def apply( if not topic_service: raise KeyError(f"topic {topic} service not found") topic_service.delete(identity, topic["id"], *args, uow=uow, **kwargs) + uow.register( + NotificationOp( + DeletePublishedRecordRequestAcceptNotificationBuilder.build( + request=self.request + ) + ) + ) cancel_requests_on_topic_delete(self.request, topic, uow) diff --git a/oarepo_requests/actions/generic.py b/oarepo_requests/actions/generic.py index 30645b18..24f7ea77 100644 --- a/oarepo_requests/actions/generic.py +++ b/oarepo_requests/actions/generic.py @@ -12,11 +12,12 @@ from functools import cached_property from typing import TYPE_CHECKING, Any +from invenio_pidstore.errors import PersistentIdentifierError from invenio_requests.customizations import actions from oarepo_runtime.i18n import lazy_gettext as _ from oarepo_requests.proxies import current_oarepo_requests -from invenio_pidstore.errors import PersistentIdentifierError + if TYPE_CHECKING: from flask_babel.speaklater import LazyString from flask_principal import Identity diff --git a/oarepo_requests/actions/publish_draft.py b/oarepo_requests/actions/publish_draft.py index f866f8a0..fd402e28 100644 --- a/oarepo_requests/actions/publish_draft.py +++ b/oarepo_requests/actions/publish_draft.py @@ -12,10 +12,15 @@ from typing import TYPE_CHECKING, Any from invenio_access.permissions import system_identity +from invenio_notifications.services.uow import NotificationOp from invenio_records_resources.services.uow import RecordCommitOp, UnitOfWork from oarepo_runtime.datastreams.utils import get_record_service_for_record from oarepo_runtime.i18n import lazy_gettext as _ +from ..notifications.builders.publish import ( + PublishDraftRequestAcceptNotificationBuilder, + PublishDraftRequestSubmitNotificationBuilder, +) from .cascade_events import update_topic from .generic import ( AddTopicLinksOnPayloadMixin, @@ -52,6 +57,24 @@ def can_execute(self: RequestAction) -> bool: class PublishDraftSubmitAction(PublishMixin, OARepoSubmitAction): """Submit action for publishing draft requests.""" + def apply( + self, + identity: Identity, + request_type: RequestType, + topic: Record, + uow: UnitOfWork, + *args: Any, + **kwargs: Any, + ) -> Record: + """Publish the draft.""" + + uow.register( + NotificationOp( + PublishDraftRequestSubmitNotificationBuilder.build(request=self.request) + ) + ) + return super().apply(identity, request_type, topic, uow, *args, **kwargs) + class PublishDraftAcceptAction( PublishMixin, AddTopicLinksOnPayloadMixin, OARepoAcceptAction @@ -86,6 +109,11 @@ def apply( identity, id_, *args, uow=uow, expand=False, **kwargs ) update_topic(self.request, topic, published_topic._record, uow) + uow.register( + NotificationOp( + PublishDraftRequestAcceptNotificationBuilder.build(request=self.request) + ) + ) return super().apply( identity, request_type, published_topic, uow, *args, **kwargs ) diff --git a/oarepo_requests/config.py b/oarepo_requests/config.py index 977f3485..7b36fccc 100644 --- a/oarepo_requests/config.py +++ b/oarepo_requests/config.py @@ -22,6 +22,10 @@ RequestIdentityComponent, WorkflowTransitionComponent, ) +from oarepo_requests.notifications.generators import ( + GroupEmailRecipient, + UserEmailRecipient, +) from oarepo_requests.resolvers.ui import ( AutoApproveUIEntityResolver, FallbackEntityReferenceUIResolver, @@ -96,3 +100,8 @@ RequestIdentityComponent, ], } + +NOTIFICATION_RECIPIENTS_RESOLVERS = { + "user": {"email": UserEmailRecipient}, + "group": {"email": GroupEmailRecipient}, +} diff --git a/oarepo_requests/ext.py b/oarepo_requests/ext.py index 5fda5c9b..5b4bd772 100644 --- a/oarepo_requests/ext.py +++ b/oarepo_requests/ext.py @@ -14,6 +14,7 @@ from typing import TYPE_CHECKING, Callable import importlib_metadata +from deepmerge import conservative_merger from invenio_base.utils import obj_or_import_string from invenio_requests.proxies import current_events_service @@ -97,8 +98,7 @@ def default_request_receiver( :param creator: Creator of the request. :param data: Payload of the request. """ - # TODO: if the topic is one of the workflow topics, use the workflow to determine the receiver - # otherwise use the default receiver + return obj_or_import_string( self.app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"] )( @@ -214,6 +214,13 @@ def init_config(self, app: Flask) -> None: if event_type not in app_registered_event_types: app_registered_event_types.append(event_type) + app_registered_event_types = app.config.setdefault( + "NOTIFICATION_RECIPIENTS_RESOLVERS", {} + ) + app.config["NOTIFICATION_RECIPIENTS_RESOLVERS"] = conservative_merger.merge( + app_registered_event_types, config.NOTIFICATION_RECIPIENTS_RESOLVERS + ) + def api_finalize_app(app: Flask) -> None: """Finalize app.""" @@ -240,3 +247,7 @@ def finalize_app(app: Flask) -> None: # but imo this is better than entrypoints for type in app.config["REQUESTS_REGISTERED_EVENT_TYPES"]: current_event_type_registry.register_type(type) + + ext.notification_recipients_resolvers_registry = app.config[ + "NOTIFICATION_RECIPIENTS_RESOLVERS" + ] diff --git a/oarepo_requests/notifications/__init__.py b/oarepo_requests/notifications/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/oarepo_requests/notifications/builders/__init__.py b/oarepo_requests/notifications/builders/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/oarepo_requests/notifications/builders/delete_published_record.py b/oarepo_requests/notifications/builders/delete_published_record.py new file mode 100644 index 00000000..09e2dafa --- /dev/null +++ b/oarepo_requests/notifications/builders/delete_published_record.py @@ -0,0 +1,18 @@ +from ..generators import EntityRecipient +from .oarepo import OARepoRequestActionNotificationBuilder + + +class DeletePublishedRecordRequestSubmitNotificationBuilder( + OARepoRequestActionNotificationBuilder +): + type = "delete-published-record-request-event.submit" + + recipients = [EntityRecipient(key="request.receiver")] # email only + + +class DeletePublishedRecordRequestAcceptNotificationBuilder( + OARepoRequestActionNotificationBuilder +): + type = "delete-published-record-request-event.accept" + + recipients = [EntityRecipient(key="request.created_by")] diff --git a/oarepo_requests/notifications/builders/oarepo.py b/oarepo_requests/notifications/builders/oarepo.py new file mode 100644 index 00000000..f3a12b77 --- /dev/null +++ b/oarepo_requests/notifications/builders/oarepo.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +from invenio_notifications.backends import EmailNotificationBackend +from invenio_notifications.models import Notification +from invenio_notifications.registry import EntityResolverRegistry +from invenio_notifications.services.builders import NotificationBuilder +from invenio_notifications.services.generators import EntityResolve, UserEmailBackend + +if TYPE_CHECKING: + from invenio_requests.records.api import Request + + +class OARepoUserEmailBackend(UserEmailBackend): + backend_id = EmailNotificationBackend.id + + +class OARepoRequestActionNotificationBuilder(NotificationBuilder): + + @classmethod + def build(cls, request: Request): + """Build notification with context.""" + return Notification( + type=cls.type, + context={ + "request": EntityResolverRegistry.reference_entity(request), + "backend_ids": [ + backend.backend_id for backend in cls.recipient_backends + ], + }, + ) + + context = [ + EntityResolve(key="request"), + ] + + recipient_backends = [OARepoUserEmailBackend()] diff --git a/oarepo_requests/notifications/builders/publish.py b/oarepo_requests/notifications/builders/publish.py new file mode 100644 index 00000000..b71098d1 --- /dev/null +++ b/oarepo_requests/notifications/builders/publish.py @@ -0,0 +1,18 @@ +from ..generators import EntityRecipient +from .oarepo import OARepoRequestActionNotificationBuilder + + +class PublishDraftRequestSubmitNotificationBuilder( + OARepoRequestActionNotificationBuilder +): + type = "publish-draft-request-event.submit" + + recipients = [EntityRecipient(key="request.receiver")] # email only + + +class PublishDraftRequestAcceptNotificationBuilder( + OARepoRequestActionNotificationBuilder +): + type = "publish-draft-request-event.accept" + + recipients = [EntityRecipient(key="request.created_by")] diff --git a/oarepo_requests/notifications/generators.py b/oarepo_requests/notifications/generators.py new file mode 100644 index 00000000..773c266d --- /dev/null +++ b/oarepo_requests/notifications/generators.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +from abc import abstractmethod +from typing import TYPE_CHECKING + +from invenio_notifications.models import Recipient +from invenio_notifications.services.generators import RecipientGenerator +from invenio_records.dictutils import dict_lookup +from invenio_requests.proxies import current_requests + +from oarepo_requests.proxies import current_notification_recipients_resolvers_registry + +if TYPE_CHECKING: + from typing import Any + + from invenio_notifications.models import Notification + + +class EntityRecipient(RecipientGenerator): + """Recipient generator working as handler for generic entity.""" + + def __init__(self, key: str): + self.key = key + + def __call__(self, notification: Notification, recipients: dict[str, Recipient]): + """""" + backend_ids = notification.context["backend_ids"] + entity_ref = dict_lookup(notification.context, self.key) + entity_type = list(entity_ref.keys())[0] + for backend_id in backend_ids: + generator = current_notification_recipients_resolvers_registry[entity_type][ + backend_id + ](entity_ref) + generator(notification, recipients) + + +class SpecificEntityRecipient(RecipientGenerator): + """Superclass for implementations of recipient generators for specific entities.""" + + def __init__(self, key): + self.key = key # todo this is entity_reference, not path to entity as EntityRecipient, might be confusing + + def __call__(self, notification: Notification, recipients: dict[str, Recipient]): + entity = self._resolve_entity() + recipients.update(self._get_recipients(entity)) + return recipients + + @abstractmethod + def _get_recipients(self, entity: Any) -> dict[str, Recipient]: + raise NotImplementedError() + + def _resolve_entity(self) -> Any: + entity_type = list(self.key)[0] + registry = current_requests.entity_resolvers_registry + + registered_resolvers = registry._registered_types + resolver = registered_resolvers.get(entity_type) + proxy = resolver.get_entity_proxy(self.key) + entity = proxy.resolve() + return entity + + +class UserEmailRecipient(SpecificEntityRecipient): + """User email recipient generator for a notification.""" + + def _get_recipients(self, entity: Any) -> dict[str, Recipient]: + return {entity.email: Recipient(data={"email": entity.email})} + + +class GroupEmailRecipient(SpecificEntityRecipient): + """Recipient generator returning emails of the members of the recipient group""" + + def _get_recipients(self, entity: Any) -> dict[str, Recipient]: + return { + user.email: Recipient(data={"email": user.email}) + for user in entity.users.all() + } diff --git a/oarepo_requests/proxies.py b/oarepo_requests/proxies.py index 2365876a..4e60399c 100644 --- a/oarepo_requests/proxies.py +++ b/oarepo_requests/proxies.py @@ -28,3 +28,9 @@ current_oarepo_requests_resource: OARepoRequestsResource = LocalProxy( # type: ignore lambda: current_app.extensions["oarepo-requests"].requests_resource ) + +current_notification_recipients_resolvers_registry = LocalProxy( # type: ignore + lambda: current_app.extensions[ + "oarepo-requests" + ].notification_recipients_resolvers_registry +) diff --git a/oarepo_requests/resolvers/interface.py b/oarepo_requests/resolvers/interface.py index 980f3029..ef66298c 100644 --- a/oarepo_requests/resolvers/interface.py +++ b/oarepo_requests/resolvers/interface.py @@ -1,15 +1,17 @@ from __future__ import annotations -from typing import Any, TYPE_CHECKING +import logging +from typing import TYPE_CHECKING, Any from invenio_pidstore.errors import PersistentIdentifierError from oarepo_requests.resolvers.ui import resolve -import logging + if TYPE_CHECKING: from invenio_requests.records import Request log = logging.getLogger(__name__) + # todo consider - we are not using this strictly in the ui context - so how should we separate these things in the future def resolve_entity(entity: str, obj: Request, ctx: dict[str, Any]) -> dict: """Resolve the entity and put it into the context cache. diff --git a/oarepo_requests/resolvers/ui.py b/oarepo_requests/resolvers/ui.py index d994e968..7022d0d4 100644 --- a/oarepo_requests/resolvers/ui.py +++ b/oarepo_requests/resolvers/ui.py @@ -64,16 +64,14 @@ def resolve(identity: Identity, reference: dict[str, str]) -> UIResolvedReferenc entity_resolvers = current_oarepo_requests.entity_reference_ui_resolvers - if reference_type == 'multiple': + if reference_type == "multiple": # TODO(mirekys): add test coverage resolved = [] reference_values_list = list(json.loads(reference_value)) for reference_values_item in reference_values_list: for key, value in reference_values_item.items(): - resolved.append(entity_resolvers[key].resolve_one( - identity, value - )) + resolved.append(entity_resolvers[key].resolve_one(identity, value)) elif reference_type in entity_resolvers: resolved = entity_resolvers[reference_type].resolve_one( identity, reference_value diff --git a/oarepo_requests/resources/events/config.py b/oarepo_requests/resources/events/config.py index 076c34e2..9eacc5f0 100644 --- a/oarepo_requests/resources/events/config.py +++ b/oarepo_requests/resources/events/config.py @@ -9,12 +9,12 @@ from __future__ import annotations +import marshmallow as ma from flask_resources import ResponseHandler from invenio_records_resources.services.base.config import ConfiguratorMixin from invenio_requests.resources.events.config import RequestCommentsResourceConfig from oarepo_requests.resources.ui import OARepoRequestEventsUIJSONSerializer -import marshmallow as ma class OARepoRequestsCommentsResourceConfig( @@ -36,9 +36,9 @@ class OARepoRequestsCommentsResourceConfig( @property def request_item_view_args(self): return { - **super().request_item_view_args, - "event_type": ma.fields.Str(), - } + **super().request_item_view_args, + "event_type": ma.fields.Str(), + } @property def response_handlers(self) -> dict[str, ResponseHandler]: diff --git a/oarepo_requests/resources/events/resource.py b/oarepo_requests/resources/events/resource.py index f2bc08ef..87421e6d 100644 --- a/oarepo_requests/resources/events/resource.py +++ b/oarepo_requests/resources/events/resource.py @@ -9,9 +9,6 @@ from __future__ import annotations -from flask_resources import route -from copy import deepcopy - from flask import g from flask_resources import ( from_conf, @@ -81,7 +78,6 @@ def search_extended(self) -> tuple[dict, int]: """Search for comments.""" return super().search() - # list args parser in invenio parses request_id input through UUID instead of Str; does this have any relevance for us? @item_view_args_parser @request_extra_args @@ -89,7 +85,9 @@ def search_extended(self) -> tuple[dict, int]: @response_handler() def create_event(self): """Create a comment.""" - type_ = current_event_type_registry.lookup(resource_requestctx.view_args["event_type"], quiet=True) + type_ = current_event_type_registry.lookup( + resource_requestctx.view_args["event_type"], quiet=True + ) item = self.service.create( identity=g.identity, request_id=resource_requestctx.view_args["request_id"], diff --git a/oarepo_requests/resources/record/types/resource.py b/oarepo_requests/resources/record/types/resource.py index 247263a2..54579c71 100644 --- a/oarepo_requests/resources/record/types/resource.py +++ b/oarepo_requests/resources/record/types/resource.py @@ -25,8 +25,6 @@ from ....services.record.types.service import RecordRequestTypesService from .config import RecordRequestTypesResourceConfig -# TODO: is this class used? - class RecordRequestTypesResource(ErrorHandlersMixin, Resource): """API resource for applicable request types for a record.""" diff --git a/oarepo_requests/services/permissions/generators/conditional.py b/oarepo_requests/services/permissions/generators/conditional.py index 999f0ca2..c0a0d555 100644 --- a/oarepo_requests/services/permissions/generators/conditional.py +++ b/oarepo_requests/services/permissions/generators/conditional.py @@ -17,15 +17,9 @@ from invenio_requests.resolvers.registry import ResolverRegistry from oarepo_runtime.datastreams.utils import get_record_service_for_record from oarepo_workflows.requests import RecipientGeneratorMixin -from oarepo_workflows.requests.generators import ( - IfEventType as WorkflowIfEventType, -) -from oarepo_workflows.requests.generators import ( - IfRequestType as WorkflowIfRequestType, -) -from oarepo_workflows.requests.generators import ( - IfRequestTypeBase, -) +from oarepo_workflows.requests.generators import IfEventType as WorkflowIfEventType +from oarepo_workflows.requests.generators import IfRequestType as WorkflowIfRequestType +from oarepo_workflows.requests.generators import IfRequestTypeBase from sqlalchemy.exc import NoResultFound from typing_extensions import deprecated diff --git a/oarepo_requests/services/record/types/service.py b/oarepo_requests/services/record/types/service.py index a04a4d84..944fa374 100644 --- a/oarepo_requests/services/record/types/service.py +++ b/oarepo_requests/services/record/types/service.py @@ -15,9 +15,7 @@ from invenio_records_resources.services import LinksTemplate from invenio_records_resources.services.base.links import Link -from oarepo_requests.services.results import ( - RequestTypesList, -) +from oarepo_requests.services.results import RequestTypesList from oarepo_requests.services.schema import RequestTypeSchema from oarepo_requests.utils import allowed_request_types_for_record diff --git a/oarepo_requests/templates/semantic-ui/invenio_notifications/delete-published-record-request-event.accept.jinja b/oarepo_requests/templates/semantic-ui/invenio_notifications/delete-published-record-request-event.accept.jinja new file mode 100644 index 00000000..16264c91 --- /dev/null +++ b/oarepo_requests/templates/semantic-ui/invenio_notifications/delete-published-record-request-event.accept.jinja @@ -0,0 +1,20 @@ +{% set access_request = notification.context.request %} +{% set topic = notification.context.request.topic %} +{% set topic_id = notification.context.request.topic.thesis %} + +{%- block subject -%} + {{ _("❗️Delete published request for topic '{topic_id}' accepted").format(topic_id=topic_id) }} +{%- endblock subject -%} + +{%- block html_body -%} + + + + +
{{ _("This is an auto-generated message. To manage notifications, visit your")}} {{ _("account settings")}}.
+{%- endblock html_body -%} + +{%- block plain_body -%} +{{ _("Request for deleting your record '%(topic_id)s' has been accepted.", topic_id=topic_id) }} + +{%- endblock plain_body -%} diff --git a/oarepo_requests/templates/semantic-ui/invenio_notifications/delete-published-record-request-event.submit.jinja b/oarepo_requests/templates/semantic-ui/invenio_notifications/delete-published-record-request-event.submit.jinja new file mode 100644 index 00000000..61ffd59a --- /dev/null +++ b/oarepo_requests/templates/semantic-ui/invenio_notifications/delete-published-record-request-event.submit.jinja @@ -0,0 +1,20 @@ +{% set access_request = notification.context.request %} +{% set topic = notification.context.request.topic %} +{% set topic_id = notification.context.request.topic.thesis %} + +{%- block subject -%} + {{ _("❗️Request for deletion of topic '{topic_id}' waits for your approval").format(topic_id=topic_id) }} +{%- endblock subject -%} + +{%- block html_body -%} + + + + +
{{ _("This is an auto-generated message. To manage notifications, visit your")}} {{ _("account settings")}}.
+{%- endblock html_body -%} + +{%- block plain_body -%} +{{ _("Request for deletion of record '%(topic_id)s' waits for your approval.", topic_id=topic_id) }} + +{%- endblock plain_body -%} diff --git a/oarepo_requests/templates/semantic-ui/invenio_notifications/publish-draft-request-event.accept.jinja b/oarepo_requests/templates/semantic-ui/invenio_notifications/publish-draft-request-event.accept.jinja new file mode 100644 index 00000000..7337315b --- /dev/null +++ b/oarepo_requests/templates/semantic-ui/invenio_notifications/publish-draft-request-event.accept.jinja @@ -0,0 +1,20 @@ +{% set access_request = notification.context.request %} +{% set topic = notification.context.request.topic %} +{% set topic_id = notification.context.request.topic.thesis %} + +{%- block subject -%} + {{ _("❗️Publish request for topic '{topic_id}' accepted").format(topic_id=topic_id) }} +{%- endblock subject -%} + +{%- block html_body -%} + + + + +
{{ _("This is an auto-generated message. To manage notifications, visit your")}} {{ _("account settings")}}.
+{%- endblock html_body -%} + +{%- block plain_body -%} +{{ _("Request for publishing of your record '%(topic_id)s' has been accepted.", topic_id=topic_id) }} + +{%- endblock plain_body -%} diff --git a/oarepo_requests/templates/semantic-ui/invenio_notifications/publish-draft-request-event.submit.jinja b/oarepo_requests/templates/semantic-ui/invenio_notifications/publish-draft-request-event.submit.jinja new file mode 100644 index 00000000..dd759833 --- /dev/null +++ b/oarepo_requests/templates/semantic-ui/invenio_notifications/publish-draft-request-event.submit.jinja @@ -0,0 +1,20 @@ +{% set access_request = notification.context.request %} +{% set topic = notification.context.request.topic %} +{% set topic_id = notification.context.request.topic.thesis %} + +{%- block subject -%} + {{ _("❗️Publish request for topic '{topic_id}' waits for your approval").format(topic_id=topic_id) }} +{%- endblock subject -%} + +{%- block html_body -%} + + + + +
{{ _("This is an auto-generated message. To manage notifications, visit your")}} {{ _("account settings")}}.
+{%- endblock html_body -%} + +{%- block plain_body -%} +{{ _("Publish request for record '%(topic_id)s' waits for your approval.", topic_id=topic_id) }} + +{%- endblock plain_body -%} diff --git a/oarepo_requests/types/delete_published_record.py b/oarepo_requests/types/delete_published_record.py index 59f904ba..b8ac2e63 100644 --- a/oarepo_requests/types/delete_published_record.py +++ b/oarepo_requests/types/delete_published_record.py @@ -18,6 +18,7 @@ from oarepo_requests.actions.delete_published_record import ( DeletePublishedRecordAcceptAction, DeletePublishedRecordDeclineAction, + DeletePublishedRecordSubmitAction, ) from ..utils import classproperty, is_auto_approved, request_identity_matches @@ -51,6 +52,7 @@ def available_actions(cls) -> dict[str, type[RequestAction]]: """Return available actions for the request type.""" return { **super().available_actions, + "submit": DeletePublishedRecordSubmitAction, "accept": DeletePublishedRecordAcceptAction, "decline": DeletePublishedRecordDeclineAction, } diff --git a/oarepo_requests/views/api.py b/oarepo_requests/views/api.py index dfc0fa10..10910a26 100644 --- a/oarepo_requests/views/api.py +++ b/oarepo_requests/views/api.py @@ -9,10 +9,13 @@ from __future__ import annotations +from pathlib import Path from typing import TYPE_CHECKING +from flask import Blueprint + if TYPE_CHECKING: - from flask import Blueprint, Flask + from flask import Flask def create_oarepo_requests(app: Flask) -> Blueprint: @@ -32,3 +35,14 @@ def create_oarepo_requests_events(app: Flask) -> Blueprint: ext = app.extensions["oarepo-requests"] blueprint = ext.request_events_resource.as_blueprint() return blueprint + + +def create_notifications(app: Flask) -> Blueprint: + """Register blueprint routes on app.""" + blueprint = Blueprint( + "oarepo_notifications", + __name__, + template_folder=Path(__file__).parent.parent / "templates", + ) + + return blueprint diff --git a/oarepo_requests/views/app.py b/oarepo_requests/views/app.py index 1803bd23..755419c2 100644 --- a/oarepo_requests/views/app.py +++ b/oarepo_requests/views/app.py @@ -9,6 +9,7 @@ from __future__ import annotations +from pathlib import Path from typing import TYPE_CHECKING from flask import Blueprint @@ -35,3 +36,14 @@ def create_app_events_blueprint(app: Flask) -> Blueprint: "oarepo_requests_events_app", __name__, url_prefix="/requests/" ) return blueprint + + +def create_notifications(app: Flask) -> Blueprint: + """Register blueprint routes on app.""" + blueprint = Blueprint( + "oarepo_notifications", + __name__, + template_folder=Path(__file__).parent.parent / "templates", + ) + + return blueprint diff --git a/run-tests.sh b/run-tests.sh index d28d3108..35397d8e 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e - +export PYTHONWARNINGS="ignore" OAREPO_VERSION=${OAREPO_VERSION:-12} PYTHON="${PYTHON:-python3.12}" @@ -10,6 +10,9 @@ BUILDER_VENV=.venv-builder BUILD_TEST_DIR="tests" CODE_TEST_DIR="tests" +export PIP_EXTRA_INDEX_URL=https://gitlab.cesnet.cz/api/v4/projects/1408/packages/pypi/simple +export UV_EXTRA_INDEX_URL=https://gitlab.cesnet.cz/api/v4/projects/1408/packages/pypi/simple + curl -L -o forked_install.sh https://github.com/oarepo/nrp-devtools/raw/main/tests/forked_install.sh if test -d $BUILDER_VENV ; then @@ -41,7 +44,7 @@ fi "${PYTHON}" -m venv $MODEL_VENV . $MODEL_VENV/bin/activate pip install -U setuptools pip wheel -pip install "oarepo[tests]==$OAREPO_VERSION.*" +pip install "oarepo[tests,rdm]==$OAREPO_VERSION.*" pip install -e "./$BUILD_TEST_DIR/${MODEL}" # local development @@ -54,9 +57,5 @@ done | python # now install the tests (might bring more dependencies, that's why we have checked the imports before) pip install -e ".[tests]" - -sh forked_install.sh invenio-records-resources -sh forked_install.sh invenio-requests -sh forked_install.sh invenio-drafts-resources pytest $BUILD_TEST_DIR/test_requests pytest $BUILD_TEST_DIR/test_ui \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index df16c9b6..fad44f2e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = oarepo-requests -version = 2.3.14 +version = 2.3.15 description = authors = Ronald Krist readme = README.md @@ -30,6 +30,7 @@ exclude = tests = deepdiff oarepo-ui + pytest-oarepo [options.entry_points] invenio_base.api_apps = @@ -39,11 +40,13 @@ invenio_base.apps = invenio_base.api_blueprints = oarepo_requests = oarepo_requests.views.api:create_oarepo_requests oarepo_requests_events = oarepo_requests.views.api:create_oarepo_requests_events + oarepo_notifications = oarepo_requests.views.api:create_notifications invenio_base.blueprints = oarepo_requests = oarepo_requests.views.app:create_app_blueprint oarepo_requests_events = oarepo_requests.views.app:create_app_events_blueprint oarepo_requests_ui = oarepo_requests.ui.views:create_blueprint oarepo_request_form_config = oarepo_requests.ui.views:create_requests_form_config_blueprint + oarepo_notifications = oarepo_requests.views.app:create_notifications invenio_assets.webpack = oarepo_requests_ui_theme = oarepo_requests.ui.theme.webpack:theme invenio_i18n.translations = diff --git a/tests/conftest.py b/tests/conftest.py index 1a2f00ab..8ff0a189 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,34 +5,25 @@ # modify it under the terms of the MIT License; see LICENSE file for more # details. # -import copy import os -from io import BytesIO from typing import Dict import pytest -from deepmerge import always_merger -from flask_principal import UserNeed -from flask_security import login_user -from invenio_access.permissions import system_identity -from invenio_accounts.proxies import current_datastore -from invenio_accounts.testutils import login_user_via_session -from invenio_app.factory import create_api +from invenio_notifications.backends import EmailNotificationBackend from invenio_records_permissions.generators import ( AnyUser, AuthenticatedUser, - Generator, SystemProcess, ) +from invenio_records_resources.references.entity_resolvers import ServiceResultResolver from invenio_records_resources.services.uow import RecordCommitOp from invenio_requests.customizations import CommentEventType, LogEventType -from invenio_requests.proxies import current_requests, current_requests_service -from invenio_requests.records.api import Request, RequestEvent, RequestEventFormat +from invenio_requests.proxies import current_requests_service +from invenio_requests.records.api import Request, RequestEvent from invenio_requests.services.generators import Receiver from invenio_requests.services.permissions import ( PermissionPolicy as InvenioRequestsPermissionPolicy, ) -from invenio_users_resources.records import UserAggregate from oarepo_runtime.i18n import lazy_gettext as _ from oarepo_runtime.services.permissions import RecordOwners from oarepo_workflows import ( @@ -45,15 +36,22 @@ ) from oarepo_workflows.base import Workflow from oarepo_workflows.requests.events import WorkflowEvent -from oarepo_workflows.requests.generators import RecipientGeneratorMixin +from pytest_oarepo.requests.classes import TestEventType, UserGenerator from thesis.proxies import current_service -from thesis.records.api import ThesisDraft from oarepo_requests.actions.generic import ( OARepoAcceptAction, OARepoDeclineAction, OARepoSubmitAction, ) +from oarepo_requests.notifications.builders.delete_published_record import ( + DeletePublishedRecordRequestAcceptNotificationBuilder, + DeletePublishedRecordRequestSubmitNotificationBuilder, +) +from oarepo_requests.notifications.builders.publish import ( + PublishDraftRequestAcceptNotificationBuilder, + PublishDraftRequestSubmitNotificationBuilder, +) from oarepo_requests.receiver import default_workflow_receiver_function from oarepo_requests.services.permissions.generators.conditional import ( IfNoEditDraft, @@ -65,18 +63,35 @@ ) from oarepo_requests.types import ModelRefTypes, NonDuplicableOARepoRequestType from oarepo_requests.types.events.topic_update import TopicUpdateEventType -from tests.test_requests.utils import link2testclient -can_comment_only_receiver = [ - Receiver(), - SystemProcess(), +pytest_plugins = [ + "pytest_oarepo.requests.fixtures", + "pytest_oarepo.records", + "pytest_oarepo.fixtures", + "pytest_oarepo.users", + "pytest_oarepo.files", ] -class TestEventType(CommentEventType): - type_id = "test" - """""" # to test permissions +@pytest.fixture(scope="module") +def record_service(): + return current_service + + +@pytest.fixture(scope="module", autouse=True) +def location(location): + return location + +@pytest.fixture(autouse=True) +def vocab_cf(vocab_cf): + return vocab_cf + + +can_comment_only_receiver = [ + Receiver(), + SystemProcess(), +] events_only_receiver_can_comment = { CommentEventType.type_id: WorkflowEvent(submitters=can_comment_only_receiver), @@ -90,17 +105,6 @@ class TestEventType(CommentEventType): } -class UserGenerator(RecipientGeneratorMixin, Generator): - def __init__(self, user_id): - self.user_id = user_id - - def needs(self, **kwargs): - return [UserNeed(self.user_id)] - - def reference_receivers(self, **kwargs): - return [{"user": str(self.user_id)}] - - class DefaultRequests(WorkflowRequestPolicy): publish_draft = WorkflowRequest( requesters=[IfInState("draft", [RecordOwners()])], @@ -321,26 +325,11 @@ class WithApprovalPermissions(RequestBasedWorkflowPermissions): ), } - -@pytest.fixture -def change_workflow_function(): - from oarepo_workflows.proxies import current_oarepo_workflows - - return current_oarepo_workflows.set_workflow - - +""" @pytest.fixture(scope="module") def create_app(instance_path, entry_points): - """Application factory fixture.""" return create_api - - -@pytest.fixture() -def vocab_cf(app, db, cache): - from oarepo_runtime.services.custom_fields.mappings import prepare_cf_indices - - prepare_cf_indices() - ThesisDraft.index.refresh() +""" @pytest.fixture() @@ -348,84 +337,6 @@ def urls(): return {"BASE_URL": "/thesis/", "BASE_URL_REQUESTS": "/requests/"} -@pytest.fixture() -def publish_request_data_function(): - def ret_data(record_id): - return { - "request_type": "publish_draft", - "topic": {"thesis_draft": record_id}, - "payload": {"version": "1.0"}, - } - - return ret_data - - -@pytest.fixture() -def conditional_recipient_request_data_function(): - def ret_data(record_id): - return { - "request_type": "conditional_recipient_rt", - "topic": {"thesis_draft": record_id}, - } - - return ret_data - - -@pytest.fixture() -def another_topic_updating_request_function(): - def ret_data(record_id): - return { - "request_type": "another_topic_updating", - "topic": {"thesis_draft": record_id}, - } - - return ret_data - - -@pytest.fixture() -def edit_record_data_function(): - def ret_data(record_id): - return { - "request_type": "edit_published_record", - "topic": {"thesis": record_id}, - } - - return ret_data - - -@pytest.fixture() -def new_version_data_function(): - def ret_data(record_id): - return { - "request_type": "new_version", - "topic": {"thesis": record_id}, - } - - return ret_data - - -@pytest.fixture() -def delete_record_data_function(): - def ret_data(record_id): - return { - "request_type": "delete_published_record", - "topic": {"thesis": record_id}, - } - - return ret_data - - -@pytest.fixture() -def delete_draft_function(): - def ret_data(record_id): - return { - "request_type": "delete_draft", - "topic": {"thesis_draft": record_id}, - } - - return ret_data - - @pytest.fixture() def serialization_result(): def _result(topic_id, request_id): @@ -539,319 +450,24 @@ def app_config(app_config): "R": "Remote", } app_config["FILES_REST_DEFAULT_STORAGE_CLASS"] = "L" - return app_config - - -@pytest.fixture(scope="module", autouse=True) -def location(location): - return location - - -@pytest.fixture(scope="module") -def requests_service(app): - """Request Factory fixture.""" - - return current_requests.requests_service - -@pytest.fixture(scope="module") -def request_events_service(app): - """Request Factory fixture.""" - service = current_requests.request_events_service - return service - - -@pytest.fixture() -def users(app, db, UserFixture): - user1 = UserFixture( - email="user1@example.org", - password="password", - active=True, - confirmed=True, - ) - user1.create(app, db) - - user2 = UserFixture( - email="user2@example.org", - password="beetlesmasher", - username="beetlesmasher", - active=True, - confirmed=True, - ) - user2.create(app, db) - - user3 = UserFixture( - email="user3@example.org", - password="beetlesmasher", - username="beetlesmasherXXL", - user_profile={ - "full_name": "Maxipes Fik", - "affiliations": "CERN", - }, - active=True, - confirmed=True, - ) - user3.create(app, db) - - db.session.commit() - UserAggregate.index.refresh() - return [user1, user2, user3] - - -class LoggedClient: - def __init__(self, client, user_fixture): - self.client = client - self.user_fixture = user_fixture - - def _login(self): - login_user(self.user_fixture.user, remember=True) - login_user_via_session(self.client, email=self.user_fixture.email) - - def post(self, *args, **kwargs): - self._login() - return self.client.post(*args, **kwargs) - - def get(self, *args, **kwargs): - self._login() - return self.client.get(*args, **kwargs) - - def put(self, *args, **kwargs): - self._login() - return self.client.put(*args, **kwargs) - - def delete(self, *args, **kwargs): - self._login() - return self.client.delete(*args, **kwargs) - - -@pytest.fixture() -def logged_client(client): - def _logged_client(user): - return LoggedClient(client, user) - - return _logged_client - - -@pytest.fixture(scope="function") -def request_record_input_data(): - """Input data to a Request record.""" - ret = { - "title": "Doc1 approval", - "payload": { - "content": "Can you approve my document doc1 please?", - "format": RequestEventFormat.HTML.value, - }, - } - return ret - - -@pytest.fixture(scope="module") -def record_service(): - return current_service - - -@pytest.fixture() -def example_topic_draft(record_service, users, default_workflow_json): # needed for ui - identity = users[0].identity - draft = record_service.create(identity, default_workflow_json) - return draft._obj - - -@pytest.fixture() -def record_factory(record_service, default_workflow_json): - def record(identity, custom_workflow=None, additional_data=None): - json = copy.deepcopy(default_workflow_json) - if custom_workflow: # specifying this assumes use of workflows - json["parent"]["workflow"] = custom_workflow - json_metadata = { - "metadata": { - "creators": [ - "Creator 1", - "Creator 2", - ], - "contributors": ["Contributor 1"], - } - } - json = always_merger.merge(json, json_metadata) - if additional_data: - always_merger.merge(json, additional_data) - draft = record_service.create(identity, json) - record = record_service.publish(system_identity, draft.id) - return record._obj - - return record - - -@pytest.fixture() -def record_with_files_factory(record_service, default_workflow_json): - def record(identity, custom_workflow=None, additional_data=None): - json = copy.deepcopy(default_workflow_json) - if ( - "files" in default_workflow_json - and "enabled" in default_workflow_json["files"] - ): - default_workflow_json["files"]["enabled"] = True - if custom_workflow: # specifying this assumes use of workflows - json["parent"]["workflow"] = custom_workflow - json = { - "metadata": { - "creators": [ - "Creator 1", - "Creator 2", - ], - "contributors": ["Contributor 1"], - } - } - json = always_merger.merge(json, default_workflow_json) - if additional_data: - always_merger.merge(json, additional_data) - draft = record_service.create(identity, json) - - # upload file - # Initialize files upload - files_service = record_service._draft_files - init = files_service.init_files( - identity, - draft["id"], - data=[ - {"key": "test.pdf", "metadata": {"title": "Test file"}}, - ], - ) - upload = files_service.set_file_content( - identity, draft["id"], "test.pdf", stream=BytesIO(b"testfile") - ) - commit = files_service.commit_file(identity, draft["id"], "test.pdf") - - record = record_service.publish(system_identity, draft.id) - return record._obj - - return record - - -@pytest.fixture() -def create_draft_via_resource(default_workflow_json, urls): - def _create_draft( - client, expand=True, custom_workflow=None, additional_data=None, **kwargs - ): - json = copy.deepcopy(default_workflow_json) - if custom_workflow: - json["parent"]["workflow"] = custom_workflow - if additional_data: - json = always_merger.merge(json, additional_data) - url = urls["BASE_URL"] + "?expand=true" if expand else urls["BASE_URL"] - return client.post(url, json=json, **kwargs) - - return _create_draft - - -@pytest.fixture() -def events_resource_data(): - """Input data for the Request Events Resource (REST body).""" - return { - "payload": { - "content": "This is a comment.", - "format": RequestEventFormat.HTML.value, - } - } - - -def _create_role(id, name, description, is_managed, database): - """Creates a Role/Group.""" - r = current_datastore.create_role( - id=id, name=name, description=description, is_managed=is_managed - ) - current_datastore.commit() - return r - - -@pytest.fixture() -def role(database): - """A single group.""" - r = _create_role( - id="it-dep", - name="it-dep", - description="IT Department", - is_managed=False, - database=database, - ) - return r - - -@pytest.fixture() -def role_ui_serialization(): - return { - "label": "it-dep", - "links": { - "avatar": "https://127.0.0.1:5000/api/groups/it-dep/avatar.svg", - "self": "https://127.0.0.1:5000/api/groups/it-dep", - }, - "reference": {"group": "it-dep"}, - "type": "group", + app_config["NOTIFICATIONS_BACKENDS"] = { + EmailNotificationBackend.id: EmailNotificationBackend(), } - - -@pytest.fixture() -def default_workflow_json(): - return { - "parent": {"workflow": "default"}, - "metadata": {"title": "blabla"}, - "files": {"enabled": False}, + app_config["NOTIFICATIONS_BUILDERS"] = { + PublishDraftRequestAcceptNotificationBuilder.type: PublishDraftRequestAcceptNotificationBuilder, + PublishDraftRequestSubmitNotificationBuilder.type: PublishDraftRequestSubmitNotificationBuilder, + DeletePublishedRecordRequestSubmitNotificationBuilder.type: DeletePublishedRecordRequestSubmitNotificationBuilder, + DeletePublishedRecordRequestAcceptNotificationBuilder.type: DeletePublishedRecordRequestAcceptNotificationBuilder, } + app_config["NOTIFICATIONS_ENTITY_RESOLVERS"] = [ + ServiceResultResolver(service_id="users", type_key="user"), + ServiceResultResolver(service_id="requests", type_key="request"), + ServiceResultResolver(service_id="request_events", type_key="request_event"), + ] + app_config["MAIL_DEFAULT_SENDER"] = "test@invenio-rdm-records.org" - -@pytest.fixture() -def get_request_type(): - """ - gets request create link from serialized request types - """ - - def _get_request_type(request_types_json, request_type): - selected_entry = [ - entry for entry in request_types_json if entry["type_id"] == request_type - ][0] - return selected_entry - - return _get_request_type - - -@pytest.fixture() -def get_request_link(get_request_type): - """ - gets request create link from serialized request types - """ - - def _create_request_from_link(request_types_json, request_type): - selected_entry = get_request_type(request_types_json, request_type) - return selected_entry["links"]["actions"]["create"] - - return _create_request_from_link - - -@pytest.fixture -def create_request_by_link(get_request_link): - def _create_request(client, record, request_type): - applicable_requests = client.get( - link2testclient(record.json["links"]["applicable-requests"]) - ).json["hits"]["hits"] - create_link = link2testclient( - get_request_link(applicable_requests, request_type) - ) - create_response = client.post(create_link) - return create_response - - return _create_request - - -@pytest.fixture -def submit_request_by_link(create_request_by_link): - def _submit_request(client, record, request_type): - create_response = create_request_by_link(client, record, request_type) - submit_response = client.post( - link2testclient(create_response.json["links"]["actions"]["submit"]) - ) - return submit_response - - return _submit_request + return app_config @pytest.fixture @@ -859,19 +475,19 @@ def check_publish_topic_update(): def _check_publish_topic_update( creator_client, urls, record, before_update_response ): - request_id = before_update_response.json["id"] - record_id = record.json["id"] + request_id = before_update_response["id"] + record_id = record["id"] after_update_response = creator_client.get( f"{urls['BASE_URL_REQUESTS']}{request_id}" - ) + ).json RequestEvent.index.refresh() events = creator_client.get( f"{urls['BASE_URL_REQUESTS']}extended/{request_id}/timeline" ).json["hits"]["hits"] - assert before_update_response.json["topic"] == {"thesis_draft": record_id} - assert after_update_response.json["topic"] == {"thesis": record_id} + assert before_update_response["topic"] == {"thesis_draft": record_id} + assert after_update_response["topic"] == {"thesis": record_id} topic_updated_events = [ e for e in events if e["type"] == TopicUpdateEventType.type_id @@ -891,7 +507,7 @@ def user_links(): def _user_links(user_id): return { "avatar": f"https://127.0.0.1:5000/api/users/{user_id}/avatar.svg", - "records_html": f"https://127.0.0.1:5000/search/records?q=user:{user_id}", + "records_html": f"https://127.0.0.1:5000/search/records?q=parent.access.owned_by.user:{user_id}", "self": f"https://127.0.0.1:5000/api/users/{user_id}", } diff --git a/tests/test_requests/test_allowed_request_types_link_and_service.py b/tests/test_requests/test_allowed_request_types_link_and_service.py index 4f847fa2..d8a7ee13 100644 --- a/tests/test_requests/test_allowed_request_types_link_and_service.py +++ b/tests/test_requests/test_allowed_request_types_link_and_service.py @@ -7,32 +7,24 @@ # from flask import current_app from thesis.ext import ThesisExt -from thesis.records.api import ThesisDraft, ThesisRecord - -from tests.test_requests.utils import link2testclient def test_allowed_request_types_on_draft_service( - vocab_cf, - logged_client, users, - urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, search_clear, ): - creator = users[0] - receiver = users[1] - creator_client = logged_client(creator) + identity = users[0].identity - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(identity) + draft1_id = draft1["id"] thesis_ext: ThesisExt = current_app.extensions["thesis"] thesis_requests_service = thesis_ext.service_record_request_types allowed_request_types = ( thesis_requests_service.get_applicable_request_types_for_draft_record( - creator.identity, draft1.json["id"] + identity, draft1_id ) ) assert sorted( @@ -41,7 +33,7 @@ def test_allowed_request_types_on_draft_service( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{draft1.json["id"]}/draft/requests/delete_draft' + "create": f"https://127.0.0.1:5000/api/thesis/{draft1_id}/draft/requests/delete_draft" } }, "type_id": "delete_draft", @@ -49,7 +41,7 @@ def test_allowed_request_types_on_draft_service( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{draft1.json["id"]}/draft/requests/publish_draft' + "create": f"https://127.0.0.1:5000/api/thesis/{draft1_id}/draft/requests/publish_draft" } }, "type_id": "publish_draft", @@ -58,25 +50,22 @@ def test_allowed_request_types_on_draft_service( def test_allowed_request_types_on_draft_resource( - vocab_cf, logged_client, users, - urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + link2testclient, search_clear, ): creator = users[0] - receiver = users[1] creator_client = logged_client(creator) - receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] - applicable_requests_link = draft1.json["links"]["applicable-requests"] + applicable_requests_link = draft1["links"]["applicable-requests"] assert ( applicable_requests_link - == f'https://127.0.0.1:5000/api/thesis/{draft1.json["id"]}/draft/requests/applicable' + == f"https://127.0.0.1:5000/api/thesis/{draft1_id}/draft/requests/applicable" ) allowed_request_types = creator_client.get( link2testclient(applicable_requests_link) @@ -87,7 +76,7 @@ def test_allowed_request_types_on_draft_resource( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{draft1.json["id"]}/draft/requests/delete_draft' + "create": f"https://127.0.0.1:5000/api/thesis/{draft1_id}/draft/requests/delete_draft" } }, "type_id": "delete_draft", @@ -95,7 +84,7 @@ def test_allowed_request_types_on_draft_resource( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{draft1.json["id"]}/draft/requests/publish_draft' + "create": f"https://127.0.0.1:5000/api/thesis/{draft1_id}/draft/requests/publish_draft" } }, "type_id": "publish_draft", @@ -103,61 +92,24 @@ def test_allowed_request_types_on_draft_resource( ] -def publish_record( - creator_client, urls, publish_request_data_function, draft1, receiver_client -): - id_ = draft1.json["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), - ) - ThesisRecord.index.refresh() - ThesisDraft.index.refresh() - - record = receiver_client.get( - f"{urls['BASE_URL']}{id_}/draft?expand=true" - ) - - assert record.json["expanded"]["requests"][0]["links"]["actions"].keys() == { - "accept", - "decline", - } - publish = receiver_client.post( - link2testclient( - record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] - ), - ) - return creator_client.get(f"{urls['BASE_URL']}{id_}?expand=true").json - - def test_allowed_request_types_on_published_resource( - vocab_cf, logged_client, users, - urls, - publish_request_data_function, - create_draft_via_resource, + record_factory, + link2testclient, search_clear, - app, ): creator = users[0] receiver = users[1] creator_client = logged_client(creator) - receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - published1 = publish_record( - creator_client, urls, publish_request_data_function, draft1, receiver_client - ) + published1 = record_factory(creator.identity) + published1_id = published1["id"] applicable_requests_link = published1["links"]["applicable-requests"] assert ( applicable_requests_link - == f'https://127.0.0.1:5000/api/thesis/{published1["id"]}/requests/applicable' + == f"https://127.0.0.1:5000/api/thesis/{published1_id}/requests/applicable" ) allowed_request_types = creator_client.get( link2testclient(applicable_requests_link) @@ -169,7 +121,7 @@ def test_allowed_request_types_on_published_resource( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{published1["id"]}/requests/delete_published_record' + "create": f"https://127.0.0.1:5000/api/thesis/{published1_id}/requests/delete_published_record" } }, "type_id": "delete_published_record", @@ -177,7 +129,7 @@ def test_allowed_request_types_on_published_resource( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{published1["id"]}/requests/edit_published_record' + "create": f"https://127.0.0.1:5000/api/thesis/{published1_id}/requests/edit_published_record" } }, "type_id": "edit_published_record", @@ -185,7 +137,7 @@ def test_allowed_request_types_on_published_resource( { "links": { "actions": { - "create": f'https://127.0.0.1:5000/api/thesis/{published1["id"]}/requests/new_version' + "create": f"https://127.0.0.1:5000/api/thesis/{published1_id}/requests/new_version" } }, "type_id": "new_version", @@ -194,34 +146,23 @@ def test_allowed_request_types_on_published_resource( def test_ui_serialization( - vocab_cf, logged_client, users, - urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, record_factory, + link2testclient, search_clear, ): creator = users[0] - receiver = users[1] creator_client = logged_client(creator) - receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + published1 = record_factory(creator.identity) - draft_to_publish = create_draft_via_resource(creator_client) - published1 = publish_record( - creator_client, - urls, - publish_request_data_function, - draft_to_publish, - receiver_client, - ) - draft_id = draft1.json["id"] + draft_id = draft1["id"] published_id = published1["id"] - applicable_requests_link_draft = draft1.json["links"]["applicable-requests"] + applicable_requests_link_draft = draft1["links"]["applicable-requests"] applicable_requests_link_published = published1["links"]["applicable-requests"] allowed_request_types_draft = creator_client.get( diff --git a/tests/test_requests/test_cascade_events.py b/tests/test_requests/test_cascade_events.py index 4fdb4b50..f7681f76 100644 --- a/tests/test_requests/test_cascade_events.py +++ b/tests/test_requests/test_cascade_events.py @@ -9,18 +9,16 @@ from oarepo_requests.types.events import TopicDeleteEventType -from .utils import link2testclient - def test_cascade_update( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - another_topic_updating_request_function, - create_draft_via_resource, + draft_factory, check_publish_topic_update, + create_request_on_draft, + submit_request_on_draft, + link2testclient, search_clear, ): creator = users[0] @@ -29,30 +27,27 @@ def test_cascade_update( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client, custom_workflow="cascade_update") - draft2 = create_draft_via_resource(creator_client, custom_workflow="cascade_update") + draft1 = draft_factory(creator.identity, custom_workflow="cascade_update") + draft2 = draft_factory(creator.identity, custom_workflow="cascade_update") + draft1_id = draft1["id"] + draft2_id = draft2["id"] - publish_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - another_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=another_topic_updating_request_function(draft1.json["id"]), + publish_request_create = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) - publish_request_on_second_draft = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), + another_request_create = create_request_on_draft( + creator.identity, draft1_id, "another_topic_updating" ) - resp_request_submit = creator_client.post( - link2testclient(publish_request_create.json["links"]["actions"]["submit"]), + publish_request_on_second_draft = create_request_on_draft( + creator.identity, draft2_id, "publish_draft" ) + record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" + ).json publish = receiver_client.post( link2testclient( - record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] + record["expanded"]["requests"][0]["links"]["actions"]["accept"] ), ) @@ -60,23 +55,20 @@ def test_cascade_update( check_publish_topic_update(creator_client, urls, record, another_request_create) second_draft_request = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}{publish_request_on_second_draft.json['id']}" - ) - assert second_draft_request.json["topic"] == { - "thesis_draft": draft2.json["id"] + f"{urls['BASE_URL_REQUESTS']}{publish_request_on_second_draft['id']}" + ).json + assert second_draft_request["topic"] == { + "thesis_draft": draft2_id } # check request on the other draft is unchanged def test_cascade_cancel( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - another_topic_updating_request_function, - create_draft_via_resource, - create_request_by_link, - submit_request_by_link, + draft_factory, + create_request_on_draft, + submit_request_on_draft, search_clear, ): creator = users[0] @@ -85,32 +77,36 @@ def test_cascade_cancel( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client, custom_workflow="cascade_update") - draft2 = create_draft_via_resource(creator_client, custom_workflow="cascade_update") + draft1 = draft_factory(creator.identity, custom_workflow="cascade_update") + draft2 = draft_factory(creator.identity, custom_workflow="cascade_update") + draft1_id = draft1["id"] + draft2_id = draft2["id"] - r1 = submit_request_by_link(creator_client, draft1, "publish_draft") - r2 = create_request_by_link(creator_client, draft1, "another_topic_updating") - r3 = submit_request_by_link(creator_client, draft2, "publish_draft") + r1 = submit_request_on_draft(creator.identity, draft1_id, "publish_draft") + r2 = create_request_on_draft(creator.identity, draft1_id, "another_topic_updating") + r3 = submit_request_on_draft(creator.identity, draft2_id, "publish_draft") - delete_request = submit_request_by_link(creator_client, draft1, "delete_draft") + delete_request = submit_request_on_draft( + creator.identity, draft1_id, "delete_draft" + ) - r1_read = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{r1.json['id']}") - r2_read = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{r2.json['id']}") - r3_read = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{r3.json['id']}") + r1_read = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{r1['id']}").json + r2_read = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{r2['id']}").json + r3_read = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{r3['id']}").json - assert r1_read.json["status"] == "cancelled" - assert r2_read.json["status"] == "cancelled" - assert r3_read.json["status"] == "submitted" + assert r1_read["status"] == "cancelled" + assert r2_read["status"] == "cancelled" + assert r3_read["status"] == "submitted" RequestEvent.index.refresh() events1 = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}extended/{r1.json['id']}/timeline" + f"{urls['BASE_URL_REQUESTS']}extended/{r1['id']}/timeline" ).json["hits"]["hits"] events2 = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}extended/{r2.json['id']}/timeline" + f"{urls['BASE_URL_REQUESTS']}extended/{r2['id']}/timeline" ).json["hits"]["hits"] events3 = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}extended/{r3.json['id']}/timeline" + f"{urls['BASE_URL_REQUESTS']}extended/{r3['id']}/timeline" ).json["hits"]["hits"] topic_deleted_events1 = [ diff --git a/tests/test_requests/test_conditional_recipient.py b/tests/test_requests/test_conditional_recipient.py index b2a22a46..37376d94 100644 --- a/tests/test_requests/test_conditional_recipient.py +++ b/tests/test_requests/test_conditional_recipient.py @@ -9,8 +9,8 @@ def test_conditional_receiver_creator_matches( logged_client, users, urls, - conditional_recipient_request_data_function, - create_draft_via_resource, + create_request_on_draft, + draft_factory, search_clear, ): # user[0] is creator, user[1] is receiver @@ -19,25 +19,21 @@ def test_conditional_receiver_creator_matches( creator = users[0] assert creator.id == "1" - creator_client = logged_client(creator) + draft1 = draft_factory(creator.identity, custom_workflow="with_ct") - draft1 = create_draft_via_resource(creator_client, custom_workflow="with_ct") - - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=conditional_recipient_request_data_function(draft1.json["id"]), + resp_request_create = create_request_on_draft( + creator.identity, draft1["id"], "conditional_recipient_rt" ) - assert resp_request_create.status_code == 201 - assert resp_request_create.json["receiver"] == {"user": "2"} + assert resp_request_create["receiver"] == {"user": "2"} def test_conditional_receiver_creator_does_not_match( logged_client, users, urls, - conditional_recipient_request_data_function, - create_draft_via_resource, + create_request_on_draft, + draft_factory, search_clear, ): # user[0] is creator, user[1] is receiver @@ -46,14 +42,10 @@ def test_conditional_receiver_creator_does_not_match( creator = users[1] assert creator.id != 1 - creator_client = logged_client(creator) - - draft1 = create_draft_via_resource(creator_client, custom_workflow="with_ct") + draft1 = draft_factory(creator.identity, custom_workflow="with_ct") - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=conditional_recipient_request_data_function(draft1.json["id"]), + resp_request_create = create_request_on_draft( + creator.identity, draft1["id"], "conditional_recipient_rt" ) - assert resp_request_create.status_code == 201 - assert resp_request_create.json["receiver"] == {"user": "3"} + assert resp_request_create["receiver"] == {"user": "3"} diff --git a/tests/test_requests/test_create_conditions.py b/tests/test_requests/test_create_conditions.py index ca44f476..979e84ec 100644 --- a/tests/test_requests/test_create_conditions.py +++ b/tests/test_requests/test_create_conditions.py @@ -9,15 +9,13 @@ from oarepo_requests.errors import OpenRequestAlreadyExists -from .utils import link2testclient - def test_can_create( logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + link2testclient, search_clear, ): creator = users[0] @@ -26,61 +24,56 @@ def test_can_create( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - draft2 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft2 = draft_factory(creator.identity) + + draft1_id = draft1["id"] + draft2_id = draft2["id"] resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) + f"{urls['BASE_URL']}{draft1_id}/draft/requests/publish_draft" + ).json with pytest.raises(OpenRequestAlreadyExists): creator_client.post( # create request after create - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), + f"{urls['BASE_URL']}{draft1_id}/draft/requests/publish_draft" ) resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]), ) with pytest.raises(OpenRequestAlreadyExists): creator_client.post( # create request after submit - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), + f"{urls['BASE_URL']}{draft1_id}/draft/requests/publish_draft" ) # should still be creatable for draft2 create_for_request_draft2 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), + f"{urls['BASE_URL']}{draft2_id}/draft/requests/publish_draft" ) assert create_for_request_draft2.status_code == 201 # try declining the request for draft2, we should be able to create again then resp_request_submit = creator_client.post( - link2testclient( - create_for_request_draft2.json["links"]["actions"]["submit"] - ), + link2testclient(create_for_request_draft2.json["links"]["actions"]["submit"]), ) with pytest.raises(OpenRequestAlreadyExists): create_for_request_draft2 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), + f"{urls['BASE_URL']}{draft2_id}/draft/requests/publish_draft" ) record = receiver_client.get( - f"{urls['BASE_URL']}{draft2.json['id']}/draft?expand=true" - ) + f"{urls['BASE_URL']}{draft2_id}/draft?expand=true" + ).json decline = receiver_client.post( link2testclient( - record.json["expanded"]["requests"][0]["links"]["actions"]["decline"] + record["expanded"]["requests"][0]["links"]["actions"]["decline"] ), ) resp_request_create_again = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), + f"{urls['BASE_URL']}{draft2_id}/draft/requests/publish_draft" ) assert resp_request_create_again.status_code == 201 @@ -89,8 +82,8 @@ def test_can_possibly_create( logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + link2testclient, search_clear, ): creator = users[0] @@ -99,23 +92,22 @@ def test_can_possibly_create( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - draft2 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] record_resp_no_request = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" + ).json resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) + f"{urls['BASE_URL']}{draft1_id}/draft/requests/publish_draft" + ).json record_resp_after_create = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" + ).json resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]), ) def find_request_type(requests, type): @@ -125,23 +117,23 @@ def find_request_type(requests, type): return None record_resp_with_request = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" + ).json assert find_request_type( - record_resp_no_request.json["expanded"]["request_types"], "publish_draft" + record_resp_no_request["expanded"]["request_types"], "publish_draft" ) assert ( find_request_type( - record_resp_with_request.json["expanded"]["request_types"], "publish_draft" + record_resp_with_request["expanded"]["request_types"], "publish_draft" ) is None ) assert ( find_request_type( - record_resp_after_create.json["expanded"]["request_types"], "publish_draft" + record_resp_after_create["expanded"]["request_types"], "publish_draft" ) is None ) diff --git a/tests/test_requests/test_create_inmodel.py b/tests/test_requests/test_create_inmodel.py index 12ce0aed..10501bbf 100644 --- a/tests/test_requests/test_create_inmodel.py +++ b/tests/test_requests/test_create_inmodel.py @@ -5,25 +5,18 @@ # modify it under the terms of the MIT License; see LICENSE file for more # details. # -from thesis.records.api import ThesisRecord -from tests.test_requests.utils import link2testclient - - -def pick_request_type(types_list, queried_type): - for type in types_list: - if type["type_id"] == queried_type: - return type - return None +from thesis.records.api import ThesisDraft, ThesisRecord +# todo since inline is now the default way to create records, these might be redundant def test_record( - vocab_cf, logged_client, record_factory, users, urls, - delete_record_data_function, + create_request_on_record, + link2testclient, search_clear, ): creator = users[0] @@ -32,38 +25,33 @@ def test_record( receiver_client = logged_client(receiver) record1 = record_factory(creator.identity) - record1 = creator_client.get(f"{urls['BASE_URL']}{record1['id']}?expand=true") - - link = link2testclient( - pick_request_type( - record1.json["expanded"]["request_types"], "delete_published_record" - )["links"]["actions"]["create"] + record1_id = record1["id"] + resp_request_create = create_request_on_record( + creator.identity, record1_id, "delete_published_record" ) - - resp_request_create = creator_client.post(link) - assert resp_request_create.status_code == 201 resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]), ) - record = receiver_client.get(f"{urls['BASE_URL']}{record1.json['id']}?expand=true") + record = receiver_client.get(f"{urls['BASE_URL']}{record1_id}?expand=true") delete = receiver_client.post( link2testclient( record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] ) ) ThesisRecord.index.refresh() + ThesisDraft.index.refresh() lst = creator_client.get(urls["BASE_URL"]) assert len(lst.json["hits"]["hits"]) == 0 def test_draft( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + create_request_on_draft, + link2testclient, search_clear, ): creator = users[0] @@ -71,28 +59,22 @@ def test_draft( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - link = link2testclient( - pick_request_type(draft1.json["expanded"]["request_types"], "publish_draft")[ - "links" - ]["actions"]["create"] - ) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] - resp_request_create = creator_client.post( - link, json={"payload": {"version": "1.0"}} + resp_request_create = create_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) - assert resp_request_create.status_code == 201 resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]), ) record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) - delete = receiver_client.post( - link2testclient( - record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] - ) + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" + ).json + receiver_client.post( + link2testclient(record["expanded"]["requests"][0]["links"]["actions"]["accept"]) ) ThesisRecord.index.refresh() - lst = creator_client.get(urls["BASE_URL"]) - assert len(lst.json["hits"]["hits"]) == 1 + ThesisDraft.index.refresh() + lst = creator_client.get(urls["BASE_URL"]).json + assert len(lst["hits"]["hits"]) == 1 diff --git a/tests/test_requests/test_delete.py b/tests/test_requests/test_delete.py index fab8e93c..76d149dd 100644 --- a/tests/test_requests/test_delete.py +++ b/tests/test_requests/test_delete.py @@ -5,18 +5,17 @@ # modify it under the terms of the MIT License; see LICENSE file for more # details. # +from pytest_oarepo.requests.functions import get_request_create_link from thesis.records.api import ThesisDraft, ThesisRecord -from .utils import link2testclient - def test_delete( - vocab_cf, logged_client, record_factory, users, urls, - delete_record_data_function, + submit_request_on_record, + link2testclient, search_clear, ): creator = users[0] @@ -27,20 +26,19 @@ def test_delete( record1 = record_factory(creator.identity) record2 = record_factory(creator.identity) record3 = record_factory(creator.identity) + record1_id = record1["id"] + record2_id = record2["id"] + record3_id = record3["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() lst = creator_client.get(urls["BASE_URL"]) assert len(lst.json["hits"]["hits"]) == 3 - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1_id, "delete_published_record" ) - record = receiver_client.get(f"{urls['BASE_URL']}{record1['id']}?expand=true") + record = receiver_client.get(f"{urls['BASE_URL']}{record1_id}?expand=true") assert record.json["expanded"]["requests"][0]["links"]["actions"].keys() == { "accept", "decline", @@ -59,32 +57,24 @@ def test_delete( lst = creator_client.get(urls["BASE_URL"]) assert len(lst.json["hits"]["hits"]) == 2 - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record2["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record2_id, "delete_published_record" ) - record = receiver_client.get(f"{urls['BASE_URL']}{record2['id']}?expand=true") + record = receiver_client.get(f"{urls['BASE_URL']}{record2_id}?expand=true") decline = receiver_client.post( link2testclient( record.json["expanded"]["requests"][0]["links"]["actions"]["decline"] ) ) declined_request = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}{resp_request_create.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{resp_request_submit['id']}" ) assert declined_request.json["status"] == "declined" - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record3["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record3_id, "delete_published_record" ) - record = creator_client.get(f"{urls['BASE_URL']}{record3['id']}?expand=true") + record = creator_client.get(f"{urls['BASE_URL']}{record3_id}?expand=true") assert record.json["expanded"]["requests"][0]["links"]["actions"].keys() == { "cancel" } @@ -94,32 +84,33 @@ def test_delete( ), ) canceled_request = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}{resp_request_create.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{resp_request_submit['id']}" ) assert canceled_request.json["status"] == "cancelled" def test_delete_draft( - vocab_cf, logged_client, - create_draft_via_resource, + draft_factory, users, urls, - delete_draft_function, - get_request_link, + link2testclient, search_clear, ): - creator_client = logged_client(users[0]) + creator = users[0] + creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - draft_id = draft1.json["id"] + draft1 = draft_factory(creator.identity) + draft_id = draft1["id"] read = creator_client.get(f"{urls['BASE_URL']}{draft_id}/draft?expand=true") assert read.status_code == 200 resp_request_create = creator_client.post( link2testclient( - get_request_link(read.json["expanded"]["request_types"], "delete_draft") + get_request_create_link( + read.json["expanded"]["request_types"], "delete_draft" + ) ) ) resp_request_submit = creator_client.post( diff --git a/tests/test_requests/test_edit.py b/tests/test_requests/test_edit.py index c737281e..2dd80fbf 100644 --- a/tests/test_requests/test_edit.py +++ b/tests/test_requests/test_edit.py @@ -7,15 +7,12 @@ # from thesis.records.api import ThesisDraft, ThesisRecord -from tests.test_requests.utils import _create_request, link2testclient - def test_edit_autoaccept( - vocab_cf, logged_client, users, urls, - edit_record_data_function, + submit_request_on_record, record_factory, search_clear, ): @@ -31,16 +28,12 @@ def test_edit_autoaccept( ) assert direct_edit.status_code == 403 - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=edit_record_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, id_, "edit_published_record" ) # is request accepted and closed? request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', ).json assert request["status"] == "accepted" @@ -64,12 +57,13 @@ def test_edit_autoaccept( def test_redirect_url( - vocab_cf, logged_client, users, urls, - edit_record_data_function, + submit_request_on_record, + submit_request_on_draft, record_factory, + link2testclient, search_clear, ): creator = users[0] @@ -78,16 +72,13 @@ def test_redirect_url( receiver_client = logged_client(receiver) record1 = record_factory(creator.identity, custom_workflow="different_recipients") - id_ = record1["id"] + record_id = record1["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=edit_record_data_function(record1["id"]), - ) - edit_request_id = resp_request_create.json["id"] - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record_id, "edit_published_record" ) + edit_request_id = resp_request_submit["id"] + receiver_get = receiver_client.get(f"{urls['BASE_URL_REQUESTS']}{edit_request_id}") resp_request_accept = receiver_client.post( link2testclient(receiver_get.json["links"]["actions"]["accept"]) @@ -106,13 +97,13 @@ def test_redirect_url( assert ( link2testclient(creator_edit_accepted["links"]["ui_redirect_url"], ui=True) - == f"/thesis/{record1['id']}/edit" + == f"/thesis/{record_id}/edit" ) assert receiver_edit_accepted["links"]["ui_redirect_url"] == None - publish_request = _create_request(creator_client, id_, "publish_draft", urls) - creator_client.post( - link2testclient(publish_request.json["links"]["actions"]["submit"]) + draft = creator_client.get(f"{urls['BASE_URL']}{record_id}/draft").json + publish_request = submit_request_on_draft( + creator.identity, draft["id"], "publish_draft" ) receiver_edit_request_after_publish_draft_submitted = receiver_client.get( f"{urls['BASE_URL_REQUESTS']}{edit_request_id}" @@ -124,11 +115,11 @@ def test_redirect_url( ], ui=True, ) - == f"/thesis/{record1['id']}/preview" + == f"/thesis/{record_id}/preview" ) receiver_publish_request = receiver_client.get( - f"{urls['BASE_URL_REQUESTS']}{publish_request.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{publish_request['id']}" ).json receiver_client.post( link2testclient(receiver_publish_request["links"]["actions"]["accept"]) diff --git a/tests/test_requests/test_expand.py b/tests/test_requests/test_expand.py index 000254fa..0e092af1 100644 --- a/tests/test_requests/test_expand.py +++ b/tests/test_requests/test_expand.py @@ -5,17 +5,15 @@ # modify it under the terms of the MIT License; see LICENSE file for more # details. # -from tests.test_requests.test_create_inmodel import pick_request_type -from tests.test_requests.utils import link2testclient def test_requests_field( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + create_request_on_draft, + link2testclient, search_clear, ): creator = users[0] @@ -23,21 +21,18 @@ def test_requests_field( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - link = link2testclient( - pick_request_type(draft1.json["expanded"]["request_types"], "publish_draft")[ - "links" - ]["actions"]["create"] - ) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] - resp_request_create = creator_client.post(link) - assert resp_request_create.status_code == 201 + resp_request_create = create_request_on_draft( + creator.identity, draft1_id, "publish_draft" + ) resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]), ) - record = receiver_client.get(f"{urls['BASE_URL']}{draft1.json['id']}/draft") + record = receiver_client.get(f"{urls['BASE_URL']}{draft1_id}/draft") expanded_record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" ) assert "requests" not in record.json.get("expanded", {}) @@ -45,11 +40,10 @@ def test_requests_field( def test_autoaccept_receiver( - vocab_cf, logged_client, users, urls, - edit_record_data_function, + create_request_on_record, record_factory, search_clear, ): @@ -57,15 +51,10 @@ def test_autoaccept_receiver( creator_client = logged_client(creator) record1 = record_factory(creator.identity) - id_ = record1["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=edit_record_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = create_request_on_record( + creator.identity, record1["id"], "edit_published_record" ) request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}?expand=true' + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}?expand=true' ).json assert request["expanded"]["receiver"] == {"auto_approve": "true"} diff --git a/tests/test_requests/test_extended.py b/tests/test_requests/test_extended.py index d1701d17..54c8eabb 100644 --- a/tests/test_requests/test_extended.py +++ b/tests/test_requests/test_extended.py @@ -6,34 +6,27 @@ # details. # from invenio_requests.records.api import RequestEvent +from pytest_oarepo.functions import is_valid_subdict from thesis.records.api import ThesisDraft -from .utils import is_valid_subdict, link2testclient - def test_listing( logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + create_request_on_draft, + draft_factory, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - draft2 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft2 = draft_factory(creator.identity) - creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) + create_request_on_draft(creator.identity, draft1["id"], "publish_draft") + create_request_on_draft(creator.identity, draft2["id"], "publish_draft") - creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), - ) ThesisDraft.index.refresh() search = creator_client.get( urls["BASE_URL_REQUESTS"], @@ -45,43 +38,39 @@ def test_read_extended( logged_client, users, urls, - publish_request_data_function, + submit_request_on_draft, serialization_result, ui_serialization_result, - create_draft_via_resource, + draft_factory, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - draft_id = draft1.json["id"] + draft1 = draft_factory(creator.identity) + draft_id = draft1["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft_id), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_draft( + creator.identity, draft_id, "publish_draft" ) old_call = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}{resp_request_create.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{resp_request_submit['id']}" ) new_call = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}extended/{resp_request_create.json['id']}", + f"{urls['BASE_URL_REQUESTS']}extended/{resp_request_submit['id']}", ) new_call2 = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}extended/{resp_request_create.json['id']}", + f"{urls['BASE_URL_REQUESTS']}extended/{resp_request_submit['id']}", headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) assert is_valid_subdict( - serialization_result(draft_id, resp_request_create.json["id"]), + serialization_result(draft_id, resp_request_submit["id"]), new_call.json, ) assert is_valid_subdict( - ui_serialization_result(draft_id, resp_request_create.json["id"]), + ui_serialization_result(draft_id, resp_request_submit["id"]), new_call2.json, ) @@ -90,29 +79,28 @@ def test_update_self_link( logged_client, users, urls, - publish_request_data_function, serialization_result, + submit_request_on_draft, ui_serialization_result, - create_draft_via_resource, + draft_factory, + link2testclient, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]) + resp_request_submit = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) + read_before = creator_client.get( - link2testclient(resp_request_submit.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), ) read_from_record = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true", + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true", ) link_to_extended = link2testclient( read_from_record.json["expanded"]["requests"][0]["links"]["self"] @@ -125,7 +113,7 @@ def test_update_self_link( ) assert update_extended.status_code == 200 read_after = creator_client.get( - link2testclient(resp_request_submit.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), ) assert read_before.json["title"] == "" assert read_after.json["title"] == "lalala" @@ -135,30 +123,29 @@ def test_events_resource( logged_client, users, urls, - publish_request_data_function, + submit_request_on_draft, serialization_result, ui_serialization_result, events_resource_data, - create_draft_via_resource, + draft_factory, + link2testclient, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]) + resp_request_submit = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) + read_before = creator_client.get( - link2testclient(resp_request_submit.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) read_from_record = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true", + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true", ) comments_link = link2testclient( diff --git a/tests/test_requests/test_index_refresh.py b/tests/test_requests/test_index_refresh.py index f0275302..1ccb468e 100644 --- a/tests/test_requests/test_index_refresh.py +++ b/tests/test_requests/test_index_refresh.py @@ -5,25 +5,24 @@ # modify it under the terms of the MIT License; see LICENSE file for more # details. # -from tests.test_requests.utils import link2testclient def test_search( logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + create_request_on_draft, + draft_factory, + link2testclient, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), + resp_request_create = create_request_on_draft( + creator.identity, draft1["id"], "publish_draft" ) # should work without refreshing requests index requests_search = creator_client.get(urls["BASE_URL_REQUESTS"]).json diff --git a/tests/test_requests/test_new_version.py b/tests/test_requests/test_new_version.py index ee8c12e0..2ba5f39c 100644 --- a/tests/test_requests/test_new_version.py +++ b/tests/test_requests/test_new_version.py @@ -8,15 +8,12 @@ from thesis.records.api import ThesisDraft, ThesisRecord -from tests.test_requests.utils import _create_request, link2testclient - def test_new_version_autoaccept( - vocab_cf, logged_client, users, urls, - new_version_data_function, + submit_request_on_record, record_factory, search_clear, ): @@ -24,22 +21,19 @@ def test_new_version_autoaccept( creator_client = logged_client(creator) record1 = record_factory(creator.identity) + record1_id = record1["id"] new_version_direct = creator_client.post( - f"{urls['BASE_URL']}{record1['id']}/versions", + f"{urls['BASE_URL']}{record1_id}/versions", ) assert new_version_direct.status_code == 403 - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=new_version_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1_id, "new_version" ) # is request accepted and closed? request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', ).json assert request["status"] == "accepted" @@ -63,11 +57,10 @@ def test_new_version_autoaccept( def test_new_version_files( - vocab_cf, logged_client, users, urls, - new_version_data_function, + submit_request_on_record, record_with_files_factory, search_clear, ): @@ -76,25 +69,16 @@ def test_new_version_files( record1 = record_with_files_factory(creator.identity) record2 = record_with_files_factory(creator.identity) - - resp_request_create1 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json={ - **new_version_data_function(record1["id"]), - "payload": {"keep_files": "yes"}, - }, - ) - resp_request_create2 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=new_version_data_function(record2["id"]), - ) - - resp_request_submit1 = creator_client.post( - link2testclient(resp_request_create1.json["links"]["actions"]["submit"]), - ) - resp_request_submit2 = creator_client.post( - link2testclient(resp_request_create2.json["links"]["actions"]["submit"]), + record1_id = record1["id"] + record2_id = record2["id"] + + submit1 = submit_request_on_record( + creator.identity, + record1_id, + "new_version", + create_additional_data={"payload": {"keep_files": "yes"}}, ) + submit2 = submit_request_on_record(creator.identity, record2_id, "new_version") ThesisDraft.index.refresh() draft_search = creator_client.get(f"/user/thesis/").json["hits"][ @@ -103,12 +87,12 @@ def test_new_version_files( new_version_1 = [ x for x in draft_search - if x["parent"]["id"] == record1.parent["id"] and x["state"] == "draft" + if x["parent"]["id"] == record1["parent"]["id"] and x["state"] == "draft" ] new_version_2 = [ x for x in draft_search - if x["parent"]["id"] == record2.parent["id"] and x["state"] == "draft" + if x["parent"]["id"] == record2["parent"]["id"] and x["state"] == "draft" ] assert len(new_version_1) == 1 @@ -126,28 +110,25 @@ def test_new_version_files( def test_redirect_url( - vocab_cf, logged_client, users, urls, - new_version_data_function, record_factory, + submit_request_on_record, + submit_request_on_draft, + link2testclient, search_clear, ): creator = users[0] creator_client = logged_client(creator) receiver_client = logged_client(users[1]) record1 = record_factory(creator.identity) - original_id = record1["id"] + record1_id = record1["id"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=new_version_data_function(original_id), - ) - original_request_id = resp_request_create.json["id"] - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1_id, "new_version" ) + original_request_id = resp_request_submit["id"] # is request accepted and closed? request = creator_client.get( @@ -158,24 +139,22 @@ def test_redirect_url( draft_search = creator_client.get(f"/user/thesis/").json["hits"][ "hits" ] # a link is in another pull request for now - new_version = [ + new_draft = [ x for x in draft_search - if x["parent"]["id"] == record1.parent["id"] and x["state"] == "draft" + if x["parent"]["id"] == record1["parent"]["id"] and x["state"] == "draft" ][0] assert ( link2testclient(request["links"]["ui_redirect_url"], ui=True) - == f"/thesis/{new_version['id']}/edit" + == f"/thesis/{new_draft['id']}/edit" ) - publish_request = _create_request( - creator_client, new_version["id"], "publish_draft", urls - ) - submit = creator_client.post( - link2testclient(publish_request.json["links"]["actions"]["submit"]) + new_draft = creator_client.get(f"{urls['BASE_URL']}{new_draft['id']}/draft").json + publish_request = submit_request_on_draft( + creator.identity, new_draft["id"], "publish_draft" ) receiver_request = receiver_client.get( - f"{urls['BASE_URL_REQUESTS']}{submit.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{publish_request['id']}" ) accept = receiver_client.post( link2testclient(receiver_request.json["links"]["actions"]["accept"]) @@ -185,5 +164,5 @@ def test_redirect_url( f'{urls["BASE_URL_REQUESTS"]}{original_request_id}', ).json assert original_request["topic"] == { - "thesis": original_id + "thesis": record1_id } # check no weird topic kerfluffle happened here diff --git a/tests/test_requests/test_no_recipient.py b/tests/test_requests/test_no_recipient.py index 76526e9f..79cd69f4 100644 --- a/tests/test_requests/test_no_recipient.py +++ b/tests/test_requests/test_no_recipient.py @@ -9,23 +9,23 @@ def test_no_recipient( logged_client, users, urls, - create_draft_via_resource, + draft_factory, search_clear, ): creator = users[0] - assert creator.id == '1' + assert creator.id == "1" creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client, custom_workflow="with_ct") + draft1 = draft_factory(creator.identity, custom_workflow="with_ct") resp_request_create = creator_client.post( urls["BASE_URL_REQUESTS"], json={ "request_type": "approve_draft", - "topic": {"thesis_draft": draft1.json["id"]}, - } + "topic": {"thesis_draft": draft1["id"]}, + }, ) assert resp_request_create.status_code == 201 - assert resp_request_create.json['receiver'] is None - assert resp_request_create.json['links']['receiver'] == {} + assert resp_request_create.json["receiver"] is None + assert resp_request_create.json["links"]["receiver"] == {} diff --git a/tests/test_requests/test_notifications.py b/tests/test_requests/test_notifications.py new file mode 100644 index 00000000..d454ffaf --- /dev/null +++ b/tests/test_requests/test_notifications.py @@ -0,0 +1,119 @@ +def test_publish_notifications( + app, + users, + logged_client, + draft_factory, + submit_request_on_draft, + link2testclient, + urls, +): + """Test notification being built on review submit.""" + + mail = app.extensions.get("mail") + assert mail + + creator = users[0] + receiver = users[1] + receiver_client = logged_client(receiver) + draft1 = draft_factory(creator.identity) + + with mail.record_messages() as outbox: + resp_request_submit = submit_request_on_draft( + creator.identity, draft1["id"], "publish_draft" + ) + # check notification is build on submit + assert len(outbox) == 1 + sent_mail = outbox[0] + + record = receiver_client.get(f"{urls['BASE_URL']}{draft1['id']}/draft?expand=true") + + with mail.record_messages() as outbox: + # Validate that email was sent + publish = receiver_client.post( + link2testclient( + record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] + ), + ) + # check notification is build on submit + assert len(outbox) == 1 + sent_mail = outbox[0] + + +def test_delete_published_notifications( + app, + users, + logged_client, + record_factory, + submit_request_on_record, + link2testclient, + urls, +): + """Test notification being built on review submit.""" + + mail = app.extensions.get("mail") + assert mail + + creator = users[0] + receiver = users[1] + receiver_client = logged_client(receiver) + record1 = record_factory(creator.identity) + + with mail.record_messages() as outbox: + resp_request_submit = submit_request_on_record( + creator.identity, record1["id"], "delete_published_record" + ) + # check notification is build on submit + assert len(outbox) == 1 + sent_mail = outbox[0] + + record = receiver_client.get(f"{urls['BASE_URL']}{record1['id']}?expand=true") + + with mail.record_messages() as outbox: + # Validate that email was sent + publish = receiver_client.post( + link2testclient( + record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] + ), + ) + # check notification is build on submit + assert len(outbox) == 1 + sent_mail = outbox[0] + + +def test_group( + app, + users, + logged_client, + draft_factory, + submit_request_on_draft, + add_user_in_role, + role, + link2testclient, + urls, +): + """Test notification being built on review submit.""" + + mail = app.extensions.get("mail") + config_restore = app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"] + add_user_in_role(users[0], role) + add_user_in_role(users[1], role) + + def current_receiver(record=None, request_type=None, **kwargs): + if request_type.type_id == "publish_draft": + return role + return config_restore(record, request_type, **kwargs) + + try: + app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"] = current_receiver + + creator = users[0] + draft1 = draft_factory(creator.identity) + + with mail.record_messages() as outbox: + submit_request_on_draft(creator.identity, draft1["id"], "publish_draft") + assert len(outbox) == 2 + receivers = {m.recipients[0] for m in outbox} + assert receivers == {"user1@example.org", "user2@example.org"} + + finally: + app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"] = config_restore diff --git a/tests/test_requests/test_param_interpreters.py b/tests/test_requests/test_param_interpreters.py index 976dffa3..fa1f70c2 100644 --- a/tests/test_requests/test_param_interpreters.py +++ b/tests/test_requests/test_param_interpreters.py @@ -6,28 +6,23 @@ # details. # import json -from tests.test_requests.utils import link2testclient -def _init(users, logged_client, create_draft_via_resource, submit_request, urls): +def _init(users, logged_client, draft_factory, submit_request, urls): user1 = users[0] user2 = users[1] user1_client = logged_client(user1) user2_client = logged_client(user2) - draft1 = create_draft_via_resource( - user1_client, custom_workflow="different_recipients" - ) - draft2 = create_draft_via_resource( - user2_client, custom_workflow="different_recipients" - ) + draft1 = draft_factory(user1.identity, custom_workflow="different_recipients") + draft2 = draft_factory(user2.identity, custom_workflow="different_recipients") submit_response_user1 = submit_request( - user1_client, draft1, "publish_draft" + user1.identity, draft1["id"], "publish_draft" ) # recipient should be 2 submit_response_user2 = submit_request( - user2_client, draft2, "another_topic_updating" + user2.identity, draft2["id"], "another_topic_updating" ) # should be 1 search_unfiltered = user2_client.get(urls["BASE_URL_REQUESTS"]) @@ -39,12 +34,12 @@ def test_receiver_param_interpreter( logged_client, users, urls, - create_draft_via_resource, - submit_request_by_link, + draft_factory, + submit_request_on_draft, search_clear, ): user1_client, user2_client = _init( - users, logged_client, create_draft_via_resource, submit_request_by_link, urls + users, logged_client, draft_factory, submit_request_on_draft, urls ) search_receiver_only = user2_client.get( f'{urls["BASE_URL_REQUESTS"]}?assigned=true' @@ -58,12 +53,12 @@ def test_owner_param_interpreter( logged_client, users, urls, - create_draft_via_resource, - submit_request_by_link, + draft_factory, + submit_request_on_draft, search_clear, ): user1_client, user2_client = _init( - users, logged_client, create_draft_via_resource, submit_request_by_link, urls + users, logged_client, draft_factory, submit_request_on_draft, urls ) search_user1_only = user1_client.get(f'{urls["BASE_URL_REQUESTS"]}?mine=true') @@ -82,15 +77,17 @@ def test_owner_param_interpreter( search_user1_only = user1_client.get(f'{urls["BASE_URL_REQUESTS"]}?all=true') print(json.dumps(search_user1_only.json)) for hit in search_user1_only.json["hits"]["hits"]: - assert hit['created_by'] == {"user": "1"} or hit['receiver'] == {"user": "1"} + assert hit["created_by"] == {"user": "1"} or hit["receiver"] == {"user": "1"} + def test_open_param_interpreter( logged_client, users, urls, - create_draft_via_resource, - create_request_by_link, - submit_request_by_link, + draft_factory, + create_request_on_draft, + submit_request_on_draft, + link2testclient, search_clear, ): user1 = users[0] @@ -99,19 +96,24 @@ def test_open_param_interpreter( user1_client = logged_client(user1) user2_client = logged_client(user2) - draft1 = create_draft_via_resource(user1_client) - draft2 = create_draft_via_resource(user1_client) - draft3 = create_draft_via_resource(user2_client) + draft1 = draft_factory(user1.identity) + draft2 = draft_factory(user1.identity) + draft3 = draft_factory(user2.identity) + draft1_id = draft1["id"] + draft2_id = draft2["id"] + draft3_id = draft3["id"] - submit_response_user1 = submit_request_by_link( - user1_client, draft1, "publish_draft" + submit_response_user1 = submit_request_on_draft( + user1.identity, draft1_id, "publish_draft" + ) + submit_response_user2 = submit_request_on_draft( + user1.identity, draft2_id, "publish_draft" ) - submit_response_user2 = submit_request_by_link( - user1_client, draft2, "publish_draft" + create_response = create_request_on_draft( + user2.identity, draft3_id, "publish_draft" ) - create_response = create_request_by_link(user2_client, draft3, "publish_draft") - read = user2_client.get(f'{urls["BASE_URL"]}{draft1.json["id"]}/draft?expand=true') + read = user2_client.get(f'{urls["BASE_URL"]}{draft1_id}/draft?expand=true') publish = user2_client.post( link2testclient( read.json["expanded"]["requests"][0]["links"]["actions"]["accept"] diff --git a/tests/test_requests/test_publish.py b/tests/test_requests/test_publish.py index 60f98716..b298cb6c 100644 --- a/tests/test_requests/test_publish.py +++ b/tests/test_requests/test_publish.py @@ -9,10 +9,10 @@ from thesis.records.api import ThesisDraft, ThesisRecord -from .utils import link2testclient - -def test_publish_service(users, record_service, default_workflow_json, search_clear): +def test_publish_service( + users, record_service, default_record_with_workflow_json, search_clear +): from invenio_requests.proxies import ( current_requests_service as current_invenio_requests_service, ) @@ -21,7 +21,7 @@ def test_publish_service(users, record_service, default_workflow_json, search_cl creator = users[0] receiver = users[1] - draft = record_service.create(creator.identity, default_workflow_json) + draft = record_service.create(creator.identity, default_record_with_workflow_json) request = current_oarepo_requests_service.create( identity=creator.identity, data={"payload": {"version": "1.0"}}, @@ -51,12 +51,12 @@ def test_publish_service(users, record_service, default_workflow_json, search_cl def test_publish( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + submit_request_on_draft, + link2testclient, search_clear, ): creator = users[0] @@ -65,30 +65,28 @@ def test_publish( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - draft2 = create_draft_via_resource(creator_client) - draft3 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft2 = draft_factory(creator.identity) + draft3 = draft_factory(creator.identity) + draft1_id = draft1["id"] + draft2_id = draft2["id"] + draft3_id = draft3["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() draft_lst = creator_client.get(f"/user{urls['BASE_URL']}") - lst = creator_client.get(urls["BASE_URL"]) + lst = creator_client.get( + urls["BASE_URL"], query_string={"record_status": "published"} + ) assert len(draft_lst.json["hits"]["hits"]) == 3 assert len(lst.json["hits"]["hits"]) == 0 - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) ThesisRecord.index.refresh() ThesisDraft.index.refresh() - record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + record = receiver_client.get(f"{urls['BASE_URL']}{draft1_id}/draft?expand=true") assert record.json["expanded"]["requests"][0]["links"]["actions"].keys() == { "accept", "decline", @@ -102,50 +100,37 @@ def test_publish( assert "published_record:links:self" in publish.json["payload"] assert "published_record:links:self_html" in publish.json["payload"] - published_record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}?expand=true" - ) + published_record = receiver_client.get(f"{urls['BASE_URL']}{draft1_id}?expand=true") assert "version" in published_record.json["metadata"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() draft_lst = creator_client.get(f"/user{urls['BASE_URL']}") - lst = creator_client.get(urls["BASE_URL"]) + lst = creator_client.get( + urls["BASE_URL"], query_string={"record_status": "published"} + ) assert len(draft_lst.json["hits"]["hits"]) == 3 assert len(lst.json["hits"]["hits"]) == 1 - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), - ) - record = receiver_client.get( - f"{urls['BASE_URL']}{draft2.json['id']}/draft?expand=true" + resp_request_submit = submit_request_on_draft( + creator.identity, draft2_id, "publish_draft" ) + record = receiver_client.get(f"{urls['BASE_URL']}{draft2_id}/draft?expand=true") decline = receiver_client.post( link2testclient( record.json["expanded"]["requests"][0]["links"]["actions"]["decline"] ), ) declined_request = creator_client.get( - f"{urls['BASE_URL_REQUESTS']}{resp_request_create.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{resp_request_submit['id']}" ) assert declined_request.json["status"] == "declined" - record = receiver_client.get(f"{urls['BASE_URL']}{draft2.json['id']}/draft") - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft3.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), - ) - record = creator_client.get( - f"{urls['BASE_URL']}{draft3.json['id']}/draft?expand=true" + resp_request_submit = submit_request_on_draft( + creator.identity, draft3_id, "publish_draft" ) + record = creator_client.get(f"{urls['BASE_URL']}{draft3_id}/draft?expand=true") assert record.json["expanded"]["requests"][0]["links"]["actions"].keys() == { "cancel" } @@ -155,19 +140,17 @@ def test_publish( ), ) canceled_request = logged_client(creator).get( - f"{urls['BASE_URL_REQUESTS']}{resp_request_create.json['id']}" + f"{urls['BASE_URL_REQUESTS']}{resp_request_submit['id']}" ) assert canceled_request.json["status"] == "cancelled" def test_create_fails_if_draft_not_validated( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, - default_workflow_json, + draft_factory, + default_record_with_workflow_json, search_clear, ): creator = users[0] @@ -175,15 +158,14 @@ def test_create_fails_if_draft_not_validated( creator_client = logged_client(creator) - json = copy.deepcopy(default_workflow_json) + json = copy.deepcopy(default_record_with_workflow_json) del json["metadata"]["title"] draft = creator_client.post(f"{urls['BASE_URL']}?expand=true", json=json) assert "publish_draft" not in draft.json["expanded"]["request_types"] resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft.json["id"]), + f"{urls['BASE_URL']}{draft.json['id']}/draft/requests/publish_draft", ) assert resp_request_create.status_code == 400 assert resp_request_create.json["message"] == "A validation error occurred." diff --git a/tests/test_requests/test_record_requests.py b/tests/test_requests/test_record_requests.py index 65e5dad0..0572d248 100644 --- a/tests/test_requests/test_record_requests.py +++ b/tests/test_requests/test_record_requests.py @@ -7,15 +7,15 @@ # from thesis.records.api import ThesisDraft, ThesisRecord -from .utils import link2testclient - def test_read_requests_on_draft( logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + submit_request_on_draft, + create_request_on_draft, + draft_factory, + link2testclient, search_clear, ): creator = users[0] @@ -23,50 +23,37 @@ def test_read_requests_on_draft( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - draft2 = create_draft_via_resource(creator_client) - draft3 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft2 = draft_factory(creator.identity) + draft3 = draft_factory(creator.identity) + draft1_id = draft1["id"] + draft2_id = draft2["id"] + draft3_id = draft3["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() - r1 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(r1.json["links"]["actions"]["submit"]), - ) - record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" + resp_request_submit = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) + record = receiver_client.get(f"{urls['BASE_URL']}{draft1_id}/draft?expand=true") decline = receiver_client.post( link2testclient( record.json["expanded"]["requests"][0]["links"]["actions"]["decline"] - ), - ) - - r2 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - r3 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), + ) ) - creator_client.get(link2testclient(r1.json["links"]["actions"]["submit"])) - creator_client.get(link2testclient(r2.json["links"]["actions"]["submit"])) - creator_client.get(link2testclient(r3.json["links"]["actions"]["submit"])) + r2 = create_request_on_draft(creator.identity, draft1_id, "publish_draft") + r3 = create_request_on_draft(creator.identity, draft2_id, "publish_draft") - resp1 = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft/requests" - ).json["hits"]["hits"] - resp2 = creator_client.get( - f"{urls['BASE_URL']}{draft2.json['id']}/draft/requests" - ).json["hits"]["hits"] - resp3 = creator_client.get( - f"{urls['BASE_URL']}{draft3.json['id']}/draft/requests" - ).json["hits"]["hits"] + resp1 = creator_client.get(f"{urls['BASE_URL']}{draft1_id}/draft/requests").json[ + "hits" + ]["hits"] + resp2 = creator_client.get(f"{urls['BASE_URL']}{draft2_id}/draft/requests").json[ + "hits" + ]["hits"] + resp3 = creator_client.get(f"{urls['BASE_URL']}{draft3_id}/draft/requests").json[ + "hits" + ]["hits"] assert len(resp1) == 2 assert len(resp2) == 1 @@ -78,7 +65,9 @@ def test_read_requests_on_record( record_factory, users, urls, - delete_record_data_function, + submit_request_on_record, + create_request_on_record, + link2testclient, search_clear, ): creator = users[0] @@ -89,44 +78,36 @@ def test_read_requests_on_record( record1 = record_factory(creator.identity) record2 = record_factory(creator.identity) record3 = record_factory(creator.identity) + record1_id = record1["id"] + record2_id = record2["id"] + record3_id = record3["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() - r1 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record1["id"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1_id, "delete_published_record" ) - resp_request_submit = creator_client.post( - link2testclient(r1.json["links"]["actions"]["submit"]), - ) - record = receiver_client.get(f"{urls['BASE_URL']}{record1['id']}?expand=true") + record = receiver_client.get(f"{urls['BASE_URL']}{record1_id}?expand=true") decline = receiver_client.post( link2testclient( record.json["expanded"]["requests"][0]["links"]["actions"]["decline"] ), ) - - r2 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record1["id"]), + r2 = create_request_on_record( + creator.identity, record1_id, "delete_published_record" ) - r3 = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record2["id"]), + r3 = create_request_on_record( + creator.identity, record2_id, "delete_published_record" ) - creator_client.post(link2testclient(r1.json["links"]["actions"]["submit"])) - creator_client.post(link2testclient(r2.json["links"]["actions"]["submit"])) - creator_client.post(link2testclient(r3.json["links"]["actions"]["submit"])) - - resp1 = creator_client.get(f"{urls['BASE_URL']}{record1['id']}/requests").json[ + resp1 = creator_client.get(f"{urls['BASE_URL']}{record1_id}/requests").json["hits"][ "hits" - ]["hits"] - resp2 = creator_client.get(f"{urls['BASE_URL']}{record2['id']}/requests").json[ + ] + resp2 = creator_client.get(f"{urls['BASE_URL']}{record2_id}/requests").json["hits"][ "hits" - ]["hits"] - resp3 = creator_client.get(f"{urls['BASE_URL']}{record3['id']}/requests").json[ + ] + resp3 = creator_client.get(f"{urls['BASE_URL']}{record3_id}/requests").json["hits"][ "hits" - ]["hits"] + ] assert len(resp1) == 2 assert len(resp2) == 1 diff --git a/tests/test_requests/test_timeline.py b/tests/test_requests/test_timeline.py index 6443ae1f..ca3426b7 100644 --- a/tests/test_requests/test_timeline.py +++ b/tests/test_requests/test_timeline.py @@ -7,54 +7,43 @@ # from invenio_requests.records.api import RequestEvent -from tests.test_requests.test_create_inmodel import pick_request_type -from tests.test_requests.utils import link2testclient - def test_timeline( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, + submit_request_on_draft, user_links, + link2testclient, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - link = link2testclient( - pick_request_type(draft1.json["expanded"]["request_types"], "publish_draft")[ - "links" - ]["actions"]["create"] - ) - - publish_request_resp = creator_client.post(link) - assert publish_request_resp.status_code == 201 + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] - publish_request_submit_resp = creator_client.post( - link2testclient(publish_request_resp.json["links"]["actions"]["submit"]), + publish_request_submit_resp = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) - assert publish_request_submit_resp.status_code == 200 comment_resp = creator_client.post( - link2testclient(publish_request_resp.json["links"]["comments"]), + link2testclient(publish_request_submit_resp["links"]["comments"]), json={"payload": {"content": "test"}}, ) assert comment_resp.status_code == 201 RequestEvent.index.refresh() timeline_resp = creator_client.get( - link2testclient(publish_request_resp.json["links"]["timeline"]), + link2testclient(publish_request_submit_resp["links"]["timeline"]), ) assert timeline_resp.status_code == 200 assert len(timeline_resp.json["hits"]["hits"]) == 1 # vnd serialization timeline_resp = creator_client.get( - link2testclient(publish_request_resp.json["links"]["timeline"]), + link2testclient(publish_request_submit_resp["links"]["timeline"]), headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) assert timeline_resp.status_code == 200 diff --git a/tests/test_requests/test_topic_resolve.py b/tests/test_requests/test_topic_resolve.py index e585374c..f7fadedc 100644 --- a/tests/test_requests/test_topic_resolve.py +++ b/tests/test_requests/test_topic_resolve.py @@ -10,18 +10,16 @@ from invenio_access.permissions import system_identity from thesis.records.api import ThesisDraft, ThesisRecord -from .utils import link2testclient - def test_resolve_topic( db, - vocab_cf, logged_client, record_factory, users, urls, - delete_record_data_function, + submit_request_on_record, record_service, + link2testclient, search_clear, ): creator = users[0] @@ -30,25 +28,22 @@ def test_resolve_topic( receiver_client = logged_client(receiver) record1 = record_factory(creator.identity) + record1_id = record1["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1_id, "delete_published_record" ) - assert resp_request_submit.json["status"] == "submitted" + assert resp_request_submit["status"] == "submitted" resp = creator_client.get( - link2testclient(resp_request_create.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), query_string={"expand": "true"}, ) assert resp.status_code == 200 assert resp.json["expanded"]["topic"] == { - "id": record1["id"], + "id": record1_id, "metadata": { "contributors": ["Contributor 1"], "creators": ["Creator 1", "Creator 2"], @@ -56,37 +51,37 @@ def test_resolve_topic( }, } - record_service.delete(system_identity, record1["id"]) + record_service.delete(system_identity, record1_id) ThesisRecord.index.refresh() resp = creator_client.get( - link2testclient(resp_request_create.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), ) assert resp.status_code == 200 - assert resp.json["topic"] == {"thesis": record1["id"]} + assert resp.json["topic"] == {"thesis": record1_id} resp = creator_client.get( - link2testclient(resp_request_create.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), query_string={"expand": "true"}, ) assert resp.status_code == 200 print(json.dumps(resp.json, indent=2)) - assert resp.json["topic"] == {"thesis": record1["id"]} + assert resp.json["topic"] == {"thesis": record1_id} assert resp.json["expanded"]["topic"] == { - "id": record1["id"], + "id": record1_id, "metadata": {"title": "Deleted record"}, } def test_ui_resolve_topic( db, - vocab_cf, logged_client, record_factory, users, urls, - delete_record_data_function, + submit_request_on_record, record_service, + link2testclient, search_clear, ): creator = users[0] @@ -95,27 +90,24 @@ def test_ui_resolve_topic( receiver_client = logged_client(receiver) record1 = record_factory(creator.identity) + record1_id = record1["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=delete_record_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1_id, "delete_published_record" ) - assert resp_request_submit.json["status"] == "submitted" + assert resp_request_submit["status"] == "submitted" resp = creator_client.get( - link2testclient(resp_request_create.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) assert resp.status_code == 200 assert ( resp.json["topic"].items() >= { - "reference": {"thesis": record1["id"]}, + "reference": {"thesis": record1_id}, "type": "thesis", "label": "blabla", }.items() @@ -123,8 +115,8 @@ def test_ui_resolve_topic( assert ( resp.json["topic"]["links"].items() >= { - "self": f"https://127.0.0.1:5000/api/thesis/{record1['id']}", - "self_html": f"https://127.0.0.1:5000/thesis/{record1['id']}", + "self": f"https://127.0.0.1:5000/api/thesis/{record1_id}", + "self_html": f"https://127.0.0.1:5000/thesis/{record1_id}", }.items() ) assert resp.json["stateful_name"] == "Record deletion requested" @@ -133,18 +125,18 @@ def test_ui_resolve_topic( "You will be notified about the decision by email." ) - record_service.delete(system_identity, record1["id"]) + record_service.delete(system_identity, record1_id) ThesisRecord.index.refresh() resp = creator_client.get( - link2testclient(resp_request_create.json["links"]["self"]), + link2testclient(resp_request_submit["links"]["self"]), headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) assert resp.status_code == 200 print(json.dumps(resp.json, indent=2)) assert resp.json["topic"] == { "reference": { - "thesis": record1["id"], + "thesis": record1_id, }, "status": "deleted", } diff --git a/tests/test_requests/test_topic_update.py b/tests/test_requests/test_topic_update.py index f48e5229..24401d85 100644 --- a/tests/test_requests/test_topic_update.py +++ b/tests/test_requests/test_topic_update.py @@ -6,17 +6,15 @@ # details. # -from .utils import link2testclient - def test_publish( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + draft_factory, check_publish_topic_update, + submit_request_on_draft, + link2testclient, search_clear, ): creator = users[0] @@ -25,20 +23,17 @@ def test_publish( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] + resp_request_submit = submit_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) record = receiver_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + f"{urls['BASE_URL']}{draft1_id}/draft?expand=true" + ).json publish = receiver_client.post( link2testclient( - record.json["expanded"]["requests"][0]["links"]["actions"]["accept"] + record["expanded"]["requests"][0]["links"]["actions"]["accept"] ), ) - check_publish_topic_update(creator_client, urls, record, resp_request_create) + check_publish_topic_update(creator_client, urls, record, resp_request_submit) diff --git a/tests/test_requests/test_ui_serialialization.py b/tests/test_requests/test_ui_serialialization.py index afe3bcbb..c6beacc8 100644 --- a/tests/test_requests/test_ui_serialialization.py +++ b/tests/test_requests/test_ui_serialialization.py @@ -13,56 +13,64 @@ from oarepo_requests.resolvers.ui import FallbackEntityReferenceUIResolver -from .utils import link2testclient - def test_user_serialization( users, urls, - publish_request_data_function, ui_serialization_result, - create_draft_via_resource, + draft_factory, logged_client, user_links, + create_request_on_draft, + link2testclient, search_clear, ): - client_fallback_label = logged_client(users[0]) - client_username_label = logged_client(users[1]) - client_fullname_label = logged_client(users[2]) - - draft1 = create_draft_via_resource(client_fallback_label) - draft2 = create_draft_via_resource(client_username_label) - draft3 = create_draft_via_resource(client_fullname_label) - - draft_id = draft1.json["id"] + fallback_label = users[0] + username_label = users[1] + fullname_label = users[2] + + fallback_label_client = logged_client(users[0]) + username_label_client = logged_client(users[1]) + fullname_label_client = logged_client(users[2]) + + draft1 = draft_factory(fallback_label.identity) + draft2 = draft_factory(username_label.identity) + draft3 = draft_factory(fullname_label.identity) + draft1_id = draft1["id"] + draft2_id = draft2["id"] + draft3_id = draft3["id"] + + draft_id = draft1_id ThesisRecord.index.refresh() ThesisDraft.index.refresh() - resp_request_create = client_fallback_label.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - headers={"Accept": "application/vnd.inveniordm.v1+json"}, + resp_request_create = create_request_on_draft( + fallback_label.identity, draft1_id, "publish_draft" ) - resp_request_create_username = client_username_label.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft2.json["id"]), + resp_request_create = fallback_label_client.get( + f"{urls['BASE_URL_REQUESTS']}{resp_request_create['id']}", headers={"Accept": "application/vnd.inveniordm.v1+json"}, + ).json + resp_request_create_username = create_request_on_draft( + username_label.identity, + draft2_id, + "publish_draft", ) - resp_request_create_fullname = client_fullname_label.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft3.json["id"]), - headers={"Accept": "application/vnd.inveniordm.v1+json"}, + resp_request_create_fullname = create_request_on_draft( + fullname_label.identity, + draft3_id, + "publish_draft", ) - pprint(resp_request_create.json) - assert resp_request_create.json["stateful_name"] == "Submit for review" - assert resp_request_create.json["stateful_description"] == ( + pprint(resp_request_create) + assert resp_request_create["stateful_name"] == "Submit for review" + assert resp_request_create["stateful_description"] == ( "Submit for review. After submitting the draft for review, " "it will be locked and no further modifications will be possible." ) - resp_request_submit = client_fallback_label.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = fallback_label_client.post( + link2testclient(resp_request_create["links"]["actions"]["submit"]), headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) pprint(resp_request_submit.json) @@ -72,8 +80,8 @@ def test_user_serialization( == "The draft has been submitted for review. It is now locked and no further changes are possible. You will be notified about the decision by email." ) - record = client_fallback_label.get(f"{urls['BASE_URL']}{draft_id}/draft").json - ui_record = client_fallback_label.get( + record = fallback_label_client.get(f"{urls['BASE_URL']}{draft_id}/draft").json + ui_record = fallback_label_client.get( f"{urls['BASE_URL']}{draft_id}/draft?expand=true", headers={"Accept": "application/vnd.inveniordm.v1+json"}, ).json @@ -105,12 +113,12 @@ def test_user_serialization( "type": "user", } - ui_record_username = client_username_label.get( - f"{urls['BASE_URL']}{draft2.json['id']}/draft?expand=true", + ui_record_username = username_label_client.get( + f"{urls['BASE_URL']}{draft2_id}/draft?expand=true", headers={"Accept": "application/vnd.inveniordm.v1+json"}, ).json - ui_record_fullname = client_fullname_label.get( - f"{urls['BASE_URL']}{draft3.json['id']}/draft?expand=true", + ui_record_fullname = fullname_label_client.get( + f"{urls['BASE_URL']}{draft3_id}/draft?expand=true", headers={"Accept": "application/vnd.inveniordm.v1+json"}, ).json @@ -129,10 +137,11 @@ def test_resolver_fallback( app, users, urls, - publish_request_data_function, ui_serialization_result, - create_draft_via_resource, + draft_factory, + create_request_on_draft, logged_client, + link2testclient, search_clear, ): config_restore = copy.deepcopy(app.config["ENTITY_REFERENCE_UI_RESOLVERS"]) @@ -143,29 +152,37 @@ def test_resolver_fallback( creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - draft_id = draft1.json["id"] + draft1 = draft_factory(creator.identity) + draft_id = draft1["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - headers={"Accept": "application/vnd.inveniordm.v1+json"}, + resp_request_create = create_request_on_draft( + creator.identity, draft_id, "publish_draft" ) - assert resp_request_create.json["stateful_name"] == "Submit for review" + request_id = resp_request_create["id"] + ui_serialization_read = creator_client.get( + f"{urls['BASE_URL_REQUESTS']}{request_id}", + headers={"Accept": "application/vnd.inveniordm.v1+json"}, + ).json + assert ui_serialization_read["stateful_name"] == "Submit for review" assert ( - resp_request_create.json["stateful_description"] + ui_serialization_read["stateful_description"] == "Submit for review. After submitting the draft for review, it will be locked and no further modifications will be possible." ) resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]) + ) + ui_serialization_read_submitted = creator_client.get( + f"{urls['BASE_URL_REQUESTS']}{request_id}", headers={"Accept": "application/vnd.inveniordm.v1+json"}, + ).json + assert ( + ui_serialization_read_submitted["stateful_name"] == "Submitted for review" ) - assert resp_request_submit.json["stateful_name"] == "Submitted for review" assert ( - resp_request_submit.json["stateful_description"] + ui_serialization_read_submitted["stateful_description"] == "The draft has been submitted for review. It is now locked and no further changes are possible. You will be notified about the decision by email." ) @@ -211,10 +228,10 @@ def test_role( users, role, urls, - publish_request_data_function, + create_request_on_draft, logged_client, role_ui_serialization, - create_draft_via_resource, + draft_factory, search_clear, ): config_restore = app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"] @@ -230,19 +247,24 @@ def current_receiver(record=None, request_type=None, **kwargs): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - draft_id = draft1.json["id"] + draft1 = draft_factory(creator.identity) + draft_id = draft1["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), + resp_request_create = create_request_on_draft( + creator.identity, + draft_id, + "publish_draft", headers={"Accept": "application/vnd.inveniordm.v1+json"}, ) - assert resp_request_create.json["stateful_name"] == "Submit for review" + ui_serialization_read = creator_client.get( + f"{urls['BASE_URL_REQUESTS']}{resp_request_create['id']}", + headers={"Accept": "application/vnd.inveniordm.v1+json"}, + ).json + assert ui_serialization_read["stateful_name"] == "Submit for review" assert ( - resp_request_create.json["stateful_description"] + ui_serialization_read["stateful_description"] == "Submit for review. After submitting the draft for review, it will be locked and no further modifications will be possible." ) @@ -257,11 +279,10 @@ def current_receiver(record=None, request_type=None, **kwargs): def test_auto_approve( - vocab_cf, logged_client, users, urls, - new_version_data_function, + submit_request_on_record, record_factory, search_clear, ): @@ -270,16 +291,12 @@ def test_auto_approve( record1 = record_factory(creator.identity) - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=new_version_data_function(record1["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record1["id"], "new_version" ) # is request accepted and closed? request_json = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', headers={"Accept": "application/vnd.inveniordm.v1+json"}, ).json diff --git a/tests/test_requests/test_workflows.py b/tests/test_requests/test_workflows.py index 91edebae..71f48d43 100644 --- a/tests/test_requests/test_workflows.py +++ b/tests/test_requests/test_workflows.py @@ -17,7 +17,6 @@ CreatorsFromWorkflowRequestsPermissionPolicy, ) from tests.conftest import TestEventType -from tests.test_requests.utils import link2testclient @unit_of_work() @@ -63,26 +62,15 @@ def events_service(): return current_events_service -@pytest.fixture() -def status_changing_publish_request_data_function(): - def ret_data(record_id): - return { - "request_type": "publish_draft", - "topic": {"thesis_draft": record_id}, - } - - return ret_data - - def test_publish_with_workflows( - vocab_cf, logged_client, users, urls, - status_changing_publish_request_data_function, - create_draft_via_resource, + draft_factory, + create_request_on_draft, patch_requests_permissions, record_service, + link2testclient, search_clear, ): creator = users[0] @@ -91,38 +79,36 @@ def test_publish_with_workflows( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client) + draft1 = draft_factory(creator.identity) + draft1_id = draft1["id"] ThesisRecord.index.refresh() ThesisDraft.index.refresh() # test record owner can create publish request create_non_owner = receiver_client.post( - urls["BASE_URL_REQUESTS"], - json=status_changing_publish_request_data_function(draft1.json["id"]), + f"{urls['BASE_URL']}{draft1_id}/draft/requests/publish_draft", ) - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=status_changing_publish_request_data_function(draft1.json["id"]), + resp_request_create = create_request_on_draft( + creator.identity, draft1_id, "publish_draft" ) assert create_non_owner.status_code == 403 - assert resp_request_create.status_code == 201 resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + link2testclient(resp_request_create["links"]["actions"]["submit"]), ) assert resp_request_submit.status_code == 200 # test state of the record is changed to published draft_with_submitted_request = record_service.read_draft( - creator.identity, draft1.json["id"] + creator.identity, draft1_id )._record assert draft_with_submitted_request["state"] == "publishing" record_creator = creator_client.get( - f'{urls["BASE_URL"]}{draft1.json["id"]}/draft?expand=true' + f'{urls["BASE_URL"]}{draft1_id}/draft?expand=true' ).json record_receiver = receiver_client.get( - f'{urls["BASE_URL"]}{draft1.json["id"]}/draft?expand=true' + f'{urls["BASE_URL"]}{draft1_id}/draft?expand=true' ).json assert "accept" not in record_creator["expanded"]["requests"][0]["links"]["actions"] @@ -136,19 +122,19 @@ def test_publish_with_workflows( ), ) assert accept.status_code == 200 - published_record = record_service.read(creator.identity, draft1.json["id"])._record + published_record = record_service.read(creator.identity, draft1_id)._record assert published_record["state"] == "published" def test_autorequest( db, - vocab_cf, logged_client, users, urls, patch_requests_permissions, record_service, - create_draft_via_resource, + draft_factory, + link2testclient, search_clear, ): creator = users[0] @@ -157,8 +143,8 @@ def test_autorequest( creator_client = logged_client(creator) receiver_client = logged_client(receiver) - draft1 = create_draft_via_resource(creator_client, custom_workflow="with_approve") - record_id = draft1.json["id"] + draft1 = draft_factory(creator.identity, custom_workflow="with_approve") + record_id = draft1["id"] approve_request_data = { "request_type": "approve_draft", @@ -191,13 +177,11 @@ def test_autorequest( def test_if_no_new_version_draft( - vocab_cf, patch_requests_permissions, logged_client, users, urls, - new_version_data_function, - edit_record_data_function, + submit_request_on_record, record_factory, search_clear, ): @@ -206,67 +190,53 @@ def test_if_no_new_version_draft( record = record_factory(creator.identity) record2 = record_factory(creator.identity) - id_ = record["id"] - id2_ = record2["id"] + record_id = record["id"] + record2_id = record2["id"] record = creator_client.get( - f"{urls['BASE_URL']}{id_}?expand=true", - ) - requests = record.json["expanded"]["request_types"] + f"{urls['BASE_URL']}{record_id}?expand=true", + ).json + requests = record["expanded"]["request_types"] assert "new_version" in {r["type_id"] for r in requests} - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=new_version_data_function(id_), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record_id, "new_version" ) + request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', ).json # request is autoaccepted assert request["status"] == "accepted" record = creator_client.get( - f"{urls['BASE_URL']}{id_}?expand=true", - ) - requests = record.json["expanded"]["request_types"] + f"{urls['BASE_URL']}{record_id}?expand=true", + ).json + requests = record["expanded"]["request_types"] assert "new_version" not in { r["type_id"] for r in requests } # new version created, requests should not be available again - record = creator_client.get( # try if edit is still allowed?; does it make sense edit request while also creating new version? - f"{urls['BASE_URL']}{id2_}?expand=true", - ) - requests = record.json["expanded"]["request_types"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=edit_record_data_function(id2_), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, record2_id, "edit_published_record" ) request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', ).json # request is autoaccepted assert request["status"] == "accepted" + record = creator_client.get( - f"{urls['BASE_URL']}{id2_}?expand=true", - ) - requests = record.json["expanded"]["request_types"] - assert "new_version" in { - r["type_id"] for r in requests - } # new version created, requests should not be available again + f"{urls['BASE_URL']}{record2_id}?expand=true", + ).json + requests = record["expanded"]["request_types"] + assert "new_version" in {r["type_id"] for r in requests} def test_if_no_edit_draft( - vocab_cf, patch_requests_permissions, logged_client, users, urls, - new_version_data_function, - edit_record_data_function, record_factory, + submit_request_on_record, search_clear, ): creator = users[0] @@ -282,16 +252,11 @@ def test_if_no_edit_draft( ) requests = record.json["expanded"]["request_types"] assert "edit_published_record" in {r["type_id"] for r in requests} - - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=edit_record_data_function(id_), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, id_, "edit_published_record" ) request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', ).json # request is autoaccepted assert request["status"] == "accepted" record = creator_client.get( @@ -306,15 +271,12 @@ def test_if_no_edit_draft( f"{urls['BASE_URL']}{id2_}?expand=true", ) requests = record.json["expanded"]["request_types"] - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=new_version_data_function(id2_), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_record( + creator.identity, id2_, "new_version" ) + request = creator_client.get( - f'{urls["BASE_URL_REQUESTS"]}{resp_request_create.json["id"]}', + f'{urls["BASE_URL_REQUESTS"]}{resp_request_submit["id"]}', ).json # request is autoaccepted assert request["status"] == "accepted" record = creator_client.get( @@ -331,13 +293,14 @@ def test_workflow_events( users, urls, patch_requests_permissions, + submit_request_on_draft, record_service, - publish_request_data_function, serialization_result, ui_serialization_result, events_resource_data, - create_draft_via_resource, + draft_factory, events_service, + link2testclient, search_clear, ): user1 = users[0] @@ -346,23 +309,15 @@ def test_workflow_events( user1_client = logged_client(user1) user2_client = logged_client(user2) - draft1 = create_draft_via_resource(user1_client, custom_workflow="with_approve") - record_id = draft1.json["id"] + draft1 = draft_factory(user1.identity, custom_workflow="with_approve") + record_id = draft1["id"] - approve_request_data = { - "request_type": "approve_draft", - "topic": {"thesis_draft": str(record_id)}, - } - resp_request_create = user1_client.post( - urls["BASE_URL_REQUESTS"], - json=approve_request_data, - ) - resp_request_submit = user1_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_draft( + user1.identity, record_id, "approve_draft" ) read_from_record = user1_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true", + f"{urls['BASE_URL']}{record_id}/draft?expand=true", ) request_id = read_from_record.json["expanded"]["requests"][0]["id"] @@ -394,7 +349,7 @@ def test_workflow_events( assert publishing_record["state"] == "publishing" read_from_record = user2_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true", + f"{urls['BASE_URL']}{record_id}/draft?expand=true", ) publish_request = [ request @@ -424,13 +379,14 @@ def test_workflow_events_resource( users, urls, patch_requests_permissions, + submit_request_on_draft, record_service, - publish_request_data_function, serialization_result, ui_serialization_result, events_resource_data, - create_draft_via_resource, + draft_factory, events_service, + link2testclient, search_clear, ): user1 = users[0] @@ -439,23 +395,15 @@ def test_workflow_events_resource( user1_client = logged_client(user1) user2_client = logged_client(user2) - draft1 = create_draft_via_resource(user1_client, custom_workflow="with_approve") - record_id = draft1.json["id"] + draft1 = draft_factory(user1.identity, custom_workflow="with_approve") + record_id = draft1["id"] - approve_request_data = { - "request_type": "approve_draft", - "topic": {"thesis_draft": str(record_id)}, - } - resp_request_create = user1_client.post( - urls["BASE_URL_REQUESTS"], - json=approve_request_data, - ) - resp_request_submit = user1_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), + resp_request_submit = submit_request_on_draft( + user1.identity, record_id, "approve_draft" ) read_from_record = user1_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true", + f"{urls['BASE_URL']}{record_id}/draft?expand=true", ) request_id = read_from_record.json["expanded"]["requests"][0]["id"] @@ -485,7 +433,7 @@ def test_workflow_events_resource( assert publishing_record["state"] == "publishing" read_from_record = user2_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true", + f"{urls['BASE_URL']}{record_id}/draft?expand=true", ) publish_request = [ request @@ -507,13 +455,13 @@ def test_workflow_events_resource( def test_delete_log( - vocab_cf, patch_requests_permissions, logged_client, users, urls, - submit_request_by_link, + submit_request_on_record, record_factory, + link2testclient, search_clear, ): creator = users[0] @@ -528,10 +476,10 @@ def test_delete_log( f"{urls['BASE_URL']}{record_id}?expand=true", ) - request = submit_request_by_link( - creator_client, record_response, "delete_published_record" + request = submit_request_on_record( + creator.identity, record_id, "delete_published_record" ) - request_id = request.json["id"] + request_id = request["id"] request_receiver = receiver_client.get( f'{urls["BASE_URL_REQUESTS"]}{request_id}', @@ -565,30 +513,23 @@ def test_delete_log( def test_cancel_transition( - vocab_cf, logged_client, users, urls, - publish_request_data_function, - create_draft_via_resource, + submit_request_on_draft, + draft_factory, + link2testclient, search_clear, ): creator = users[0] creator_client = logged_client(creator) - draft1 = create_draft_via_resource(creator_client) - - resp_request_create = creator_client.post( - urls["BASE_URL_REQUESTS"], - json=publish_request_data_function(draft1.json["id"]), - ) - resp_request_submit = creator_client.post( - link2testclient(resp_request_create.json["links"]["actions"]["submit"]), - ) - - record = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" + draft1 = draft_factory(creator.identity) + draft_id = draft1["id"] + resp_request_submit = submit_request_on_draft( + creator.identity, draft_id, "publish_draft" ) + record = creator_client.get(f"{urls['BASE_URL']}{draft_id}/draft?expand=true") assert record.json["expanded"]["requests"][0]["links"]["actions"].keys() == { "cancel", } @@ -599,7 +540,5 @@ def test_cancel_transition( ), ) - record = creator_client.get( - f"{urls['BASE_URL']}{draft1.json['id']}/draft?expand=true" - ) + record = creator_client.get(f"{urls['BASE_URL']}{draft_id}/draft?expand=true") assert record.json["state"] == "draft" diff --git a/tests/test_requests/utils.py b/tests/test_requests/utils.py deleted file mode 100644 index 15c344a9..00000000 --- a/tests/test_requests/utils.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (C) 2024 CESNET z.s.p.o. -# -# oarepo-requests is free software; you can redistribute it and/or -# modify it under the terms of the MIT License; see LICENSE file for more -# details. -# -from collections import defaultdict - - -def link2testclient(link, ui=False): - base_string = "https://127.0.0.1:5000/api/" if not ui else "https://127.0.0.1:5000/" - return link[len(base_string) - 1 :] - - -def _create_request(client, record_id, request_type, urls): - applicable = client.get( - f"{urls['BASE_URL']}{record_id}/draft/requests/applicable" - ).json["hits"]["hits"] - request_link = [ - type_["links"]["actions"]["create"] - for type_ in applicable - if type_["type_id"] == request_type - ][0] - ret = client.post(link2testclient(request_link)) - return ret - - -# from chatgpt -def dict_diff(dict1, dict2, path=""): - ret = defaultdict(list) - for key in dict1: - # Construct path to current element - if path == "": - new_path = key - else: - new_path = f"{path}.{key}" - - # Check if the key is in the second dictionary - if key not in dict2: - ret["second dict missing"].append( - f"{new_path}: Key missing in the second dictionary" - ) - continue - - # If both values are dictionaries, do a recursive call - if isinstance(dict1[key], dict) and isinstance(dict2[key], dict): - sub_result = dict_diff(dict1[key], dict2[key], new_path) - ret.update(sub_result) - # Check if values are the same - elif dict1[key] != dict2[key]: - ret["different values"].append(f"{new_path}: {dict1[key]} != {dict2[key]}") - - # Check for keys in the second dictionary but not in the first - for key in dict2: - if key not in dict1: - if path == "": - new_path = key - else: - new_path = f"{path}.{key}" - ret["first dict missing"].append( - f"{new_path}: Key missing in the first dictionary" - ) - return ret - - -def is_valid_subdict(subdict, dict): - diff = dict_diff(subdict, dict) - return "different values" not in diff and "second dict missing" not in diff diff --git a/tests/test_ui/test_ui_resource.py b/tests/test_ui/test_ui_resource.py index f4a1842d..19e64914 100644 --- a/tests/test_ui/test_ui_resource.py +++ b/tests/test_ui/test_ui_resource.py @@ -8,9 +8,16 @@ def test_draft_publish_request_present( - app, logged_client, users, record_ui_resource, example_topic_draft, fake_manifest + app, + logged_client, + users, + record_ui_resource, + draft_factory, + fake_manifest, ): - with logged_client(users[0]).get(f"/thesis/{example_topic_draft['id']}/edit") as c: + creator_client = logged_client(users[0]) + draft = draft_factory(users[0].identity) + with creator_client.get(f"/thesis/{draft['id']}/edit") as c: assert c.status_code == 200 data = json.loads(c.text) print(data) @@ -18,7 +25,7 @@ def test_draft_publish_request_present( "description": "Request publishing of a draft", "links": { "actions": { - "create": f"https://127.0.0.1:5000/api/thesis/{example_topic_draft['id']}/draft/requests/publish_draft" + "create": f"https://127.0.0.1:5000/api/thesis/{draft['id']}/draft/requests/publish_draft" } }, "name": "Publish draft", @@ -26,10 +33,16 @@ def test_draft_publish_request_present( def test_record_delete_request_present( - app, record_ui_resource, logged_client, users, record_factory, fake_manifest + app, + record_ui_resource, + logged_client, + users, + record_factory, + fake_manifest, ): + creator_client = logged_client(users[0]) topic = record_factory(users[0].identity) - with logged_client(users[0]).get(f"/thesis/{topic['id']}") as c: + with creator_client.get(f"/thesis/{topic['id']}") as c: assert c.status_code == 200 print(c.text) data = json.loads(c.text) @@ -55,7 +68,13 @@ def test_record_delete_request_present( def test_record_delete_unauthorized( - app, record_ui_resource, users, record_factory, client, fake_manifest + app, + record_ui_resource, + users, + record_factory, + client, + logged_client, + fake_manifest, ): topic = record_factory(users[0].identity) with client.get(f"/thesis/{topic['id']}") as c: @@ -70,24 +89,25 @@ def test_request_detail_page( record_ui_resource, users, record_factory, - client, + record_service, fake_manifest, urls, ): - topic = record_factory(users[0].identity) + identity = users[0].identity creator_client = logged_client(users[0]) + + topic = record_factory(identity) + record = record_service.read(identity, id_=topic["id"])._obj + creator_identity = users[0].identity request = current_requests_service.create( creator_identity, {}, EditPublishedRecordRequestType, - topic=topic, + topic=record, receiver=users[1].user, creator=users[0].user, ) - # resp_request_submit = creator_client.post( - # link_api2testclient(resp_request_create.json["links"]["actions"]["submit"]), - # ) request_id = request["id"] with creator_client.get(f"/requests/{request_id}") as c: