Skip to content

Commit f17793f

Browse files
committed
add pixel color test
1 parent 045aee4 commit f17793f

File tree

3 files changed

+217
-1
lines changed

3 files changed

+217
-1
lines changed

packages/yew/Cargo.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,28 @@ trybuild = "1"
9292

9393
[dev-dependencies.web-sys]
9494
version = "0.3"
95-
features = ["ShadowRootInit", "ShadowRootMode", "HtmlButtonElement"]
95+
features = [
96+
"ShadowRootInit",
97+
"ShadowRootMode",
98+
"HtmlButtonElement",
99+
"HtmlCanvasElement",
100+
"CanvasRenderingContext2d",
101+
"HtmlVideoElement",
102+
"MediaStream",
103+
"MediaStreamTrack",
104+
"MediaDevices",
105+
"Navigator",
106+
"DisplayMediaStreamConstraints",
107+
"MediaTrackSettings",
108+
"DomRect",
109+
"ImageData",
110+
"Blob",
111+
"BlobPropertyBag",
112+
"Url",
113+
"HtmlImageElement",
114+
"CssStyleDeclaration",
115+
"Element",
116+
]
96117

97118
[features]
98119
ssr = ["dep:html-escape", "dep:base64ct", "dep:bincode"]

packages/yew/tests/svg_render.rs

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#![cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
2+
3+
use wasm_bindgen::prelude::*;
4+
use wasm_bindgen_test::*;
5+
use web_sys::wasm_bindgen::JsCast;
6+
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlVideoElement};
7+
use yew::prelude::*;
8+
9+
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
10+
11+
#[function_component]
12+
fn SvgWithDropShadow() -> Html {
13+
html! {
14+
<svg id="test-svg">
15+
<defs>
16+
<filter id="glow">
17+
<feDropShadow dx="0" dy="0" stdDeviation="10" flood-color="red"/>
18+
</filter>
19+
</defs>
20+
<rect width="100" height="100" filter="url(#glow)" />
21+
</svg>
22+
}
23+
}
24+
25+
#[wasm_bindgen_test]
26+
async fn svg_camel_case_elements_render() {
27+
let window = web_sys::window().unwrap();
28+
let document = window.document().unwrap();
29+
let body = document.body().unwrap();
30+
31+
// Create container
32+
let container = document.create_element("div").unwrap();
33+
container.set_id("test-container");
34+
body.append_child(&container).unwrap();
35+
36+
// Mount component
37+
yew::Renderer::<SvgWithDropShadow>::with_root(container.clone().unchecked_into()).render();
38+
39+
// Wait for render to complete
40+
yew::platform::time::sleep(std::time::Duration::from_millis(1000)).await;
41+
42+
// Get the SVG element to verify it exists
43+
let svg_element = document
44+
.get_element_by_id("test-svg")
45+
.expect("SVG element should exist");
46+
47+
// Get SVG bounds for pixel analysis
48+
let rect = svg_element.get_bounding_client_rect();
49+
50+
// Use getDisplayMedia to capture the screen
51+
let navigator = window.navigator();
52+
let media_devices = navigator.media_devices().unwrap();
53+
54+
// Create options for getDisplayMedia
55+
let constraints = web_sys::DisplayMediaStreamConstraints::new();
56+
constraints.set_video(&JsValue::from(true));
57+
58+
// Try to get the display media stream
59+
let stream_promise = media_devices
60+
.get_display_media_with_constraints(&constraints)
61+
.unwrap();
62+
let stream_result = wasm_bindgen_futures::JsFuture::from(stream_promise).await;
63+
64+
// Check if getDisplayMedia failed (likely Firefox without user interaction)
65+
let stream = match stream_result {
66+
Ok(stream) => stream.dyn_into::<web_sys::MediaStream>().unwrap(),
67+
Err(_) => {
68+
// We are likely in Firefox, there is no way of granting permission
69+
// for screen capture without user interaction in automated tests
70+
web_sys::console::log_1(
71+
&"getDisplayMedia failed - likely Firefox, skipping pixel test".into(),
72+
);
73+
return;
74+
}
75+
};
76+
77+
// Create a video element to capture frames
78+
let video = document
79+
.create_element("video")
80+
.unwrap()
81+
.dyn_into::<HtmlVideoElement>()
82+
.unwrap();
83+
video.set_autoplay(true);
84+
video.set_src_object(Some(&stream));
85+
86+
// Add video to DOM (invisible)
87+
let style = video.dyn_ref::<web_sys::HtmlElement>().unwrap().style();
88+
style.set_property("position", "absolute").unwrap();
89+
style.set_property("left", "-9999px").unwrap();
90+
body.append_child(&video).unwrap();
91+
92+
// Wait for video to start playing
93+
let play_promise = video.play().unwrap();
94+
wasm_bindgen_futures::JsFuture::from(play_promise)
95+
.await
96+
.ok();
97+
98+
// Wait a bit for the video feed to stabilize
99+
yew::platform::time::sleep(std::time::Duration::from_millis(500)).await;
100+
101+
// Get video track settings to know dimensions
102+
let tracks = stream.get_video_tracks();
103+
let track = tracks
104+
.get(0)
105+
.dyn_into::<web_sys::MediaStreamTrack>()
106+
.unwrap();
107+
let settings = track.get_settings();
108+
109+
let width = settings.get_width().unwrap_or(1920) as u32;
110+
let height = settings.get_height().unwrap_or(1080) as u32;
111+
112+
// Create canvas and draw the video frame
113+
let canvas = document
114+
.create_element("canvas")
115+
.unwrap()
116+
.dyn_into::<HtmlCanvasElement>()
117+
.unwrap();
118+
canvas.set_width(width);
119+
canvas.set_height(height);
120+
121+
let ctx = canvas
122+
.get_context("2d")
123+
.unwrap()
124+
.unwrap()
125+
.dyn_into::<CanvasRenderingContext2d>()
126+
.unwrap();
127+
128+
// Draw the video frame to canvas
129+
ctx.draw_image_with_html_video_element(&video, 0.0, 0.0)
130+
.unwrap();
131+
132+
// Stop the capture
133+
let tracks = stream.get_tracks();
134+
for i in 0..tracks.length() {
135+
let track = tracks.get(i);
136+
if !track.is_undefined() {
137+
track
138+
.dyn_into::<web_sys::MediaStreamTrack>()
139+
.unwrap()
140+
.stop();
141+
}
142+
}
143+
144+
// Get image data for pixel analysis
145+
let image_data = ctx
146+
.get_image_data(0.0, 0.0, width as f64, height as f64)
147+
.unwrap();
148+
let data = image_data.data();
149+
150+
// Analyze pixels around the center where the rect should be
151+
let center_x = (rect.left() + rect.width() / 2.0) as i32;
152+
let center_y = (rect.top() + rect.height() / 2.0) as i32;
153+
154+
let mut has_non_white_pixels = false;
155+
let mut sample_pixels = Vec::new();
156+
157+
// Check a grid of pixels around the center
158+
for dy in (-60..=60).step_by(10) {
159+
for dx in (-60..=60).step_by(10) {
160+
let x = center_x + dx;
161+
let y = center_y + dy;
162+
163+
if x >= 0 && x < width as i32 && y >= 0 && y < height as i32 {
164+
let idx = ((y * width as i32 + x) * 4) as usize;
165+
let r = data[idx];
166+
let g = data[idx + 1];
167+
let b = data[idx + 2];
168+
169+
// Log some sample pixels for debugging
170+
if sample_pixels.len() < 10 {
171+
sample_pixels.push(format!("({},{}): rgb({},{},{})", x, y, r, g, b));
172+
}
173+
174+
// Check if pixel is not white (with tolerance)
175+
if r < 250 || g < 250 || b < 250 {
176+
has_non_white_pixels = true;
177+
}
178+
}
179+
}
180+
}
181+
182+
// Log pixel analysis
183+
web_sys::console::log_1(&format!("Has non-white pixels: {}", has_non_white_pixels).into());
184+
web_sys::console::log_1(&format!("Sample pixels: {:?}", sample_pixels).into());
185+
186+
assert!(has_non_white_pixels, "Expected the rect to render");
187+
}

packages/yew/webdriver.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"goog:chromeOptions": {
3+
"args": [
4+
"--use-fake-device-for-media-stream",
5+
"--use-fake-ui-for-media-stream"
6+
]
7+
}
8+
}

0 commit comments

Comments
 (0)