Skip to content

Commit 16949a0

Browse files
committed
refactor: move commands to modules
1 parent f81dcd4 commit 16949a0

File tree

14 files changed

+1531
-629
lines changed

14 files changed

+1531
-629
lines changed

src/commands/add.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use super::{CommandContext, CommandHandler};
2+
use crate::types::AuthConfig;
3+
use std::error::Error;
4+
5+
pub struct AddCommand {
6+
pub nickname: Option<String>,
7+
pub auth_url: String,
8+
pub client_id: String,
9+
}
10+
11+
impl CommandHandler for AddCommand {
12+
async fn execute(&self, context: CommandContext<'_>) -> Result<(), Box<dyn Error>> {
13+
let nickname = match &self.nickname {
14+
Some(name) => name,
15+
None => &self.client_id,
16+
};
17+
18+
let auth_config = AuthConfig {
19+
auth_url: self.auth_url.clone(),
20+
client_id: self.client_id.clone(),
21+
refresh_token: None,
22+
};
23+
24+
context
25+
.config_manager
26+
.add_client(context.config, nickname.to_owned(), auth_config);
27+
28+
let config_path = context.config_manager.get_config_path();
29+
context
30+
.config_manager
31+
.save_config(&config_path, context.config)?;
32+
33+
println!("Client '{nickname}' added.");
34+
Ok(())
35+
}
36+
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
use crate::{
41+
commands::{CommandContext, CommandHandler, add::AddCommand},
42+
config::ConfigManager,
43+
oauth::TokenManager,
44+
types::{ConfigFile, CredentialsProvider},
45+
};
46+
47+
use tempfile::tempdir;
48+
49+
struct MockCredentialsProvider;
50+
51+
impl CredentialsProvider for MockCredentialsProvider {
52+
fn get_credentials(&self) -> Result<(String, String), Box<dyn std::error::Error>> {
53+
Ok(("user".into(), "pass".into()))
54+
}
55+
}
56+
57+
#[tokio::test]
58+
async fn test_add_command() {
59+
let _dir = tempdir().unwrap();
60+
61+
let config_manager = ConfigManager::new();
62+
let token_manager = TokenManager::new();
63+
let mut config = ConfigFile::default();
64+
65+
let add_command = AddCommand {
66+
nickname: Some("test_client".to_string()),
67+
auth_url: "https://example.com".to_string(),
68+
client_id: "client123".to_string(),
69+
};
70+
71+
let mock_credentials_provider = MockCredentialsProvider;
72+
let context = CommandContext {
73+
config: &mut config,
74+
config_manager: &config_manager,
75+
token_manager: &token_manager,
76+
credentials_provider: &mock_credentials_provider,
77+
};
78+
79+
let result = add_command.execute(context).await;
80+
assert!(result.is_ok());
81+
assert!(config.clients.contains_key("test_client"));
82+
83+
let added_client = &config.clients["test_client"];
84+
assert_eq!(added_client.auth_url, "https://example.com");
85+
assert_eq!(added_client.client_id, "client123");
86+
}
87+
88+
#[tokio::test]
89+
async fn test_add_command_without_nickname() {
90+
let config_manager = ConfigManager::new();
91+
let token_manager = TokenManager::new();
92+
let mut config = ConfigFile::default();
93+
94+
let add_command = AddCommand {
95+
nickname: None,
96+
auth_url: "https://example.com".to_string(),
97+
client_id: "client123".to_string(),
98+
};
99+
100+
let mock_credentials_provider = MockCredentialsProvider;
101+
let context = CommandContext {
102+
config: &mut config,
103+
config_manager: &config_manager,
104+
token_manager: &token_manager,
105+
credentials_provider: &mock_credentials_provider,
106+
};
107+
108+
let result = add_command.execute(context).await;
109+
assert!(result.is_ok());
110+
assert!(config.clients.contains_key("client123"));
111+
}
112+
}

