use compose_rust::prelude::*;
use compose_rust::protocol::{Mutation, PropertyValue, decode_batch};
use compose_rust::{Host, PropertyKind, WidgetKind};
fn titled_text() -> Element {
rsx! {
Text { text: "제목", type_role: TypeRole::Title }
}
}
fn styled_column() -> Element {
rsx! {
Column {
arrangement: Arrangement::SpaceBetween,
space_role: SpaceRole::Md,
alignment: Alignment::Center,
Button { text: "확인", variant: ButtonVariant::Tonal }
}
}
}
fn scrolling() -> Element {
rsx! {
ScrollColumn {
Text { text: "long" }
}
}
}
fn props_of(app: fn() -> Element) -> Vec<(PropertyKind, PropertyValue<'static>)> {
let mut host = Host::new(app);
let batch = host.rebuild().unwrap().to_vec();
decode_batch(&batch)
.unwrap()
.into_iter()
.filter_map(|mutation| match mutation {
Mutation::SetProp {
property, value, ..
} => Some((
property,
match value {
PropertyValue::String(_) | PropertyValue::Bytes(_) => PropertyValue::None,
PropertyValue::None => PropertyValue::None,
PropertyValue::Bool(value) => PropertyValue::Bool(value),
PropertyValue::Integer(value) => PropertyValue::Integer(value),
PropertyValue::Float(value) => PropertyValue::Float(value),
},
)),
_ => None,
})
.collect()
}
#[test]
fn fr13_type_role_costs_one_set_prop() {
let props = props_of(titled_text);
let design: Vec<_> = props
.iter()
.filter(|(property, _)| *property as u16 >= PropertyKind::TypeRole as u16)
.collect();
assert_eq!(
design,
[&(
PropertyKind::TypeRole,
PropertyValue::Integer(TypeRole::Title as i64)
)]
);
}
#[test]
fn fr13_layout_roles_and_variant_are_sent_as_tags() {
let props = props_of(styled_column);
for expected in [
(
PropertyKind::Arrangement,
PropertyValue::Integer(Arrangement::SpaceBetween as i64),
),
(
PropertyKind::SpaceRole,
PropertyValue::Integer(SpaceRole::Md as i64),
),
(
PropertyKind::Alignment,
PropertyValue::Integer(Alignment::Center as i64),
),
(
PropertyKind::Variant,
PropertyValue::Integer(ButtonVariant::Tonal as i64),
),
] {
assert!(props.contains(&expected), "missing {expected:?}");
}
assert!(
!props
.iter()
.any(|(property, _)| *property == PropertyKind::Spacing)
);
}
fn monospaced_field() -> Element {
rsx! {
TextField { placeholder: "경로", type_role: TypeRole::Mono }
}
}
#[test]
fn fr13_text_field_takes_a_type_role() {
let props = props_of(monospaced_field);
assert!(
props.contains(&(
PropertyKind::TypeRole,
PropertyValue::Integer(TypeRole::Mono as i64)
)),
"the field did not send its rung: {props:?}"
);
}
fn destructive_button() -> Element {
rsx! {
Button {
text: "삭제",
variant: ButtonVariant::Text,
color: Paint::Role(ColorRole::Error),
}
}
}
fn separated_rows() -> Element {
rsx! {
Column {
Text { text: "위" }
Separator {}
Text { text: "아래" }
}
}
}
#[test]
fn fr13_button_label_colour_is_sent_as_a_role() {
let props = props_of(destructive_button);
assert!(
props.contains(&(
PropertyKind::Color,
PropertyValue::Integer(Paint::Role(ColorRole::Error).to_bits() as i64)
)),
"the button did not send its label colour: {props:?}"
);
}
#[test]
fn fr13_separator_is_one_divider_so_the_design_system_sets_its_weight() {
let mut host = Host::new(separated_rows);
let batch = host.rebuild().unwrap().to_vec();
let mutations = decode_batch(&batch).unwrap();
let divider = mutations
.iter()
.find_map(|mutation| match mutation {
Mutation::Create {
node_id,
widget: WidgetKind::Divider,
} => Some(*node_id),
_ => None,
})
.expect("the separator is drawn as a Divider");
let modifiers: Vec<_> = mutations
.iter()
.filter_map(|mutation| match mutation {
Mutation::SetModifier {
node_id, modifier, ..
} if *node_id == divider && !matches!(modifier, Modifier::Empty) => {
Some(modifier.clone())
}
_ => None,
})
.collect();
assert!(
modifiers.is_empty(),
"a separator that named its own thickness or colour would be deciding for the \
design system: {modifiers:?}"
);
assert!(
!mutations.iter().any(|mutation| matches!(
mutation,
Mutation::Create {
widget: WidgetKind::Spacer,
..
}
)),
"the hand-drawn hairline is gone, so no Spacer stands in for the rule"
);
}
#[test]
fn fr13_scroll_column_is_its_own_widget() {
let mut host = Host::new(scrolling);
let batch = host.rebuild().unwrap().to_vec();
assert!(
decode_batch(&batch)
.unwrap()
.iter()
.any(|mutation| matches!(
mutation,
Mutation::Create {
widget: WidgetKind::ScrollColumn,
..
}
))
);
}