open-standards/openpay/crates/op-tax/tests/integration.rs
Transaction Science 3fe109d58f ingest batch 4: 9 crates · table-stakes completers across all three workspaces
OpenPay (3 crates, ~13k LOC, 175 tests)
  op-connect           sub-merchant onboarding + KYB + split-payments + payouts + 1099-K
  op-3ds2              3DS2.3 SCA processor (AReq/ARes/CReq/CRes/RReq/RRes + exemptions)
  op-tax               US/EU/UK/AU/CA/IN tax with Avalara/Stripe/CCH/Vertex/TaxJar adapters

Smart Byte (3 crates, ~7k LOC, 57 tests)
  smart-byte-libp2p    libp2p transport (kad/gossipsub/mdns/autonat/relay/dcutr/identify/ping/req_resp)
  smart-byte-crdt      LWW/GCounter/PnCounter/OrSet/LwwMap/RgaList/2P-Set + HLC + vector clock + Automerge/Yjs interop
  smart-byte-keri-witness  KERI key-rotation cycle + witness layer + watchers + recovery + delegation

EOC (3 crates, ~8k LOC, 108 tests)
  eoc-tools            function-calling across Anthropic/OpenAI/Google/Mistral/Cohere + parallel exec + sandbox
  eoc-multimodal       vision (CLIP/SigLIP/ColPali) + audio (Whisper/MMS) + video sampling + modality router
  eoc-spec-decode      vanilla + SpS-with-temp + lookahead speculative decoding + EAGLE/Medusa stubs

All three workspaces compile cleanly. Forbidden-unsafe, no unwrap outside tests.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-24 04:00:04 -04:00

190 lines
6.9 KiB
Rust

