This commit is contained in:
parent
7098ac75cb
commit
df91762271
29 changed files with 3079 additions and 838 deletions
|
|
@ -127,7 +127,7 @@ void OpenShopLifecycle(TestServer& srv) {
|
|||
// picked one must survive all the way into the ledger. The ledger is the
|
||||
// assertion that matters: it is what the reconciler later reads to decide
|
||||
// WHICH provider may confirm the order, so a choice that renders but is
|
||||
// not stored would mean crypto orders being asked about at Mollie.
|
||||
// not stored would mean crypto orders being asked about at the bank.
|
||||
srv.BodyHas("/shop/fp6-pmos", "name=\"pay\"", "the form offers a payment choice");
|
||||
srv.BodyHas("/shop/fp6-pmos", "value=\"crypto\"", "crypto is one of the choices");
|
||||
srv.BodyHas("/shop/fp6-pmos", "value=\"bank\" checked", "bank is the pre-selected choice");
|
||||
|
|
@ -815,6 +815,39 @@ void RejectedFormEcho(TestServer& srv) {
|
|||
}
|
||||
}
|
||||
|
||||
// ── one rail down ─────────────────────────────────────────────────────
|
||||
//
|
||||
// The regression guard for a real outage: on 2026-08-20 the bank provider
|
||||
// closed the shop's account, the operator correctly dropped the credential,
|
||||
// and the form went on rendering a PRE-SELECTED "Bank or card" option that
|
||||
// checkout could then only answer with a 503 — the majority of buyers walking
|
||||
// into a wall. The crypto slot had always been rendered conditionally; the
|
||||
// bank slot never was, because until that day it had never been absent.
|
||||
//
|
||||
// Its own server, because a rail roster is fixed at startup. Donations are
|
||||
// what this asserts against: they are open in BOTH shop states, so this runs
|
||||
// whatever fp6-pmos's status is.
|
||||
void OneRailDown(const char* binary) {
|
||||
ServerOptions options;
|
||||
options.extraArgs = { "--rail=off", "--crypto-rail=fake-crypto" };
|
||||
TestServer srv(binary, 8221, options);
|
||||
|
||||
srv.BodyHas("/shop/donation", "name=\"pay\"",
|
||||
"with one rail down the form still names the choice it has");
|
||||
srv.BodyHas("/shop/donation", "value=\"crypto\" checked",
|
||||
"the surviving rail is pre-selected, so a plain submit is payable");
|
||||
srv.BodyLacks("/shop/donation", "value=\"bank\"",
|
||||
"the dead rail is not offered at all");
|
||||
|
||||
// The proof that the rendering and the handler agree: submitting the form
|
||||
// exactly as rendered — no pay field touched — must create an order rather
|
||||
// than be refused. An absent `pay` resolves to the BANK rail by design, so
|
||||
// this is what would fail if the fieldset ever stopped pre-selecting.
|
||||
const auto created = srv.Post("/shop/donation", "amount=5&pay=crypto");
|
||||
Check(created.status == "303",
|
||||
"a donation on the surviving rail goes through");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
@ -838,5 +871,7 @@ int main(int argc, char** argv) {
|
|||
RejectedFormEcho(srv);
|
||||
}
|
||||
|
||||
OneRailDown(argv[1]);
|
||||
|
||||
return Finish();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue