diff --git a/.github/workflows/build_validation_develop.yml b/.github/workflows/build_validation_develop.yml index 21276a47d..f66e227cd 100644 --- a/.github/workflows/build_validation_develop.yml +++ b/.github/workflows/build_validation_develop.yml @@ -103,6 +103,7 @@ jobs: VALIDATE_TSX: true VALIDATE_TYPESCRIPT_ES: true + - name: Docs validation if: ${{ steps.filter.outputs.docs == 'true' }} run: | diff --git a/api_app/pytest.ini b/api_app/pytest.ini index 9e90ef7cb..a86e89e4b 100644 --- a/api_app/pytest.ini +++ b/api_app/pytest.ini @@ -1,3 +1,5 @@ [pytest] filterwarnings = error +asyncio_mode = strict +asyncio_default_fixture_loop_scope = function diff --git a/api_app/tests_ma/conftest.py b/api_app/tests_ma/conftest.py index 6245ec23e..b47ec5a81 100644 --- a/api_app/tests_ma/conftest.py +++ b/api_app/tests_ma/conftest.py @@ -1,5 +1,5 @@ import pytest -import pytest_asyncio + from mock import AsyncMock, patch from azure.cosmos.aio import CosmosClient, DatabaseProxy @@ -575,8 +575,8 @@ def simple_pipeline_step() -> PipelineStep: ) -@pytest_asyncio.fixture(autouse=True) -async def no_database(): +@pytest.fixture(autouse=True) +def no_database(): with patch('api.dependencies.database.get_credential_async', return_value=AsyncMock()), \ patch('api.dependencies.database.CosmosClient', return_value=AsyncMock(spec=CosmosClient)) as cosmos_client_mock: cosmos_client_mock.return_value.get_database_client.return_value = AsyncMock(spec=DatabaseProxy) diff --git a/api_app/tests_ma/test_api/conftest.py b/api_app/tests_ma/test_api/conftest.py index ed284848a..66c889508 100644 --- a/api_app/tests_ma/test_api/conftest.py +++ b/api_app/tests_ma/test_api/conftest.py @@ -1,5 +1,7 @@ import pytest import pytest_asyncio + + from mock import patch from fastapi import FastAPI @@ -126,12 +128,12 @@ def inner(): return inner -@pytest_asyncio.fixture(scope='module') +@pytest.fixture(scope='module') def app() -> FastAPI: from main import get_application - the_app = get_application() - return the_app + + return get_application() @pytest_asyncio.fixture @@ -139,3 +141,5 @@ async def client(app: FastAPI) -> AsyncClient: async with AsyncClient(transport=ASGITransport(app=app), base_url="http://testserver", headers={"Content-Type": "application/json"}) as client: yield client + + diff --git a/api_app/tests_ma/test_api/test_routes/test_airlock.py b/api_app/tests_ma/test_api/test_routes/test_airlock.py index 852ef09db..7cfb61857 100644 --- a/api_app/tests_ma/test_api/test_routes/test_airlock.py +++ b/api_app/tests_ma/test_api/test_routes/test_airlock.py @@ -1,6 +1,8 @@ import time import pytest -import pytest_asyncio + +pytestmark = pytest.mark.asyncio + from mock import patch from fastapi import status from azure.core.exceptions import HttpResponseError @@ -17,7 +19,6 @@ from models.domain.operation import Operation from resources import strings from services.authentication import get_current_workspace_owner_or_researcher_user, get_current_workspace_owner_or_researcher_user_or_airlock_manager, get_current_airlock_manager_user -pytestmark = pytest.mark.asyncio WORKSPACE_ID = "abc000d3-82da-4bfc-b6e9-9a7853ef753e" @@ -127,18 +128,31 @@ def inner(): class TestAirlockRoutesThatRequireOwnerOrResearcherRights(): - @pytest_asyncio.fixture(autouse=True, scope='class') + @pytest.fixture(autouse=True, scope="class") def log_in_with_researcher_user(self, app, researcher_user): app.dependency_overrides[get_current_workspace_owner_or_researcher_user] = researcher_user app.dependency_overrides[get_current_workspace_owner_or_researcher_user_or_airlock_manager] = researcher_user - with patch("api.routes.airlock.AirlockRequestRepository.create_airlock_request_item", return_value=sample_airlock_request_object()), \ - patch("api.routes.workspaces.OperationRepository.resource_has_deployed_operation"), \ - patch("api.routes.airlock.AirlockRequestRepository.save_item"), \ - patch("api.dependencies.workspaces.WorkspaceRepository.get_workspace_by_id"), \ - patch("services.aad_authentication.AzureADAuthorization.get_workspace_user_emails_by_role_assignment", return_value={"WorkspaceResearcher": ["researcher@outlook.com"], "WorkspaceOwner": ["owner@outlook.com"], "AirlockManager": ["manager@outlook.com"]}): + with patch( + "api.routes.airlock.AirlockRequestRepository.create_airlock_request_item", + return_value=sample_airlock_request_object(), + ), patch( + "api.routes.workspaces.OperationRepository.resource_has_deployed_operation" + ), patch( + "api.routes.airlock.AirlockRequestRepository.save_item" + ), patch( + "api.dependencies.workspaces.WorkspaceRepository.get_workspace_by_id" + ), patch( + "services.aad_authentication.AzureADAuthorization.get_workspace_user_emails_by_role_assignment", + return_value={ + "WorkspaceResearcher": ["researcher@outlook.com"], + "WorkspaceOwner": ["owner@outlook.com"], + "AirlockManager": ["manager@outlook.com"], + }, + ): yield app.dependency_overrides = {} + # [GET] /workspaces/{workspace_id}/requests} @patch("api.routes.airlock.AirlockRequestRepository.get_airlock_requests", return_value=[]) async def test_get_all_airlock_requests_by_workspace_returns_200(self, _, app, client): @@ -303,17 +317,24 @@ async def test_get_airlock_container_link_returned_as_expected(self, get_airlock class TestAirlockRoutesThatRequireAirlockManagerRights(): - @pytest_asyncio.fixture(autouse=True, scope='class') + @pytest.fixture(autouse=True, scope="class") def log_in_with_airlock_manager_user(self, app, airlock_manager_user): app.dependency_overrides[get_current_airlock_manager_user] = airlock_manager_user app.dependency_overrides[get_current_workspace_owner_or_researcher_user_or_airlock_manager] = airlock_manager_user - with patch("services.airlock.AirlockRequestRepository.create_airlock_request_item", return_value=sample_airlock_request_object()), \ - patch("api.routes.workspaces.OperationRepository.resource_has_deployed_operation"), \ - patch("services.airlock.AirlockRequestRepository.save_item"), \ - patch("api.dependencies.workspaces.WorkspaceRepository.get_workspace_by_id"): + with patch( + "services.airlock.AirlockRequestRepository.create_airlock_request_item", + return_value=sample_airlock_request_object(), + ), patch( + "api.routes.workspaces.OperationRepository.resource_has_deployed_operation" + ), patch( + "services.airlock.AirlockRequestRepository.save_item" + ), patch( + "api.dependencies.workspaces.WorkspaceRepository.get_workspace_by_id" + ): yield app.dependency_overrides = {} + # [POST] /workspaces/{workspace_id}/requests/{airlock_request_id}/review @patch("services.airlock.AirlockRequestRepository.read_item_by_id", return_value=sample_airlock_request_object(status=AirlockRequestStatus.InReview)) @patch("services.airlock.AirlockRequestRepository.create_airlock_review_item", return_value=sample_airlock_review_object()) @@ -463,7 +484,7 @@ async def test_post_revoke_airlock_request_missing_reason_returns_422(self, _, a class TestAirlockRoutesPermissions(): - @pytest_asyncio.fixture() + @pytest.fixture() def log_in_with_user(self, app): def inner(user): app.dependency_overrides[get_current_workspace_owner_or_researcher_user] = user @@ -471,6 +492,7 @@ def inner(user): app.dependency_overrides[get_current_workspace_owner_or_researcher_user_or_airlock_manager] = user return inner + @pytest.mark.parametrize("role", (role for role in get_required_roles(endpoint=create_draft_request))) @patch("api.routes.workspaces.OperationRepository.resource_has_deployed_operation") @patch("api.dependencies.workspaces.WorkspaceRepository.get_workspace_by_id", return_value=sample_workspace(WORKSPACE_ID))