autoreply 0.3.5

autoreply: Model Context Protocol server for Bluesky profile and post search functionality
Documentation
//! Unit tests for OAuth atproto implementation
//! Tests login_hint parameter and optional handle behavior

#[cfg(test)]
mod tests {
    use crate::auth::oauth_atproto::AtProtoOAuthManager;

    #[tokio::test]
    async fn test_submit_par_with_login_hint() {
        // This test verifies that when a handle is provided,
        // the PAR request includes the login_hint parameter
        
        // Note: This would require mocking HTTP calls
        // For now, we verify the parameter structure is correct
        
        let _manager = AtProtoOAuthManager::new().expect("Failed to create OAuth manager");
        
        // Test that start_browser_flow accepts Some(&str)
        // In a full test, we'd mock the HTTP calls and verify login_hint is included
        // This is a compilation test to ensure the API is correct
        
        assert!(true, "OAuth manager can be created with optional handle support");
    }

    #[tokio::test]
    async fn test_submit_par_without_login_hint() {
        // This test verifies that when handle is None,
        // the PAR request does NOT include the login_hint parameter
        
        let _manager = AtProtoOAuthManager::new().expect("Failed to create OAuth manager");
        
        // Test that start_browser_flow accepts None
        // In a full test, we'd mock HTTP calls and verify login_hint is absent
        // This is a compilation test to ensure the API is correct
        
        assert!(true, "OAuth manager accepts None handle for account selection");
    }

    #[test]
    fn test_pkce_generation() {
        // Verify PKCE generation produces valid values
        let (verifier, challenge) = crate::auth::oauth_atproto::AtProtoOAuthManager::generate_pkce();
        
        assert!(!verifier.is_empty(), "Code verifier should not be empty");
        assert!(!challenge.is_empty(), "Code challenge should not be empty");
        assert_ne!(verifier, challenge, "Verifier and challenge should be different");
        
        // Base64 URL-safe characters only
        assert!(verifier.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-'));
        assert!(challenge.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-'));
    }

    #[test]
    fn test_state_generation() {
        // Verify state generation produces valid random values
        let state1 = crate::auth::oauth_atproto::AtProtoOAuthManager::generate_state();
        let state2 = crate::auth::oauth_atproto::AtProtoOAuthManager::generate_state();
        
        assert!(!state1.is_empty(), "State should not be empty");
        assert!(!state2.is_empty(), "State should not be empty");
        assert_ne!(state1, state2, "Each state should be unique");
        
        // Base64 URL-safe characters only
        assert!(state1.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-'));
    }
}