"""Fixtures for a version of API testing that relies more heavily on pytest injection.""" import os from collections.abc import Iterator from dataclasses import dataclass from typing import ( Any, Optional, ) import pytest from galaxy.tool_util.verify.test_data import TestDataResolver from galaxy_test.base.api import ( AnonymousGalaxyInteractor, ApiTestInteractor, ) from galaxy_test.base.api_util import ( get_admin_api_key, get_user_api_key, ) from galaxy_test.base.env import setup_keep_outdir from galaxy_test.base.mock_http_server import ( MockHTTPRequestHandler, MockHttpServer, start_mock_http_server, ) from galaxy_test.base.populators import ( check_missing_tool, DatasetCollectionPopulator, DatasetPopulator, DescribeToolInputs, get_tool_ids, RequiredTool, TargetHistory, ) from galaxy_test.base.testcase import host_port_and_url @dataclass class ApiConfigObject: host: str port: Optional[str] url: str user_api_key: Optional[str] admin_api_key: Optional[str] test_data_resolver: Any keepOutdir: Any @pytest.fixture(scope="session") def api_test_config_object(real_driver) -> ApiConfigObject: host, port, url = host_port_and_url(real_driver) user_api_key = get_user_api_key() admin_api_key = get_admin_api_key() test_data_resolver = TestDataResolver() keepOutdir = setup_keep_outdir() return ApiConfigObject( host, port, url, user_api_key, admin_api_key, test_data_resolver, keepOutdir, ) @pytest.fixture(scope="session") def galaxy_interactor(api_test_config_object: ApiConfigObject) -> ApiTestInteractor: return ApiTestInteractor(api_test_config_object) @pytest.fixture(scope="session") def dataset_populator(galaxy_interactor: ApiTestInteractor) -> DatasetPopulator: return DatasetPopulator(galaxy_interactor) @pytest.fixture(scope="session") def dataset_collection_populator(galaxy_interactor: ApiTestInteractor) -> DatasetCollectionPopulator: return DatasetCollectionPopulator(galaxy_interactor) @pytest.fixture(scope="session") def anonymous_galaxy_interactor(api_test_config_object: ApiConfigObject) -> AnonymousGalaxyInteractor: return AnonymousGalaxyInteractor(api_test_config_object) @pytest.fixture(autouse=True, scope="session") def request_celery_app(celery_session_app, celery_config): try: yield finally: if os.environ.get("GALAXY_TEST_EXTERNAL") is None: from galaxy.celery import celery_app celery_app.fork_pool.stop() celery_app.fork_pool.join(timeout=5) @pytest.fixture(autouse=True, scope="session") def request_celery_worker(celery_session_worker, celery_config, celery_worker_parameters): yield @pytest.fixture(scope="session", autouse=True) def celery_worker_parameters(): return { "queues": ("galaxy.internal", "galaxy.external"), } @pytest.fixture(scope="session") def celery_parameters(): return { "task_create_missing_queues": True, "task_default_queue": "galaxy.internal", } @pytest.fixture def history_id(dataset_populator: DatasetPopulator, request) -> Iterator[str]: history_name = f"API Test History for {request.node.nodeid}" with dataset_populator.test_history(name=history_name) as history_id: yield history_id @pytest.fixture def target_history( dataset_populator: DatasetPopulator, dataset_collection_populator: DatasetCollectionPopulator, history_id: str ) -> TargetHistory: return TargetHistory(dataset_populator, dataset_collection_populator, history_id) @pytest.fixture def required_tools( dataset_populator: DatasetPopulator, history_id: str, required_tool_ids: list[str] ) -> list[RequiredTool]: tools = [] for tool_id in required_tool_ids: tool = RequiredTool(dataset_populator, tool_id, history_id) tools.append(tool) return tools @pytest.fixture def required_tool(dataset_populator: DatasetPopulator, history_id: str, required_tool_ids: list[str]) -> RequiredTool: if len(required_tool_ids) != 1: raise AssertionError("required_tool fixture must only be used on methods that require a single tool") tool_id = required_tool_ids[0] tool = RequiredTool(dataset_populator, tool_id, history_id) return tool @pytest.fixture(params=["legacy", "21.01", "request"]) def tool_input_format(request) -> Iterator[DescribeToolInputs]: yield DescribeToolInputs(request.param) @pytest.fixture(autouse=True) def check_required_tools(anonymous_galaxy_interactor, request): for marker in request.node.iter_markers(): if marker.name == "requires_tool_id": tool_id = _requires_marker_to_effective_tool_id(anonymous_galaxy_interactor, marker) check_missing_tool(tool_id not in get_tool_ids(anonymous_galaxy_interactor)) @pytest.fixture def required_tool_ids(anonymous_galaxy_interactor, request) -> list[str]: tool_ids = [] for marker in request.node.iter_markers(): if marker.name == "requires_tool_id": tool_id = _requires_marker_to_effective_tool_id(anonymous_galaxy_interactor, marker) tool_ids.append(tool_id) return tool_ids def _requires_marker_to_effective_tool_id(anonymous_galaxy_interactor, marker): tool_id = marker.args[0] if "|" in tool_id: any_of_tool_ids = tool_id.split("|") all_tool_ids = get_tool_ids(anonymous_galaxy_interactor) tool_id = [t for t in any_of_tool_ids if t in all_tool_ids][0] return tool_id @pytest.fixture(scope="session") def mock_http_server(): if os.environ.get("GALAXY_TEST_EXTERNAL"): yield MockHttpServer(base_url=None, handler_class=None, is_remote=True) else: server, base_url = start_mock_http_server() try: yield MockHttpServer(base_url=base_url, handler_class=MockHTTPRequestHandler, is_remote=False) finally: server.shutdown()