pub trait Options {
fn options() -> Vec<(String, String)>;
fn label_of(value: &str) -> String {
Self::options()
.into_iter()
.find(|(stored, _)| stored == value)
.map_or_else(|| value.to_string(), |(_, label)| label)
}
}
#[cfg(test)]
mod tests {
use super::Options;
use crate::Column as _;
#[derive(Debug, Clone, Copy, PartialEq, Eq, crate::Options)]
enum Status {
Draft,
#[option(label = "Live")]
Published,
#[option(value = "arch", label = "Archive")]
Archived,
}
#[test]
fn an_options_enum_shares_one_value_label_list() {
assert_eq!(
Status::options(),
vec![
("draft".to_string(), "Draft".to_string()),
("published".to_string(), "Live".to_string()),
("arch".to_string(), "Archive".to_string()),
]
);
assert_eq!(Status::Draft.value(), "draft");
assert_eq!(Status::Published.label(), "Live");
assert_eq!(Status::from_value("draft"), Some(Status::Draft));
assert_eq!(Status::from_value("arch"), Some(Status::Archived));
assert_eq!(Status::from_value("gone"), None);
assert_eq!(Status::label_of("published"), "Live");
assert_eq!(
Status::label_of("renamed"),
"renamed",
"a value no option stores reads as itself"
);
}
#[tokio::test]
async fn the_shared_list_feeds_a_choice_a_select_filter_and_a_column() {
let options = Status::options();
let schema = crate::Schema::new(
crate::Field::choice(StatusField::fields().status()).options(options.clone()),
);
let mut valid = std::collections::HashMap::new();
valid.insert("status".to_string(), "draft".to_string());
let cx = topcoat::context::CxTestBuilder::new().build();
let errors = schema.validate_async(&cx, &valid).await;
assert!(errors.is_empty(), "a shared option validates: {errors:?}");
let mut bogus = std::collections::HashMap::new();
bogus.insert("status".to_string(), "gone".to_string());
assert!(
!schema.validate_async(&cx, &bogus).await.is_empty(),
"an unlisted value fails"
);
let filter = crate::SelectFilter::new(StatusField::fields().status(), options.clone());
assert_eq!(filter.options(), options.as_slice());
let column = crate::TextColumn::new(crate::lens!(StatusField.status))
.format(|status| Status::label_of(status));
let row = StatusField {
id: uuid::Uuid::nil(),
status: "published".to_string(),
};
assert_eq!(column.text(&row), "Live");
}
#[derive(Debug, Clone, toasty::Model)]
struct StatusField {
#[key]
#[auto]
id: uuid::Uuid,
status: String,
}
}