Make TestHarness constructors take NewWidget (#1241)

Have WidgetExt methods return NewWidget instead of WrapperWidget.
Rewrite testing tutorial a bit.
Rewrite some tests to avoid relying on WidgetExt.

This overall makes code more consistent: everything which creates a
widget takes `NewWidget`.
This commit is contained in:
Olivier FAURE 2025-07-29 14:54:45 +02:00 committed by GitHub
parent d4d48d80a5
commit 7054bd42a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 378 additions and 291 deletions

View File

@ -239,18 +239,20 @@ fn set_bg(color_rectangle_mut: WidgetMut<'_, ColorRectangle>) {
mod tests {
use super::*;
use insta::assert_debug_snapshot;
use masonry::testing::{TestHarness, TestWidgetExt, widget_ids};
use masonry::testing::{TestHarness, widget_ids};
use masonry::theme::default_property_set;
use masonry_core::core::NewWidget;
// ---
use masonry::testing::assert_render_snapshot;
// ---
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
#[test]
fn simple_rect() {
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let [rect_id] = widget_ids();
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE).with_id(rect_id);
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE);
let mut harness = TestHarness::create(default_property_set(), widget);
let mut harness = TestHarness::create(default_property_set(), NewWidget::new(widget));
assert_debug_snapshot!(harness.root_widget());
@ -263,9 +265,9 @@ mod tests {
#[test]
fn hovered() {
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let [rect_id] = widget_ids();
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE).with_id(rect_id);
let widget =
NewWidget::new_with_id(ColorRectangle::new(Size::new(20.0, 20.0), BLUE), rect_id);
let mut harness = TestHarness::create(default_property_set(), widget);
@ -280,8 +282,7 @@ mod tests {
#[test]
fn edit_rect() {
const RED: Color = Color::from_rgb8(u8::MAX, 0, 0);
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE);
let widget = NewWidget::new(ColorRectangle::new(Size::new(20.0, 20.0), BLUE));
let mut harness = TestHarness::create(default_property_set(), widget);
@ -297,9 +298,9 @@ mod tests {
#[test]
fn on_click() {
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let [rect_id] = widget_ids();
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE).with_id(rect_id);
let widget =
NewWidget::new_with_id(ColorRectangle::new(Size::new(20.0, 20.0), BLUE), rect_id);
let mut harness = TestHarness::create(default_property_set(), widget);

View File

@ -1,8 +1,6 @@
---
source: masonry/src/doc/color_rectangle.rs
assertion_line: 188
assertion_line: 257
expression: harness.root_widget()
---
WrapperWidget(
ColorRectangle,
)
ColorRectangle

View File

@ -32,14 +32,15 @@ First, let's write a test module with a first unit test:
mod tests {
use super::*;
use insta::assert_debug_snapshot;
use masonry::testing::{widget_ids, TestHarness, TestWidgetExt};
use masonry::testing::{TestHarness, TestWidgetExt, widget_ids};
use masonry::theme::default_property_set;
use masonry_core::core::NewWidget;
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
#[test]
fn simple_rect() {
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let [rect_id] = widget_ids();
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE).with_id(rect_id);
let widget = NewWidget::new(ColorRectangle::new(Size::new(20.0, 20.0), BLUE));
let mut harness = TestHarness::create(default_property_set(), widget);
@ -50,13 +51,11 @@ mod tests {
}
```
<!-- TODO - Rewrite this once we have a better way to assign ids to widgets. -->
First, we create a `ColorRectangle` with an arbitrary size and color.
We use `TestWidgetExt::with_id()` to assign it a pre-drawn id.
(As a side-effect, this also wraps our `ColorRectangle` in a [`WrapperWidget`].)
Then we instantiate the [`TestHarness`], with our (wrapped) `ColorRectangle` as the root.
<!-- TODO - Document NewWidget in previous chapter. -->
Then we instantiate the [`TestHarness`], with our `ColorRectangle`, wrapped in a `NewWidget`, as the root.
We use `TestHarness::root_widget()` to get a [`WidgetRef`] to our root.
@ -113,9 +112,9 @@ Let's create another snapshot test to check that our widget correctly changes co
#[test]
fn hovered() {
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let [rect_id] = widget_ids();
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE).with_id(rect_id);
let widget =
NewWidget::new_with_id(ColorRectangle::new(Size::new(20.0, 20.0), BLUE), rect_id);
let mut harness = TestHarness::create(default_property_set(), widget);
@ -126,6 +125,9 @@ Let's create another snapshot test to check that our widget correctly changes co
}
```
We use `NewWidget::new_with_id()` to create our widget a pre-drawn id.
Then we move the mouse to our rectangle widget, and we check the widget's new appearance.
<!-- TODO - Include screenshot. -->
@ -143,8 +145,7 @@ Let's add a test that changes a rectangle's color, then checks its visual appear
#[test]
fn edit_rect() {
const RED: Color = Color::from_rgb8(u8::MAX, 0, 0);
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE);
let widget = NewWidget::new(ColorRectangle::new(Size::new(20.0, 20.0), BLUE));
let mut harness = TestHarness::create(default_property_set(), widget);
@ -164,16 +165,16 @@ Let's add a test that changes a rectangle's color, then checks its visual appear
The `TestHarness` is also capable of reading actions emitted by our widget with the `pop_action()` method.
Since our `WidgetRectangle` doesn't emit actions, let's look at a unit test for the [`Button`] widget instead:
<!-- TODO - Explain this. -->
```rust
// ...
#[test]
fn on_click() {
const BLUE: Color = Color::from_rgb8(0, 0, u8::MAX);
let [rect_id] = widget_ids();
let widget = ColorRectangle::new(Size::new(20.0, 20.0), BLUE).with_id(rect_id);
let widget =
NewWidget::new_with_id(ColorRectangle::new(Size::new(20.0, 20.0), BLUE), rect_id);
let mut harness = TestHarness::create(default_property_set(), widget);

View File

@ -181,7 +181,7 @@ mod tests {
#[test]
fn centered() {
let widget = Align::centered(Label::new("hello").with_auto_id());
let widget = Align::centered(Label::new("hello").with_auto_id()).with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
@ -190,7 +190,7 @@ mod tests {
#[test]
fn right() {
let widget = Align::right(Label::new("hello").with_auto_id());
let widget = Align::right(Label::new("hello").with_auto_id()).with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
@ -199,7 +199,7 @@ mod tests {
#[test]
fn left() {
let widget = Align::left(Label::new("hello").with_auto_id());
let widget = Align::left(Label::new("hello").with_auto_id()).with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);

View File

@ -305,14 +305,14 @@ mod tests {
use crate::core::keyboard::NamedKey;
use crate::core::{PointerButton, Properties, StyleProperty};
use crate::properties::TextColor;
use crate::testing::{TestHarness, TestWidgetExt, assert_render_snapshot, widget_ids};
use crate::testing::{TestHarness, assert_render_snapshot, widget_ids};
use crate::theme::{ACCENT_COLOR, default_property_set};
use crate::widgets::{Grid, GridParams};
#[test]
fn simple_button() {
let [button_id] = widget_ids();
let widget = Button::new("Hello").with_id(button_id);
let widget = NewWidget::new_with_id(Button::new("Hello"), button_id);
let window_size = Size::new(100.0, 40.0);
let mut harness =
@ -356,7 +356,7 @@ mod tests {
Properties::new().with(TextColor::new(ACCENT_COLOR)),
);
let button = Button::from_label(label);
let button = NewWidget::new(Button::from_label(label));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -368,7 +368,7 @@ mod tests {
};
let image_2 = {
let button = Button::new("Hello world");
let button = NewWidget::new(Button::new("Hello world"));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -394,7 +394,7 @@ mod tests {
#[test]
fn set_properties() {
let red = crate::palette::css::RED;
let button = Button::new("Some random text");
let button = NewWidget::new(Button::new("Some random text"));
let window_size = Size::new(200.0, 80.0);
let mut harness =

View File

@ -320,13 +320,13 @@ mod tests {
use super::*;
use crate::core::{Properties, StyleProperty};
use crate::properties::TextColor;
use crate::testing::{TestHarness, TestWidgetExt, assert_render_snapshot, widget_ids};
use crate::testing::{TestHarness, assert_render_snapshot, widget_ids};
use crate::theme::{ACCENT_COLOR, default_property_set};
#[test]
fn simple_checkbox() {
let [checkbox_id] = widget_ids();
let widget = Checkbox::new(false, "Hello").with_id(checkbox_id);
let widget = NewWidget::new_with_id(Checkbox::new(false, "Hello"), checkbox_id);
let window_size = Size::new(100.0, 40.0);
let mut harness =
@ -365,7 +365,7 @@ mod tests {
label,
Properties::new().with(TextColor::new(ACCENT_COLOR)),
);
let checkbox = Checkbox::from_label(true, label);
let checkbox = NewWidget::new(Checkbox::from_label(true, label));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -377,7 +377,7 @@ mod tests {
};
let image_2 = {
let checkbox = Checkbox::new(false, "Hello world");
let checkbox = NewWidget::new(Checkbox::new(false, "Hello world"));
let mut harness = TestHarness::create_with_size(
default_property_set(),

View File

@ -1067,7 +1067,8 @@ mod tests {
.with_flex_child(
Label::new("bar").with_auto_id(),
FlexParams::new(2.0, CrossAxisAlignment::Start),
);
)
.with_auto_id();
let window_size = Size::new(200.0, 150.0);
let mut harness =
@ -1108,7 +1109,8 @@ mod tests {
.with_flex_child(
Label::new("bar").with_auto_id(),
FlexParams::new(2.0, CrossAxisAlignment::Start),
);
)
.with_auto_id();
let window_size = Size::new(200.0, 150.0);
let mut harness =
@ -1164,7 +1166,8 @@ mod tests {
.with_flex_child(
Label::new("bar").with_auto_id(),
FlexParams::new(2.0, CrossAxisAlignment::Start),
);
)
.with_auto_id();
let window_size = Size::new(200.0, 150.0);
let mut harness =
@ -1205,7 +1208,8 @@ mod tests {
.with_flex_child(
Label::new("bar").with_auto_id(),
FlexParams::new(2.0, CrossAxisAlignment::Start),
);
)
.with_auto_id();
let window_size = Size::new(200.0, 150.0);
let mut harness =
@ -1259,7 +1263,8 @@ mod tests {
.with_child(Label::new("a").with_auto_id())
.with_child(Label::new("b").with_auto_id())
.with_child(Label::new("c").with_auto_id())
.with_child(Label::new("d").with_auto_id());
.with_child(Label::new("d").with_auto_id())
.with_auto_id();
// -> abcd
let window_size = Size::new(200.0, 150.0);
@ -1302,7 +1307,8 @@ mod tests {
.with_child(Label::new("x").with_auto_id())
.with_flex_child(Label::new("y").with_auto_id(), 2.0)
.with_spacer(5.0)
.with_flex_spacer(1.0);
.with_flex_spacer(1.0)
.with_auto_id();
let window_size = Size::new(200.0, 150.0);
let mut harness =
@ -1319,7 +1325,8 @@ mod tests {
let widget = Flex::column()
.with_child(Label::new("hello").with_auto_id())
.with_child(Label::new("world").with_auto_id())
.with_spacer(1.0);
.with_spacer(1.0)
.with_auto_id();
let window_size = Size::new(200.0, 150.0);
let mut harness =
@ -1345,7 +1352,7 @@ mod tests {
#[test]
fn divide_by_zero() {
let widget = Flex::column().with_flex_spacer(0.0);
let widget = Flex::column().with_flex_spacer(0.0).with_auto_id();
// Running layout should not panic when the flex sum is zero.
let window_size = Size::new(200.0, 150.0);

View File

@ -351,10 +351,10 @@ mod tests {
#[test]
fn test_grid_basics() {
// Start with a 1x1 grid
let widget = Grid::with_dimensions(1, 1).with_child(
let widget = NewWidget::new(Grid::with_dimensions(1, 1).with_child(
button::Button::new("A").with_auto_id(),
GridParams::new(0, 0, 1, 1),
);
));
let window_size = Size::new(200.0, 200.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -417,10 +417,10 @@ mod tests {
#[test]
fn test_widget_removal_and_modification() {
let widget = Grid::with_dimensions(2, 2).with_child(
let widget = NewWidget::new(Grid::with_dimensions(2, 2).with_child(
button::Button::new("A").with_auto_id(),
GridParams::new(0, 0, 1, 1),
);
));
let window_size = Size::new(200.0, 200.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -458,10 +458,10 @@ mod tests {
#[test]
fn test_widget_order() {
let widget = Grid::with_dimensions(2, 2).with_child(
let widget = NewWidget::new(Grid::with_dimensions(2, 2).with_child(
button::Button::new("A").with_auto_id(),
GridParams::new(0, 0, 1, 1),
);
));
let window_size = Size::new(200.0, 200.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);

View File

@ -152,6 +152,7 @@ impl Widget for Image {
// --- MARK: TESTS
#[cfg(test)]
mod tests {
use masonry_core::core::NewWidget;
use vello::peniko::ImageFormat;
use super::*;
@ -164,7 +165,7 @@ mod tests {
// TODO - Blob::empty() function?
let image_data = ImageBuf::new(Vec::new().into(), ImageFormat::Rgba8, 0, 0);
let image_widget = Image::new(image_data);
let image_widget = NewWidget::new(Image::new(image_data));
let mut harness = TestHarness::create(default_property_set(), image_widget);
let _ = harness.render();
}
@ -189,7 +190,7 @@ mod tests {
2,
2,
);
let image_widget = Image::new(image_data);
let image_widget = NewWidget::new(Image::new(image_data));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -204,7 +205,7 @@ mod tests {
let image_data = ImageBuf::new(vec![255; 4 * 8 * 8].into(), ImageFormat::Rgba8, 8, 8);
let render_1 = {
let image_widget = Image::new(image_data.clone());
let image_widget = NewWidget::new(Image::new(image_data.clone()));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -218,7 +219,7 @@ mod tests {
let render_2 = {
let other_image_data =
ImageBuf::new(vec![10; 4 * 8 * 8].into(), ImageFormat::Rgba8, 8, 8);
let image_widget = Image::new(other_image_data);
let image_widget = NewWidget::new(Image::new(other_image_data));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -243,46 +244,50 @@ mod tests {
let image_data = ImageBuf::new(vec![255; 4 * 8 * 8].into(), ImageFormat::Rgba8, 8, 8);
let harness_size = Size::new(100.0, 50.0);
// Contain.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::Contain);
let image_widget = NewWidget::new(Image::new(image_data.clone()));
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
// Contain.
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::Contain);
});
assert_render_snapshot!(harness, "image_layout_contain");
// Cover.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::Cover);
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::Cover);
});
assert_render_snapshot!(harness, "image_layout_cover");
// Fill.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::Fill);
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::Fill);
});
assert_render_snapshot!(harness, "image_layout_fill");
// FitHeight.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::FitHeight);
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::FitHeight);
});
assert_render_snapshot!(harness, "image_layout_fitheight");
// FitWidth.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::FitWidth);
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::FitWidth);
});
assert_render_snapshot!(harness, "image_layout_fitwidth");
// None.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::None);
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::None);
});
assert_render_snapshot!(harness, "image_layout_none");
// ScaleDown.
let image_widget = Image::new(image_data.clone()).fit_mode(ObjectFit::ScaleDown);
let mut harness =
TestHarness::create_with_size(default_property_set(), image_widget, harness_size);
harness.edit_root_widget(|mut image| {
Image::set_fit_mode(&mut image, ObjectFit::ScaleDown);
});
assert_render_snapshot!(harness, "image_layout_scaledown");
}
}

View File

@ -290,7 +290,7 @@ mod tests {
#[test]
fn test_indexed_stack_basics() {
let widget = IndexedStack::new();
let widget = IndexedStack::new().with_auto_id();
let window_size = Size::new(50.0, 50.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -321,7 +321,8 @@ mod tests {
.with_child(button::Button::new("A").with_auto_id())
.with_child(button::Button::new("B").with_auto_id())
.with_child(button::Button::new("C").with_auto_id())
.with_active_child(1);
.with_active_child(1)
.with_auto_id();
let window_size = Size::new(50.0, 50.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);

View File

@ -420,8 +420,6 @@ impl Widget for Label {
// --- MARK: TESTS
#[cfg(test)]
mod tests {
use masonry_testing::TestWidgetExt as _;
use parley::style::GenericFamily;
use parley::{FontFamily, StyleProperty};
@ -434,7 +432,7 @@ mod tests {
#[test]
fn simple_label() {
let label = Label::new("Hello");
let label = Label::new("Hello").with_auto_id();
let window_size = Size::new(100.0, 40.0);
let mut harness = TestHarness::create_with_size(default_property_set(), label, window_size);
@ -461,7 +459,8 @@ mod tests {
fn underline_label() {
let label = Label::new("Emphasis")
.with_line_break_mode(LineBreaking::WordWrap)
.with_style(StyleProperty::Underline(true));
.with_style(StyleProperty::Underline(true))
.with_auto_id();
let window_size = Size::new(100.0, 40.0);
let mut harness = TestHarness::create_with_size(default_property_set(), label, window_size);
@ -473,7 +472,8 @@ mod tests {
let label = Label::new("Tpyo")
.with_line_break_mode(LineBreaking::WordWrap)
.with_style(StyleProperty::Strikethrough(true))
.with_style(StyleProperty::StrikethroughSize(Some(4.)));
.with_style(StyleProperty::StrikethroughSize(Some(4.)))
.with_auto_id();
let window_size = Size::new(100.0, 40.0);
let mut harness = TestHarness::create_with_size(default_property_set(), label, window_size);
@ -504,7 +504,8 @@ mod tests {
.with_flex_child(label4.with_auto_id(), CrossAxisAlignment::Center)
.with_flex_child(label5.with_auto_id(), CrossAxisAlignment::Center)
.with_flex_child(label6.with_auto_id(), CrossAxisAlignment::Center)
.with_gap(0.0);
.with_gap(0.0)
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), flex, Size::new(200.0, 200.0));
@ -545,7 +546,8 @@ mod tests {
.width(180.0)
.with_auto_id(),
)
.with_flex_spacer(1.0);
.with_flex_spacer(1.0)
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(200.0, 200.0));
@ -570,7 +572,9 @@ mod tests {
};
let image_2 = {
let label = Label::new("Hello world").with_style(StyleProperty::FontSize(40.0));
let label = Label::new("Hello world")
.with_style(StyleProperty::FontSize(40.0))
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), label, Size::new(50.0, 50.0));

View File

@ -532,7 +532,8 @@ mod tests {
.with_spacer(10.0)
.with_child(button("Item 14").with_auto_id())
.with_spacer(10.0),
));
))
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(400., 400.));
@ -573,7 +574,8 @@ mod tests {
))
.with_spacer(500.0)
.with_auto_id(),
);
)
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(200., 200.));

View File

@ -197,15 +197,16 @@ impl Widget for ProgressBar {
// --- MARK: TESTS
#[cfg(test)]
mod tests {
use masonry_core::core::NewWidget;
use super::*;
use crate::testing::{TestHarness, TestWidgetExt, assert_render_snapshot, widget_ids};
use crate::testing::{TestHarness, assert_render_snapshot};
use crate::theme::default_property_set;
use crate::{core::Properties, palette};
#[test]
fn indeterminate_progressbar() {
let [progressbar_id] = widget_ids();
let widget = ProgressBar::new(None).with_id(progressbar_id);
let widget = NewWidget::new(ProgressBar::new(None));
let window_size = Size::new(150.0, 60.0);
let mut harness =
@ -216,9 +217,7 @@ mod tests {
#[test]
fn _0_percent_progressbar() {
let [_0percent] = widget_ids();
let widget = ProgressBar::new(Some(0.)).with_id(_0percent);
let widget = NewWidget::new(ProgressBar::new(Some(0.)));
let window_size = Size::new(150.0, 60.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -228,9 +227,7 @@ mod tests {
#[test]
fn _25_percent_progressbar() {
let [_25percent] = widget_ids();
let widget = ProgressBar::new(Some(0.25)).with_id(_25percent);
let widget = NewWidget::new(ProgressBar::new(Some(0.25)));
let window_size = Size::new(150.0, 60.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -240,9 +237,7 @@ mod tests {
#[test]
fn _50_percent_progressbar() {
let [_50percent] = widget_ids();
let widget = ProgressBar::new(Some(0.5)).with_id(_50percent);
let widget = NewWidget::new(ProgressBar::new(Some(0.5)));
let window_size = Size::new(150.0, 60.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -252,9 +247,7 @@ mod tests {
#[test]
fn _75_percent_progressbar() {
let [_75percent] = widget_ids();
let widget = ProgressBar::new(Some(0.75)).with_id(_75percent);
let widget = NewWidget::new(ProgressBar::new(Some(0.75)));
let window_size = Size::new(150.0, 60.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -264,9 +257,7 @@ mod tests {
#[test]
fn _100_percent_progressbar() {
let [_100percent] = widget_ids();
let widget = ProgressBar::new(Some(1.)).with_id(_100percent);
let widget = NewWidget::new(ProgressBar::new(Some(1.)));
let window_size = Size::new(150.0, 60.0);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, window_size);
@ -287,7 +278,7 @@ mod tests {
};
let image_2 = {
let bar = ProgressBar::new(None);
let bar = NewWidget::new(ProgressBar::new(None));
let mut harness =
TestHarness::create_with_size(default_property_set(), bar, Size::new(60.0, 20.0));

View File

@ -199,13 +199,12 @@ mod tests {
.with_word_wrap(false)
.with_auto_id(),
)
.with_clip(true);
.with_clip(true)
.with_auto_id();
let root_widget = Flex::row().with_child(
SizedBox::new(prose.with_auto_id())
.width(60.)
.with_auto_id(),
);
let root_widget = Flex::row()
.with_child(SizedBox::new(prose).width(60.).with_auto_id())
.with_auto_id();
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -243,7 +242,8 @@ mod tests {
.with_flex_child(prose4.with_auto_id(), CrossAxisAlignment::Center)
.with_flex_child(prose5.with_auto_id(), CrossAxisAlignment::Center)
.with_flex_child(prose6.with_auto_id(), CrossAxisAlignment::Center)
.with_gap(0.0);
.with_gap(0.0)
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), flex, Size::new(200.0, 120.0));

View File

@ -260,15 +260,18 @@ impl AllowRawMut for ScrollBar {}
// --- MARK: TESTS
#[cfg(test)]
mod tests {
use masonry_core::core::NewWidget;
use super::*;
use crate::core::PointerButton;
use crate::testing::{TestHarness, TestWidgetExt, assert_render_snapshot, widget_ids};
use crate::testing::{TestHarness, assert_render_snapshot, widget_ids};
use crate::theme::default_property_set;
#[test]
fn simple_scrollbar() {
let [scrollbar_id] = widget_ids();
let widget = ScrollBar::new(Axis::Vertical, 200.0, 600.0).with_id(scrollbar_id);
let widget =
NewWidget::new_with_id(ScrollBar::new(Axis::Vertical, 200.0, 600.0), scrollbar_id);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(50.0, 200.0));
@ -295,7 +298,8 @@ mod tests {
#[test]
fn horizontal_scrollbar() {
let [scrollbar_id] = widget_ids();
let widget = ScrollBar::new(Axis::Horizontal, 200.0, 600.0).with_id(scrollbar_id);
let widget =
NewWidget::new_with_id(ScrollBar::new(Axis::Horizontal, 200.0, 600.0), scrollbar_id);
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(200.0, 50.0));

View File

@ -302,9 +302,7 @@ mod tests {
use crate::core::Properties;
use crate::palette;
use crate::properties::types::{Gradient, UnitPoint};
use crate::testing::{
TestHarness, TestWidgetExt, assert_failing_render_snapshot, assert_render_snapshot,
};
use crate::testing::{TestHarness, assert_failing_render_snapshot, assert_render_snapshot};
use crate::theme::default_property_set;
use crate::widgets::Label;

View File

@ -162,6 +162,8 @@ impl Widget for Spinner {
// --- MARK: TESTS
#[cfg(test)]
mod tests {
use masonry_core::core::NewWidget;
use super::*;
use crate::palette;
use crate::testing::{TestHarness, assert_render_snapshot};
@ -169,7 +171,7 @@ mod tests {
#[test]
fn simple_spinner() {
let spinner = Spinner::new();
let spinner = NewWidget::new(Spinner::new());
let window_size = Size::new(100.0, 100.0);
let mut harness =
@ -186,7 +188,7 @@ mod tests {
#[test]
fn edit_spinner() {
let image_1 = {
let spinner = Spinner::new().with_color(palette::css::PURPLE);
let spinner = NewWidget::new(Spinner::new().with_color(palette::css::PURPLE));
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -197,7 +199,7 @@ mod tests {
};
let image_2 = {
let spinner = Spinner::new();
let spinner = NewWidget::new(Spinner::new());
let mut harness = TestHarness::create_with_size(
default_property_set(),

View File

@ -612,7 +612,7 @@ mod tests {
let widget = Split::new(
Label::new("Hello").with_auto_id(),
Label::new("World").with_auto_id(),
).split_axis(Axis::Horizontal).draggable(false);
).split_axis(Axis::Horizontal).draggable(false).with_auto_id();
let window_size = Size::new(150.0, 150.0);
let mut harness =
@ -627,7 +627,7 @@ mod tests {
let widget = Split::new(
Label::new("Hello").with_auto_id(),
Label::new("World").with_auto_id(),
).split_axis(Axis::Vertical).draggable(false);
).split_axis(Axis::Vertical).draggable(false).with_auto_id();
let window_size = Size::new(150.0, 150.0);
let mut harness =
@ -650,7 +650,8 @@ mod tests {
.min_size(40.0, 10.0)
.bar_size(12.0)
.draggable(true)
.solid_bar(true);
.solid_bar(true)
.with_auto_id();
let mut harness = TestHarness::create_with_size(
default_property_set(),
@ -665,7 +666,8 @@ mod tests {
let widget = Split::new(
Label::new("Hello").with_auto_id(),
Label::new("World").with_auto_id(),
);
)
.with_auto_id();
let mut harness = TestHarness::create_with_size(
default_property_set(),

View File

@ -11,13 +11,15 @@ use crate::widgets::{Flex, TextArea, TextInput};
#[test]
fn ime_on_remove() {
let [text_area] = widget_ids();
let widget = Flex::column().with_child(
TextInput::from_text_area(NewWidget::new_with_id(
TextArea::new_editable("Simple input test"),
text_area,
))
.with_auto_id(),
);
let widget = Flex::column()
.with_child(
TextInput::from_text_area(NewWidget::new_with_id(
TextArea::new_editable("Simple input test"),
text_area,
))
.with_auto_id(),
)
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
harness.focus_on(Some(text_area));

View File

@ -6,7 +6,7 @@
use vello::kurbo::{Insets, Size};
use crate::core::{NewWidget, Widget as _};
use crate::testing::{ModularWidget, TestHarness, TestWidgetExt, widget_ids};
use crate::testing::{ModularWidget, TestHarness, widget_ids};
use crate::theme::default_property_set;
use crate::widgets::{Flex, SizedBox};
@ -30,7 +30,8 @@ fn layout_simple() {
.with_flex_spacer(1.0)
.with_auto_id(),
)
.with_flex_spacer(1.0);
.with_flex_spacer(1.0)
.with_auto_id();
let harness = TestHarness::create(default_property_set(), widget);

View File

@ -5,6 +5,7 @@
use insta::assert_debug_snapshot;
use crate::core::Widget;
use crate::testing::{
Record, Recording, TestHarness, TestWidgetExt as _, WrapperWidget, widget_ids,
};
@ -15,7 +16,7 @@ use crate::*;
#[test]
fn app_creation() {
let record = Recording::default();
let widget = SizedBox::empty().record(&record);
let widget = SizedBox::empty().record(&record).with_auto_id();
let _harness = TestHarness::create(default_property_set(), widget);

View File

@ -4,7 +4,7 @@
use vello::kurbo::{Point, Size};
use crate::core::{ChildrenIds, PointerButton, Update, Widget, WidgetId, WidgetPod};
use crate::testing::{ModularWidget, TestHarness, TestWidgetExt};
use crate::testing::{ModularWidget, TestHarness};
use crate::theme::default_property_set;
use crate::widgets::Flex;
@ -26,9 +26,11 @@ fn make_parent_widget<W: Widget>(child: W) -> ModularWidget<WidgetPod<W>> {
#[should_panic(expected = "not visited in method on_text_event")]
#[test]
fn check_forget_to_recurse_text_event() {
let widget = make_parent_widget(Flex::row()).text_event_fn(|_child, _ctx, _, _event| {
// We forget to call child.on_text_event();
});
let widget = make_parent_widget(Flex::row())
.text_event_fn(|_child, _ctx, _, _event| {
// We forget to call child.on_text_event();
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.mouse_move(Point::ZERO);
@ -42,9 +44,11 @@ fn check_forget_to_recurse_text_event() {
ignore = "This test doesn't work without debug assertions (i.e. in release mode). See https://github.com/linebender/xilem/issues/477"
)]
fn check_forget_to_recurse_lifecycle() {
let widget = make_parent_widget(Flex::row()).lifecycle_fn(|_child, _ctx, _event| {
// We forget to call child.lifecycle();
});
let widget = make_parent_widget(Flex::row())
.lifecycle_fn(|_child, _ctx, _event| {
// We forget to call child.lifecycle();
})
.with_auto_id();
let _harness = TestHarness::create(widget);
}
@ -53,14 +57,16 @@ fn check_forget_to_recurse_lifecycle() {
#[should_panic(expected = "before receiving WidgetAdded.")]
#[test]
fn check_forget_to_recurse_widget_added() {
let widget = make_parent_widget(Flex::row()).lifecycle_fn(|child, ctx, event| {
if let Update::WidgetAdded = event {
// We forget to call child.lifecycle();
ctx.skip_child(child);
} else {
child.lifecycle(ctx, event);
}
});
let widget = make_parent_widget(Flex::row())
.lifecycle_fn(|child, ctx, event| {
if let Update::WidgetAdded = event {
// We forget to call child.lifecycle();
ctx.skip_child(child);
} else {
child.lifecycle(ctx, event);
}
})
.with_auto_id();
let _harness = TestHarness::create(widget);
}
@ -72,9 +78,11 @@ fn check_forget_to_recurse_widget_added() {
ignore = "This test doesn't work without debug assertions (i.e. in release mode). See https://github.com/linebender/xilem/issues/477"
)]
fn check_forget_register_child() {
let widget = make_parent_widget(Flex::row()).register_children_fn(|_child, _ctx| {
// We forget to call ctx.register_child();
});
let widget = make_parent_widget(Flex::row())
.register_children_fn(|_child, _ctx| {
// We forget to call ctx.register_child();
})
.with_auto_id();
let _harness = TestHarness::create(default_property_set(), widget);
}
@ -86,10 +94,12 @@ fn check_forget_register_child() {
ignore = "This test doesn't work without debug assertions (i.e. in release mode). See https://github.com/linebender/xilem/issues/477"
)]
fn check_register_invalid_child() {
let widget = make_parent_widget(Flex::row()).register_children_fn(|child, ctx| {
ctx.register_child(child);
ctx.register_child(&mut WidgetPod::new(Flex::row()));
});
let widget = make_parent_widget(Flex::row())
.register_children_fn(|child, ctx| {
ctx.register_child(child);
ctx.register_child(&mut WidgetPod::new(Flex::row()));
})
.with_auto_id();
let _harness = TestHarness::create(default_property_set(), widget);
}
@ -101,9 +111,11 @@ fn check_register_invalid_child() {
ignore = "This test doesn't work without debug assertions (i.e. in release mode). See https://github.com/linebender/xilem/issues/477"
)]
fn check_pointer_capture_outside_pointer_down() {
let widget = ModularWidget::new(()).pointer_event_fn(|_, ctx, _, _event| {
ctx.capture_pointer();
});
let widget = ModularWidget::new(())
.pointer_event_fn(|_, ctx, _, _event| {
ctx.capture_pointer();
})
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
harness.mouse_move((10.0, 10.0));
@ -137,10 +149,12 @@ fn check_pointer_capture_text_event() {
ignore = "This test doesn't work without debug assertions (i.e. in release mode). See https://github.com/linebender/xilem/issues/477"
)]
fn check_forget_to_recurse_layout() {
let widget = make_parent_widget(Flex::row()).layout_fn(|_child, _ctx, _, _| {
// We forget to call ctx.run_layout();
Size::ZERO
});
let widget = make_parent_widget(Flex::row())
.layout_fn(|_child, _ctx, _, _| {
// We forget to call ctx.run_layout();
Size::ZERO
})
.with_auto_id();
let _harness = TestHarness::create(default_property_set(), widget);
}
@ -152,10 +166,12 @@ fn check_forget_to_recurse_layout() {
ignore = "This test doesn't work without debug assertions (i.e. in release mode). See https://github.com/linebender/xilem/issues/477"
)]
fn check_forget_to_call_place_child() {
let widget = make_parent_widget(Flex::row()).layout_fn(|child, ctx, _, bc| {
// We call ctx.run_layout(), but forget place_child
ctx.run_layout(child, bc)
});
let widget = make_parent_widget(Flex::row())
.layout_fn(|child, ctx, _, bc| {
// We call ctx.run_layout(), but forget place_child
ctx.run_layout(child, bc)
})
.with_auto_id();
let _harness = TestHarness::create(default_property_set(), widget);
}
@ -175,7 +191,8 @@ fn allow_non_recurse_event_handled() {
.text_event_fn(|_child, ctx, _, _event| {
// Event handled, we don't need to recurse
ctx.set_handled();
});
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.mouse_move(Point::ZERO);
@ -194,7 +211,8 @@ fn allow_non_recurse_cursor_oob() {
let _size = ctx.run_layout(child, bc);
ctx.place_child(child, Point::ZERO);
Size::new(6000.0, 6000.0)
});
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.mouse_move(Point::new(5000.0, 5000.0));
@ -211,7 +229,8 @@ fn allow_non_recurse_oob_paint() {
let _size = ctx.run_layout(child, bc);
ctx.place_child(child, Point::new(500.0, 500.0));
Size::new(600.0, 600.0)
});
})
.with_auto_id();
let mut harness = TestHarness::create_with_size(widget, Size::new(400.0, 400.0));
harness.render();
@ -262,7 +281,8 @@ fn check_forget_children_changed() {
} else {
ChildrenIds::new()
}
});
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.submit_command(ADD_CHILD);
@ -274,10 +294,12 @@ fn check_forget_children_changed() {
#[should_panic]
#[test]
fn check_recurse_event_twice() {
let widget = make_parent_widget(Flex::row()).pointer_event_fn(|child, ctx, _, event| {
child.on_pointer_event(ctx, event);
child.on_pointer_event(ctx, event);
});
let widget = make_parent_widget(Flex::row())
.pointer_event_fn(|child, ctx, _, event| {
child.on_pointer_event(ctx, event);
child.on_pointer_event(ctx, event);
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.mouse_move(Point::ZERO);
@ -287,10 +309,12 @@ fn check_recurse_event_twice() {
#[should_panic]
#[test]
fn check_recurse_lifecycle_twice() {
let widget = make_parent_widget(Flex::row()).lifecycle_fn(|child, ctx, event| {
child.lifecycle(ctx, event);
child.lifecycle(ctx, event);
});
let widget = make_parent_widget(Flex::row())
.lifecycle_fn(|child, ctx, event| {
child.lifecycle(ctx, event);
child.lifecycle(ctx, event);
})
.with_auto_id();
let _harness = TestHarness::create(widget);
}
@ -299,12 +323,14 @@ fn check_recurse_lifecycle_twice() {
#[should_panic]
#[test]
fn check_recurse_layout_twice() {
let widget = make_parent_widget(Flex::row()).layout_fn(|child, ctx, _, bc| {
let size = ctx.run_layout(child, bc);
let _ = ctx.run_layout(child, bc);
ctx.place_child(child, Point::ZERO);
size
});
let widget = make_parent_widget(Flex::row())
.layout_fn(|child, ctx, _, bc| {
let size = ctx.run_layout(child, bc);
let _ = ctx.run_layout(child, bc);
ctx.place_child(child, Point::ZERO);
size
})
.with_auto_id();
let _harness = TestHarness::create(widget);
}
@ -313,10 +339,12 @@ fn check_recurse_layout_twice() {
#[should_panic]
#[test]
fn check_recurse_paint_twice() {
let widget = make_parent_widget(Flex::row()).paint_fn(|child, ctx, scene| {
child.paint(ctx, scene);
child.paint(ctx, scene);
});
let widget = make_parent_widget(Flex::row())
.paint_fn(|child, ctx, scene| {
child.paint(ctx, scene);
child.paint(ctx, scene);
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.render();
@ -337,7 +365,8 @@ fn check_layout_stashed() {
let size = ctx.run_layout(child, bc);
ctx.place_child(child, Point::ZERO);
size
});
})
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
harness.mouse_move(Point::ZERO);
@ -351,11 +380,13 @@ fn check_layout_stashed() {
#[test]
fn check_paint_rect_includes_children() {
use crate::widgets::Label;
let widget = make_parent_widget(Label::new("Hello world")).layout_fn(|child, ctx, _, bc| {
let _size = ctx.run_layout(child, bc);
ctx.place_child(child, Point::ZERO);
Size::ZERO
});
let widget = make_parent_widget(Label::new("Hello world"))
.layout_fn(|child, ctx, _, bc| {
let _size = ctx.run_layout(child, bc);
ctx.place_child(child, Point::ZERO);
Size::ZERO
})
.with_auto_id();
let mut harness = TestHarness::create(widget);
harness.mouse_move(Point::ZERO);

View File

@ -5,13 +5,14 @@
use std::f64::consts::PI;
use masonry_testing::WrapperWidget;
use vello::kurbo::{Affine, Vec2};
use vello::peniko::color::palette;
use crate::core::{NewWidget, PointerButton, Properties, Widget, WidgetOptions};
use crate::properties::types::UnitPoint;
use crate::properties::{Background, BorderColor, BorderWidth};
use crate::testing::{TestHarness, TestWidgetExt, assert_render_snapshot};
use crate::testing::{TestHarness, assert_render_snapshot};
use crate::theme::default_property_set;
use crate::widgets::{Button, ChildAlignment, Label, SizedBox, ZStack};
@ -21,10 +22,12 @@ fn blue_box(inner: impl Widget) -> impl Widget {
box_props.insert(BorderColor::new(palette::css::TEAL));
box_props.insert(BorderWidth::all(2.0));
SizedBox::new(inner.with_auto_id())
.width(200.)
.height(100.)
.with_props(box_props)
WrapperWidget::new(
SizedBox::new(inner.with_auto_id())
.width(200.)
.height(100.)
.with_props(box_props),
)
}
#[test]
@ -41,7 +44,9 @@ fn transforms_translation_rotation() {
..Default::default()
},
);
let widget = ZStack::new().with_child(transformed_widget, ChildAlignment::ParentAligned);
let widget = ZStack::new()
.with_child(transformed_widget, ChildAlignment::ParentAligned)
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
assert_render_snapshot!(harness, "transforms_translation_rotation");
@ -59,7 +64,9 @@ fn transforms_pointer_events() {
..Default::default()
},
);
let widget = ZStack::new().with_child(transformed_widget, ChildAlignment::ParentAligned);
let widget = ZStack::new()
.with_child(transformed_widget, ChildAlignment::ParentAligned)
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
harness.mouse_move((335.0, 350.0)); // Should hit the last "d" of the button text

View File

@ -22,7 +22,8 @@ fn access_grandchild_widget() {
)
.with_auto_id(),
)
.with_flex_spacer(1.0);
.with_flex_spacer(1.0)
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);

View File

@ -952,7 +952,9 @@ mod tests {
#[test]
fn edit_wordwrap() {
let base_with_wrapping = {
let area = TextArea::new_immutable("String which will wrap").with_word_wrap(true);
let area = NewWidget::new(
TextArea::new_immutable("String which will wrap").with_word_wrap(true),
);
let mut harness =
TestHarness::create_with_size(default_property_set(), area, Size::new(60.0, 40.0));
@ -961,7 +963,9 @@ mod tests {
};
{
let area = TextArea::new_immutable("String which will wrap").with_word_wrap(false);
let area = NewWidget::new(
TextArea::new_immutable("String which will wrap").with_word_wrap(false),
);
let mut harness =
TestHarness::create_with_size(default_property_set(), area, Size::new(60.0, 40.0));
@ -1089,8 +1093,9 @@ mod tests {
},
];
for scenario in scenarios {
let area =
TextArea::new_editable("hello world").with_insert_newline(scenario.insert_newline);
let area = NewWidget::new(
TextArea::new_editable("hello world").with_insert_newline(scenario.insert_newline),
);
let mut harness = TestHarness::create(default_property_set(), area);
let text_id = harness.root_id();

View File

@ -228,11 +228,11 @@ mod tests {
#[test]
fn text_input_outline() {
let text_input = TextInput::from_text_area(
let text_input = NewWidget::new(TextInput::from_text_area(
TextArea::new_editable("TextInput contents")
.with_style(StyleProperty::FontSize(14.0))
.with_auto_id(),
);
));
let mut harness = TestHarness::create_with_size(
default_property_set(),
text_input,

View File

@ -1065,7 +1065,7 @@ mod tests {
fn sensible_driver() {
type ScrollContents = Label;
let widget = VirtualScroll::<ScrollContents>::new(0);
let widget = VirtualScroll::<ScrollContents>::new(0).with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(100., 200.));
@ -1113,7 +1113,7 @@ mod tests {
fn small_gaps() {
type ScrollContents = Label;
let widget = VirtualScroll::<ScrollContents>::new(0);
let widget = VirtualScroll::<ScrollContents>::new(0).with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(100., 200.));
@ -1158,7 +1158,7 @@ mod tests {
fn big_gaps() {
type ScrollContents = Label;
let widget = VirtualScroll::<ScrollContents>::new(0);
let widget = VirtualScroll::<ScrollContents>::new(0).with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(100., 200.));
@ -1203,7 +1203,7 @@ mod tests {
fn degenerate_driver() {
type ScrollContents = Label;
let widget = VirtualScroll::<ScrollContents>::new(0);
let widget = VirtualScroll::<ScrollContents>::new(0).with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(100., 200.));
@ -1248,7 +1248,9 @@ mod tests {
type ScrollContents = Label;
const MIN: i64 = 10;
let widget = VirtualScroll::<ScrollContents>::new(0).with_valid_range(MIN..i64::MAX);
let widget = VirtualScroll::<ScrollContents>::new(0)
.with_valid_range(MIN..i64::MAX)
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(100., 200.));
@ -1322,7 +1324,9 @@ mod tests {
type ScrollContents = Label;
const MAX: i64 = 10;
let widget = VirtualScroll::<ScrollContents>::new(100).with_valid_range(i64::MIN..MAX);
let widget = VirtualScroll::<ScrollContents>::new(100)
.with_valid_range(i64::MIN..MAX)
.with_auto_id();
let mut harness =
TestHarness::create_with_size(default_property_set(), widget, Size::new(100., 200.));

View File

@ -254,7 +254,8 @@ mod tests {
fg_props,
),
ChildAlignment::ParentAligned,
);
)
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
assert_render_snapshot!(harness, "zstack_alignment_default");
@ -297,7 +298,8 @@ mod tests {
.with_child(
Label::new("BottomRight").with_auto_id(),
UnitPoint::BOTTOM_RIGHT,
);
)
.with_auto_id();
let mut harness = TestHarness::create(default_property_set(), widget);
assert_render_snapshot!(harness, "zstack_alignments_self_aligned");

View File

@ -15,8 +15,8 @@ use vello::kurbo::{Point, Size};
use crate::core::{
AccessCtx, AccessEvent, BoxConstraints, ComposeCtx, CursorIcon, EventCtx, LayoutCtx, NewWidget,
PaintCtx, PointerEvent, PropertiesMut, PropertiesRef, QueryCtx, RegisterCtx, TextEvent, Update,
UpdateCtx, WidgetRef,
PaintCtx, PointerEvent, Properties, PropertiesMut, PropertiesRef, QueryCtx, RegisterCtx,
TextEvent, Update, UpdateCtx, WidgetOptions, WidgetRef,
};
/// A unique identifier for a single [`Widget`].
@ -391,13 +391,31 @@ pub trait Widget: AsDynWidget + Any {
.unwrap_or(name)
}
/// Convenience method to create a [`NewWidget`] from this.
/// Convenience method to create wrap this in a [`NewWidget`].
fn with_auto_id(self) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new(self)
}
// TODO - We eventually want to remove the ability to reserve widget ids.
// See https://github.com/linebender/xilem/issues/1255
/// Convenience method to create wrap this in a [`NewWidget`] with the given id.
fn with_id(self, id: WidgetId) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new_with_id(self, id)
}
/// Convenience method to create wrap this in a [`NewWidget`] with the given [`Properties`].
fn with_props(self, props: Properties) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new_with(self, WidgetId::next(), WidgetOptions::default(), props)
}
}
/// See [`Widget::find_widget_under_pointer`] for more details.

View File

@ -221,29 +221,25 @@ impl Default for TestHarnessParams {
}
impl<W: Widget> TestHarness<W> {
// -- MARK: CREATE
/// Builds harness with given root widget.
///
/// Window size will be [`TestHarnessParams::DEFAULT_SIZE`].
/// Background color will be [`TestHarnessParams::DEFAULT_BACKGROUND_COLOR`].
// TODO - Take NewWidget
pub fn create(default_props: DefaultProperties, root_widget: W) -> Self {
Self::create_with(
default_props,
NewWidget::new(root_widget),
TestHarnessParams::default(),
)
pub fn create(default_props: DefaultProperties, root_widget: NewWidget<W>) -> Self {
Self::create_with(default_props, root_widget, TestHarnessParams::default())
}
/// Builds harness with given root widget and window size.
// TODO - Take NewWidget
pub fn create_with_size(
default_props: DefaultProperties,
root_widget: W,
root_widget: NewWidget<W>,
window_size: Size,
) -> Self {
Self::create_with(
default_props,
NewWidget::new(root_widget),
root_widget,
TestHarnessParams {
window_size,
..Default::default()

View File

@ -17,9 +17,7 @@ pub use modular_widget::ModularWidget;
pub use recorder_widget::{Record, Recorder, Recording};
pub use wrapper_widget::WrapperWidget;
use masonry_core::core::{NewWidget, Properties, Widget, WidgetId, WidgetOptions};
// TODO - Split off into separate file
use masonry_core::core::{Widget, WidgetId};
/// External trait implemented for all widgets.
///
@ -29,26 +27,12 @@ pub trait TestWidgetExt: Widget + Sized + 'static {
fn record(self, recording: &Recording) -> Recorder<Self> {
Recorder::new(self, recording)
}
// TODO - Move to `Widget` trait.
/// Wrap this widget in a [`WrapperWidget`] with the given id.
fn with_id(self, id: WidgetId) -> WrapperWidget {
let child = NewWidget::new_with_id(self, id).erased().to_pod();
WrapperWidget::new_pod(child)
}
// TODO - Move to `Widget` trait.
/// Wrap this widget in a [`WrapperWidget`] with the given [`Properties`].
fn with_props(self, props: Properties) -> WrapperWidget {
let child = NewWidget::new_with(self, WidgetId::next(), WidgetOptions::default(), props)
.erased()
.to_pod();
WrapperWidget::new_pod(child)
}
}
impl<W: Widget + 'static> TestWidgetExt for W {}
// TODO - We eventually want to remove the ability to reserve widget ids.
// See https://github.com/linebender/xilem/issues/1255
/// Convenience function to return an array of unique widget ids.
pub fn widget_ids<const N: usize>() -> [WidgetId; N] {
std::array::from_fn(|_| WidgetId::next())

View File

@ -8,9 +8,9 @@ use tracing::trace_span;
use masonry_core::accesskit::{Node, Role};
use masonry_core::core::{
AccessCtx, AccessEvent, BoxConstraints, ChildrenIds, ComposeCtx, CursorIcon, EventCtx,
LayoutCtx, NewWidget, PaintCtx, PointerEvent, PropertiesMut, PropertiesRef, QueryCtx,
RegisterCtx, TextEvent, Update, UpdateCtx, Widget, WidgetId, WidgetRef,
find_widget_under_pointer,
LayoutCtx, NewWidget, PaintCtx, PointerEvent, Properties, PropertiesMut, PropertiesRef,
QueryCtx, RegisterCtx, TextEvent, Update, UpdateCtx, Widget, WidgetId, WidgetOptions,
WidgetRef, find_widget_under_pointer,
};
use masonry_core::kurbo::{Point, Size};
use masonry_core::vello::Scene;
@ -384,4 +384,18 @@ impl<S: 'static> Widget for ModularWidget<S> {
{
NewWidget::new(self)
}
fn with_id(self, id: WidgetId) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new_with_id(self, id)
}
fn with_props(self, props: Properties) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new_with(self, WidgetId::next(), WidgetOptions::default(), props)
}
}

View File

@ -16,8 +16,9 @@ use std::rc::Rc;
use masonry_core::accesskit::{Node, Role};
use masonry_core::core::{
AccessCtx, AccessEvent, BoxConstraints, ChildrenIds, ComposeCtx, CursorIcon, EventCtx,
LayoutCtx, NewWidget, PaintCtx, PointerEvent, PropertiesMut, PropertiesRef, QueryCtx,
RegisterCtx, TextEvent, Update, UpdateCtx, Widget, WidgetId, WidgetRef,
LayoutCtx, NewWidget, PaintCtx, PointerEvent, Properties, PropertiesMut, PropertiesRef,
QueryCtx, RegisterCtx, TextEvent, Update, UpdateCtx, Widget, WidgetId, WidgetOptions,
WidgetRef,
};
use masonry_core::kurbo::{Point, Size};
use masonry_core::vello::Scene;
@ -269,4 +270,18 @@ impl<W: Widget> Widget for Recorder<W> {
{
NewWidget::new(self)
}
fn with_id(self, id: WidgetId) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new_with_id(self, id)
}
fn with_props(self, props: Properties) -> NewWidget<Self>
where
Self: Sized,
{
NewWidget::new_with(self, WidgetId::next(), WidgetOptions::default(), props)
}
}

View File

@ -21,16 +21,10 @@ impl WrapperWidget {
/// Create a new `WrapperWidget`.
///
/// The `child` is the initial child widget.
pub fn new<W: Widget + 'static>(child: impl Widget) -> Self {
// FIXME - Take NewWidget argument
Self::new_pod(NewWidget::new(child).erased().to_pod())
}
/// Create a new `WrapperWidget` with a `WidgetPod`.
///
/// The `child` is the initial child widget.
pub fn new_pod(child: WidgetPod<dyn Widget>) -> Self {
Self { child }
pub fn new(child: NewWidget<impl Widget>) -> Self {
Self {
child: child.erased().to_pod(),
}
}
/// Get mutable reference to the child widget.

View File

@ -230,7 +230,10 @@ mod tests {
fn screenshot_test() {
let my_string = "Masonry + Vello".to_string();
let mut harness = TestHarness::create(default_property_set(), CustomWidget(my_string));
let mut harness = TestHarness::create(
default_property_set(),
NewWidget::new(CustomWidget(my_string)),
);
assert_render_snapshot!(harness, "example_custom_widget_initial");
}
}

View File

@ -57,7 +57,7 @@ fn grid_button(params: GridParams) -> Button {
}
/// Create a grid with a bunch of buttons
pub fn make_grid(grid_spacing: f64) -> Grid {
pub fn make_grid(grid_spacing: f64) -> NewWidget<Grid> {
let label = Prose::from_text_area(
TextArea::new_immutable("Change spacing by right and left clicking on the buttons")
.with_style(StyleProperty::FontSize(14.0))
@ -130,7 +130,7 @@ pub fn make_grid(grid_spacing: f64) -> Grid {
main_widget = main_widget.with_child(button.with_auto_id(), button_input);
}
main_widget
NewWidget::new(main_widget)
}
fn main() {
@ -148,11 +148,7 @@ fn main() {
masonry_winit::app::run(
masonry_winit::app::EventLoop::with_user_event(),
vec![(
driver.window_id,
window_attributes,
NewWidget::new(main_widget).erased(),
)],
vec![(driver.window_id, window_attributes, main_widget.erased())],
driver,
default_property_set(),
)

View File

@ -30,7 +30,7 @@ impl AppDriver for Driver {
}
/// Return an image with hardcoded data
pub fn make_image() -> Image {
pub fn make_image() -> NewWidget<Image> {
let image_bytes = include_bytes!("./assets/PicWithAlpha.png");
let image_data = image::load_from_memory(image_bytes).unwrap().to_rgba8();
let (width, height) = image_data.dimensions();
@ -41,7 +41,7 @@ pub fn make_image() -> Image {
height,
);
Image::new(png_data).fit_mode(ObjectFit::Contain)
NewWidget::new(Image::new(png_data).fit_mode(ObjectFit::Contain))
}
fn main() {
@ -53,11 +53,7 @@ fn main() {
masonry_winit::app::run(
masonry_winit::app::EventLoop::with_user_event(),
vec![(
WindowId::next(),
window_attributes,
NewWidget::new(make_image()).erased(),
)],
vec![(WindowId::next(), window_attributes, make_image().erased())],
Driver,
default_property_set(),
)

View File

@ -58,7 +58,7 @@ impl AppDriver for Driver {
}
/// Return initial to-do-list without items.
pub fn make_widget_tree() -> impl Widget {
pub fn make_widget_tree() -> NewWidget<impl Widget> {
Portal::new(
Flex::column()
.with_child(NewWidget::new_with_props(
@ -70,6 +70,7 @@ pub fn make_widget_tree() -> impl Widget {
.with_spacer(WIDGET_SPACING)
.with_auto_id(),
)
.with_auto_id()
}
fn main() {
@ -91,7 +92,7 @@ fn main() {
vec![(
driver.window_id,
window_attributes,
NewWidget::new(make_widget_tree()).erased(),
make_widget_tree().erased(),
)],
driver,
default_property_set(),

View File

@ -59,7 +59,7 @@ mod tests {
fn zero_size_grid_masonry() {
let mut harness = TestHarness::create_with(
default_property_set(),
others::grid_masonry::make_grid(1.0).with_auto_id(),
others::grid_masonry::make_grid(1.0),
PARAMS_ZERO_SIZE,
);
let _ = harness.render();
@ -69,7 +69,7 @@ mod tests {
fn zero_size_simple_image() {
let mut harness = TestHarness::create_with(
default_property_set(),
others::simple_image::make_image().with_auto_id(),
others::simple_image::make_image(),
PARAMS_ZERO_SIZE,
);
let _ = harness.render();
@ -79,7 +79,7 @@ mod tests {
fn zero_size_to_do_list() {
let mut harness = TestHarness::create_with(
default_property_set(),
others::to_do_list::make_widget_tree().with_auto_id(),
others::to_do_list::make_widget_tree(),
PARAMS_ZERO_SIZE,
);
let _ = harness.render();