use bsv::wallet::error::WalletError;
use bsv::wallet::interfaces::{
CreateActionArgs, CreateActionInput, CreateActionOptions, CreateActionOutput,
};
use bsv::wallet::validation::validate_create_action_args;
fn default_options() -> Option<CreateActionOptions> {
None
}
fn valid_args() -> CreateActionArgs {
CreateActionArgs {
description: "12345".to_string(), input_beef: None,
inputs: vec![],
outputs: vec![],
lock_time: None,
version: None,
labels: vec![],
options: default_options(),
reference: None,
}
}
fn assert_invalid_parameter(result: Result<(), WalletError>, field_substring: &str) {
match result {
Err(WalletError::InvalidParameter(msg)) => {
assert!(
msg.contains(field_substring),
"expected error message to contain '{}', got: {}",
field_substring,
msg
);
}
Err(other) => panic!(
"expected InvalidParameter containing '{}', got: {:?}",
field_substring, other
),
Ok(()) => panic!(
"expected InvalidParameter containing '{}', got Ok",
field_substring
),
}
}
#[test]
fn create_action_rejects_description_too_short() {
let mut args = valid_args();
args.description = "t".to_string(); let result = validate_create_action_args(&args);
assert_invalid_parameter(result, "description");
}
#[test]
fn create_action_rejects_empty_locking_script_with_empty_description() {
let mut args = valid_args();
args.outputs = vec![CreateActionOutput {
locking_script: None, satoshis: 0,
output_description: String::new(), basket: None,
custom_instructions: None,
tags: vec![],
}];
let result = validate_create_action_args(&args);
assert_invalid_parameter(result, "output");
}
#[test]
fn create_action_accepts_valid_args() {
let args = valid_args();
let result = validate_create_action_args(&args);
assert!(result.is_ok(), "valid args should pass validation");
}
#[test]
fn create_action_accepts_valid_output_with_locking_script() {
let mut args = valid_args();
args.outputs = vec![CreateActionOutput {
locking_script: Some(vec![0x12, 0x34]),
satoshis: 100,
output_description: "test output".to_string(),
basket: None,
custom_instructions: None,
tags: vec![],
}];
let result = validate_create_action_args(&args);
assert!(
result.is_ok(),
"output with locking_script and description should be valid"
);
}
#[test]
fn create_action_accepts_output_with_locking_script_and_empty_description() {
let mut args = valid_args();
args.outputs = vec![CreateActionOutput {
locking_script: Some(vec![0x12, 0x34]),
satoshis: 0,
output_description: String::new(), basket: None,
custom_instructions: None,
tags: vec![],
}];
let result = validate_create_action_args(&args);
assert!(
result.is_ok(),
"output with locking_script should be valid even with empty description"
);
}
#[test]
fn create_action_rejects_input_without_unlocking_script_or_length() {
let mut args = valid_args();
args.inputs = vec![CreateActionInput {
outpoint: "abc123.0".to_string(),
input_description: "test input".to_string(),
unlocking_script: None,
unlocking_script_length: None,
sequence_number: None,
}];
let result = validate_create_action_args(&args);
assert_invalid_parameter(result, "input");
}
#[test]
fn create_action_rejects_label_too_long() {
let mut args = valid_args();
args.labels = vec!["x".repeat(301)];
let result = validate_create_action_args(&args);
assert_invalid_parameter(result, "label");
}
#[test]
fn create_action_rejects_description_too_long() {
let mut args = valid_args();
args.description = "x".repeat(2001);
let result = validate_create_action_args(&args);
assert_invalid_parameter(result, "description");
}