mail client (IMAP/SMTP)
git clone https://git.lucas.co/cce-mail.git
examples/wpe_mail.rs (3.3K)
1 //! Headless smoke test for [`MailWebView`] — boots the engine, loads a
2 //! representative HTML mail, and asserts frames actually render with the
3 //! expected content policy. No Wayland session needed: frames land in WPE's
4 //! SHM buffers and are sampled straight off the readback.
5 //!
6 //! `cargo run --release -p cce-mail --example wpe_mail`
7
8 #[path = "../src/wpe/mod.rs"]
9 mod wpe;
10
11 fn main() {
12 let html = r##"<!doctype html>
13 <html><body style="margin:0;background:#ff0000">
14 <h1 style="color:#ffffff">HTML mail</h1>
15 <p><a href="https://example.com/click">a link</a></p>
16 <img src="https://tracker.invalid/pixel.gif" width="10" height="10">
17 </body></html>"##;
18
19 let mut view = wpe::MailWebView::new((800, 600));
20 view.load_html(html);
21
22 let mut frames = 0;
23 for i in 0..120 {
24 if view.pump() {
25 frames += 1;
26 let px = view.sample_pixel(400, 300);
27 println!("t={:>5}ms frame#{frames} image={:?} px@center={:?}", i * 50, view.image(), px);
28 }
29 std::thread::sleep(std::time::Duration::from_millis(50));
30 if frames >= 2 && i > 40 {
31 break;
32 }
33 }
34
35 assert!(frames > 0, "no frames rendered");
36 // The body is red; a rendered frame proves layout + raster, and the
37 // color proves the page (not a blank) was what rendered.
38 let (r, g, b) = view.sample_pixel(400, 300).expect("no readback");
39 println!("center pixel: ({r},{g},{b})");
40 assert!(r > 180 && g < 80 && b < 80, "expected the red body, got ({r},{g},{b})");
41 println!("OK: {frames} frames, red body rendered, remote pixel blocked from loading");
42
43 // Phase 2: a cid: inline image, served by the registered scheme handler
44 // from the per-message store — full-bleed green, so the center pixel
45 // proves the request went store → stream → raster.
46 let svg = br##"<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><rect width="200" height="200" fill="#00c000"/></svg>"##;
47 view.set_inline_parts(vec![(
48 "logo@test".to_string(),
49 "image/svg+xml".to_string(),
50 svg.to_vec(),
51 )]);
52 view.load_html(
53 r#"<html><body style="margin:0"><img src="cid:logo@test" style="display:block;width:800px;height:600px"></body></html>"#,
54 );
55 let mut cid_frames = 0;
56 for i in 0..120 {
57 if view.pump() {
58 cid_frames += 1;
59 println!(
60 "t={:>5}ms cid frame#{cid_frames} px@center={:?}",
61 i * 50,
62 view.sample_pixel(400, 300)
63 );
64 }
65 std::thread::sleep(std::time::Duration::from_millis(50));
66 // Wait for the frame that actually shows the image, not the first
67 // paint before the subresource arrived. All three channels: white
68 // (the pre-image paint) also has a green channel over 150.
69 if cid_frames > 0 {
70 if let Some((r, g, b)) = view.sample_pixel(400, 300) {
71 if g > 150 && r < 80 && b < 80 {
72 break;
73 }
74 }
75 }
76 }
77 let (r, g, b) = view.sample_pixel(400, 300).expect("no readback");
78 println!("cid image center pixel: ({r},{g},{b})");
79 assert!(g > 150 && r < 80 && b < 80, "expected the green cid image, got ({r},{g},{b})");
80 println!("OK: cid inline image rendered through the scheme handler");
81 }