Skip to content

Commit 70c7ea7

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

3 files changed

Lines changed: 224 additions & 1 deletion

File tree

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: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
use wasm_bindgen::prelude::*;
2+
use wasm_bindgen_test::*;
3+
use web_sys::wasm_bindgen::JsCast;
4+
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlVideoElement};
5+
use yew::prelude::*;
6+
7+
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
8+
9+
#[function_component]
10+
fn SvgWithDropShadow() -> Html {
11+
html! {
12+
<svg id="test-svg">
13+
<defs>
14+
<filter id="glow">
15+
<feDropShadow dx="0" dy="0" stdDeviation="10" flood-color="red"/>
16+
</filter>
17+
</defs>
18+
<rect width="100" height="100" filter="url(#glow)" />
19+
</svg>
20+
}
21+
}
22+
23+
#[wasm_bindgen_test]
24+
async fn svg_camel_case_elements_render() {
25+
let window = web_sys::window().unwrap();
26+
let document = window.document().unwrap();
27+
let body = document.body().unwrap();
28+
29+
// Create container
30+
let container = document.create_element("div").unwrap();
31+
container.set_id("test-container");
32+
body.append_child(&container).unwrap();
33+
34+
// Mount component
35+
yew::Renderer::<SvgWithDropShadow>::with_root(container.clone().unchecked_into()).render();
36+
37+
// Wait for render to complete
38+
yew::platform::time::sleep(std::time::Duration::from_millis(1000)).await;
39+
40+
// Get the SVG element to verify it exists
41+
let svg_element = document
42+
.get_element_by_id("test-svg")
43+
.expect("SVG element should exist");
44+
45+
// Get SVG bounds for pixel analysis
46+
let rect = svg_element.get_bounding_client_rect();
47+
48+
// Use getDisplayMedia to capture the screen
49+
let navigator = window.navigator();
50+
let media_devices = navigator.media_devices().unwrap();
51+
52+
// Create options for getDisplayMedia
53+
let mut constraints = web_sys::DisplayMediaStreamConstraints::new();
54+
constraints.set_video(&JsValue::from(true));
55+
56+
// Try to get the display media stream
57+
let stream_promise = media_devices
58+
.get_display_media_with_constraints(&constraints)
59+
.unwrap();
60+
let stream_result = wasm_bindgen_futures::JsFuture::from(stream_promise).await;
61+
62+
// Check if getDisplayMedia failed (likely Firefox without user interaction)
63+
let stream = match stream_result {
64+
Ok(stream) => stream.dyn_into::<web_sys::MediaStream>().unwrap(),
65+
Err(_) => {
66+
// We are likely in Firefox, there is no way of granting permission
67+
// for screen capture without user interaction in automated tests
68+
web_sys::console::log_1(
69+
&"getDisplayMedia failed - likely Firefox, skipping pixel test".into(),
70+
);
71+
container.remove();
72+
return;
73+
}
74+
};
75+
76+
// Create a video element to capture frames
77+
let video = document
78+
.create_element("video")
79+
.unwrap()
80+
.dyn_into::<HtmlVideoElement>()
81+
.unwrap();
82+
video.set_autoplay(true);
83+
video.set_src_object(Some(&stream));
84+
85+
// Add video to DOM (invisible)
86+
let style = video.dyn_ref::<web_sys::HtmlElement>().unwrap().style();
87+
style.set_property("position", "absolute").unwrap();
88+
style.set_property("left", "-9999px").unwrap();
89+
body.append_child(&video).unwrap();
90+
91+
// Wait for video to start playing
92+
let play_promise = video.play().unwrap();
93+
wasm_bindgen_futures::JsFuture::from(play_promise)
94+
.await
95+
.ok();
96+
97+
// Wait a bit for the video feed to stabilize
98+
yew::platform::time::sleep(std::time::Duration::from_millis(500)).await;
99+
100+
// Get video track settings to know dimensions
101+
let tracks = stream.get_video_tracks();
102+
let track = tracks
103+
.get(0)
104+
.dyn_into::<web_sys::MediaStreamTrack>()
105+
.unwrap();
106+
let settings = track.get_settings();
107+
108+
let width = settings.get_width().unwrap_or(1920) as u32;
109+
let height = settings.get_height().unwrap_or(1080) as u32;
110+
111+
// Create canvas and draw the video frame
112+
let canvas = document
113+
.create_element("canvas")
114+
.unwrap()
115+
.dyn_into::<HtmlCanvasElement>()
116+
.unwrap();
117+
canvas.set_width(width);
118+
canvas.set_height(height);
119+
120+
let ctx = canvas
121+
.get_context("2d")
122+
.unwrap()
123+
.unwrap()
124+
.dyn_into::<CanvasRenderingContext2d>()
125+
.unwrap();
126+
127+
// Draw the video frame to canvas
128+
ctx.draw_image_with_html_video_element(&video, 0.0, 0.0)
129+
.unwrap();
130+
131+
// Stop the capture
132+
let tracks = stream.get_tracks();
133+
for i in 0..tracks.length() {
134+
let track = tracks.get(i);
135+
if !track.is_undefined() {
136+
track
137+
.dyn_into::<web_sys::MediaStreamTrack>()
138+
.unwrap()
139+
.stop();
140+
}
141+
}
142+
video.remove();
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+
// Clean up
183+
container.remove();
184+
canvas.remove();
185+
186+
// Log pixel analysis
187+
web_sys::console::log_1(&format!("Has non-white pixels: {}", has_non_white_pixels).into());
188+
web_sys::console::log_1(&format!("Sample pixels: {:?}", sample_pixels).into());
189+
190+
assert!(
191+
has_non_white_pixels,
192+
"Expected no red pixels due to feDropShadow being lowercased incorrectly"
193+
);
194+
}

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)