429 lines
13 KiB
Rust
429 lines
13 KiB
Rust
//! Common tests for Veza Common Library
|
|
//!
|
|
//! This module provides integration tests and test utilities for the Veza common library.
|
|
|
|
use veza_common::utils::{
|
|
generate_uuid, format_duration, format_file_size,
|
|
validate_email, validate_username, validate_password,
|
|
validate_email_result, validate_username_result,
|
|
to_json, from_json,
|
|
format_timestamp, parse_date, format_relative_time,
|
|
format_log_message, StructuredLogEntry,
|
|
};
|
|
use veza_common::types::{
|
|
Track,
|
|
};
|
|
use veza_common::config::{
|
|
DatabaseConfig, RedisConfig,
|
|
};
|
|
use veza_common::error::{
|
|
CommonError, ErrorResponse,
|
|
};
|
|
|
|
/// Test fixtures for common library tests
|
|
pub mod fixtures {
|
|
use veza_common::types::{User, Track, Playlist};
|
|
use veza_common::config::{DatabaseConfig, RedisConfig};
|
|
use uuid::Uuid;
|
|
use std::collections::HashMap;
|
|
|
|
/// Create a test user
|
|
pub fn create_test_user(id: i64) -> User {
|
|
User::new(id, format!("testuser{}", id), format!("test{}@example.com", id))
|
|
}
|
|
|
|
/// Create a test track
|
|
pub fn create_test_track(id: Uuid) -> Track {
|
|
Track::new(id, "Test Track".to_string(), "Test Artist".to_string(), 180)
|
|
}
|
|
|
|
/// Create a test playlist
|
|
pub fn create_test_playlist(id: Uuid, owner_id: Uuid) -> Playlist {
|
|
Playlist::new(id, "Test Playlist".to_string(), owner_id)
|
|
}
|
|
|
|
/// Create a test database configuration
|
|
pub fn create_test_database_config() -> DatabaseConfig {
|
|
DatabaseConfig::new(
|
|
"postgresql://test:test@localhost:5432/test_db".to_string(),
|
|
10
|
|
)
|
|
}
|
|
|
|
/// Create a test Redis configuration
|
|
pub fn create_test_redis_config() -> RedisConfig {
|
|
RedisConfig::new("redis://localhost:6379".to_string())
|
|
}
|
|
|
|
/// Create test context for logging
|
|
pub fn create_test_context() -> HashMap<String, String> {
|
|
let mut context = HashMap::new();
|
|
context.insert("user_id".to_string(), "123".to_string());
|
|
context.insert("ip".to_string(), "192.168.1.1".to_string());
|
|
context.insert("request_id".to_string(), Uuid::new_v4().to_string());
|
|
context
|
|
}
|
|
}
|
|
|
|
/// Test helpers for common library tests
|
|
pub mod helpers {
|
|
use veza_common::types::{ApiResponse, PaginationParams, PaginatedResponse};
|
|
|
|
/// Assert that a result is ok
|
|
pub fn assert_ok<T, E: std::fmt::Debug>(result: Result<T, E>) -> T {
|
|
result.expect("Expected Ok result")
|
|
}
|
|
|
|
/// Assert that a result is an error
|
|
pub fn assert_err<T: std::fmt::Debug, E>(result: Result<T, E>) -> E {
|
|
result.expect_err("Expected Err result")
|
|
}
|
|
|
|
/// Assert that two values are equal
|
|
pub fn assert_eq_expected<T: PartialEq + std::fmt::Debug>(
|
|
actual: T,
|
|
expected: T,
|
|
message: &str,
|
|
) {
|
|
assert_eq!(
|
|
actual, expected,
|
|
"{}: expected {:?}, got {:?}",
|
|
message, expected, actual
|
|
);
|
|
}
|
|
|
|
/// Create a test API response
|
|
pub fn create_test_api_response<T>(data: T) -> ApiResponse<T> {
|
|
ApiResponse::success(data)
|
|
}
|
|
|
|
/// Create a test error API response
|
|
pub fn create_test_error_response(message: &str) -> ApiResponse<String> {
|
|
ApiResponse::error(message.to_string())
|
|
}
|
|
|
|
/// Create test pagination parameters
|
|
pub fn create_test_pagination(page: u32, limit: u32) -> PaginationParams {
|
|
PaginationParams { page, limit }
|
|
}
|
|
|
|
/// Create test paginated response
|
|
pub fn create_test_paginated_response<T>(items: Vec<T>, total: u64) -> PaginatedResponse<T> {
|
|
PaginatedResponse::new(items, total, 1, 20)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use fixtures::*;
|
|
use helpers::*;
|
|
use uuid::Uuid;
|
|
|
|
#[test]
|
|
fn test_common_utilities() {
|
|
// Test UUID generation
|
|
let uuid1 = generate_uuid();
|
|
let uuid2 = generate_uuid();
|
|
assert_ne!(uuid1, uuid2);
|
|
|
|
// Test duration formatting
|
|
let formatted = format_duration(125);
|
|
assert_eq!(formatted, "2:05");
|
|
|
|
// Test file size formatting
|
|
let size = format_file_size(1024);
|
|
assert_eq!(size, "1.00 KB");
|
|
}
|
|
|
|
#[test]
|
|
fn test_validation_utilities() {
|
|
// Test email validation
|
|
assert!(validate_email("test@example.com"));
|
|
assert!(!validate_email("invalid-email"));
|
|
|
|
// Test username validation
|
|
assert!(validate_username("user123"));
|
|
assert!(!validate_username("ab")); // Too short
|
|
|
|
// Test password validation
|
|
assert!(validate_password("Password123"));
|
|
assert!(!validate_password("short")); // Too short
|
|
}
|
|
|
|
#[test]
|
|
fn test_serialization_utilities() {
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
|
struct TestData {
|
|
name: String,
|
|
value: i32,
|
|
}
|
|
|
|
let data = TestData {
|
|
name: "test".to_string(),
|
|
value: 42,
|
|
};
|
|
|
|
// Test serialization
|
|
let json = to_json(&data).unwrap();
|
|
assert!(json.contains("test"));
|
|
assert!(json.contains("42"));
|
|
|
|
// Test deserialization
|
|
let deserialized: TestData = from_json(&json).unwrap();
|
|
assert_eq!(data, deserialized);
|
|
}
|
|
|
|
#[test]
|
|
fn test_date_utilities() {
|
|
use chrono::{Utc, Duration, Datelike};
|
|
|
|
// Test timestamp formatting
|
|
let timestamp = 1609459200; // 2021-01-01 00:00:00 UTC
|
|
let formatted = format_timestamp(timestamp);
|
|
assert!(formatted.contains("2021"));
|
|
|
|
// Test date parsing
|
|
let date_str = "2021-01-01T00:00:00Z";
|
|
let dt = parse_date(date_str).unwrap();
|
|
assert_eq!(dt.year(), 2021);
|
|
|
|
// Test relative time
|
|
let now = Utc::now();
|
|
let past = now - Duration::hours(2);
|
|
let relative = format_relative_time(&past, &now);
|
|
assert!(relative.contains("2"));
|
|
assert!(relative.contains("hour"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_logging_utilities() {
|
|
// Test log message formatting
|
|
let message = format_log_message("api", "INFO", "Test message");
|
|
assert!(message.contains("api"));
|
|
assert!(message.contains("INFO"));
|
|
assert!(message.contains("Test message"));
|
|
|
|
// Test structured log entry
|
|
let entry = StructuredLogEntry::new("api", "INFO", "Test message")
|
|
.with_context("user_id".to_string(), "123".to_string());
|
|
|
|
let json = entry.to_json();
|
|
assert!(json.contains("api"));
|
|
assert!(json.contains("user_id"));
|
|
assert!(json.contains("123"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_type_utilities() {
|
|
// Test User
|
|
let user = create_test_user(1);
|
|
assert_eq!(user.id, 1);
|
|
assert_eq!(user.username, "testuser1");
|
|
assert!(user.validate().is_ok());
|
|
|
|
// Test Track
|
|
let track_id = Uuid::new_v4();
|
|
let track = create_test_track(track_id);
|
|
assert_eq!(track.id, track_id);
|
|
assert_eq!(track.title, "Test Track");
|
|
assert!(track.validate().is_ok());
|
|
|
|
// Test Playlist
|
|
let playlist_id = Uuid::new_v4();
|
|
let owner_id = Uuid::new_v4();
|
|
let playlist = create_test_playlist(playlist_id, owner_id);
|
|
assert_eq!(playlist.id, playlist_id);
|
|
assert_eq!(playlist.owner_id, owner_id);
|
|
assert!(playlist.validate().is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_utilities() {
|
|
// Test DatabaseConfig
|
|
let db_config = create_test_database_config();
|
|
assert!(db_config.validate().is_ok());
|
|
assert_eq!(db_config.host(), Some("localhost".to_string()));
|
|
assert_eq!(db_config.port(), Some(5432));
|
|
|
|
// Test RedisConfig
|
|
let redis_config = create_test_redis_config();
|
|
assert!(redis_config.validate().is_ok());
|
|
assert_eq!(redis_config.host(), Some("localhost".to_string()));
|
|
assert_eq!(redis_config.port(), Some(6379));
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_response_utilities() {
|
|
// Test success response
|
|
let response = create_test_api_response("test data");
|
|
assert!(response.success);
|
|
assert!(response.data.is_some());
|
|
assert_eq!(response.data.unwrap(), "test data");
|
|
|
|
// Test error response
|
|
let error_response = create_test_error_response("Test error");
|
|
assert!(!error_response.success);
|
|
assert!(error_response.data.is_none());
|
|
assert_eq!(error_response.error, Some("Test error".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn test_pagination_utilities() {
|
|
// Test pagination parameters
|
|
let params = create_test_pagination(2, 50);
|
|
assert_eq!(params.page, 2);
|
|
assert_eq!(params.limit, 50);
|
|
|
|
// Test paginated response
|
|
let items = vec![1, 2, 3, 4, 5];
|
|
let response = create_test_paginated_response(items.clone(), 100);
|
|
assert_eq!(response.items.len(), 5);
|
|
assert_eq!(response.total, 100);
|
|
assert_eq!(response.total_pages, 5); // 100 / 20
|
|
}
|
|
|
|
#[test]
|
|
fn test_error_handling() {
|
|
// Test CommonError
|
|
let error = CommonError::NotFound("Resource not found".to_string());
|
|
assert_eq!(error.code(), "NOT_FOUND");
|
|
assert_eq!(error.http_status_code(), 404);
|
|
assert_eq!(error.message(), "Resource not found");
|
|
|
|
// Test ErrorResponse
|
|
let error_response: ErrorResponse = (&error).into();
|
|
assert_eq!(error_response.code, "NOT_FOUND");
|
|
assert_eq!(error_response.status, 404);
|
|
}
|
|
|
|
#[test]
|
|
fn test_validation_result() {
|
|
// Test validation with Result
|
|
assert!(validate_email_result("test@example.com").is_ok());
|
|
assert!(validate_email_result("invalid-email").is_err());
|
|
|
|
assert!(validate_username_result("user123").is_ok());
|
|
assert!(validate_username_result("ab").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_validation() {
|
|
// Test DatabaseConfig validation
|
|
let mut db_config = create_test_database_config();
|
|
assert!(db_config.validate().is_ok());
|
|
|
|
// Test invalid URL
|
|
db_config.url = "invalid-url".to_string();
|
|
assert!(db_config.validate().is_err());
|
|
|
|
// Test RedisConfig validation
|
|
let mut redis_config = create_test_redis_config();
|
|
assert!(redis_config.validate().is_ok());
|
|
|
|
// Test invalid URL
|
|
redis_config.url = "invalid-url".to_string();
|
|
assert!(redis_config.validate().is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_playlist_operations() {
|
|
let playlist_id = Uuid::new_v4();
|
|
let owner_id = Uuid::new_v4();
|
|
let track_id = Uuid::new_v4();
|
|
|
|
let mut playlist = create_test_playlist(playlist_id, owner_id);
|
|
|
|
// Test adding tracks
|
|
playlist.add_track(track_id);
|
|
assert_eq!(playlist.track_count(), 1);
|
|
assert!(!playlist.is_empty());
|
|
|
|
// Test removing tracks
|
|
playlist.remove_track(track_id);
|
|
assert_eq!(playlist.track_count(), 0);
|
|
assert!(playlist.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_track_utilities() {
|
|
let track_id = Uuid::new_v4();
|
|
let track = Track::new(track_id, "Test Song".to_string(), "Test Artist".to_string(), 125);
|
|
|
|
// Test formatted duration
|
|
assert_eq!(track.formatted_duration(), "2:05");
|
|
|
|
// Test validation
|
|
assert!(track.validate().is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_helper_functions() {
|
|
// Test assert_ok
|
|
let ok_result: Result<i32, String> = Ok(42);
|
|
let value = assert_ok(ok_result);
|
|
assert_eq!(value, 42);
|
|
|
|
// Test assert_err
|
|
let err_result: Result<i32, String> = Err("Error".to_string());
|
|
let error = assert_err(err_result);
|
|
assert_eq!(error, "Error");
|
|
|
|
// Test assert_eq_expected
|
|
assert_eq_expected(5, 5, "Values should be equal");
|
|
}
|
|
|
|
#[test]
|
|
fn test_context_creation() {
|
|
let context = create_test_context();
|
|
assert!(context.contains_key("user_id"));
|
|
assert!(context.contains_key("ip"));
|
|
assert!(context.contains_key("request_id"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_round_trip_serialization() {
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
|
struct TestStruct {
|
|
id: i32,
|
|
name: String,
|
|
active: bool,
|
|
}
|
|
|
|
let original = TestStruct {
|
|
id: 1,
|
|
name: "Test".to_string(),
|
|
active: true,
|
|
};
|
|
|
|
// Serialize
|
|
let json = to_json(&original).unwrap();
|
|
|
|
// Deserialize
|
|
let deserialized: TestStruct = from_json(&json).unwrap();
|
|
|
|
assert_eq!(original, deserialized);
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_url_parsing() {
|
|
// Test database URL parsing
|
|
let db_config = DatabaseConfig::new(
|
|
"postgresql://user:pass@localhost:5433/mydb?sslmode=require".to_string(),
|
|
10
|
|
);
|
|
assert_eq!(db_config.host(), Some("localhost".to_string()));
|
|
assert_eq!(db_config.port(), Some(5433));
|
|
assert_eq!(db_config.database_name(), Some("mydb".to_string()));
|
|
|
|
// Test Redis URL parsing
|
|
let redis_config = RedisConfig::new("redis://user:pass@localhost:6380/1".to_string());
|
|
assert_eq!(redis_config.host(), Some("localhost".to_string()));
|
|
assert_eq!(redis_config.port(), Some(6380));
|
|
}
|
|
}
|
|
|