import pytest from components.BaseComponent import BaseComponent from constants import NO_SESSION, SESSION_USER_ID_KEY, NOT_LOGGED from core.instance_manager import InstanceManager class MockBaseComponent(BaseComponent): """ Mock BaseComponent that matches the expected behavior of a BaseComponent-compatible class. """ def __init__(self, session, instance_id, **kwargs): super().__init__(session, instance_id, **kwargs) self.kwargs = kwargs def __repr__(self): return f"MockBaseComponent(instance_id={self._id})" class MockInstance: """ A mock class for non-BaseComponent objects. """ def __init__(self, _id, **kwargs): self._id = _id self.kwargs = kwargs def __repr__(self): return f"MockInstance(instance_id={self._id})" class MockInstanceWithDispose(MockInstance): def __init__(self, _id, **kwargs): super().__init__(_id, **kwargs) self.disposed = False def dispose(self): self.disposed = True @pytest.fixture(autouse=True) def reset_instance_manager(): """ Automatically clears the `InstanceManager` before each test to ensure no state is carried between tests. """ InstanceManager.clear() @pytest.fixture def session(): """ Fixture to provide a default mocked session dictionary with a fixed user_id. """ return {SESSION_USER_ID_KEY: "test_user"} @pytest.fixture def instance_id(): """ Fixture to provide a default instance_id for tests. """ return "instance_1" @pytest.fixture def base_component_instance(session, instance_id): """ Fixture to provide a mock instance of MockBaseComponent for tests. """ return MockBaseComponent(session, instance_id) @pytest.fixture def mock_instance(instance_id): """ Fixture to provide a mock instance of MockInstance for tests. """ return MockInstance(instance_id) def test_get_creates_new_instance_if_not_exists(session, instance_id): """ Test that InstanceManager.get creates and returns a new instance when not already present. """ instance = InstanceManager.get(session, instance_id, instance_type=MockInstance) assert isinstance(instance, MockInstance) assert instance._id == instance_id def test_get_creates_new_instance_if_not_exists_with_extra_value(session, instance_id): """ Test that InstanceManager.get creates and returns a new instance when not already present. extra_param are passed to the constructor. """ instance = InstanceManager.get(session, instance_id, instance_type=MockInstance, extra_param="value") assert isinstance(instance, MockInstance) assert instance._id == instance_id assert instance.kwargs.get("extra_param") == "value" def test_get_creates_new_base_component_instance_if_not_exists(session, instance_id): """ Test that InstanceManager.get creates and returns a new instance for BaseComponent-derived objects. """ instance = InstanceManager.get(session, instance_id, instance_type=MockBaseComponent) assert isinstance(instance, MockBaseComponent) assert instance._id == instance_id def test_get_creates_new_base_component_instance_if_not_exists_with_extra_value(session, instance_id): """ Test that InstanceManager.get creates and returns a new instance for BaseComponent-derived objects. extra_param are passed to the constructor. """ instance = InstanceManager.get(session, instance_id, instance_type=MockBaseComponent, extra_param="value") assert isinstance(instance, MockBaseComponent) assert instance._id == instance_id assert instance.kwargs.get("extra_param") == "value" def test_get_returns_existing_instance(session, instance_id): """ Test that InstanceManager.get returns an existing instance if already registered. """ instance1 = InstanceManager.get(session, instance_id, instance_type=MockInstance) instance2 = InstanceManager.get(session, instance_id) assert instance1 == instance2 assert instance1 is instance2 # Same reference def test_register_registers_instance(session, base_component_instance): """ Test that InstanceManager.register properly stores an instance. """ InstanceManager.register(session, base_component_instance) key = (session[SESSION_USER_ID_KEY], base_component_instance._id) assert key in InstanceManager._instances assert InstanceManager._instances[key] == base_component_instance def test_register_raises_value_error_when_no_id_provided(): """ Test that InstanceManager.register raises ValueError if no instance_id is given and the instance does not have an '_id' attribute. """ instance = object() # Instance with no `_id` and not a valid `instance_id` with pytest.raises(ValueError, match="`instance_id` is not provided"): InstanceManager.register(None, instance) def test_register_fetches_id_from_instance_attribute(session): """ Test that InstanceManager.register fetches the instance_id from the '_id' attribute of the instance. """ class MockInstanceWithId: _id = "dynamic_id" instance = MockInstanceWithId() InstanceManager.register(session, instance) key = (session[SESSION_USER_ID_KEY], instance._id) # `_id` value taken from the instance assert key in InstanceManager._instances assert InstanceManager._instances[key] == instance def test_register_many_without_session(): """ Test that InstanceManager.register_many registers all provided instances even with a None session. """ instance1 = MockInstance("id1") instance2 = MockInstance("id2") InstanceManager.register_many(instance1, instance2) key1 = (NO_SESSION, "id1") key2 = (NO_SESSION, "id2") assert key1 in InstanceManager._instances assert InstanceManager._instances[key1] == instance1 assert key2 in InstanceManager._instances assert InstanceManager._instances[key2] == instance2 def test_remove_registered_instance(session, instance_id): """ Test that InstanceManager.remove removes an instance if it exists. """ instance = MockInstance(instance_id) InstanceManager.register(session, instance) InstanceManager.remove(session, instance_id) key = (session[SESSION_USER_ID_KEY], instance_id) assert key not in InstanceManager._instances def test_remove_with_dispose_method(session, instance_id): """ Register and remove an instance with a dispose method """ instance = MockInstanceWithDispose(instance_id) InstanceManager.register(session, instance) InstanceManager.remove(session, instance_id) assert hasattr(instance, "disposed") and instance.disposed key = (session[SESSION_USER_ID_KEY], instance_id) assert key not in InstanceManager._instances def test_clear_clears_all_instances(session, instance_id): """ Test that InstanceManager.clear removes all registered instances. """ instance = MockInstance(instance_id) InstanceManager.register(session, instance) InstanceManager.clear() assert not InstanceManager._instances def test_get_session_id_returns_logged_in_user_id(session): """ Test that _get_session_id extracts the session ID correctly. """ session_id = InstanceManager.get_session_id(session) assert session_id == session[SESSION_USER_ID_KEY] def test_get_session_id_returns_default_logged_out_value(): """ Test that _get_session_id returns NOT_LOGGED when session is None. """ session_id = InstanceManager.get_session_id(None) assert session_id == NO_SESSION session_id = InstanceManager.get_session_id({}) assert session_id == NOT_LOGGED