//! End-to-end integration tests for `op-tax`. These complement the
//! unit tests inside each module and cover the scenarios the spec
//! flags explicitly:
//!
//! - US sales-tax compound across state + county + city + special district.
//! - VAT inclusive math (€100 gross with 20% VAT → €83.33 net + €16.67 tax).
//! - Exemption certificate application.
//! - Reverse charge for EU B2B cross-border.
//! - Nexus monitor 199th vs 200th transaction.
//! - Property tests: rate-table + line ⇒ bounded, deterministic, additive.
use chrono::NaiveDate;
use op_core::{Currency, Money};
use op_tax::{
CustomerType, ExemptionCertificate, Jurisdiction, NativeCalculator, NexusEvent, NexusMonitor,
ProductTaxCategory, RateTable, TaxCalculator, TaxContext, TaxableLine, TransactionRecord,
};
use rust_decimal::Decimal;
fn date(s: &str) -> NaiveDate {
NaiveDate::parse_from_str(s, "%Y-%m-%d").unwrap()
}
fn line(amount_minor: i64, currency: Currency, to: Jurisdiction) -> TaxableLine {
TaxableLine {
line_id: "L1".into(),
amount: Money::from_minor(amount_minor, currency),
category: ProductTaxCategory::TangibleGoods,
ship_from: None,
ship_to: to,
}
}
#[tokio::test]
async fn us_sales_tax_state_county_city_district_compound() {
// Construct a deliberate four-layer stack (state + city +
// district — county base is 0 in WA's actual rate schedule):
// - State WA: 6.5%
// - City Seattle: 3.85%
// - District KingTransit: 0.9%
// Total = 11.25% on $100 = $11.25
let calc = NativeCalculator::bundled();
let line = line(
10_000,
Currency::USD,
Jurisdiction::full("US", "WA", "Seattle", "KingTransit"),
);
let ctx = TaxContext::consumer(date("2026-06-15"));
let r = calc.calculate(&[line], &ctx).await.unwrap();
assert_eq!(r.total_tax.minor_units, 1125);
let bd = r.per_line.get("L1").unwrap();
assert_eq!(bd.jurisdiction_layers.len(), 3);
}
#[tokio::test]
async fn vat_inclusive_eur_100_at_20pct_yields_16_67() {
let calc = NativeCalculator::bundled();
let line = line(10_000, Currency::EUR, Jurisdiction::country("FR")); // 20% VAT
let ctx = TaxContext::consumer(date("2026-06-15"));
let r = calc.calculate(&[line], &ctx).await.unwrap();
// €100/1.20 = €83.33; tax = €16.67.
assert_eq!(r.total_tax.minor_units, 1667);
let bd = r.per_line.get("L1").unwrap();
assert_eq!(bd.taxable_amount.minor_units, 8333);
}
#[tokio::test]
async fn resale_certificate_zero_rates_line() {
let calc = NativeCalculator::bundled();
let cert = ExemptionCertificate {
id: "RESALE-WA-1".into(),
holder: "Acme Resellers".into(),
jurisdictions: vec![Jurisdiction::region("US", "WA")],
categories: vec![ProductTaxCategory::TangibleGoods],
valid_from: date("2026-01-01"),
valid_until: Some(date("2026-12-31")),
certificate_data: b"<pdf>".to_vec(),
};
let mut ctx = TaxContext::consumer(date("2026-06-15"));
ctx.customer_type = CustomerType::Business {
tax_id: "12-3456789".into(),
};
ctx.exemption_certs.push(cert);
let line = line(
10_000,
Currency::USD,
Jurisdiction::locality("US", "WA", "Seattle"),
);
let r = calc.calculate(&[line], &ctx).await.unwrap();
assert_eq!(r.total_tax.minor_units, 0);
let bd = r.per_line.get("L1").unwrap();
assert!(bd.exemption_reason.is_some());
}
#[tokio::test]
async fn eu_b2b_cross_border_reverse_charge_zero_rates() {
let calc = NativeCalculator::bundled();
let mut ctx = TaxContext::consumer(date("2026-06-15"));
ctx.customer_type = CustomerType::Business {
tax_id: "FR12345678901".into(),
};
let line = TaxableLine {
line_id: "L1".into(),
amount: Money::from_minor(10_000, Currency::EUR),
category: ProductTaxCategory::Saas,
ship_from: Some(Jurisdiction::country("DE")),
ship_to: Jurisdiction::country("FR"),
};
let r = calc.calculate(&[line], &ctx).await.unwrap();
assert_eq!(r.total_tax.minor_units, 0);
}
#[test]
fn nexus_monitor_199_vs_200_transactions_baseline_state() {
let mut m = NexusMonitor::with_default_us_states();
let mk_tx = || TransactionRecord {
state: op_tax::RegionCode::new("SD"),
date: date("2026-06-15"),
revenue_usd: Decimal::new(10, 0),
};
for i in 0..199 {
let events = m.record(&mk_tx());
assert!(
!events
.iter()
.any(|e| matches!(e, NexusEvent::Triggered { .. })),
"should not trigger before 200th transaction; failed at i={i}"
);
}
let events = m.record(&mk_tx());
let trig = events.iter().find_map(|e| match e {
NexusEvent::Triggered { dimension, .. } => Some(*dimension),
_ => None,
});
assert_eq!(trig, Some("transactions"));
}
#[tokio::test]
async fn nexus_filter_in_calculator_zero_rates_outside_jurisdictions() {
let calc = NativeCalculator::bundled();
let mut ctx = TaxContext::consumer(date("2026-06-15"));
ctx.nexus_jurisdictions.insert(Jurisdiction::region("US", "WA"));
// Ship to NY — no nexus.
let line = line(10_000, Currency::USD, Jurisdiction::region("US", "NY"));
let r = calc.calculate(&[line], &ctx).await.unwrap();
assert_eq!(r.total_tax.minor_units, 0);
}
#[tokio::test]
async fn deterministic_repeated_calls_match() {
let calc = NativeCalculator::bundled();
let ctx = TaxContext::consumer(date("2026-06-15"));
let l = line(
10_000,
Currency::USD,
Jurisdiction::locality("US", "WA", "Seattle"),
);
let r1 = calc.calculate(std::slice::from_ref(&l), &ctx).await.unwrap();
let r2 = calc.calculate(&[l], &ctx).await.unwrap();
assert_eq!(r1.total_tax.minor_units, r2.total_tax.minor_units);
assert_eq!(
r1.per_line.get("L1").unwrap().tax_amount.minor_units,
r2.per_line.get("L1").unwrap().tax_amount.minor_units
);
}
#[tokio::test]
async fn cbor_snapshot_roundtrip_via_disk() {
let t = RateTable::bundled();
let tmp = std::env::temp_dir().join("op_tax_test_rate_table.cbor");
{
let f = std::fs::File::create(&tmp).unwrap();
t.write_cbor(f).unwrap();
}
let loaded = RateTable::load_cbor(&tmp).unwrap();
assert_eq!(loaded.entries.len(), t.entries.len());
// Calculator over the loaded table should match a calculator over
// the in-memory table.
let calc_disk = NativeCalculator::new(loaded);
let calc_mem = NativeCalculator::new(t);
let ctx = TaxContext::consumer(date("2026-06-15"));
let l = line(10_000, Currency::EUR, Jurisdiction::country("DE"));
let r_disk = calc_disk
.calculate(std::slice::from_ref(&l), &ctx)
.await
.unwrap();
let r_mem = calc_mem.calculate(&[l], &ctx).await.unwrap();
assert_eq!(r_disk.total_tax.minor_units, r_mem.total_tax.minor_units);
let _ = std::fs::remove_file(&tmp);
}