#[cfg(test)]
mod tests {
use super::super::repository::{
PostgresRepository, DatabaseOperations, Entity,
PaginationParams, SortParams, SortDirection,
FilterParams, FilterCondition, PaginatedResult, PaginationInfo
};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, postgres::PgRow};
use chrono::NaiveDateTime;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
struct TestUser {
id: String,
name: String,
email: String,
created_at: Option<NaiveDateTime>,
updated_at: Option<NaiveDateTime>,
deleted_at: Option<NaiveDateTime>,
}
impl Entity for TestUser {
fn id(&self) -> Option<&str> {
Some(&self.id)
}
fn table_name() -> &'static str {
"test_users"
}
fn is_deleted(&self) -> bool {
self.deleted_at.is_some()
}
fn created_at(&self) -> Option<NaiveDateTime> {
self.created_at
}
fn updated_at(&self) -> Option<NaiveDateTime> {
self.updated_at
}
}
#[test]
fn test_pagination_params_new() {
let pagination = PaginationParams::new(2, 25);
assert_eq!(pagination.page, 2);
assert_eq!(pagination.per_page, 25);
}
#[test]
fn test_pagination_params_page_minimum() {
let pagination = PaginationParams::new(0, 25);
assert_eq!(pagination.page, 1); assert_eq!(pagination.per_page, 25);
}
#[test]
fn test_pagination_params_per_page_limits() {
let pagination1 = PaginationParams::new(1, 0);
assert_eq!(pagination1.per_page, 1);
let pagination2 = PaginationParams::new(1, 200);
assert_eq!(pagination2.per_page, 100);
let pagination3 = PaginationParams::new(1, 50);
assert_eq!(pagination3.per_page, 50); }
#[test]
fn test_pagination_params_offset() {
let pagination = PaginationParams::new(3, 20);
assert_eq!(pagination.offset(), 40); }
#[test]
fn test_pagination_params_limit() {
let pagination = PaginationParams::new(1, 15);
assert_eq!(pagination.limit(), 15);
}
#[test]
fn test_sort_params_default() {
let sort = SortParams::default();
assert_eq!(sort.field, "");
match sort.direction {
SortDirection::Asc => assert!(true),
_ => assert!(false),
}
}
#[test]
fn test_sort_direction_default() {
let direction = SortDirection::default();
match direction {
SortDirection::Asc => assert!(true),
_ => assert!(false),
}
}
#[test]
fn test_filter_params_default() {
let filter = FilterParams::default();
assert!(filter.conditions.is_empty());
}
#[test]
fn test_filter_params_with_conditions() {
let mut conditions = HashMap::new();
conditions.insert("name".to_string(), FilterCondition::Equals("John".to_string()));
conditions.insert("age".to_string(), FilterCondition::GreaterThan("25".to_string()));
let filter = FilterParams { conditions };
assert_eq!(filter.conditions.len(), 2);
assert!(filter.conditions.contains_key("name"));
assert!(filter.conditions.contains_key("age"));
}
#[test]
fn test_filter_condition_variants() {
let equals = FilterCondition::Equals("test".to_string());
let not_equals = FilterCondition::NotEquals("test".to_string());
let greater_than = FilterCondition::GreaterThan("100".to_string());
let less_than = FilterCondition::LessThan("200".to_string());
let like = FilterCondition::Like("%pattern%".to_string());
let in_values = FilterCondition::In(vec!["a".to_string(), "b".to_string()]);
let is_null = FilterCondition::IsNull;
let is_not_null = FilterCondition::IsNotNull;
match equals {
FilterCondition::Equals(_) => assert!(true),
_ => assert!(false),
}
match not_equals {
FilterCondition::NotEquals(_) => assert!(true),
_ => assert!(false),
}
match greater_than {
FilterCondition::GreaterThan(_) => assert!(true),
_ => assert!(false),
}
match less_than {
FilterCondition::LessThan(_) => assert!(true),
_ => assert!(false),
}
match like {
FilterCondition::Like(_) => assert!(true),
_ => assert!(false),
}
match in_values {
FilterCondition::In(_) => assert!(true),
_ => assert!(false),
}
match is_null {
FilterCondition::IsNull => assert!(true),
_ => assert!(false),
}
match is_not_null {
FilterCondition::IsNotNull => assert!(true),
_ => assert!(false),
}
}
#[test]
fn test_pagination_info_new() {
let pagination_info = PaginationInfo::new(2, 10, 95);
assert_eq!(pagination_info.page, 2);
assert_eq!(pagination_info.per_page, 10);
assert_eq!(pagination_info.total, 95);
assert_eq!(pagination_info.total_pages, 10); }
#[test]
fn test_pagination_info_exact_pages() {
let pagination_info = PaginationInfo::new(1, 10, 100);
assert_eq!(pagination_info.total_pages, 10); }
#[test]
fn test_pagination_info_less_than_per_page() {
let pagination_info = PaginationInfo::new(1, 10, 5);
assert_eq!(pagination_info.total_pages, 1); }
#[test]
fn test_paginated_result_structure() {
let data = vec!["item1", "item2", "item3"];
let pagination = PaginationInfo::new(1, 10, 100);
let result = PaginatedResult {
data: data.clone(),
pagination: pagination.clone(),
};
assert_eq!(result.data, data);
assert_eq!(result.pagination.page, pagination.page);
assert_eq!(result.pagination.per_page, pagination.per_page);
assert_eq!(result.pagination.total, pagination.total);
assert_eq!(result.pagination.total_pages, pagination.total_pages);
}
#[test]
fn test_test_user_entity_implementation() {
let user = TestUser {
id: "123".to_string(),
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
created_at: Some(NaiveDateTime::from_timestamp_opt(1609459200, 0).unwrap()),
updated_at: Some(NaiveDateTime::from_timestamp_opt(1609459260, 0).unwrap()),
deleted_at: None,
};
assert_eq!(user.id(), Some("123"));
assert_eq!(TestUser::table_name(), "test_users");
assert!(!user.is_deleted()); assert!(user.created_at().is_some());
assert!(user.updated_at().is_some());
}
#[test]
fn test_test_user_deleted() {
let user = TestUser {
id: "123".to_string(),
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
created_at: None,
updated_at: None,
deleted_at: Some(NaiveDateTime::from_timestamp_opt(1609459200, 0).unwrap()),
};
assert!(user.is_deleted()); }
#[test]
fn test_test_user_no_id() {
let user = TestUser {
id: "".to_string(), name: "John Doe".to_string(),
email: "john@example.com".to_string(),
created_at: None,
updated_at: None,
deleted_at: None,
};
assert_eq!(user.id(), Some("")); }
#[test]
fn test_postgres_repository_structure() {
fn check_repository_types() {
let _: Option<Box<dyn DatabaseOperations<TestUser>>> = None;
let _: Option<PostgresRepository<TestUser>> = None;
}
check_repository_types();
}
#[test]
fn test_all_traits_can_be_implemented() {
fn check_trait_compatibility(user: TestUser) {
let _id = user.id();
let _table = TestUser::table_name();
let _is_deleted = user.is_deleted();
fn expects_from_row<T: for<'a> FromRow<'a, PgRow>>(_: T) {}
expects_from_row(user);
}
let user = TestUser {
id: "test".to_string(),
name: "Test".to_string(),
email: "test@example.com".to_string(),
created_at: None,
updated_at: None,
deleted_at: None,
};
check_trait_compatibility(user);
}
#[test]
fn test_database_operations_trait_exists() {
fn check_database_operations<T: DatabaseOperations<TestUser>>(_: T) {
}
check_database_operations_type::<PostgresRepository<TestUser>>();
}
fn check_database_operations_type<T: DatabaseOperations<TestUser>>() {}
}