diff options
author | rtkay123 <dev@kanjala.com> | 2025-08-11 17:19:08 +0200 |
---|---|---|
committer | rtkay123 <dev@kanjala.com> | 2025-08-11 17:19:08 +0200 |
commit | a08c283d68b4a15d7c0b703332f3ec179ebc3a89 (patch) | |
tree | a79cd167da00d0ef8244f33bf901eb57841f54ca | |
parent | 577cb84226b832118677b5338a4e91897117f53a (diff) | |
download | warden-a08c283d68b4a15d7c0b703332f3ec179ebc3a89.tar.bz2 warden-a08c283d68b4a15d7c0b703332f3ec179ebc3a89.zip |
test(warden): http post
-rw-r--r-- | crates/pseudonyms/tests/helpers.rs | 5 | ||||
-rw-r--r-- | crates/warden/src/main.rs | 3 | ||||
-rw-r--r-- | crates/warden/src/server.rs | 8 | ||||
-rw-r--r-- | crates/warden/src/server/routes/processor/pacs002.rs | 2 | ||||
-rw-r--r-- | crates/warden/src/server/routes/processor/pacs008.rs | 422 | ||||
-rw-r--r-- | lib/warden-stack/src/cache.rs | 2 | ||||
-rw-r--r-- | lib/warden-stack/src/config.rs | 1 | ||||
-rw-r--r-- | lib/warden-stack/src/nats.rs | 2 | ||||
-rw-r--r-- | lib/warden-stack/src/postgres.rs | 4 |
9 files changed, 436 insertions, 13 deletions
diff --git a/crates/pseudonyms/tests/helpers.rs b/crates/pseudonyms/tests/helpers.rs index 589049a..5e2545b 100644 --- a/crates/pseudonyms/tests/helpers.rs +++ b/crates/pseudonyms/tests/helpers.rs @@ -8,7 +8,7 @@ use warden_stack::{Configuration, cache::RedisManager}; use std::sync::Arc; pub struct TestApp { - state: AppHandle, + _state: AppHandle, pub mutate: MutatePseudonymClient<Channel>, } @@ -24,6 +24,7 @@ impl TestApp { .build() .unwrap(); + let mut config = config.try_deserialize::<Configuration>().unwrap(); config.application.port = 0; @@ -47,7 +48,7 @@ impl TestApp { .expect("expect server to be running"); Self { - state, + _state: state, mutate: mutation_client, } } diff --git a/crates/warden/src/main.rs b/crates/warden/src/main.rs index 49c171d..7734ecc 100644 --- a/crates/warden/src/main.rs +++ b/crates/warden/src/main.rs @@ -84,7 +84,8 @@ async fn main() -> Result<(), error::AppError> { let listener = tokio::net::TcpListener::bind(addr).await?; info!(port = addr.port(), "starting warden"); - axum::serve(listener, server::router(state)).await?; + let router = server::router(state).merge(server::metrics_app()); + axum::serve(listener, router).await?; Ok(()) } diff --git a/crates/warden/src/server.rs b/crates/warden/src/server.rs index 832c4ac..72e79d9 100644 --- a/crates/warden/src/server.rs +++ b/crates/warden/src/server.rs @@ -2,6 +2,7 @@ pub mod grpc; mod middleware; mod publish; mod routes; +pub use routes::metrics::metrics_app; use axum::Router; use utoipa::OpenApi; @@ -12,10 +13,7 @@ use utoipa_redoc::Servable; #[cfg(feature = "scalar")] use utoipa_scalar::Servable as _; -use crate::{ - server::routes::{ApiDoc, metrics::metrics_app}, - state::AppHandle, -}; +use crate::{server::routes::ApiDoc, state::AppHandle}; pub fn router(state: AppHandle) -> Router { let (router, _api) = OpenApiRouter::with_openapi(ApiDoc::openapi()) @@ -41,7 +39,7 @@ pub fn router(state: AppHandle) -> Router { #[cfg(feature = "scalar")] let router = router.merge(utoipa_scalar::Scalar::with_url("/scalar", _api)); - middleware::apply(router).merge(metrics_app()) + middleware::apply(router) } /// Get health of the API. diff --git a/crates/warden/src/server/routes/processor/pacs002.rs b/crates/warden/src/server/routes/processor/pacs002.rs index 9237afe..503939c 100644 --- a/crates/warden/src/server/routes/processor/pacs002.rs +++ b/crates/warden/src/server/routes/processor/pacs002.rs @@ -145,6 +145,7 @@ pub async fn post_pacs002( let pseudonyms_fut = async { debug!("creating pseudonyms"); let span = info_span!("create.pseudonyms.account"); + span.set_attribute("otel.kind", "client"); span.set_attribute(attribute::RPC_SERVICE, "pseudonyms"); pseudonyms_client .create_pseudonym(pseudonyms_request) @@ -188,7 +189,6 @@ pub async fn post_pacs002( transaction: Some(warden_core::message::payload::Transaction::Pacs002( request.clone(), )), - ..Default::default() }; publish_message(&state, payload, msg_id).await?; diff --git a/crates/warden/src/server/routes/processor/pacs008.rs b/crates/warden/src/server/routes/processor/pacs008.rs index 6924212..fded5f0 100644 --- a/crates/warden/src/server/routes/processor/pacs008.rs +++ b/crates/warden/src/server/routes/processor/pacs008.rs @@ -312,3 +312,425 @@ pub async fn set_cache( Ok(()) } + +#[cfg(test)] +mod tests { + use axum::{ + Router, + body::Body, + http::{Request, StatusCode}, + }; + use sqlx::PgPool; + use time::{OffsetDateTime, format_description::well_known::Rfc3339}; + use tower::ServiceExt; + use uuid::Uuid; + use warden_stack::cache::RedisManager; + + use crate::{ + server::{self, test_config}, + state::{AppState, Services}, + }; + + #[sqlx::test] + async fn post(pool: PgPool) { + let config = test_config(); + + let cache = RedisManager::new(&config.cache).await.unwrap(); + let client = async_nats::connect(&config.nats.hosts[0]).await.unwrap(); + let jetstream = async_nats::jetstream::new(client); + + let state = AppState::create( + Services { + postgres: pool, + cache, + jetstream, + }, + &test_config(), + ) + .await + .unwrap(); + let app = server::router(state); + + let ccy = "XTS"; + + let msg_id = generate_id(); + let cre_dt_tm = OffsetDateTime::now_utc().format(&Rfc3339).unwrap(); + + let debtor_fsp = "fsp001"; + let creditor_fsp = "fsp002"; + + let end_to_end_id = generate_id(); + + let v = serde_json::json!({ + "f_i_to_f_i_cstmr_cdt_trf": { + "grp_hdr": { + "msg_id": msg_id, + "cre_dt_tm": cre_dt_tm, + "nb_of_txs": "CLRG", + "sttlm_inf": { + "sttlm_mtd": 1 + } + }, + "splmtry_data": [], + "cdt_trf_tx_inf": [ + { + "pmt_id": { + "instr_id": generate_id(), + "end_to_end_id": end_to_end_id + }, + "intr_bk_sttlm_amt": { + "value": 294.3, + "ccy": ccy, + }, + "instd_amt": { + "value": 294.3, + "ccy": ccy + }, + "xchg_rate": 1, + "chrg_br": 1, + "chrgs_inf": [ + { + "amt": { + "value": 0, + "ccy": ccy + }, + "agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": debtor_fsp, + } + } + } + } + ], + "initg_pty": { + "nm": "April Blake Grant", + "id": { + "org_id": { + "othr": [] + }, + "prvt_id": { + "dt_and_plc_of_birth": { + "birth_dt": "1968-02-01", + "city_of_birth": "Unknown", + "ctry_of_birth": "ZZ" + }, + "othr": [ + { + "id": "+27730975224", + "schme_nm": { + "prtry": "MSISDN", + "cd": "cd-value" + } + } + ] + } + }, + "ctct_dtls": { + "mob_nb": "+27-730975224", + "othr": [] + } + }, + "dbtr": { + "nm": "April Blake Grant", + "id": { + "org_id": { + "othr": [] + }, + "prvt_id": { + "dt_and_plc_of_birth": { + "birth_dt": "2000-07-23", + "city_of_birth": "Unknown", + "ctry_of_birth": "ZZ" + }, + "othr": [ + { + "id": generate_id(), + "schme_nm": { + "prtry": "EID", + "cd": "cd-value" + } + } + ] + } + }, + "ctct_dtls": { + "mob_nb": "+27-730975224", + "othr": [] + } + }, + "dbtr_acct": { + "id": { + "i_b_a_n": "value", + "othr": { + "id": generate_id(), + "schme_nm": { + "prtry": "MSISDN", + "cd": "value" + } + } + }, + "nm": "April Grant" + }, + "dbtr_agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": debtor_fsp, + } + } + }, + "cdtr_agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": creditor_fsp, + } + } + }, + "cdtr": { + "nm": "Felicia Easton Quill", + "id": { + "org_id": { + "othr": [] + }, + "prvt_id": { + "dt_and_plc_of_birth": { + "birth_dt": "1935-05-08", + "city_of_birth": "Unknown", + "ctry_of_birth": "ZZ" + }, + "othr": [ + { + "id": generate_id(), + "schme_nm": { + "prtry": "EID", + "cd": "" + } + } + ] + } + }, + "ctct_dtls": { + "mob_nb": "+27-707650428", + "othr": [] + } + }, + "cdtr_acct": { + "id": { + "i_b_a_n": "", + "othr": { + "id": generate_id(), + "schme_nm": { + "prtry": "MSISDN", + "cd": "acc" + } + } + }, + "nm": "Felicia Quill" + }, + "purp": { + "cd": "MP2P", + "prtry": "" + }, + "rgltry_rptg": [ + { + "dtls": [ + { + "tp": "BALANCE OF PAYMENTS", + "cd": "100", + "inf": [] + } + ] + } + ], + "rmt_inf": { + "ustrd": [], + "strd": [] + }, + "splmtry_data": [ + { + "envlp": { + "doc": { + "xprtn": "2021-11-30T10:38:56.000Z", + "initg_pty": { + "glctn": { + "lat": "-3.1609", + "long": "38.3588" + } + } + } + } + } + ], + "instr_for_cdtr_agt": [], + "instr_for_nxt_agt": [], + "rltd_rmt_inf": [] + } + ] + } + }); + let body = serde_json::to_vec(&v).unwrap(); + + let response = app.clone() + .oneshot( + Request::builder() + .method("POST") + .header("Content-Type", "application/json") + .uri("/api/v0/pacs008") + .body(Body::from(body)) + .unwrap(), + ) + .await + .unwrap(); + + assert_eq!(response.status(), StatusCode::CREATED); + + post_clearance(app, &end_to_end_id, ccy, debtor_fsp, creditor_fsp).await; + } + + fn generate_id() -> String { + let id = Uuid::new_v4().to_string(); + id.replace("-", "") + } + + async fn post_clearance(app: Router, end_to_end_id: &str, ccy: &str, debtor_fsp: &str, creditor_fsp: &str) { + let msg_id = generate_id(); + let cre_dt_tm = OffsetDateTime::now_utc().format(&Rfc3339).unwrap(); + + let v = serde_json::json!({ + "f_i_to_f_i_pmt_sts_rpt": { + "grp_hdr": { + "msg_id": msg_id, + "cre_dt_tm": cre_dt_tm + }, + "orgnl_grp_inf_and_sts": [ + { + "grp_sts": "ACCC", + "nb_of_txs_per_sts": [ + { + "dtld_ctrl_sum": 1, + "dtld_nb_of_txs": "1", + "dtld_sts": "ACCC" + } + ], + "orgnl_cre_dt_tm": null, + "orgnl_ctrl_sum": 2, + "orgnl_msg_id": "ce569868c865-4986-94ac-906e46022617", + "orgnl_msg_nm_id": "pacs.008.001.10", + "orgnl_nb_of_txs": "1", + "sts_rsn_inf": [ + { + "addtl_inf": [ + "Transaction accepted and settled" + ], + "orgtr": null, + "rsn": null + } + ] + } + ], + "splmtry_data": [], + "tx_inf_and_sts": [ + { + "orgnl_instr_id": generate_id(), + "orgnl_end_to_end_id": end_to_end_id, + "tx_sts": "ACCC", + "sts_rsn_inf": [ + { + "addtl_inf": [ + "Transaction processed successfully" + ], + "orgtr": null, + "rsn": null + } + ], + "splmtry_data": [], + "chrgs_inf": [ + { + "amt": { + "value": 0, + "ccy": ccy + }, + "agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": debtor_fsp + }, + "b_i_c_f_i": "BANKXXX", + "l_e_i": "1234567890", + "nm": "Bank" + } + } + }, + { + "amt": { + "value": 0, + "ccy": ccy + }, + "agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": debtor_fsp + } + } + } + }, + { + "amt": { + "value": 0, + "ccy": ccy + }, + "agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": creditor_fsp + } + } + } + } + ], + "accptnc_dt_tm": "2023-06-02T07:52:31.000Z", + "instg_agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": debtor_fsp + } + } + }, + "instd_agt": { + "fin_instn_id": { + "clr_sys_mmb_id": { + "mmb_id": creditor_fsp + } + } + } + } + ] + } + }); + let body = serde_json::to_vec(&v).unwrap(); + + let response = app + .oneshot( + Request::builder() + .method("POST") + .header("Content-Type", "application/json") + .uri("/api/v0/pacs002") + .body(Body::from(body)) + .unwrap(), + ) + .await + .unwrap(); + + let status = response.status(); + + let body_bytes = axum::body::to_bytes(response.into_body(), usize::MAX) + .await + .unwrap(); + + let body_str = String::from_utf8(body_bytes.to_vec()).unwrap(); + + dbg!(body_str); + + assert_eq!(status, StatusCode::CREATED); + } +} diff --git a/lib/warden-stack/src/cache.rs b/lib/warden-stack/src/cache.rs index 9be3778..4d476ff 100644 --- a/lib/warden-stack/src/cache.rs +++ b/lib/warden-stack/src/cache.rs @@ -272,7 +272,7 @@ mod tests { // Ensure basic set/get works -- should test sharding as well: #[tokio::test] // run with `cargo test -- --ignored redis` only when redis is up and configured - #[ignore] + //#[ignore] async fn test_set_read_random_keys() { let config = CacheConfig { redis_dsn: "redis://localhost:6379".into(), diff --git a/lib/warden-stack/src/config.rs b/lib/warden-stack/src/config.rs index 9f42f43..c0fe44a 100644 --- a/lib/warden-stack/src/config.rs +++ b/lib/warden-stack/src/config.rs @@ -40,6 +40,7 @@ pub struct Configuration { #[cfg(feature = "tracing")] pub monitoring: Monitoring, #[cfg(any(feature = "nats-core", feature = "nats-jetstream"))] + #[serde(default)] pub nats: crate::nats::NatsConfig, } diff --git a/lib/warden-stack/src/nats.rs b/lib/warden-stack/src/nats.rs index 952490c..d1811f0 100644 --- a/lib/warden-stack/src/nats.rs +++ b/lib/warden-stack/src/nats.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use serde::Deserialize; -#[derive(Deserialize, Clone, Debug)] +#[derive(Deserialize, Clone, Debug, Default)] /// Nats configuration pub struct NatsConfig { /// Hosts dsn diff --git a/lib/warden-stack/src/postgres.rs b/lib/warden-stack/src/postgres.rs index 3264368..31a0fc9 100644 --- a/lib/warden-stack/src/postgres.rs +++ b/lib/warden-stack/src/postgres.rs @@ -99,7 +99,7 @@ impl<S: State> ServicesBuilder<S> { } } -#[cfg(all(test, target_os = "linux"))] +#[cfg(test)] mod test { use super::*; use crate::Services; @@ -111,7 +111,7 @@ mod test { let host = "localhost"; let user = user(); let pool_size = default_pool_size(); - let password = "postgres"; + let password = "password"; let config = PostgresConfig { pool_size, |