pg-api 0.2.0

A high-performance PostgreSQL REST API driver with rate limiting, connection pooling, and observability
//! Testes de integração para autenticação
//!
//! Estes testes verificam o comportamento do sistema de autenticação.

use std::time::Duration;

/// Testa autenticação com API key inválida
#[tokio::test]
async fn test_invalid_api_key() {
    let client = reqwest::Client::new();
    
    let result = tokio::time::timeout(
        Duration::from_secs(5),
        client
            .get("http://localhost:8580/v1/account")
            .header("X-API-Key", "invalid_key_12345")
            .send()
    ).await;
    
    let response = match result {
        Ok(Ok(resp)) => resp,
        _ => {
            println!("⚠️  Servidor não está rodando, pulando teste");
            return;
        }
    };
    
    assert_eq!(response.status(), 401);
}

/// Testa autenticação com header Authorization Bearer
#[tokio::test]
async fn test_bearer_token_auth() {
    let client = reqwest::Client::new();
    
    let result = tokio::time::timeout(
        Duration::from_secs(5),
        client
            .get("http://localhost:8580/v1/account")
            .header("Authorization", "Bearer invalid_key")
            .send()
    ).await;
    
    let response = match result {
        Ok(Ok(resp)) => resp,
        _ => {
            println!("⚠️  Servidor não está rodando, pulando teste");
            return;
        }
    };
    
    // Deve retornar 401 (key inválida) mas não 404
    assert_ne!(response.status(), 404);
}

/// Testa requisição sem nenhuma autenticação
#[tokio::test]
async fn test_no_auth_header() {
    let client = reqwest::Client::new();
    
    let result = tokio::time::timeout(
        Duration::from_secs(5),
        client.get("http://localhost:8580/v1/account").send()
    ).await;
    
    let response = match result {
        Ok(Ok(resp)) => resp,
        _ => {
            println!("⚠️  Servidor não está rodando, pulando teste");
            return;
        }
    };
    
    assert_eq!(response.status(), 401);
}

/// Testa que endpoints protegidos retornam 401
#[tokio::test]
async fn test_protected_endpoints_require_auth() {
    let client = reqwest::Client::new();
    let endpoints = vec![
        "/v1/account",
        "/v1/account/usage",
        "/v1/databases",
        "/v1/query",
        "/v1/batch",
        "/v1/transaction",
    ];
    
    for endpoint in endpoints {
        let result = tokio::time::timeout(
            Duration::from_secs(5),
            client.get(&format!("http://localhost:8580{}", endpoint)).send()
        ).await;
        
        let response = match result {
            Ok(Ok(resp)) => resp,
            _ => {
                println!("⚠️  Servidor não está rodando, pulando teste");
                return;
            }
        };
        
        // Endpoints protegidos devem retornar 401 sem auth
        // (exceto POST endpoints que podem retornar 405 para GET)
        let status = response.status();
        if status != 401 && status != 405 {
            panic!("Endpoint {} retornou {} em vez de 401", endpoint, status);
        }
    }
}

/// Testa estrutura da resposta de erro de autenticação
#[tokio::test]
async fn test_auth_error_response_format() {
    let client = reqwest::Client::new();
    
    let result = tokio::time::timeout(
        Duration::from_secs(5),
        client.get("http://localhost:8580/v1/account").send()
    ).await;
    
    let response = match result {
        Ok(Ok(resp)) => resp,
        _ => {
            println!("⚠️  Servidor não está rodando, pulando teste");
            return;
        }
    };
    
    if response.status() == 401 {
        let body: serde_json::Value = response.json().await.unwrap();
        // A resposta deve conter informação de erro
        assert!(
            body.get("success").is_some() || 
            body.get("error").is_some() ||
            body.get("message").is_some(),
            "Resposta de erro deve conter 'success', 'error' ou 'message'"
        );
    }
}