use structform::{
derive_form_input, impl_text_input_with_stringops, ParseAndFormat, ParseError, StructForm,
};
#[derive(Default, Debug, PartialEq, Eq)]
struct UserDetails {
username: String,
primary_address: Address,
secondary_address: Option<Address>,
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
struct Address {
street_address: String,
city: String,
country: String,
}
#[derive(Default, Clone, StructForm)]
#[structform(model = "UserDetails")]
struct UserDetailsForm {
username: FormTextInput<String>,
#[structform(subform)]
primary_address: AddressForm,
secondary_address: Option<AddressForm>,
}
#[derive(Default, Clone, StructForm)]
#[structform(model = "Address")]
struct AddressForm {
street_address: FormTextInput<String>,
city: FormTextInput<String>,
country: FormTextInput<String>,
}
derive_form_input! {FormTextInput}
impl_text_input_with_stringops!(FormTextInput, String);
#[test]
fn set_input_delegates_to_subform() {
let mut form = UserDetailsForm::default();
assert_eq!(form.primary_address.city.value, Err(ParseError::Required));
form.set_input(
UserDetailsFormField::PrimaryAddress(AddressFormField::City),
"Johannesburg".to_string(),
);
assert_eq!(
form.primary_address.city.value,
Ok("Johannesburg".to_string())
);
}
#[test]
fn optional_subforms_can_be_toggled_on_and_off() {
let mut form = UserDetailsForm::default();
assert!(form.secondary_address.is_none());
form.set_input(
UserDetailsFormField::SecondaryAddress(AddressFormField::City),
"Johannesburg".to_string(),
);
assert!(form.secondary_address.is_none());
form.set_input(UserDetailsFormField::ToggleSecondaryAddress, "".to_string());
assert!(form.secondary_address.is_some());
assert_eq!(
form.secondary_address.as_ref().unwrap().city.value,
Err(ParseError::Required)
);
form.set_input(
UserDetailsFormField::SecondaryAddress(AddressFormField::City),
"Johannesburg".to_string(),
);
assert_eq!(
form.secondary_address.as_ref().unwrap().city.value,
Ok("Johannesburg".to_string())
);
}
#[test]
fn the_subforms_are_populated_when_initializing_from_an_existing_model() {
let model = UserDetails {
username: "justin".to_string(),
primary_address: Address {
street_address: "123 StructForm Drive".to_string(),
city: "Johannesburg".to_string(),
country: "South Africa".to_string(),
},
secondary_address: Some(Address {
street_address: "321 StructForm Laan".to_string(),
city: "Pretoria".to_string(),
country: "South Africa".to_string(),
}),
};
let form = UserDetailsForm::new(&model);
assert_eq!(form.username.input, "justin".to_string());
assert_eq!(
form.primary_address.street_address.input,
"123 StructForm Drive".to_string()
);
assert!(form.secondary_address.is_some());
assert_eq!(
form.secondary_address.unwrap().street_address.input,
"321 StructForm Laan".to_string()
);
}
#[test]
fn the_whole_form_can_be_completed() {
let mut form = UserDetailsForm::default();
form.set_input(UserDetailsFormField::Username, "justin".to_string());
assert_eq!(form.submit(), Err(ParseError::Required));
form.set_input(
UserDetailsFormField::PrimaryAddress(AddressFormField::StreetAddress),
"123 StructForm Drive".to_string(),
);
form.set_input(
UserDetailsFormField::PrimaryAddress(AddressFormField::City),
"Johannesburg".to_string(),
);
form.set_input(
UserDetailsFormField::PrimaryAddress(AddressFormField::Country),
"South Africa".to_string(),
);
assert_eq!(
form.submit(),
Ok(UserDetails {
username: "justin".to_string(),
primary_address: Address {
street_address: "123 StructForm Drive".to_string(),
city: "Johannesburg".to_string(),
country: "South Africa".to_string(),
},
secondary_address: None,
})
);
form.set_input(UserDetailsFormField::ToggleSecondaryAddress, "".to_string());
assert_eq!(form.submit(), Err(ParseError::Required));
form.set_input(
UserDetailsFormField::SecondaryAddress(AddressFormField::StreetAddress),
"321 StructForm Laan".to_string(),
);
form.set_input(
UserDetailsFormField::SecondaryAddress(AddressFormField::City),
"Pretoria".to_string(),
);
form.set_input(
UserDetailsFormField::SecondaryAddress(AddressFormField::Country),
"South Africa".to_string(),
);
assert_eq!(
form.submit(),
Ok(UserDetails {
username: "justin".to_string(),
primary_address: Address {
street_address: "123 StructForm Drive".to_string(),
city: "Johannesburg".to_string(),
country: "South Africa".to_string(),
},
secondary_address: Some(Address {
street_address: "321 StructForm Laan".to_string(),
city: "Pretoria".to_string(),
country: "South Africa".to_string(),
}),
})
);
}