src/commands/delete.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
use super::{CommandContext, CommandHandler};
2+
use std::error::Error;
3+
4+
pub struct DeleteCommand {
5+
pub nickname: String,
6+
}
7+
8+
impl CommandHandler for DeleteCommand {
9+
async fn execute(&self, context: CommandContext<'_>) -> Result<(), Box<dyn Error>> {
10+
if context
11+
.config_manager
12+
.remove_client(context.config, &self.nickname)
13+
{
14+
let config_path = context.config_manager.get_config_path();
15+
match context
16+
.config_manager
17+
.save_config(&config_path, context.config)
18+
{
19+
Ok(()) => println!("Client '{}' removed", self.nickname),
20+
Err(e) => println!("Failed to update config file.\n{e}"),
21+
}
22+
} else {
23+
println!("Client '{}' doesn't exist", self.nickname);
24+
}
25+
Ok(())
26+
}
27+
}
28+
29+
#[cfg(test)]
30+
mod tests {
31+
use std::collections::HashMap;
32+
33+
use crate::{
34+
commands::{CommandContext, CommandHandler, delete::DeleteCommand},
35+
config::ConfigManager,
36+
oauth::TokenManager,
37+
types::{AuthConfig, ConfigFile, CredentialsProvider},
38+
};
39+
40+
struct MockCredentialsProvider;
41+
42+
impl CredentialsProvider for MockCredentialsProvider {
43+
fn get_credentials(&self) -> Result<(String, String), Box<dyn std::error::Error>> {
44+
Ok(("user".into(), "pass".into()))
45+
}
46+
}
47+
48+
#[test]
49+
fn test_delete_client() {
50+
let mut config = ConfigFile {
51+
clients: [
52+
(
53+
"test1".to_string(),
54+
AuthConfig {
55+
auth_url: "https://auth1.com".to_string(),
56+
client_id: "client_id_1".to_string(),
57+
refresh_token: Some("token1".to_string()),
58+
},
59+
),
60+
(
61+
"test2".to_string(),
62+
AuthConfig {
63+
auth_url: "https://auth2.com".to_string(),
64+
client_id: "client_id_2".to_string(),
65+
refresh_token: None,
66+
},
67+
),
68+
]
69+
.into_iter()
70+
.collect(),
71+
};
72+
73+
let config_manager = ConfigManager::new();
74+
config_manager.remove_client(&mut config, "test1");
75+
76+
let target = ConfigFile {
77+
clients: [(
78+
"test2".to_string(),
79+
AuthConfig {
80+
auth_url: "https://auth2.com".to_string(),
81+
client_id: "client_id_2".to_string(),
82+
refresh_token: None,
83+
},
84+
)]
85+
.into_iter()
86+
.collect(),
87+
};
88+
89+
assert_eq!(config, target);
90+
}
91+
92+
#[tokio::test]
93+
async fn test_delete_command_existing_client() {
94+
let config_manager = ConfigManager::new();
95+
let token_manager = TokenManager::new();
96+
let mut config = ConfigFile {
97+
clients: {
98+
let mut clients = HashMap::new();
99+
clients.insert(
100+
"test_client".to_string(),
101+
AuthConfig {
102+
auth_url: "https://example.com".to_string(),
103+
client_id: "client123".to_string(),
104+
refresh_token: Some("refresh123".to_string()),
105+
},
106+
);
107+
clients
108+
},
109+
};
110+
111+
let delete_command = DeleteCommand {
112+
nickname: "test_client".to_string(),
113+
};
114+
115+
let mock_credentials_provider = MockCredentialsProvider;
116+
let context = CommandContext {
117+
config: &mut config,
118+
config_manager: &config_manager,
119+
token_manager: &token_manager,
120+
credentials_provider: &mock_credentials_provider,
121+
};
122+
123+
let result = delete_command.execute(context).await;
124+
assert!(result.is_ok());
125+
assert!(!config.clients.contains_key("test_client"));
126+
}
127+
128+
#[tokio::test]
129+
async fn test_delete_command_nonexistent_client() {
130+
let config_manager = ConfigManager::new();
131+
let token_manager = TokenManager::new();
132+
let mut config = ConfigFile::default();
133+
134+
let delete_command = DeleteCommand {
135+
nickname: "nonexistent_client".to_string(),
136+
};
137+
138+
let mock_credentials_provider = MockCredentialsProvider;
139+
let context = CommandContext {
140+
config: &mut config,
141+
config_manager: &config_manager,
142+
token_manager: &token_manager,
143+
credentials_provider: &mock_credentials_provider,
144+
};
145+
146+
let result = delete_command.execute(context).await;
147+
assert!(result.is_ok()); // Command succeeds but prints message that client doesn't exist
148+
}
149+
}

0 commit comments

Comments
 (0)