"""Reusable authentication tests for components with ``authRequired=true``. Any test class that includes :class:`AuthenticationTests` as a mixin must: 1. Implement :meth:`_connect_unauthenticated` returning a client with a ``test_login(username, password, expect_success)`` method. 2. Have ``self.auth_required``, ``self.test_name``, and ``self.call_expectations_manager`` available (provided by the standard ``conftest.py`` fixtures and per-class ``setup``). Tests are automatically skipped when ``self.auth_required`` is ``False``. """ import pytest from tests.conftest import DEFAULT_PASSWORD class AuthenticationTests: def _connect_unauthenticated(self): """Connect to the component under test *without* logging in.""" raise NotImplementedError def test_login_with_valid_credentials(self) -> None: if not self.auth_required: pytest.skip("Component does not require authentication") client = self._connect_unauthenticated() client.test_login(username=self.test_name, password=DEFAULT_PASSWORD) self.call_expectations_manager.verify_no_unexpected_calls() def test_login_with_invalid_username(self) -> None: if not self.auth_required: pytest.skip("Component does not require authentication") client = self._connect_unauthenticated() client.test_login(username="invalid_username", expect_success=False) self.call_expectations_manager.verify_no_unexpected_calls() def test_login_with_wrong_password(self) -> None: if not self.auth_required: pytest.skip("Component does not require authentication") client = self._connect_unauthenticated() client.test_login(username=self.test_name, password="wrong_password", expect_success=False) self.call_expectations_manager.verify_no_unexpected_calls() def test_login_twice_on_same_connection_is_rejected(self) -> None: if not self.auth_required: pytest.skip("Component does not require authentication") client = self._connect_unauthenticated() client.test_login(username=self.test_name, password=DEFAULT_PASSWORD) client.test_login(username=self.test_name, expect_success=False) self.call_expectations_manager.verify_no_unexpected_calls()