Files
foxhunt/testing/test-common/src/fixtures/orders.rs
jgrusewski 9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:56:00 +01:00

258 lines
5.6 KiB
Rust

//! Order test fixtures
//!
//! Provides mock order and trade builders used across 22+ test files.
use chrono::{DateTime, Utc};
use uuid::Uuid;
/// Mock order builder for testing
///
/// Pattern found in 22+ test files with `create_mock_order()` functions.
pub struct MockOrderBuilder {
symbol: String,
quantity: f64,
price: Option<f64>,
side: Side,
order_type: OrderType,
status: OrderStatus,
timestamp: DateTime<Utc>,
}
#[derive(Clone, Copy, Debug)]
pub enum Side {
Buy,
Sell,
}
#[derive(Clone, Copy, Debug)]
pub enum OrderType {
Market,
Limit,
Stop,
StopLimit,
}
#[derive(Clone, Copy, Debug)]
pub enum OrderStatus {
Pending,
PartiallyFilled,
Filled,
Cancelled,
Rejected,
}
#[derive(Clone, Debug)]
pub struct MockOrder {
pub id: String,
pub symbol: String,
pub quantity: f64,
pub price: Option<f64>,
pub side: Side,
pub order_type: OrderType,
pub status: OrderStatus,
pub timestamp: DateTime<Utc>,
pub filled_quantity: f64,
pub average_fill_price: Option<f64>,
}
impl MockOrderBuilder {
/// Create a new order builder with defaults
pub fn new() -> Self {
Self {
symbol: "AAPL".to_string(),
quantity: 100.0,
price: None,
side: Side::Buy,
order_type: OrderType::Market,
status: OrderStatus::Pending,
timestamp: Utc::now(),
}
}
/// Set the symbol
pub fn symbol(mut self, symbol: &str) -> Self {
self.symbol = symbol.to_string();
self
}
/// Set buy side
pub fn buy(mut self) -> Self {
self.side = Side::Buy;
self
}
/// Set sell side
pub fn sell(mut self) -> Self {
self.side = Side::Sell;
self
}
/// Set quantity
pub fn quantity(mut self, quantity: f64) -> Self {
self.quantity = quantity;
self
}
/// Set limit price
pub fn limit_price(mut self, price: f64) -> Self {
self.price = Some(price);
self.order_type = OrderType::Limit;
self
}
/// Set as market order
pub fn market(mut self) -> Self {
self.order_type = OrderType::Market;
self.price = None;
self
}
/// Set as filled
pub fn filled(mut self) -> Self {
self.status = OrderStatus::Filled;
self
}
/// Build the mock order
pub fn build(self) -> MockOrder {
let is_filled = matches!(self.status, OrderStatus::Filled);
MockOrder {
id: Uuid::new_v4().to_string(),
symbol: self.symbol,
quantity: self.quantity,
price: self.price,
side: self.side,
order_type: self.order_type,
status: self.status,
timestamp: self.timestamp,
filled_quantity: if is_filled { self.quantity } else { 0.0 },
average_fill_price: self.price,
}
}
}
impl Default for MockOrderBuilder {
fn default() -> Self {
Self::new()
}
}
/// Mock trade builder
pub struct MockTradeBuilder {
symbol: String,
price: f64,
quantity: f64,
side: Side,
timestamp: DateTime<Utc>,
}
#[derive(Clone, Debug)]
pub struct MockTrade {
pub id: String,
pub symbol: String,
pub price: f64,
pub quantity: f64,
pub side: Side,
pub timestamp: DateTime<Utc>,
}
impl MockTradeBuilder {
pub fn new() -> Self {
Self {
symbol: "AAPL".to_string(),
price: 150.0,
quantity: 100.0,
side: Side::Buy,
timestamp: Utc::now(),
}
}
pub fn symbol(mut self, symbol: &str) -> Self {
self.symbol = symbol.to_string();
self
}
pub fn price(mut self, price: f64) -> Self {
self.price = price;
self
}
pub fn quantity(mut self, quantity: f64) -> Self {
self.quantity = quantity;
self
}
pub fn buy(mut self) -> Self {
self.side = Side::Buy;
self
}
pub fn sell(mut self) -> Self {
self.side = Side::Sell;
self
}
pub fn build(self) -> MockTrade {
MockTrade {
id: Uuid::new_v4().to_string(),
symbol: self.symbol,
price: self.price,
quantity: self.quantity,
side: self.side,
timestamp: self.timestamp,
}
}
}
impl Default for MockTradeBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_order_builder_defaults() {
let order = MockOrderBuilder::new().build();
assert_eq!(order.symbol, "AAPL");
assert_eq!(order.quantity, 100.0);
assert!(matches!(order.side, Side::Buy));
}
#[test]
fn test_order_builder_customization() {
let order = MockOrderBuilder::new()
.symbol("TSLA")
.sell()
.quantity(50.0)
.limit_price(200.0)
.filled()
.build();
assert_eq!(order.symbol, "TSLA");
assert_eq!(order.quantity, 50.0);
assert!(matches!(order.side, Side::Sell));
assert_eq!(order.price, Some(200.0));
assert!(matches!(order.status, OrderStatus::Filled));
assert_eq!(order.filled_quantity, 50.0);
}
#[test]
fn test_trade_builder() {
let trade = MockTradeBuilder::new()
.symbol("NVDA")
.price(450.0)
.quantity(25.0)
.sell()
.build();
assert_eq!(trade.symbol, "NVDA");
assert_eq!(trade.price, 450.0);
assert_eq!(trade.quantity, 25.0);
assert!(matches!(trade.side, Side::Sell));
}
}