use docker_wrapper::{ensure_docker, DockerCommand, LoginCommand};
async fn setup_docker() -> Result<(), Box<dyn std::error::Error>> {
ensure_docker().await?;
Ok(())
}
#[tokio::test]
async fn test_login_command_validation() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("testuser", "testpass");
assert_eq!(login.get_username(), "testuser");
assert!(!login.is_password_stdin());
assert_eq!(login.get_registry(), None);
let args = login.build_command_args();
assert_eq!(args[0], "login");
assert!(args.contains(&"--username".to_string()));
assert!(args.contains(&"testuser".to_string()));
assert!(args.contains(&"--password".to_string()));
assert!(args.contains(&"testpass".to_string()));
Ok(())
}
#[tokio::test]
async fn test_login_command_with_registry() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("user", "pass").registry("my-registry.com");
assert_eq!(login.get_registry(), Some("my-registry.com"));
let args = login.build_command_args();
assert!(args.contains(&"my-registry.com".to_string()));
Ok(())
}
#[tokio::test]
async fn test_login_command_password_stdin() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("user", "").password_stdin();
assert!(login.is_password_stdin());
let args = login.build_command_args();
assert!(args.contains(&"--password-stdin".to_string()));
assert!(!args.contains(&"--password".to_string()));
Ok(())
}
#[tokio::test]
async fn test_login_command_docker_hub_default() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("dockeruser", "dockerpass");
assert_eq!(login.get_registry(), None);
let args = login.build_command_args();
assert!(!args.iter().any(|arg| arg.contains("docker.io")));
Ok(())
}
#[tokio::test]
async fn test_login_command_multiple_registries() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let registries = vec![
"gcr.io",
"my-registry.example.com:5000",
"localhost:5000",
"registry.gitlab.com",
];
for registry in registries {
let login = LoginCommand::new("user", "pass").registry(registry);
assert_eq!(login.get_registry(), Some(registry));
let args = login.build_command_args();
assert!(args.contains(®istry.to_string()));
}
Ok(())
}
#[tokio::test]
async fn test_login_command_builder_pattern() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("admin", "secret").registry("private-registry.company.com");
assert_eq!(login.get_username(), "admin");
assert_eq!(login.get_registry(), Some("private-registry.company.com"));
assert!(!login.is_password_stdin());
Ok(())
}
#[tokio::test]
async fn test_login_command_display() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("testuser", "testpass").registry("example.com");
let display = format!("{login}");
assert!(display.contains("docker login"));
assert!(display.contains("example.com"));
assert!(display.contains("--username testuser"));
assert!(display.contains("--password [HIDDEN]"));
assert!(!display.contains("testpass"));
Ok(())
}
#[tokio::test]
async fn test_login_command_display_stdin() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("testuser", "").password_stdin();
let display = format!("{login}");
assert!(display.contains("--password-stdin"));
assert!(!display.contains("[HIDDEN]"));
Ok(())
}
#[tokio::test]
async fn test_login_command_extensibility() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let mut login = LoginCommand::new("user", "pass");
login
.arg("--verbose")
.args(vec!["--debug"])
.flag("--insecure")
.option("--timeout", "30");
let args = login.build_command_args();
assert_eq!(args[0], "login");
assert_eq!(login.get_username(), "user");
Ok(())
}
#[tokio::test]
async fn test_login_prerequisites_validation() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("test", "test");
let args = login.build_command_args();
assert_eq!(args[0], "login");
Ok(())
}
#[tokio::test]
async fn test_login_command_security_considerations() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login_with_password = LoginCommand::new("user", "supersecret");
let display = format!("{login_with_password}");
assert!(!display.contains("supersecret"));
assert!(display.contains("[HIDDEN]"));
let login_stdin = LoginCommand::new("user", "").password_stdin();
assert!(login_stdin.is_password_stdin());
let args = login_stdin.build_command_args();
assert!(args.contains(&"--password-stdin".to_string()));
Ok(())
}
#[tokio::test]
async fn test_login_edge_cases() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login_empty_user = LoginCommand::new("", "pass");
assert_eq!(login_empty_user.get_username(), "");
let long_registry = "very-long-registry-name.example.com";
let login_long = LoginCommand::new("user", "pass").registry(long_registry);
assert_eq!(login_long.get_registry(), Some(long_registry));
let login_default = LoginCommand::default();
assert_eq!(login_default.get_username(), "");
assert!(!login_default.is_password_stdin());
Ok(())
}
#[tokio::test]
async fn test_login_command_name() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("user", "pass");
let args = login.build_command_args();
assert_eq!(args[0], "login");
Ok(())
}
#[tokio::test]
async fn test_login_command_argument_order() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let login = LoginCommand::new("testuser", "testpass").registry("example.com");
let args = login.build_command_args();
let login_pos = args.iter().position(|s| s == "login").unwrap();
let username_pos = args.iter().position(|s| s == "--username").unwrap();
let password_pos = args.iter().position(|s| s == "--password").unwrap();
let registry_pos = args.iter().position(|s| s == "example.com").unwrap();
assert!(login_pos < username_pos);
assert!(username_pos < password_pos);
assert!(password_pos < registry_pos);
Ok(())
}
#[tokio::test]
async fn test_login_various_registry_formats() -> Result<(), Box<dyn std::error::Error>> {
setup_docker().await?;
let test_cases = vec![
("gcr.io", "Google Container Registry"),
("registry-1.docker.io", "Docker Hub explicit"),
("localhost:5000", "Local registry"),
("my-registry.com:443", "Custom port"),
("registry.example.com/path", "Registry with path"),
];
for (registry, _description) in test_cases {
let login = LoginCommand::new("user", "pass").registry(registry);
let args = login.build_command_args();
assert!(args.contains(®istry.to_string()));
}
Ok(())
}