pagetop/tests/waypoint.rs
Manuel Cillero af548b03c9 (core): Añade Route, RoutePath y Waypoint
`Route` resuelve URLs sensibles al `Context`/idioma en propiedades de
componentes; `RoutePath` (renombrado desde html/route.rs) es el valor
concreto de ruta + query. `Waypoint` transporta la URL de retorno entre
pantallas de listado/alta/edición vía query string.

Ajusta `Context::route()`, `Redirect` y los componentes que aceptan
rutas para integrarse con el nuevo tipo `Route`.
2026-07-19 22:16:21 +02:00

63 lines
2.2 KiB
Rust

use pagetop::prelude::*;
// **< Waypoint - only accepts local paths >********************************************************
#[pagetop::test]
async fn waypoint_accepts_local_paths() {
for path in ["/", "/admin/users", "/admin/users?page=2"] {
let w = Waypoint::from(path.to_owned());
assert_eq!(w.as_str(), Some(path));
}
}
#[pagetop::test]
async fn waypoint_rejects_open_redirect_targets() {
// Targets that a malicious client could slip into `?waypoint=...` to redirect off-site: they
// must be discarded just as if no waypoint had been provided.
for target in [
"",
"https://evil.example",
"//evil.example",
"/\\evil.example",
"javascript:alert(1)",
] {
let w = Waypoint::from(target.to_owned());
assert_eq!(w.as_str(), None, "expected {target:?} to be rejected");
}
}
#[pagetop::test]
async fn waypoint_deserialize_rejects_open_redirect_targets() {
// Reproduces the real entry point (`web::Query<Waypoint>`): the value arrives via
// deserialization, not through `Waypoint::from(String)` as in the previous test.
let w: Waypoint = serde_json::from_str(r#"{"waypoint":"https://evil.example"}"#).unwrap();
assert_eq!(w.as_str(), None);
}
// **< Waypoint::or() >*****************************************************************************
#[pagetop::test]
async fn waypoint_or_returns_transported_local_path() {
let w = Waypoint::from("/admin/users?page=2".to_owned());
assert_eq!(w.or("/fallback").to_string(), "/admin/users?page=2");
}
#[pagetop::test]
async fn waypoint_or_falls_back_when_target_is_not_local() {
let w = Waypoint::from("https://evil.example".to_owned());
assert_eq!(w.or("/admin/users").to_string(), "/admin/users");
}
// **< Waypoint::append_to() >**********************************************************************
#[pagetop::test]
async fn waypoint_append_to_adds_param_only_when_present() {
let w = Waypoint::from("/admin/users".to_owned());
assert_eq!(
w.append_to("/items").to_string(),
"/items?waypoint=%2Fadmin%2Fusers"
);
let empty = Waypoint::default();
assert_eq!(empty.append_to("/items").to_string(), "/items");
}