1
use axum::{extract::State, http::StatusCode, response::IntoResponse};
2
use axum_extra::extract::CookieJar;
3
use redis::Client;
4
use std::sync::Arc;
5
use tokio::sync::Mutex;
6
use uuid::Uuid;
7
use web::{AppState, Config, User, pages};
8

            
9
6
fn create_test_app_state() -> Arc<AppState> {
10
6
    let conf = Config {
11
6
        site_url: "http://localhost:8080".to_string(),
12
6
        redis_url: "redis://127.0.0.1:6379".to_string(),
13
6
        client_origin: "http://localhost:3000".to_string(),
14
6
        access_token_private_key: "test_private_key".to_string(),
15
6
        access_token_public_key: "test_public_key".to_string(),
16
6
        refresh_token_private_key: "test_refresh_private".to_string(),
17
6
        refresh_token_public_key: "test_refresh_public".to_string(),
18
6
        access_token_expires_in: "15m".to_string(),
19
6
        access_token_max_age: 900,
20
6
        refresh_token_expires_in: "60m".to_string(),
21
6
        refresh_token_max_age: 3600,
22
6
        ssh: web::config::SshConnectInfo {
23
6
            hostname: "ssh.example.invalid".to_string(),
24
6
            port: 2222,
25
6
            host_fingerprint: "(test)".to_string(),
26
6
        },
27
6
    };
28

            
29
6
    let redis_client = Client::open("redis://127.0.0.1:6379").unwrap();
30

            
31
6
    Arc::new(AppState {
32
6
        conf,
33
6
        redis_client,
34
6
        frac: 42,
35
6
        user: Mutex::new(Some(User {
36
6
            id: Uuid::new_v4(),
37
6
            name: "Test User".to_string(),
38
6
            email: "test@example.com".to_string(),
39
6
            password: "hashed".to_string(),
40
6
            role: "user".to_string(),
41
6
            photo: String::new(),
42
6
            verified: true,
43
6
            database: "testdb".to_string(),
44
6
            created_at: Some(chrono::Utc::now()),
45
6
            updated_at: Some(chrono::Utc::now()),
46
6
        })),
47
6
    })
48
6
}
49

            
50
#[tokio::test]
51
1
async fn test_index_handler_logged_out() {
52
1
    let app_state = create_test_app_state();
53
1
    let cookie_jar = CookieJar::new();
54

            
55
1
    let response = pages::index(State(app_state), cookie_jar).await;
56
1
    let response = response.into_response();
57

            
58
1
    assert_eq!(response.status(), StatusCode::OK);
59
1
}
60

            
61
#[tokio::test]
62
1
async fn test_index_handler_returns_correct_fraction() {
63
1
    let app_state = create_test_app_state();
64
1
    let cookie_jar = CookieJar::new();
65

            
66
    // Verify the fraction value is passed correctly
67
1
    assert_eq!(app_state.frac, 42);
68

            
69
1
    let _response = pages::index(State(app_state), cookie_jar).await;
70
    // Template should receive fraction: 42
71
1
}
72

            
73
#[tokio::test]
74
1
async fn test_index_handler_user_data() {
75
1
    let app_state = create_test_app_state();
76
1
    let cookie_jar = CookieJar::new();
77

            
78
    // Verify user data is accessible
79
1
    let user_guard = app_state.user.lock().await;
80
1
    assert!(user_guard.is_some());
81
1
    assert_eq!(user_guard.as_ref().unwrap().name, "Test User");
82
1
    drop(user_guard);
83

            
84
1
    let _response = pages::index(State(app_state), cookie_jar).await;
85
1
}
86

            
87
#[tokio::test]
88
1
async fn test_file_table_handler() {
89
1
    let app_state = create_test_app_state();
90

            
91
    // This will likely fail due to S3 dependencies, but we can test the structure
92
1
    let result = pages::file_table(State(app_state)).await;
93

            
94
    // Should return either Ok or Err, both are valid outcomes for this test
95
1
    match result {
96
1
        Ok(response) => {
97
1
            let response = response.into_response();
98
1
            assert_eq!(response.status(), StatusCode::OK);
99
1
        }
100
1
        Err(status) => {
101
1
            // Expected to fail in test environment due to S3 dependencies
102
1
            assert!(matches!(
103
1
                status,
104
1
                StatusCode::INTERNAL_SERVER_ERROR | StatusCode::SERVICE_UNAVAILABLE
105
1
            ));
106
1
        }
107
1
    }
108
1
}
109

            
110
#[tokio::test]
111
1
async fn test_register_handler() {
112
1
    let response = pages::register().await;
113
1
    let response = response.into_response();
114

            
115
1
    assert_eq!(response.status(), StatusCode::OK);
116
1
}
117

            
118
#[tokio::test]
119
1
async fn test_login_handler() {
120
1
    let response = pages::login().await;
121
1
    let response = response.into_response();
122

            
123
1
    assert_eq!(response.status(), StatusCode::OK);
124
1
}
125

            
126
#[tokio::test]
127
1
async fn test_app_state_fraction_value() {
128
1
    let app_state = create_test_app_state();
129

            
130
    // Verify the test value in AppState
131
1
    assert_eq!(app_state.frac, 42);
132
1
}
133

            
134
#[tokio::test]
135
1
async fn test_app_state_user_value() {
136
1
    let app_state = create_test_app_state();
137

            
138
1
    let user_guard = app_state.user.lock().await;
139
1
    assert!(user_guard.is_some());
140

            
141
1
    let user = user_guard.as_ref().unwrap();
142
1
    assert_eq!(user.name, "Test User");
143
1
    assert_eq!(user.email, "test@example.com");
144
1
    assert_eq!(user.database, "testdb");
145
1
    assert!(user.verified);
146
1
}