diff --git a/services/capability/capability/views/capability_request.py b/services/capability/capability/views/capability_request.py index 78f5636d82d7b88943d2c9f647dff67c9cce6d77..eb52292a0722b331cd066af4b39f002077050ef0 100644 --- a/services/capability/capability/views/capability_request.py +++ b/services/capability/capability/views/capability_request.py @@ -4,12 +4,7 @@ File containing definitions for the other half of the capability side of the Workspaces REST API, concerning capability requests """ -from pyramid.httpexceptions import ( - HTTPBadRequest, - HTTPExpectationFailed, - HTTPNotFound, - HTTPPreconditionFailed, -) +from pyramid.httpexceptions import HTTPBadRequest, HTTPNotFound, HTTPPreconditionFailed from pyramid.request import Request from pyramid.response import Response from pyramid.view import view_config @@ -52,9 +47,7 @@ def create_capability_request(request: Request) -> Response: or 412 response (HTTPPreconditionFailed) if capability with given name does not exist and thus cannot be requested """ - expected_params = ["parameters", "versions"] - # TODO: What is the versions parameter going to look like? - # We can error check for a well-formatted param once we decide + expected_params = ["parameters"] capability_name = request.matchdict["capability_name"] params = request.json_body @@ -71,13 +64,10 @@ def create_capability_request(request: Request) -> Response: ) return HTTPPreconditionFailed(detail=does_not_exist_msg) else: - new_capability_request = CapabilityRequest( - parameters=params["parameters"], - versions=params["versions"], - capability_name=capability_name, - state="Created", + # TODO: Implement future products + new_capability_request = request.capabilities.create_request( + capability_name, parameters=params["parameters"], products=None ) - request.capability_info.save_entity(new_capability_request) return Response(json_body=new_capability_request.__json__()) diff --git a/services/capability/test/conftest.py b/services/capability/test/conftest.py index d84c2405674b43c5bb9906639181029c5511d239..3d83cb6fa5206ecb878bbdd665f190d59245eaaa 100644 --- a/services/capability/test/conftest.py +++ b/services/capability/test/conftest.py @@ -1,11 +1,19 @@ -from typing import Any +from typing import Any, List from unittest.mock import MagicMock import pytest from pyramid.config import Configurator from pyramid.testing import DummyRequest, setUp, tearDown -from workspaces.capability.schema import Capability, CapabilityRequest +from workspaces.capability.enums import CapabilityRequestState +from workspaces.capability.helpers import Parameter +from workspaces.capability.schema import ( + Capability, + CapabilityRequest, + CapabilityVersion, +) +from workspaces.capability.schema_interfaces import CapabilityRequestIF +from workspaces.products.schema import FutureProduct @pytest.fixture(scope="module") @@ -26,6 +34,98 @@ def test_config() -> Configurator: tearDown() +class MockCapabilityInfo(MagicMock): + capabilities = [ + Capability( + name="null", + steps="test", + max_jobs=2, + ), + Capability( + name="error", + steps="error", + max_jobs=-1, + ), + ] + capability_requests = [ + CapabilityRequest( + id=0, + state="Created", + capability_name="null", + parameters="-g", + versions=[], + ) + ] + + def edit_capability( + self, name: str, steps: str = None, max_jobs: int = None, enabled: bool = None + ) -> bool: + if name == "error": + # This is here to mimic the case where an update fails to happen + return False + for capability in self.capabilities: + if name == capability.name: + if steps: + capability.steps = steps + if max_jobs: + capability.max_jobs = max_jobs + if enabled: + capability.enabled = enabled + return True + return False + + def lookup_capability(self, capability_name: str) -> Capability: + for capability in self.capabilities: + if capability_name == capability.name: + return capability + return None + + def lookup_capability_request(self, request_id: int) -> CapabilityRequest: + for capability_request in self.capability_requests: + if request_id == capability_request.id: + return capability_request + return None + + def save_entity(self, entity: Any): + if type(entity) is Capability: + self.capabilities.append(entity) + elif type(entity) is CapabilityRequest: + entity.id = len(self.capability_requests) + self.capability_requests.append(entity) + + +class MockCapabilityService(MagicMock): + def __init__(self, capability_info: MockCapabilityInfo): + super().__init__() + self.capability_info = capability_info + + def create_request( + self, + capability_name: str, + parameters: List[Parameter] = None, + products: List[FutureProduct] = None, + ) -> CapabilityRequestIF: + """ + Mocked version of the corresponding `CapabilityService.create_request` method + + :param capability_name: Name of capability + :param parameters: Parameters for request + :param products: Product that the request will give back + :return: Newly created request + """ + capability = self.capability_info.lookup_capability(capability_name) + request = CapabilityRequest( + state=CapabilityRequestState.Ready.name, + capability=capability, + capability_name=capability_name, + parameters=str(parameters), + # a trick here is to ensure that we always have a first version, with the original parameters + versions=[CapabilityVersion(version_number=1, parameters=str(parameters))], + ) + self.capability_info.save_entity(request) + return request + + @pytest.fixture(scope="module") def request_null_capability() -> DummyRequest: """ @@ -34,64 +134,9 @@ def request_null_capability() -> DummyRequest: :return: DummyRequest with configured mock CapabilityInfo """ - class MockCapabilityInfo(MagicMock): - capabilities = [ - Capability( - name="null", - steps="test", - max_jobs=2, - ), - Capability( - name="error", - steps="error", - max_jobs=-1, - ), - ] - capability_requests = [ - CapabilityRequest( - id=0, - state="Created", - capability_name="null", - parameters="-g", - versions=[], - ) - ] - - def edit_capability( - self, name: str, steps: str = None, max_jobs: int = None, enabled: bool = None - ) -> bool: - if name == "error": - # This is here to mimic the case where an update fails to happen - return False - for capability in self.capabilities: - if name == capability.name: - if steps: - capability.steps = steps - if max_jobs: - capability.max_jobs = max_jobs - if enabled: - capability.enabled = enabled - return True - return False - - def lookup_capability(self, capability_name: str) -> Capability: - for capability in self.capabilities: - if capability_name == capability.name: - return capability - return None - - def lookup_capability_request(self, request_id: int) -> CapabilityRequest: - for capability_request in self.capability_requests: - if request_id == capability_request.id: - return capability_request - return None - - def save_entity(self, entity: Any): - if type(entity) is Capability: - self.capabilities.append(entity) - elif type(entity) is CapabilityRequest: - entity.id = len(self.capability_requests) - self.capability_requests.append(entity) - - request = DummyRequest(capability_info=MockCapabilityInfo()) + mock_capability_info = MockCapabilityInfo() + request = DummyRequest( + capability_info=mock_capability_info, + capabilities=MockCapabilityService(mock_capability_info), + ) return request diff --git a/services/capability/test/test_capability_request_views.py b/services/capability/test/test_capability_request_views.py index 8a6f71db4d07a28a412bf528b747b3065b2b737a..76c895aa6bd370e9a310e23b498c14fb01478a35 100644 --- a/services/capability/test/test_capability_request_views.py +++ b/services/capability/test/test_capability_request_views.py @@ -72,9 +72,7 @@ def test_create_capability_request( response = create_capability_request(request_null_capability) assert response.status_code == 200 - expected_response = ( - '{"id": 1, "capability_name": "null", "state": "Created", "parameters": "-g"}' - ) + expected_response = '{"id": 1, "capability_name": "null", "state": "Ready", "parameters": "-g"}' assert response.json_body == expected_response # Assert test capability has been added to list of capabilities (mocked) assert request_null_capability.capability_info.lookup_capability_request(1) diff --git a/shared/workspaces/test/test_capability_info.py b/shared/workspaces/test/test_capability_info.py index 7d996efbabeb605edb9506bf4d1ddea9f4f64488..329d386b39ac7ff6e6b652c14b36c1da7f30c278 100644 --- a/shared/workspaces/test/test_capability_info.py +++ b/shared/workspaces/test/test_capability_info.py @@ -8,14 +8,19 @@ def test_edit_capability(mock_capability_info: CapabilityInfo): Tests that edit_capability method properly follows its logic """ mock_capability_info.session.update.return_value = 1 + # Test edit with all inputs assert mock_capability_info.edit_capability("null", "test", 2) assert mock_capability_info.session.flush.call_count == 2 + # Test edit with just name and steps assert mock_capability_info.edit_capability("null", steps="test") assert mock_capability_info.session.flush.call_count == 3 + # Test edit with just name and max_jobs assert mock_capability_info.edit_capability("null", max_jobs=2) assert mock_capability_info.session.flush.call_count == 4 + # Test edit with just name assert mock_capability_info.edit_capability("null") assert mock_capability_info.session.flush.call_count == 4 + # Test "unable to edit" condition mock_capability_info.session.update.return_value = 0 assert not mock_capability_info.edit_capability("null", "test", 2) assert mock_capability_info.session.flush.call_count == 4