diff --git a/cli/synapse-cli/README.md b/cli/synapse-cli/README.md index edd06dc..adac553 100644 --- a/cli/synapse-cli/README.md +++ b/cli/synapse-cli/README.md @@ -446,3 +446,42 @@ Run all tests: ```bash cargo test ``` + +## Settlement Example + +In one terminal, start the mock API: + +```powershell +cargo run --manifest-path cli/synapse-cli/Cargo.toml --bin mock-server +``` + +Then update a settlement status against it and print the resulting settlement: + +```powershell +cargo run --manifest-path cli/synapse-cli/Cargo.toml -- ` + --base-url http://127.0.0.1:4010 ` + admin settlements update-status ` + 8f9b0f0c-9a89-4d1f-9d7d-0c7d7d0d9a11 ` + --status adjusted ` + --reason "Audit correction" ` + --new-total 125.0000000 +``` + +Sample output: + +```text +Settlement updated successfully + +Settlement ID: 8f9b0f0c-9a89-4d1f-9d7d-0c7d7d0d9a11 +Asset code: USDC +Status: adjusted +Total amount: 125.0000000 +Tx count: 8 +Period: 2026-06-26T00:00:00Z to 2026-06-27T00:00:00Z +Dispute reason: Audit correction +Original total amount: 130.0000000 +Reviewed by: admin +Reviewed at: 2026-06-27T09:15:00Z +Created at: 2026-06-27T09:00:00Z +Updated at: 2026-06-27T09:15:00Z +``` diff --git a/cli/synapse-cli/tests/cli.rs b/cli/synapse-cli/tests/cli.rs index 28ffc6b..aef6212 100644 --- a/cli/synapse-cli/tests/cli.rs +++ b/cli/synapse-cli/tests/cli.rs @@ -2,7 +2,7 @@ use assert_cmd::Command; use mockito::{Matcher, Server}; use serde_json::json; use std::net::TcpListener; -use std::process::{Child, Command as StdCommand, Stdio}; +use std::process::{Child, Stdio}; use std::thread; use std::time::Duration; @@ -499,6 +499,79 @@ fn quotas_set_rejects_zero_limit_before_sending() { assert!(stderr.contains("quota limit must be positive")); } +#[test] +fn settlement_update_status_help_mentions_required_and_optional_flags() { + let mut cmd = synapse_command(); + cmd.args(["admin", "settlements", "update-status", "--help"]); + + let output = cmd.output().expect("help output"); + assert!(output.status.success()); + let stdout = String::from_utf8(output.stdout).expect("valid utf-8"); + + assert!(stdout.contains("Required arguments:")); + assert!(stdout.contains("")); + assert!(stdout.contains("Required flags:")); + assert!(stdout.contains("--status ")); + assert!(stdout.contains("Optional flags:")); + assert!(stdout.contains("--new-total ")); + assert!(stdout.contains("--actor ")); +} + +#[test] +fn settlement_update_status_table_and_json_modes() { + let server = MockServer::spawn("happy"); + let base_url = server.base_url(); + + let mut cmd = synapse_command(); + cmd.args([ + "--base-url", + &base_url, + "admin", + "settlements", + "update-status", + SAMPLE_SETTLEMENT_ID, + "--status", + "adjusted", + "--reason", + "Audit correction", + "--new-total", + "125.0000000", + ]); + + let output = cmd.output().expect("settlement output"); + assert!(output.status.success()); + let stdout = String::from_utf8(output.stdout).expect("valid utf-8"); + assert!(stdout.contains("Settlement updated successfully")); + assert!(stdout.contains("Settlement ID: 8f9b0f0c-9a89-4d1f-9d7d-0c7d7d0d9a11")); + assert!(stdout.contains("Status: adjusted")); + assert!(stdout.contains("Dispute reason: Audit correction")); + assert!(stdout.contains("Original total amount: 130.0000000")); + + let mut cmd = synapse_command(); + cmd.args([ + "--base-url", + &base_url, + "admin", + "settlements", + "update-status", + SAMPLE_SETTLEMENT_ID, + "--status", + "adjusted", + "--reason", + "Audit correction", + "--new-total", + "125.0000000", + "--json", + ]); + + let output = cmd.output().expect("settlement json output"); + assert!(output.status.success()); + let stdout = String::from_utf8(output.stdout).expect("valid utf-8"); + assert!(stdout.contains("\"status\": \"adjusted\"")); + assert!(stdout.contains("\"original_total_amount\": \"130.0000000\"")); + assert!(stdout.contains("\"reviewed_by\": \"admin\"")); +} + fn synapse_command() -> Command { Command::cargo_bin("synapse").expect("synapse binary exists") }