crates/monetize-site-buy/tests/relay.rs
//! ★ **The relay keeps the buyer on the site** (owner 2026-10-23): every step goes to the ONE
//! monetize over the site's own bearer, every way back from the vendor is on the site, the
//! e-mail is asked once (at account creation, never in a buy), and the product vouches for a
//! signed-in buyer with its own ticket.
mod common;
use axum::http::StatusCode;
use common::{call, relay, relay_with, BEARER, ORIGIN};
use serde_json::json;
#[tokio::test]
async fn a_visitors_sign_up_goes_to_the_shop_with_the_sites_own_ways_back() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(&r, "POST", "/auth/signup/start", None, Some(json!({"username": "x14", "email": "ops@mock.invalid", "plan": "holger/5gb-1m", "next": "/"}))).await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(
body["url"],
"https://checkout.mock.invalid/c/pay/cs_test_abcdefghijkl"
);
let h = fake.heard.lock().unwrap();
let s = h.signup_start.as_ref().unwrap();
assert_eq!(
(
s.username.as_str(),
s.product.as_str(),
s.plan.as_str(),
s.email.as_str(),
s.vendor.as_str()
),
("x14", "holger", "holger/5gb-1m", "ops@mock.invalid", ""),
"A32-15: the site names no vendor: the shop routes it"
);
assert_eq!(
s.success_url,
format!("{ORIGIN}/welcome?session={{session}}&next=%2F")
);
assert_eq!(s.cancel_url, format!("{ORIGIN}/signup?plan=account"));
assert!(
h.bearers.iter().all(|b| b == &format!("Bearer {BEARER}")),
"every call carries the site's bearer"
);
}
#[tokio::test]
async fn the_shops_verdict_is_shown_and_a_member_buys_nothing() {
let (r, _) = relay("holger").await;
let (st, body, _) = call(
&r,
"POST",
"/auth/signup/start",
None,
Some(json!({"username": "held", "email": "ops@mock.invalid"})),
)
.await;
assert_eq!(st, StatusCode::CONFLICT);
assert!(body["error"]
.as_str()
.unwrap()
.starts_with("Someone is signing up with this account name"));
let (st, body, _) = call(
&r,
"POST",
"/auth/signup/start",
Some("member:acme"),
Some(json!({"username": "ann2", "email": "ops@mock.invalid"})),
)
.await;
assert_eq!(st, StatusCode::FORBIDDEN);
assert_eq!(
body["error"],
"You are a member of acme. A member buys nothing: acme's room is its admin's to buy."
);
let (st, body, _) = call(
&r,
"POST",
"/auth/signup/start",
None,
Some(json!({"username": "x14", "email": "not-an-address"})),
)
.await;
assert_eq!(st, StatusCode::BAD_REQUEST, "{body}");
}
#[tokio::test]
async fn the_plans_and_the_name_check_are_the_shops_in_the_browsers_market() {
let (r, _) = relay("holger").await;
let (st, body, _) = call(&r, "GET", "/auth/signup/ladder", None, None).await;
assert_eq!(st, StatusCode::OK);
assert_eq!(body["market"], "SE", "Accept-Language sv-SE names Sweden");
assert_eq!(body["plans"][1]["price_words"], "100.00 SEK a month");
let (_, body, _) = call(&r, "GET", "/auth/signup/name?u=taken", None, None).await;
assert_eq!(
body,
json!({"free": false, "reason": "username \"taken\" is taken; choose another"})
);
let (_, body, _) = call(&r, "GET", "/auth/signup/name?u=X", None, None).await;
assert_eq!(body["free"], false);
}
#[tokio::test]
async fn a_made_account_is_handed_the_passkey_link_on_the_site_and_only_while_it_holds_none() {
let (r, fake) = relay("holger").await;
let (_, body, _) = call(
&r,
"GET",
"/auth/signup/status?session=cs_test_abcdefghijkl",
None,
None,
)
.await;
assert_eq!(body["state"], "pending");
assert!(
body.get("reason").is_none(),
"the operator's reason never reaches the page"
);
*fake.created_user.lock().unwrap() = "x14".into();
let (_, body, _) = call(
&r,
"GET",
"/auth/signup/status?session=cs_test_abcdefghijkl",
None,
None,
)
.await;
assert_eq!(body["state"], "created");
assert_eq!(
body["invite_url"],
"/login?signup=cs_test_abcdefghijkl&user=x14"
);
*fake.created_user.lock().unwrap() = "done".into();
let (_, body, _) = call(
&r,
"GET",
"/auth/signup/status?session=cs_test_abcdefghijkl",
None,
None,
)
.await;
assert_eq!(body["invite_url"], serde_json::Value::Null);
let (st, _, _) = call(&r, "GET", "/auth/signup/status?session=../etc", None, None).await;
assert_eq!(st, StatusCode::BAD_REQUEST);
*fake.created_user.lock().unwrap() = "x14".into();
let (st, body, _) = call(
&r,
"POST",
"/auth/signup/sign-in-again",
None,
Some(json!({"session": "cs_test_abcdefghijkl", "next": "/"})),
)
.await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(
fake.heard
.lock()
.unwrap()
.sign_in_again
.as_ref()
.unwrap()
.welcome_url,
format!("{ORIGIN}/welcome?session={{session}}&next=%2F")
);
}
#[tokio::test]
async fn a_visitor_pays_once_for_a_private_instance_and_the_new_account_is_welcomed_on_the_site() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(&r, "POST", "/auth/private/start", None, Some(json!({"company": "acme", "account": "x14", "email": "ops@mock.invalid", "front_plan": "f", "main_plan": "m", "main_data_gib": 40}))).await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(body["price_words"], "385.20 EUR");
let h = fake.heard.lock().unwrap();
let s = h.estate_start.as_ref().unwrap();
assert!(s.new_account && s.actor_ticket.is_empty());
assert_eq!(
(s.account.as_str(), s.email.as_str()),
("x14", "ops@mock.invalid")
);
assert_eq!(
s.welcome_url,
format!(
"{ORIGIN}/welcome?session={{session}}&next=%2Fsignup%3Fplan%3Dprivate%26company%3Dacme"
)
);
assert_eq!(s.cancel_url, format!("{ORIGIN}/signup?plan=private"));
}
/// ★ **The product's own order rides from the page to the ONE box** (monetize v2.0 P3, the
/// parametric order): the values the page sends as `order` reach `EstateOrder.Start` and
/// `ChangePlan` as `EstateSizes.order` (JSON), unchanged; the ONE box checks them against the
/// product's form. A page that sends no order sends none; an order that is not a set of named
/// values, or is overlong, is refused on the site and never sent.
#[tokio::test]
async fn the_products_own_order_rides_to_the_one_box_as_it_came() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(
&r,
"POST",
"/auth/private/start",
Some("x14"),
Some(json!({"company": "acme", "order": {"be": 3, "fe": 3, "graph": true}})),
)
.await;
assert_eq!(st, StatusCode::OK, "{body}");
let s = fake.heard.lock().unwrap().estate_start.clone().unwrap();
let sent: serde_json::Value = serde_json::from_str(&s.sizes.unwrap().order).unwrap();
assert_eq!(
sent,
json!({"be": 3, "fe": 3, "graph": true}),
"the order as the page sent it"
);
let (st, _, _) = call(
&r,
"POST",
"/auth/private/start",
Some("x14"),
Some(json!({"company": "acme2", "front_plan": "f"})),
)
.await;
assert_eq!(st, StatusCode::OK);
assert_eq!(
fake.heard
.lock()
.unwrap()
.estate_start
.clone()
.unwrap()
.sizes
.unwrap()
.order,
"",
"no order: none sent"
);
let (st, _, _) = call(
&r,
"POST",
"/auth/private/change",
Some("x14"),
Some(json!({"company": "acme", "order": {"be": 4}})),
)
.await;
assert_eq!(st, StatusCode::OK);
assert_eq!(
fake.heard
.lock()
.unwrap()
.change
.clone()
.unwrap()
.sizes
.unwrap()
.order,
r#"{"be":4}"#,
"a change carries the order too"
);
for bad in [
json!([1, 2]),
json!("be=3"),
json!({"blob": "x".repeat(monetize_site_buy::relay::ORDER_MAX)}),
] {
fake.heard.lock().unwrap().estate_start = None;
let (st, body, _) = call(
&r,
"POST",
"/auth/private/start",
Some("x14"),
Some(json!({"company": "acme3", "order": bad})),
)
.await;
assert_eq!(st, StatusCode::BAD_REQUEST, "{body}");
assert!(
fake.heard.lock().unwrap().estate_start.is_none(),
"a refused order is never sent"
);
}
}
#[tokio::test]
async fn a_signed_in_buyer_orders_as_their_own_account_with_its_ticket_and_no_e_mail() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(&r, "POST", "/auth/private/start", Some("x14"), Some(json!({"company": "acme", "account": "somebody-else", "email": "other@mock.invalid", "front_plan": "f", "main_plan": "m", "main_data_gib": 40}))).await;
assert_eq!(st, StatusCode::OK, "{body}");
let s = fake.heard.lock().unwrap().estate_start.clone().unwrap();
assert_eq!(
s.account, "x14",
"the order is the session's account, whatever the form says"
);
assert_eq!(s.actor_ticket, b"estate:x14:{}".to_vec());
assert!(!s.new_account && s.welcome_url.is_empty());
assert!(
s.email.is_empty(),
"the e-mail is asked once, never in a buy: a page's address is not sent ({:?})",
s.email
);
// A credential that is no person, and a member, buy nothing.
let (st, body, _) = call(
&r,
"POST",
"/auth/private/start",
Some("machine"),
Some(json!({"company": "acme"})),
)
.await;
assert_eq!(st, StatusCode::UNAUTHORIZED);
assert_eq!(body["error"], "A private Holger is bought by your account at holger.mock.invalid, where you see and grow what you bought. Sign in, or Create your account at holger.mock.invalid first.");
let (st, body, _) = call(
&r,
"POST",
"/auth/private/start",
Some("member:acme"),
Some(json!({"company": "acme"})),
)
.await;
assert_eq!(st, StatusCode::FORBIDDEN);
assert_eq!(
body["error"],
"You are a member of acme. Members don’t buy: boss buys for acme."
);
let (st, _, _) = call(
&r,
"POST",
"/auth/private/start",
Some("x14"),
Some(json!({"company": "taken"})),
)
.await;
assert_eq!(st, StatusCode::CONFLICT);
}
#[tokio::test]
async fn an_instance_is_grown_and_followed_with_its_accounts_ticket() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(
&r,
"POST",
"/auth/private/change",
Some("x14"),
Some(
json!({"company": "acme", "front_plan": "f", "main_plan": "m2", "main_data_gib": 120}),
),
)
.await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(body["reference"], "estate/acme/change-1");
assert_eq!(
fake.heard
.lock()
.unwrap()
.change
.as_ref()
.unwrap()
.actor_ticket,
b"estate:x14:{}".to_vec()
);
let (_, body, _) = call(&r, "GET", "/auth/private/status?company=acme", None, None).await;
assert_eq!(body["state"], "queued");
assert!(
fake.heard
.lock()
.unwrap()
.status_ticket
.as_ref()
.unwrap()
.is_empty(),
"a visitor reads the state word only"
);
let (st, _, _) = call(
&r,
"GET",
"/auth/private/status?company=acme",
Some("down"),
None,
)
.await;
assert_eq!(
st,
StatusCode::SERVICE_UNAVAILABLE,
"an outage is never a stranger's view"
);
let (_, body, _) = call(&r, "GET", "/auth/private/ladder", None, None).await;
assert_eq!(body["steps"][0]["monthly_words"], "96.20 EUR a month");
}
#[tokio::test]
async fn the_vendors_way_back_from_a_private_order_lands_on_the_sites_watch() {
let (r, _) = relay("holger").await;
let (st, _, to) = call(&r, "GET", "/paid/estate/acme", None, None).await;
assert_eq!(
(st, to.as_deref()),
(
StatusCode::SEE_OTHER,
Some("/signup?plan=private&company=acme")
)
);
let (_, _, to) = call(&r, "GET", "/paid/estate/acme/change-3", None, None).await;
assert_eq!(
to.as_deref(),
Some("/signup?plan=private&company=acme&change=1")
);
}
#[tokio::test]
async fn the_accounts_grow_is_the_shops_window_and_the_ticket_covers_the_exact_target() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(
&r,
"GET",
"/api/account/subscription/bundles",
Some("x14"),
None,
)
.await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(
body["offers"].as_array().unwrap().len(),
1,
"a row the box cannot serve is not shown"
);
assert_eq!(body["withheld"], 1);
assert_eq!(body["offers"][0]["price_words"], "220.00 SEK");
assert_eq!(body["market"], "SE");
assert_eq!(
fake.heard
.lock()
.unwrap()
.bundles
.as_ref()
.unwrap()
.actor_ticket,
b"read:x14:{}".to_vec()
);
let (st, body, _) = call(
&r,
"POST",
"/api/account/subscription/buy-bundle",
Some("x14"),
Some(json!({"bundle": "more10"})),
)
.await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(
body["url"],
"https://checkout.mock.invalid/c/pay/cs_test_room"
);
assert_eq!(
(
body["before"]["disk_bytes"].as_u64(),
body["after"]["disk_bytes"].as_u64()
),
(Some(5), Some(15))
);
let p = fake.heard.lock().unwrap().purchase_start.clone().unwrap();
assert_eq!((p.bundle.as_str(), p.tenant.as_str()), ("more10", "x14"));
assert!(
p.caps.is_empty(),
"the caps go in the ticket, never beside the bundle"
);
assert_eq!(p.actor_ticket, b"order:x14:{\"disk_bytes\": 15}".to_vec());
let (st, _, _) = call(
&r,
"POST",
"/api/account/subscription/buy-bundle",
Some("x14"),
Some(json!({"bundle": "nope"})),
)
.await;
assert_eq!(
st,
StatusCode::BAD_REQUEST,
"a row monetize does not list is not ordered"
);
let (_, body, _) = call(
&r,
"GET",
"/api/account/subscription/status?reference=p-1",
Some("x14"),
None,
)
.await;
assert_eq!(
(body["state"].as_str(), body["phase"].as_str()),
(Some("paid"), Some("done"))
);
let (st, _, _) = call(&r, "GET", "/api/account/subscription/bundles", None, None).await;
assert_eq!(st, StatusCode::UNAUTHORIZED, "a visitor grows nothing");
}
#[tokio::test]
async fn the_offer_names_the_sites_own_pages_never_the_shops() {
let (r, _) = relay("holger").await;
let (_, body, _) = call(&r, "GET", "/auth/buy/offer", Some("x14"), None).await;
assert_eq!(
body,
json!({"signed_in": true, "account": "x14", "member": null, "account_url": "/signup?plan=account", "private_offered": true, "private_url": "/signup?plan=private"})
);
assert!(
!body.to_string().contains("monetize."),
"no link leaves the site"
);
}
#[tokio::test]
async fn where_the_shop_mints_no_checkout_the_sites_fixed_link_is_used_with_the_typed_address() {
let (r, _) = relay_with("gunnar", Some("https://buy.mock.invalid/b/x")).await;
let (st, body, _) = call(
&r,
"POST",
"/auth/signup/start",
None,
Some(json!({"username": "nosink", "email": "ops@mock.invalid"})),
)
.await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(
body["url"],
"https://buy.mock.invalid/b/x?prefilled_email=ops%40mock.invalid"
);
let (r, _) = relay("holger").await;
let (st, body, _) = call(
&r,
"POST",
"/auth/signup/start",
None,
Some(json!({"username": "nosink", "email": "ops@mock.invalid"})),
)
.await;
assert_eq!(
(st, body["error"].as_str()),
(
StatusCode::NOT_IMPLEMENTED,
Some("An account is not sold here right now.")
)
);
}
#[tokio::test]
async fn a_shop_that_does_not_answer_shows_the_last_offer_read_only_even_to_a_relay_made_again() {
let (r, _) = relay("holger").await;
let (st, _, _) = call(&r, "GET", "/auth/signup/ladder?market=fi", None, None).await;
assert_eq!(st, StatusCode::OK);
// A link to nothing: the shop does not answer.
let shop = monetize_site_buy::ShopLink::connect_lazy(
&monetize_site_buy::Door {
url: "http://127.0.0.1:9".into(),
..Default::default()
},
BEARER,
"holger",
)
.unwrap();
let dead = std::sync::Arc::new(monetize_site_buy::Relay::new(
common::Site {
word: "Holger".into(),
fixed: None,
},
shop,
));
let (st, body, _) = call(&dead, "GET", "/auth/signup/ladder?market=fi", None, None).await;
assert_eq!(st, StatusCode::SERVICE_UNAVAILABLE);
assert_eq!(
body["error"],
"The shop is unavailable right now — try again in a few minutes."
);
assert_eq!(
body["last_known"]["plans"][1]["price_words"],
"100.00 SEK a month"
);
}
/// ★ **Your purchases** (Gunnar's `api::subscription::purchases`, A14): the person's own
/// instances, each with its Grow and Manage pages on the site, asked with their `estate` ticket;
/// an account without room here gets the way to buy room here too.
#[tokio::test]
async fn your_purchases_list_the_persons_instances_with_their_grow_pages_on_the_site() {
let (r, fake) = relay("holger").await;
let (st, body, _) = call(&r, "GET", "/api/account/purchases", Some("x14"), None).await;
assert_eq!(st, StatusCode::OK, "{body}");
assert_eq!(body["estates"][0]["company"], "acme");
assert_eq!(
body["estates"][0]["grow_url"],
"/signup?plan=grow&instance=acme"
);
assert_eq!(
body["estates"][0]["renew_url"],
"/signup?plan=private&renew=acme"
);
assert_eq!(
body["storage_lines"][0]["words"],
"Your Holger is acme.holger.mock.invalid"
);
assert_eq!(body["buy"]["url"], "/signup?plan=account");
assert!(
body["buy"]["words"]
.as_str()
.unwrap()
.starts_with("Want space here on holger.mock.invalid too? Buy "),
"{body}"
);
let asked = fake.heard.lock().unwrap().purchases.clone().unwrap();
assert_eq!(
(asked.account.as_str(), asked.actor_ticket.as_slice()),
("x14", b"estate:x14:{}".as_slice())
);
let (st, _, _) = call(&r, "GET", "/api/account/purchases", None, None).await;
assert_eq!(st, StatusCode::UNAUTHORIZED, "a visitor has no purchases");
}