mod support;
use support::*;
#[test]
fn test_full_solo_developer_workflow() {
let t = Test::with_secrets(
"developer",
&[
("DATABASE_URL", "postgres://localhost/mydb"),
("API_KEY", "secret-api-key-12345"),
("JWT_SECRET", "super-secret-jwt"),
("REDIS_URL", "redis://localhost:6379"),
("S3_BUCKET", "my-app-bucket"),
],
);
let output = t.list();
assert_success(&output);
assert_stdout_contains(&output, "DATABASE_URL");
assert_stdout_contains(&output, "API_KEY");
assert_stdout_contains(&output, "JWT_SECRET");
assert_stdout_contains(&output, "REDIS_URL");
assert_stdout_contains(&output, "S3_BUCKET");
let output = t.secrets_unlock();
assert_success(&output);
#[cfg(unix)]
{
let output = t.run(&["sh", "-c", "echo $DATABASE_URL"]);
assert_success(&output);
assert_stdout_contains(&output, "postgres://localhost/mydb");
}
let output = t.secrets_export();
assert_success(&output);
assert_stdout_contains(&output, "DATABASE_URL=postgres://localhost/mydb");
assert_stdout_contains(&output, "API_KEY=secret-api-key-12345");
let test_env_path = t.dir.path().join("backup.env");
std::fs::write(&test_env_path, "NEW_KEY=new_value\n").unwrap();
let output = t.secrets_import("backup.env");
assert_success(&output);
let output = t.get("NEW_KEY");
assert_success(&output);
assert_stdout_contains(&output, "new_value");
}
#[test]
fn test_full_team_workflow() {
let t = Test::with_secrets(
"alice",
&[
("TEAM_DATABASE", "postgres://team/db"),
("TEAM_API_KEY", "team-secret"),
("SHARED_CONFIG", "config-value"),
],
);
let output = t.team_add("bob", BOB_PUBLIC_KEY);
assert_success(&output);
let output = t.team_list();
assert_success(&output);
assert_stdout_contains(&output, "alice");
assert_stdout_contains(&output, "bob");
let output = t.secrets_rotate();
assert_success(&output);
let output = t.get("TEAM_DATABASE");
assert_success(&output);
assert_stdout_contains(&output, "postgres://team/db");
let output = t.get("TEAM_API_KEY");
assert_success(&output);
assert_stdout_contains(&output, "team-secret");
let output = t.get("SHARED_CONFIG");
assert_success(&output);
assert_stdout_contains(&output, "config-value");
}
#[test]
fn test_rotation_preserves_all_secrets() {
let secrets = [
("SECRET_1", "value_1"),
("SECRET_2", "value_2"),
("SECRET_3", "value_3"),
("SECRET_4", "value_4"),
("SECRET_5", "value_5"),
("SECRET_6", "value_6"),
("SECRET_7", "value_7"),
("SECRET_8", "value_8"),
("SECRET_9", "value_9"),
("SECRET_10", "value_10"),
];
let t = Test::with_secrets("test-user", &secrets);
let output = t.secrets_rotate();
assert_success(&output);
for (key, expected_val) in &secrets {
let output = t.get(key);
assert_success(&output);
assert_stdout_contains(&output, expected_val);
}
}
#[test]
fn test_complex_env_import_workflow() {
let t = Test::init("test-user");
let test_env = t.dir.path().join("complex.env");
std::fs::write(&test_env, SAMPLE_ENV_COMPLEX).unwrap();
let output = t.secrets_import("complex.env");
assert_success(&output);
let output = t.get("SIMPLE");
assert_success(&output);
assert_stdout_contains(&output, "value");
let output = t.get("QUOTED");
assert_success(&output);
assert_stdout_contains(&output, "quoted value");
}
#[test]
fn test_standard_secrets_roundtrip() {
let t = Test::with_secrets("test-user", STANDARD_SECRETS);
let output = t.secrets_export();
assert_success(&output);
let exported = stdout(&output);
for (key, _) in STANDARD_SECRETS {
assert!(exported.contains(key), "Missing key: {}", key);
}
}
#[test]
fn test_disaster_recovery_workflow() {
let t = Test::with_secrets(
"test-user",
&[
("DATABASE_URL", "postgres://localhost/db"),
("API_KEY", "secret-key-123"),
("REDIS_URL", "redis://localhost:6379"),
],
);
let output = t.secrets_unlock();
assert_success(&output);
assert!(
t.dir.path().join(".env").exists(),
".env should exist after unlock"
);
std::fs::remove_file(t.dir.path().join(".env")).unwrap();
assert!(
!t.dir.path().join(".env").exists(),
".env should be deleted"
);
let output = t.secrets_unlock();
assert_success(&output);
assert!(
t.dir.path().join(".env").exists(),
".env should be restored"
);
let env_content = std::fs::read_to_string(t.dir.path().join(".env")).unwrap();
assert!(env_content.contains("DATABASE_URL=postgres://localhost/db"));
assert!(env_content.contains("API_KEY=secret-key-123"));
assert!(env_content.contains("REDIS_URL=redis://localhost:6379"));
}
#[test]
fn test_migration_workflow() {
let t = Test::with_secrets(
"alice",
&[
("MIGRATE_KEY_1", "migrate_value_1"),
("MIGRATE_KEY_2", "migrate_value_2"),
("MIGRATE_KEY_3", "migrate_value_3"),
],
);
let output = t.secrets_export();
assert_success(&output);
let exported_content = stdout(&output);
std::fs::write(t.dir.path().join("exported.env"), &exported_content).unwrap();
let output = t.rm("MIGRATE_KEY_1");
assert_success(&output);
let output = t.rm("MIGRATE_KEY_2");
assert_success(&output);
let output = t.rm("MIGRATE_KEY_3");
assert_success(&output);
let output = t.get("MIGRATE_KEY_1");
assert_failure(&output);
let output = t.secrets_import("exported.env");
assert_success(&output);
let output = t.get("MIGRATE_KEY_1");
assert_success(&output);
assert_stdout_contains(&output, "migrate_value_1");
let output = t.get("MIGRATE_KEY_2");
assert_success(&output);
assert_stdout_contains(&output, "migrate_value_2");
let output = t.get("MIGRATE_KEY_3");
assert_success(&output);
assert_stdout_contains(&output, "migrate_value_3");
}
#[test]
fn test_team_offboarding_workflow() {
let t = Test::with_secrets(
"alice",
&[
("TEAM_SECRET_1", "value1"),
("TEAM_SECRET_2", "value2"),
("TEAM_SECRET_3", "value3"),
],
);
let output = t.team_add("bob", BOB_PUBLIC_KEY);
assert_success(&output);
let output = t.team_list();
assert_success(&output);
assert_stdout_contains(&output, "bob");
let output = t.team_rm("bob");
assert_success(&output);
let output = t.team_list();
assert_success(&output);
assert_stdout_excludes(&output, "bob");
let output = t.get("TEAM_SECRET_1");
assert_success(&output);
assert_stdout_contains(&output, "value1");
let output = t.get("TEAM_SECRET_2");
assert_success(&output);
assert_stdout_contains(&output, "value2");
let output = t.get("TEAM_SECRET_3");
assert_success(&output);
assert_stdout_contains(&output, "value3");
}