max / quasi
5 files changed,
+127 insertions,
-12 deletions
| @@ -2350,6 +2350,7 @@ | |||
| 2350 | 2350 | "http-body-util", | |
| 2351 | 2351 | "quasi-http", | |
| 2352 | 2352 | "quasi-router", | |
| 2353 | + | "quasi-webview", | |
| 2353 | 2354 | "tokio", | |
| 2354 | 2355 | "tower", | |
| 2355 | 2356 | ] | |
| @@ -2377,6 +2378,7 @@ | |||
| 2377 | 2378 | "http", | |
| 2378 | 2379 | "quasi-http", | |
| 2379 | 2380 | "quasi-router", | |
| 2381 | + | "quasi-webview", | |
| 2380 | 2382 | "tauri", | |
| 2381 | 2383 | ] | |
| 2382 | 2384 | ||
| @@ -4528,18 +4530,6 @@ | |||
| 4528 | 4530 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 4529 | 4531 | checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" | |
| 4530 | 4532 | ||
| 4531 | - | [[patch.unused]] | |
| 4532 | - | name = "kberg" | |
| 4533 | - | version = "0.1.0" | |
| 4534 | - | ||
| 4535 | - | [[patch.unused]] | |
| 4536 | - | name = "painhours" | |
| 4537 | - | version = "0.1.0" | |
| 4538 | - | ||
| 4539 | - | [[patch.unused]] | |
| 4540 | - | name = "tagtree" | |
| 4541 | - | version = "0.4.0" | |
| 4542 | - | ||
| 4543 | 4533 | [[patch.unused]] | |
| 4544 | 4534 | name = "synckit-client" | |
| 4545 | 4535 | version = "0.8.0" | |
| @@ -4551,3 +4541,15 @@ | |||
| 4551 | 4541 | [[patch.unused]] | |
| 4552 | 4542 | name = "docengine" | |
| 4553 | 4543 | version = "0.4.0" | |
| 4544 | + | ||
| 4545 | + | [[patch.unused]] | |
| 4546 | + | name = "kberg" | |
| 4547 | + | version = "0.1.0" | |
| 4548 | + | ||
| 4549 | + | [[patch.unused]] | |
| 4550 | + | name = "painhours" | |
| 4551 | + | version = "0.1.0" | |
| 4552 | + | ||
| 4553 | + | [[patch.unused]] | |
| 4554 | + | name = "tagtree" | |
| 4555 | + | version = "0.4.0" |
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | tokio = { version = "1.50.0", features = ["rt"] } | |
| 21 | 21 | ||
| 22 | 22 | [dev-dependencies] | |
| 23 | + | quasi-webview = { path = "../quasi-webview", version = "0.1.0" } | |
| 23 | 24 | tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] } | |
| 24 | 25 | tower = { version = "0.5.3", features = ["util"] } | |
| 25 | 26 | http-body-util = "0.1.3" |
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | tauri = { version = "2.11.5", default-features = false } | |
| 23 | 23 | ||
| 24 | 24 | [dev-dependencies] | |
| 25 | + | quasi-webview = { path = "../quasi-webview", version = "0.1.0" } | |
| 25 | 26 | # The doctest names a concrete `Runtime`, and `Wry` is behind a default feature | |
| 26 | 27 | # this crate does not otherwise ask for. Only the example needs it: nothing in | |
| 27 | 28 | # the test module builds a window, which is what keeps them runnable with no |
| @@ -255,3 +255,58 @@ | |||
| 255 | 255 | "text/html; charset=utf-8" | |
| 256 | 256 | ); | |
| 257 | 257 | } | |
| 258 | + | ||
| 259 | + | /// The one screen the end-to-end test renders for real. | |
| 260 | + | /// | |
| 261 | + | /// Deliberately not the `Spy`. Everything above proves the adapter's own | |
| 262 | + | /// boundary against a renderer that says what it was handed; this proves the | |
| 263 | + | /// boundary holds when the renderer is the one an app actually ships, which is | |
| 264 | + | /// the only place the two could disagree. | |
| 265 | + | fn real_screen() -> Screen { | |
| 266 | + | Screen::list_detail("Tasks", false) | |
| 267 | + | .with( | |
| 268 | + | Slot::new("list", RegionKind::Pane) | |
| 269 | + | .with(Node::list([quasi_router::screen::Row::new("Write it down") | |
| 270 | + | .activate(quasi_router::Action::get("/task/1"))])), | |
| 271 | + | ) | |
| 272 | + | .with(Slot::new("detail", RegionKind::Pane).with(Node::text("Nothing selected"))) | |
| 273 | + | } | |
| 274 | + | ||
| 275 | + | fn real_home(_app: &App, _params: Params) -> Result<Response, RouteError> { | |
| 276 | + | Ok(real_screen().into()) | |
| 277 | + | } | |
| 278 | + | ||
| 279 | + | #[tokio::test] | |
| 280 | + | async fn a_description_served_here_is_the_renderer_s_own_output() { | |
| 281 | + | let router = Router::<App>::new().get("/", real_home); | |
| 282 | + | let service = super::Adapter::new( | |
| 283 | + | router, | |
| 284 | + | Arc::new(App), | |
| 285 | + | Arc::new(quasi_webview::Webview::under("/static")), | |
| 286 | + | ) | |
| 287 | + | .into_router(); | |
| 288 | + | ||
| 289 | + | let response = service.oneshot(get("/")).await.unwrap(); | |
| 290 | + | assert_eq!(response.status(), StatusCode::OK); | |
| 291 | + | assert_eq!( | |
| 292 | + | response | |
| 293 | + | .headers() | |
| 294 | + | .get(header::CONTENT_TYPE) | |
| 295 | + | .and_then(|v| v.to_str().ok()), | |
| 296 | + | Some("text/html; charset=utf-8") | |
| 297 | + | ); | |
| 298 | + | ||
| 299 | + | let body = response.into_body().collect().await.unwrap().to_bytes(); | |
| 300 | + | let served = String::from_utf8(body.to_vec()).unwrap(); | |
| 301 | + | ||
| 302 | + | // The adapter adds nothing to the document and removes nothing from it. | |
| 303 | + | // Anything it wanted to add would be a second party emitting markup, which | |
| 304 | + | // is the thing `quasi_http::render`'s existence rules out. | |
| 305 | + | use quasi_http::Render as _; | |
| 306 | + | assert_eq!( | |
| 307 | + | served, | |
| 308 | + | quasi_webview::Webview::under("/static").screen(&real_screen()) | |
| 309 | + | ); | |
| 310 | + | assert!(served.starts_with("<!doctype html>")); | |
| 311 | + | assert!(served.contains("hx-get=\"/task/1\"")); | |
| 312 | + | } |
| @@ -253,3 +253,59 @@ | |||
| 253 | 253 | "text/html; charset=utf-8" | |
| 254 | 254 | ); | |
| 255 | 255 | } | |
| 256 | + | ||
| 257 | + | /// The one screen the end-to-end test renders for real. | |
| 258 | + | /// | |
| 259 | + | /// The same description the axum adapter's own end-to-end test serves. Two | |
| 260 | + | /// hosts, one description, and the only difference between the documents is | |
| 261 | + | /// where the assets live — which is the stack's whole claim, and the reason | |
| 262 | + | /// `Shell` takes an asset prefix rather than hard-coding one. | |
| 263 | + | fn real_screen() -> Screen { | |
| 264 | + | Screen::list_detail("Tasks", false) | |
| 265 | + | .with( | |
| 266 | + | Slot::new("list", RegionKind::Pane) | |
| 267 | + | .with(Node::list([quasi_router::screen::Row::new("Write it down") | |
| 268 | + | .activate(quasi_router::Action::get("/task/1"))])), | |
| 269 | + | ) | |
| 270 | + | .with(Slot::new("detail", RegionKind::Pane).with(Node::text("Nothing selected"))) | |
| 271 | + | } | |
| 272 | + | ||
| 273 | + | fn real_home(_app: &App, _params: Params) -> Result<Response, RouteError> { | |
| 274 | + | Ok(real_screen().into()) | |
| 275 | + | } | |
| 276 | + | ||
| 277 | + | #[test] | |
| 278 | + | fn a_description_served_here_is_the_renderer_s_own_output() { | |
| 279 | + | use quasi_http::Render as _; | |
| 280 | + | ||
| 281 | + | let render = quasi_webview::Webview::under("quasi://localhost/static"); | |
| 282 | + | let protocol = Protocol::new( | |
| 283 | + | "quasi", | |
| 284 | + | Router::<App>::new().get("/", real_home), | |
| 285 | + | Arc::new(App), | |
| 286 | + | Arc::new(render), | |
| 287 | + | ); | |
| 288 | + | let context = Context { | |
| 289 | + | router: protocol.router, | |
| 290 | + | state: protocol.state, | |
| 291 | + | render: protocol.render, | |
| 292 | + | body_limit: protocol.body_limit, | |
| 293 | + | passthrough: protocol.passthrough, | |
| 294 | + | }; | |
| 295 | + | ||
| 296 | + | let response = serve(&context, &get("quasi://localhost/")); | |
| 297 | + | assert_eq!(response.status(), 200); | |
| 298 | + | ||
| 299 | + | let served = text(&response); | |
| 300 | + | assert_eq!( | |
| 301 | + | served, | |
| 302 | + | quasi_webview::Webview::under("quasi://localhost/static").screen(&real_screen()) | |
| 303 | + | ); | |
| 304 | + | ||
| 305 | + | // The asset paths are the custom scheme's, which is the one thing that | |
| 306 | + | // differs from the served case. | |
| 307 | + | assert!(served.contains("src=\"quasi://localhost/static/htmx.min.js\"")); | |
| 308 | + | // Everything the description said is identical to what axum emits. | |
| 309 | + | assert!(served.contains("hx-get=\"/task/1\"")); | |
| 310 | + | assert!(served.contains("id=\"detail\"")); | |
| 311 | + | } |