403Webshell
Server IP : 3.147.158.171  /  Your IP : 216.73.216.88
Web Server : Apache/2.4.67 (Amazon Linux) OpenSSL/3.5.5
System : Linux ip-172-31-2-178.us-east-2.compute.internal 6.1.172-216.329.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 20 06:31:34 UTC 2026 x86_64
User : ec2-user ( 1000)
PHP Version : 8.4.21
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /tsai/repo/api/tests/unit/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /tsai/repo/api/tests/unit/test_user.py
"""
Unit tests for the /user/ endpoint.

Tests cover:
- POST /user/login/ - User authentication
- POST /user/logout/ - User logout
"""

import pytest
from unittest.mock import MagicMock, patch
from fastapi.testclient import TestClient
from app.main import app
from app.api.v1.endpoints.user import get_site_config_service


class FakeSite:
    """Mock site configuration for testing."""
    wp_host = "https://fakewp.com"
    cb_host = "chat.example.com"
    api_host = "api.example.com"
    wp_dir = "/sites/test"
    drupal_host = "drupal.example.com"
    drupal_api = "/api"
    slug = "test"
    drupal_uid = "test-user"


class FakeSiteConfigService:
    """Mock site config service that returns FakeSite."""
    def get_site_by_cb_host(self, site):
        return FakeSite()


class FakeSiteConfigServiceNotFound:
    """Mock site config service that returns None (site not found)."""
    def get_site_by_cb_host(self, site):
        return None


@pytest.fixture
def client():
    """Create test client."""
    return TestClient(app)


@pytest.fixture
def client_with_mocks():
    """Create test client with dependency overrides for successful login."""
    app.dependency_overrides[get_site_config_service] = lambda: FakeSiteConfigService()

    client = TestClient(app)
    yield client

    # Clean up overrides after test
    app.dependency_overrides.clear()


@pytest.fixture
def client_site_not_found():
    """Create test client where site is not found."""
    app.dependency_overrides[get_site_config_service] = lambda: FakeSiteConfigServiceNotFound()

    client = TestClient(app)
    yield client

    app.dependency_overrides.clear()


class TestUserLogin:
    """Tests for POST /api/v1/user/login/"""

    def test_login_success(self, client_with_mocks):
        """Test successful user login."""
        with patch('app.api.v1.endpoints.user.requests.post') as mock_post:
            mock_response = MagicMock()
            mock_response.status_code = 200
            mock_response.text = '{"token": "wp_token_value"}'
            mock_response.content = b'{"token": "wp_token_value"}'
            mock_response.headers = {"Content-Type": "application/json"}
            mock_response.json.return_value = {"token": "wp_token_value"}
            mock_post.return_value = mock_response

            payload = {"username": "testuser", "password": "testpass", "site": "mysite"}
            response = client_with_mocks.post("/api/v1/user/login/", json=payload)

            assert response.status_code == 200
            data = response.json()
            assert "wp_token" in data
            assert "fapi_token" not in data

    def test_login_invalid_site(self, client_site_not_found):
        """Test login fails with invalid site.

        Note: The endpoint returns {"error": "..."} but the response_model
        requires wp_token, causing a ResponseValidationError. This test
        documents the actual behavior.
        """
        import fastapi.exceptions
        payload = {"username": "user", "password": "pass", "site": "invalid_site"}

        with pytest.raises(fastapi.exceptions.ResponseValidationError):
            client_site_not_found.post("/api/v1/user/login/", json=payload)

    def test_login_wp_failure(self, client_with_mocks):
        """Test login handles WordPress API failure."""
        with patch('app.api.v1.endpoints.user.requests.post') as mock_post:
            mock_response = MagicMock()
            mock_response.status_code = 403
            mock_response.text = "Forbidden"
            mock_response.content = b"Forbidden"
            mock_response.headers = {"Content-Type": "text/plain"}
            mock_post.return_value = mock_response

            payload = {"username": "user", "password": "wrong", "site": "mysite"}
            response = client_with_mocks.post("/api/v1/user/login/", json=payload)

            assert response.status_code == 403

    def test_login_missing_fields(self, client):
        """Test login fails with missing required fields."""
        payload = {"username": "user", "site": "mysite"}
        response = client.post("/api/v1/user/login/", json=payload)
        assert response.status_code == 422

        payload = {"password": "pass", "site": "mysite"}
        response = client.post("/api/v1/user/login/", json=payload)
        assert response.status_code == 422

        payload = {"username": "user", "password": "pass"}
        response = client.post("/api/v1/user/login/", json=payload)
        assert response.status_code == 422


class TestUserLogout:
    """Tests for POST /api/v1/user/logout/"""

    def test_logout_success(self, client):
        """Test successful logout."""
        payload = {"token": "some_token"}
        response = client.post("/api/v1/user/logout/", json=payload)

        assert response.status_code == 200
        data = response.json()
        assert data["detail"] == "Logout successful"

    def test_logout_missing_token(self, client):
        """Test logout fails with missing token."""
        payload = {}
        response = client.post("/api/v1/user/logout/", json=payload)
        assert response.status_code == 422

Youez - 2016 - github.com/yon3zu
LinuXploit