use rust_decimal_macros::dec;
use stateset_embedded::{
Commerce, CreateBom, CreateCustomer, CreateInventoryItem, CreateOrder, CreateOrderItem,
CreateProduct, CreateReturn, OrderStatus,
};
use uuid::Uuid;
#[test]
fn test_order_not_found() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.orders().get(fake_id.into());
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
#[test]
fn test_order_update_nonexistent() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.orders().update_status(fake_id.into(), OrderStatus::Confirmed);
assert!(result.is_err());
}
#[test]
fn test_order_delete_nonexistent() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.orders().delete(fake_id.into());
assert!(result.is_ok());
}
#[test]
fn test_order_with_invalid_customer() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.orders().create(CreateOrder {
customer_id: Uuid::new_v4().into(),
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: "TEST-001".into(),
name: "Test Product".into(),
quantity: 1,
unit_price: dec!(10.00),
..Default::default()
}],
..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_order_empty_items() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.orders().create(CreateOrder {
customer_id: Uuid::new_v4().into(),
items: vec![], ..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_order_negative_quantity() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.orders().create(CreateOrder {
customer_id: Uuid::new_v4().into(),
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: "TEST-001".into(),
name: "Test Product".into(),
quantity: -1, unit_price: dec!(10.00),
..Default::default()
}],
..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_order_zero_quantity() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.orders().create(CreateOrder {
customer_id: Uuid::new_v4().into(),
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: "TEST-001".into(),
name: "Test Product".into(),
quantity: 0, unit_price: dec!(10.00),
..Default::default()
}],
..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_customer_not_found() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.customers().get(fake_id.into());
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
#[test]
fn test_customer_duplicate_email() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
commerce
.customers()
.create(CreateCustomer {
email: "duplicate@example.com".into(),
first_name: "First".into(),
last_name: "Customer".into(),
..Default::default()
})
.expect("Failed to create first customer");
let result = commerce.customers().create(CreateCustomer {
email: "duplicate@example.com".into(),
first_name: "Second".into(),
last_name: "Customer".into(),
..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_customer_invalid_email() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.customers().create(CreateCustomer {
email: "not-an-email".into(), first_name: "Test".into(),
last_name: "User".into(),
..Default::default()
});
assert!(result.is_err(), "Expected invalid email to be rejected");
let err = result.unwrap_err().to_string();
assert!(err.contains("@") || err.contains("email"), "Error should mention email format");
}
#[test]
fn test_customer_empty_email() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.customers().create(CreateCustomer {
email: String::new(), first_name: "Test".into(),
last_name: "User".into(),
..Default::default()
});
assert!(result.is_err(), "Expected empty email to be rejected");
let err = result.unwrap_err().to_string();
assert!(
err.to_lowercase().contains("empty") || err.to_lowercase().contains("email"),
"Error should mention empty email: {}",
err
);
}
#[test]
fn test_inventory_item_not_found() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.inventory().get_item_by_sku("NONEXISTENT-SKU");
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
#[test]
fn test_inventory_duplicate_sku() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
commerce
.inventory()
.create_item(CreateInventoryItem {
sku: "DUP-SKU-001".into(),
name: "First Item".into(),
..Default::default()
})
.expect("Failed to create first item");
let result = commerce.inventory().create_item(CreateInventoryItem {
sku: "DUP-SKU-001".into(),
name: "Second Item".into(),
..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_inventory_adjust_nonexistent() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.inventory().adjust("NONEXISTENT-SKU", dec!(10), "Test adjustment");
assert!(result.is_err());
}
#[test]
fn test_inventory_reserve_insufficient_stock() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
commerce
.inventory()
.create_item(CreateInventoryItem {
sku: "LIMITED-001".into(),
name: "Limited Stock Item".into(),
initial_quantity: Some(dec!(5)),
..Default::default()
})
.expect("Failed to create item");
let result = commerce.inventory().reserve(
"LIMITED-001",
dec!(100), "order",
&Uuid::new_v4().to_string(),
None,
);
assert!(result.is_err());
}
#[test]
fn test_inventory_release_nonexistent_reservation() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_reservation_id = Uuid::new_v4();
let result = commerce.inventory().release_reservation(fake_reservation_id);
assert!(result.is_err());
}
#[test]
fn test_inventory_negative_adjustment_exceeds_stock() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
commerce
.inventory()
.create_item(CreateInventoryItem {
sku: "NEG-TEST-001".into(),
name: "Negative Test Item".into(),
initial_quantity: Some(dec!(10)),
..Default::default()
})
.expect("Failed to create item");
let result = commerce.inventory().adjust("NEG-TEST-001", dec!(-100), "Over-adjustment");
println!("Negative adjustment result: {:?}", result);
}
#[test]
fn test_product_not_found() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.products().get(fake_id.into());
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
#[test]
fn test_product_duplicate_slug() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
commerce
.products()
.create(CreateProduct {
name: "First Product".into(),
slug: Some("duplicate-slug".into()),
..Default::default()
})
.expect("Failed to create first product");
let result = commerce.products().create(CreateProduct {
name: "Second Product".into(),
slug: Some("duplicate-slug".into()),
..Default::default()
});
assert!(result.is_err());
}
#[test]
fn test_product_variant_duplicate_sku() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let product = commerce
.products()
.create(CreateProduct { name: "Test Product".into(), ..Default::default() })
.expect("Failed to create product");
commerce
.inventory()
.create_item(CreateInventoryItem {
sku: "VAR-DUP-001".into(),
name: "Variant Item".into(),
..Default::default()
})
.expect("Failed to create inventory");
println!("Product created with id: {:?}", product.id);
}
#[test]
fn test_return_not_found() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.returns().get(fake_id.into());
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
#[test]
fn test_return_for_nonexistent_order() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.returns().create(CreateReturn {
order_id: Uuid::new_v4().into(), reason: stateset_embedded::ReturnReason::Other,
reason_details: Some("Test return".into()),
..Default::default()
});
println!("Return for nonexistent order result: {:?}", result);
}
#[test]
fn test_return_approve_already_approved() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let customer = commerce
.customers()
.create(CreateCustomer {
email: "return-test@example.com".into(),
first_name: "Return".into(),
last_name: "Test".into(),
..Default::default()
})
.expect("Failed to create customer");
let order = commerce
.orders()
.create(CreateOrder {
customer_id: customer.id,
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: "RET-001".into(),
name: "Returnable Item".into(),
quantity: 1,
unit_price: dec!(50.00),
..Default::default()
}],
..Default::default()
})
.expect("Failed to create order");
let order_with_items =
commerce.orders().get(order.id).expect("Failed to get order").expect("Order not found");
let order_item = order_with_items.items.first().expect("Order should have items");
let ret = commerce
.returns()
.create(CreateReturn {
order_id: order.id,
reason: stateset_embedded::ReturnReason::Defective,
reason_details: None,
items: vec![stateset_embedded::CreateReturnItem {
order_item_id: order_item.id,
quantity: 1,
condition: None,
}],
..Default::default()
})
.expect("Failed to create return");
commerce.returns().approve(ret.id).expect("Failed to approve return");
let result = commerce.returns().approve(ret.id);
println!("Double approve result: {:?}", result);
}
#[test]
fn test_bom_not_found() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let fake_id = Uuid::new_v4();
let result = commerce.bom().get(fake_id);
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
#[test]
fn test_bom_activate_already_active() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let bom = commerce
.bom()
.create(CreateBom {
product_id: Uuid::new_v4().into(),
name: "Test BOM".into(),
..Default::default()
})
.expect("Failed to create BOM");
commerce.bom().activate(bom.id).expect("Failed to activate");
let result = commerce.bom().activate(bom.id);
println!("Double activate result: {:?}", result);
}
#[test]
fn test_bom_component_circular_reference() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let bom = commerce
.bom()
.create(CreateBom {
product_id: Uuid::new_v4().into(),
name: "Circular BOM".into(),
..Default::default()
})
.expect("Failed to create BOM");
println!("BOM created: {:?}", bom.bom_number);
}
#[test]
fn test_concurrent_inventory_updates() {
use std::sync::Arc;
use std::thread;
let commerce = Arc::new(Commerce::new(":memory:").expect("Failed to create commerce"));
commerce
.inventory()
.create_item(CreateInventoryItem {
sku: "CONC-001".into(),
name: "Concurrent Test Item".into(),
initial_quantity: Some(dec!(1000)),
..Default::default()
})
.expect("Failed to create item");
let mut handles = vec![];
for i in 0..10 {
let commerce_clone = Arc::clone(&commerce);
let handle = thread::spawn(move || {
for j in 0..10 {
let result = commerce_clone.inventory().adjust(
"CONC-001",
dec!(-1),
&format!("Thread {} adjustment {}", i, j),
);
if result.is_err() {
println!("Concurrent adjustment failed: {:?}", result);
}
}
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("Thread panicked");
}
let stock = commerce.inventory().get_stock("CONC-001").expect("Failed to get stock");
println!("Final stock after concurrent updates: {:?}", stock);
}
#[test]
fn test_concurrent_order_creation() {
use std::sync::Arc;
use std::thread;
let commerce = Arc::new(Commerce::new(":memory:").expect("Failed to create commerce"));
let customer = commerce
.customers()
.create(CreateCustomer {
email: "concurrent-test@example.com".into(),
first_name: "Concurrent".into(),
last_name: "Test".into(),
..Default::default()
})
.expect("Failed to create customer");
let customer_id = customer.id;
let mut handles = vec![];
for i in 0..5 {
let commerce_clone = Arc::clone(&commerce);
let cid = customer_id;
let handle = thread::spawn(move || {
let result = commerce_clone.orders().create(CreateOrder {
customer_id: cid,
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: format!("THREAD-{}", i),
name: format!("Thread {} Product", i),
quantity: 1,
unit_price: dec!(10.00),
..Default::default()
}],
..Default::default()
});
result.is_ok()
});
handles.push(handle);
}
let mut success_count = 0;
for handle in handles {
if handle.join().expect("Thread panicked") {
success_count += 1;
}
}
println!("Concurrent order creation: {} out of 5 succeeded", success_count);
assert!(success_count > 0, "At least one concurrent order should succeed");
}
#[test]
fn test_unicode_in_names() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let customer = commerce
.customers()
.create(CreateCustomer {
email: "unicode@example.com".into(),
first_name: "日本語".into(), last_name: "Müller".into(), ..Default::default()
})
.expect("Failed to create customer with unicode");
assert_eq!(customer.first_name, "日本語");
assert_eq!(customer.last_name, "Müller");
}
#[test]
fn test_very_long_strings() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let long_string = "x".repeat(10000);
let result = commerce.customers().create(CreateCustomer {
email: "long@example.com".into(),
first_name: long_string,
last_name: "Short".into(),
..Default::default()
});
println!("Very long string result: {:?}", result.is_ok());
}
#[test]
fn test_special_characters_in_sku() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.inventory().create_item(CreateInventoryItem {
sku: "SKU/WITH\\SPECIAL<>CHARS".into(),
name: "Special SKU Item".into(),
..Default::default()
});
println!("Special chars in SKU result: {:?}", result);
}
#[test]
fn test_decimal_precision() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let customer = commerce
.customers()
.create(CreateCustomer {
email: "decimal-test@example.com".into(),
first_name: "Decimal".into(),
last_name: "Test".into(),
..Default::default()
})
.expect("Failed to create customer");
let order = commerce
.orders()
.create(CreateOrder {
customer_id: customer.id,
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: "PRECISION-001".into(),
name: "Precision Test".into(),
quantity: 1,
unit_price: dec!(0.00000001), ..Default::default()
}],
..Default::default()
})
.expect("Failed to create order with precise decimal");
println!("Order total with tiny price: {:?}", order.total_amount);
}
#[test]
fn test_max_decimal_value() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let result = commerce.orders().create(CreateOrder {
customer_id: Uuid::new_v4().into(),
items: vec![CreateOrderItem {
product_id: Uuid::new_v4().into(),
sku: "MAX-001".into(),
name: "Max Value Test".into(),
quantity: 1,
unit_price: dec!(999999999999999999.99), ..Default::default()
}],
..Default::default()
});
println!("Max decimal value result: {:?}", result);
}
#[test]
fn test_empty_database_queries() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let orders = commerce.orders().list(Default::default()).expect("Failed to list orders");
assert!(orders.is_empty());
let customers =
commerce.customers().list(Default::default()).expect("Failed to list customers");
assert!(customers.is_empty());
let products = commerce.products().list(Default::default()).expect("Failed to list products");
assert!(products.is_empty());
}
#[test]
fn test_count_on_empty_tables() {
let commerce = Commerce::new(":memory:").expect("Failed to create commerce");
let order_count = commerce.orders().count(Default::default()).expect("Failed to count orders");
assert_eq!(order_count, 0);
let customer_count =
commerce.customers().count(Default::default()).expect("Failed to count customers");
assert_eq!(customer_count, 0);
}