use corteq_onepassword::{Error, OnePassword};
use serial_test::serial;
fn should_run_integration_tests() -> bool {
std::env::var("OP_SERVICE_ACCOUNT_TOKEN").is_ok()
}
macro_rules! skip_if_no_token {
() => {
if !should_run_integration_tests() {
eprintln!("Skipping: OP_SERVICE_ACCOUNT_TOKEN not set");
return;
}
};
}
#[test]
#[serial]
fn test_from_env_returns_error_when_no_token() {
let original = std::env::var("OP_SERVICE_ACCOUNT_TOKEN").ok();
std::env::remove_var("OP_SERVICE_ACCOUNT_TOKEN");
let result = OnePassword::from_env();
assert!(matches!(result, Err(Error::MissingAuthToken)));
if let Some(val) = original {
std::env::set_var("OP_SERVICE_ACCOUNT_TOKEN", val);
}
}
#[test]
#[serial]
fn test_from_env_returns_error_when_empty_token() {
let original = std::env::var("OP_SERVICE_ACCOUNT_TOKEN").ok();
std::env::set_var("OP_SERVICE_ACCOUNT_TOKEN", "");
let result = OnePassword::from_env();
assert!(matches!(result, Err(Error::MissingAuthToken)));
match original {
Some(val) => std::env::set_var("OP_SERVICE_ACCOUNT_TOKEN", val),
None => std::env::remove_var("OP_SERVICE_ACCOUNT_TOKEN"),
}
}
#[test]
fn test_from_token_rejects_invalid() {
let result = OnePassword::from_token("test-token");
assert!(matches!(result, Err(Error::InvalidToken)));
}
#[test]
fn test_builder_integration_method() {
use base64::Engine;
let valid_payload = base64::engine::general_purpose::URL_SAFE_NO_PAD
.encode(r#"{"signInAddress":"example.com","email":"test@test.com","deviceUuid":"123"}"#);
let token = format!("ops_{valid_payload}");
let builder = OnePassword::from_token(&token)
.expect("valid token format should be accepted")
.integration("test-app", "1.0.0");
let _ = builder;
}
#[tokio::test]
#[ignore = "requires valid OP_SERVICE_ACCOUNT_TOKEN"]
async fn test_connect_with_valid_token() {
skip_if_no_token!();
let result = OnePassword::from_env()
.expect("token should be set")
.integration("integration-test", "0.1.0")
.connect()
.await;
assert!(result.is_ok(), "Failed to connect: {:?}", result.err());
}
#[test]
fn test_invalid_token_rejected_at_parse_time() {
let result = OnePassword::from_token("invalid-token-12345");
assert!(matches!(result, Err(Error::InvalidToken)));
}
#[tokio::test]
#[ignore = "requires valid OP_SERVICE_ACCOUNT_TOKEN"]
async fn test_connect_with_wrong_credentials() {
use base64::Engine;
let fake_payload = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(
r#"{"signInAddress":"example.com","email":"test@test.com","deviceUuid":"123","secretKey":"fake","srpX":"fake"}"#
);
let fake_token = format!("ops_{fake_payload}");
let result = OnePassword::from_token(&fake_token)
.expect("valid format should be accepted")
.integration("integration-test", "0.1.0")
.connect()
.await;
assert!(result.is_err(), "Should fail with wrong credentials");
if let Err(e) = result {
let error_str = format!("{e:?}");
assert!(
error_str.contains("Authentication")
|| error_str.contains("auth")
|| error_str.contains("Sdk")
|| error_str.contains("invalid"),
"Expected auth/sdk error, got: {error_str}"
);
}
}
#[tokio::test]
#[ignore = "requires valid OP_SERVICE_ACCOUNT_TOKEN"]
async fn test_client_is_send_sync() {
skip_if_no_token!();
let client = OnePassword::from_env()
.expect("token should be set")
.connect()
.await
.expect("connect should succeed");
let client = std::sync::Arc::new(client);
let client_clone = client.clone();
let handle = tokio::spawn(async move {
let _ = &client_clone;
});
handle.await.unwrap();
}
#[cfg(feature = "blocking")]
#[test]
#[ignore = "requires valid OP_SERVICE_ACCOUNT_TOKEN"]
fn test_connect_blocking() {
if !should_run_integration_tests() {
eprintln!("Skipping: OP_SERVICE_ACCOUNT_TOKEN not set");
return;
}
let result = OnePassword::from_env()
.expect("token should be set")
.integration("blocking-test", "0.1.0")
.connect_blocking();
assert!(result.is_ok(), "Failed to connect: {:?}", result.err());
}